Failing a command with code RET_SYN prints help and doesn't charge BTUs. Failing with code RET_FAIL doesn't print help and charges BTUs. A couple of command failures were changed or added recently to fail with RET_SYN, because they're due to invalid player input. Some of them, however, can happen after the command already did something, so BTUs must be charged, or else players can deliberately fail the command to save BTUs: * Commit9eda5f87
adds RET_SYN failures when getting player input fails for: - arm third argument - deliver fourth argument - fire third argument - lmine second argument - order d fourth argument - range second argument - sail second argument - tend third argument * Commitbe41e70f
likewise for: - designate second argument - morale second argument - set third argument - tend fourth argument * Commitd000bf92
likewise (with a bogus commit message) for bdes second argument. * Commit9f4ce71a
likewise for ltend third and fourth argument. * Commit9031b03b
changes failure code from RET_FAIL when getting player input fails for threshold third argument. It adds RET_SYN failure when the argument is bad. Some bad arguments already failed that way before. * Commita7cf69af
changes it from RET_FAIL when designate second argument is bad. Change them all to fail with RET_FAIL. Many other places have the same bug, but those are left for another day.
170 lines
5 KiB
C
170 lines
5 KiB
C
/*
|
|
* Empire - A multi-player, client/server Internet based war game.
|
|
* Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
|
|
* Ken Stevens, Steve McClure
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* ---
|
|
*
|
|
* See files README, COPYING and CREDITS in the root of the source
|
|
* tree for related information and legal notices. It is expected
|
|
* that future projects/authors will amend these files as needed.
|
|
*
|
|
* ---
|
|
*
|
|
* mine.c: Lay mines from ships or units
|
|
*
|
|
* Known contributors to this file:
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "commands.h"
|
|
#include "land.h"
|
|
#include "map.h"
|
|
#include "ship.h"
|
|
|
|
/*
|
|
* format: mine <SHIPS> <NUMBER MINES>
|
|
*/
|
|
int
|
|
mine(void)
|
|
{
|
|
struct shpstr ship;
|
|
struct sctstr sect;
|
|
struct mchrstr *mp;
|
|
struct nstr_item ni;
|
|
int mines;
|
|
int shells;
|
|
int mines_avail;
|
|
|
|
if (!snxtitem(&ni, EF_SHIP, player->argp[1], NULL))
|
|
return RET_SYN;
|
|
mines = onearg(player->argp[2],
|
|
"Drop how many mines from each ship? ");
|
|
if (mines <= 0)
|
|
return RET_SYN;
|
|
while (nxtitem(&ni, &ship)) {
|
|
if (!player->owner)
|
|
continue;
|
|
mp = &mchr[(int)ship.shp_type];
|
|
if ((mp->m_flags & M_MINE) == 0)
|
|
continue;
|
|
if ((shells = ship.shp_item[I_SHELL]) == 0)
|
|
continue;
|
|
mines_avail = MIN(shells, mines);
|
|
if (getsect(ship.shp_x, ship.shp_y, §) == 0 ||
|
|
(sect.sct_type != SCT_WATER && sect.sct_type != SCT_BSPAN)) {
|
|
pr("You can't lay mines there!!\n");
|
|
continue;
|
|
}
|
|
sect.sct_mines = MIN(sect.sct_mines + mines_avail, MINES_MAX);
|
|
ship.shp_item[I_SHELL] = shells - mines_avail;
|
|
putsect(§);
|
|
ship.shp_mission = 0;
|
|
putship(ship.shp_uid, &ship);
|
|
pr("Laying %d mines from %s\n", mines_avail, prship(&ship));
|
|
if (mines_avail &&
|
|
map_set(player->cnum, sect.sct_x, sect.sct_y, 'X', 0))
|
|
writemap(player->cnum);
|
|
}
|
|
return RET_OK;
|
|
}
|
|
|
|
/*
|
|
* format: landmine <UNITS> <NUMBER MINES>
|
|
*/
|
|
int
|
|
landmine(void)
|
|
{
|
|
struct lndstr land;
|
|
struct sctstr sect;
|
|
struct lchrstr *lp;
|
|
struct nstr_item ni;
|
|
int shells;
|
|
int mines_wanted;
|
|
int mines_laid;
|
|
int total_mines_laid;
|
|
char prompt[128];
|
|
|
|
if (!snxtitem(&ni, EF_LAND, player->argp[1], NULL))
|
|
return RET_SYN;
|
|
while (nxtitem(&ni, &land)) {
|
|
if (!player->owner)
|
|
continue;
|
|
lp = &lchr[(int)land.lnd_type];
|
|
if (!(lp->l_flags & L_ENGINEER))
|
|
continue;
|
|
if (land.lnd_mobil < 1) {
|
|
pr("Unit %d is out of mobility\n", land.lnd_uid);
|
|
continue;
|
|
}
|
|
resupply_commod(&land, I_SHELL);
|
|
putland(land.lnd_uid, &land);
|
|
if (!(shells = land.lnd_item[I_SHELL]))
|
|
continue;
|
|
shells = MIN(shells, land.lnd_mobil);
|
|
if (!getsect(land.lnd_x, land.lnd_y, §) ||
|
|
sect.sct_type == SCT_WATER || sect.sct_type == SCT_BSPAN) {
|
|
pr("You can't lay mines there!!\n");
|
|
continue;
|
|
}
|
|
if (sect.sct_own == sect.sct_oldown)
|
|
pr("There are currently %d mines in %s\n",
|
|
sect.sct_mines, xyas(sect.sct_x, sect.sct_y, player->cnum));
|
|
sprintf(prompt, "Drop how many mines from %s? ", prland(&land));
|
|
mines_wanted = onearg(player->argp[2], prompt);
|
|
if (mines_wanted < 0)
|
|
return RET_FAIL;
|
|
if (mines_wanted == 0)
|
|
continue;
|
|
if (!check_land_ok(&land))
|
|
continue;
|
|
land.lnd_mission = 0;
|
|
total_mines_laid = 0;
|
|
while (shells > 0 && total_mines_laid < mines_wanted) {
|
|
mines_laid = MIN(shells, mines_wanted - total_mines_laid);
|
|
land.lnd_item[I_SHELL] = shells - mines_laid;
|
|
land.lnd_mobil -= mines_laid;
|
|
putland(land.lnd_uid, &land);
|
|
resupply_commod(&land, I_SHELL); /* Get more shells */
|
|
putland(land.lnd_uid, &land);
|
|
total_mines_laid += mines_laid;
|
|
shells = land.lnd_item[I_SHELL];
|
|
shells = MIN(shells, land.lnd_mobil);
|
|
}
|
|
getsect(sect.sct_x, sect.sct_y, §);
|
|
sect.sct_mines = MIN(sect.sct_mines + total_mines_laid, MINES_MAX);
|
|
putsect(§);
|
|
if (total_mines_laid == mines_wanted) {
|
|
pr("%s laid a total of %d mines in %s",
|
|
prland(&land), total_mines_laid,
|
|
xyas(sect.sct_x, sect.sct_y, land.lnd_own));
|
|
if (!shells)
|
|
pr(" but is now out of supply\n");
|
|
else
|
|
pr("\n");
|
|
} else
|
|
pr("%s ran out of %s before it could finish the job\n"
|
|
"Only %d mines were laid in %s\n",
|
|
prland(&land),
|
|
land.lnd_mobil > 0 ? "supply" : "mobility",
|
|
total_mines_laid,
|
|
xyas(sect.sct_x, sect.sct_y, land.lnd_own));
|
|
}
|
|
return RET_OK;
|
|
}
|