multifire() drops depth charges if the target is a submarine, else it
fires guns. It fails if the target is out of range. But players
could still find out whether the target is a sub then, because depth
charge shell use differs from gun fire shell use. This loophole
existed before 4.0.6, and was reopened by commit
a3ad623b (v4.3.12).
Change multifire() to always use guns if the target is out of range.
While there, treat failure from shp_dchrg() and shp_fire() the same,
so that the player can't distinguish the two cases. Failure there
should not happen.
pr("%s -- not enough shells\n", prland(&fland));
continue;
}
pr("%s -- not enough shells\n", prland(&fland));
continue;
}
+ fx = fland.lnd_x;
+ fy = fland.lnd_y;
} else if (type == EF_SHIP) {
if (!getship(item.ship.shp_uid, &fship))
continue;
} else if (type == EF_SHIP) {
if (!getship(item.ship.shp_uid, &fship))
continue;
pr("Ship #%d is crippled!\n", item.ship.shp_uid);
continue;
}
pr("Ship #%d is crippled!\n", item.ship.shp_uid);
continue;
}
+ fx = fship.shp_x;
+ fy = fship.shp_y;
} else if (type == EF_SECTOR) {
if (!getsect(item.sect.sct_x, item.sect.sct_y, &fsect))
continue;
} else if (type == EF_SECTOR) {
if (!getsect(item.sect.sct_x, item.sect.sct_y, &fsect))
continue;
}
pr("\nSector %s firing\n",
xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
}
pr("\nSector %s firing\n",
xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
+ fx = fsect.sct_x;
+ fy = fsect.sct_y;
if ((ptr = getstarg(player->argp[3], "Firing at? ", buf)) == 0
|| *ptr == '\0')
continue;
if ((ptr = getstarg(player->argp[3], "Firing at? ", buf)) == 0
|| *ptr == '\0')
continue;
x = vsect.sct_x;
y = vsect.sct_y;
}
x = vsect.sct_x;
y = vsect.sct_y;
}
+
+ trange = mapdist(x, y, fx, fy);
+
if (type == EF_SHIP) {
if (!check_ship_ok(&fship))
return RET_FAIL;
if (type == EF_SHIP) {
if (!check_ship_ok(&fship))
return RET_FAIL;
- fx = fship.shp_x;
- fy = fship.shp_y;
if ((mil = fship.shp_item[I_MILIT]) < 1) {
pr("Not enough military for firing crew.\n");
continue;
if ((mil = fship.shp_item[I_MILIT]) < 1) {
pr("Not enough military for firing crew.\n");
continue;
range2 = roundrange(range);
pr("range is %d.00 (%.2f)\n", range2, range);
if (target == targ_sub
range2 = roundrange(range);
pr("range is %d.00 (%.2f)\n", range2, range);
if (target == targ_sub
&& (mchr[(int)fship.shp_type].m_flags & M_DCH)) {
dam = shp_dchrg(&fship);
&& (mchr[(int)fship.shp_type].m_flags & M_DCH)) {
dam = shp_dchrg(&fship);
- putship(fship.shp_uid, &fship);
- if (dam < 0) {
- pr("Not enough shells for depth charge!\n");
- continue;
- }
} else {
if (target == targ_sub)
/* Don't tell it's a sub */
} else {
if (target == targ_sub)
/* Don't tell it's a sub */
continue;
}
dam = shp_fire(&fship);
continue;
}
dam = shp_fire(&fship);
- putship(fship.shp_uid, &fship);
- if (dam <= 0) {
- pr("Klick! ...\n");
- continue;
- }
+ }
+ putship(fship.shp_uid, &fship);
+ if (dam <= 0) {
+ pr("Klick! ...\n");
+ continue;
}
if (opt_NOMOBCOST == 0) {
fship.shp_mobil = MAX(fship.shp_mobil - 15, -100);
}
if (opt_NOMOBCOST == 0) {
fship.shp_mobil = MAX(fship.shp_mobil - 15, -100);
- fx = fland.lnd_x;
- fy = fland.lnd_y;
-
if (lchr[fland.lnd_type].l_dam == 0) {
pr("Unit %d cannot fire!\n", fland.lnd_uid);
continue;
if (lchr[fland.lnd_type].l_dam == 0) {
pr("Unit %d cannot fire!\n", fland.lnd_uid);
continue;
} else {
if (!check_sect_ok(&fsect))
return RET_FAIL;
} else {
if (!check_sect_ok(&fsect))
return RET_FAIL;
- fx = fsect.sct_x;
- fy = fsect.sct_y;
if (fsect.sct_own != player->cnum ||
fsect.sct_type != SCT_FORTR) {
pr("No fortress at %s\n",
if (fsect.sct_own != player->cnum ||
fsect.sct_type != SCT_FORTR) {
pr("No fortress at %s\n",
- trange = mapdist(x, y, fx, fy);
if (trange > range2) {
pr("Target out of range.\n");
switch (type) {
if (trange > range2) {
pr("Target out of range.\n");
switch (type) {