Movement stops when shp_interdict() or lnd_interdict() report
interdiction. However, they reported it only when there was
interdiction damage.
Zero interdiction damage commonly happens when interdicting missiles
miss, or all bombers abort. Stopping regardless of damage makes more
sense there.
Moreover, not stopping is buggy: do_unit_move() needs to take care not
to wipe out updates made by interdiction to the moving ships or land
units. It does so only when it stops. Updates made by interdiction
without interdiction damage could get wiped out, triggering a seqno
mismatch oops.
Known ways moving ships and land units can get updated by interdiction
despite there is no interdiction damage:
* Interdicting bombers get intercepted by planes based on a navigating
carrier, carrier gets charged petrol. The bug wipes out the petrol
use.
* Marching land units get interdicted by planes, but all planes miss.
Sufficiently large collateral damage to the sector can still damage
the land units. The bug wipes out the damage to land units.
To make shp_interdict() and lnd_interdict() report interdiction
regardless of damage, change lnd_missile_interdiction(),
lnd_fort_interdiction(), lnd_mission_interdiction(),
shp_missile_interdiction(), shp_fort_interdiction(),
shp_mission_interdiction() to return whether there was interdiction.
Before, they returned whether there was damage.
Change unit_interdict(), perform_mission(), perform_mission_land(),
perform_mission_ship(), perform_mission_msl(), and
perform_mission_bomb() to return -1 for no interdiction, so that
callers can distinguish no interdiction from interdiction with no
damage.
int mindam = lnd_count(list) * 20;
int hardtarget = lnd_easiest_target(list);
int dam, newdam, sublaunch;
int mindam = lnd_count(list) * 20;
int hardtarget = lnd_easiest_target(list);
int dam, newdam, sublaunch;
struct plist *plp;
struct emp_qelem msl_list, *qp, *newqp;
struct plist *plp;
struct emp_qelem msl_list, *qp, *newqp;
if (msl_launch(&plp->plane, EF_LAND, "troops",
newx, newy, victim, &sublaunch) < 0)
goto use_up_msl;
if (msl_launch(&plp->plane, EF_LAND, "troops",
newx, newy, victim, &sublaunch) < 0)
goto use_up_msl;
if (msl_hit(&plp->plane, hardtarget, EF_LAND,
N_LND_MISS, N_LND_SMISS, sublaunch, victim)) {
newdam = pln_damage(&plp->plane, 'p', 1);
if (msl_hit(&plp->plane, hardtarget, EF_LAND,
N_LND_MISS, N_LND_SMISS, sublaunch, victim)) {
newdam = pln_damage(&plp->plane, 'p', 1);
if (dam) {
mpr(victim, "missile interdiction mission does %d damage!\n", dam);
collateral_damage(newx, newy, dam);
if (dam) {
mpr(victim, "missile interdiction mission does %d damage!\n", dam);
collateral_damage(newx, newy, dam);
- return lnd_damage(list, dam);
double guneff;
int shell, gun;
int dam;
double guneff;
int shell, gun;
int dam;
putsect(&fsect);
if (dam < 0)
continue;
putsect(&fsect);
if (dam < 0)
continue;
totdam += dam;
mpr(victim, "Incoming fire does %d damage!\n", dam);
wu(0, fsect.sct_own,
totdam += dam;
mpr(victim, "Incoming fire does %d damage!\n", dam);
wu(0, fsect.sct_own,
nreport(fsect.sct_own, N_SCT_SHELL, victim, 1);
}
if (totdam > 0)
nreport(fsect.sct_own, N_SCT_SHELL, victim, 1);
}
if (totdam > 0)
- return lnd_damage(list, totdam);
- return 0;
+ lnd_damage(list, totdam);
+ return stopping;
lnd_mission_interdiction(struct emp_qelem *list, coord x, coord y,
natid victim)
{
lnd_mission_interdiction(struct emp_qelem *list, coord x, coord y,
natid victim)
{
- return lnd_damage(list,
- unit_interdict(x, y, victim, "land units",
- lnd_easiest_target(list),
- MI_INTERDICT));
+ int dam;
+
+ dam = unit_interdict(x, y, victim, "land units",
+ lnd_easiest_target(list),
+ MI_INTERDICT);
+ if (dam >= 0)
+ lnd_damage(list, dam);
+ return dam >= 0;
natid, int);
static int perform_mission_bomb(int, struct emp_qelem *, coord, coord,
natid, int, char *, int, int);
natid, int);
static int perform_mission_bomb(int, struct emp_qelem *, coord, coord,
natid, int, char *, int, int);
-static int perform_mission(coord, coord, natid, struct emp_qelem *, int,
- char *, int);
+static int perform_mission(coord, coord, natid, struct emp_qelem *,
+ int, char *, int);
+
+static int
+tally_dam(int dam, int newdam)
+{
+ return dam < 0 ? newdam : dam + newdam;
+}
/*
* Interdict commodities & transported planes
/*
* Interdict commodities & transported planes
newdam = perform_mission(x, y, victim, &mi[cn].queue,
MI_INTERDICT, s, SECT_HARDTARGET);
newdam = perform_mission(x, y, victim, &mi[cn].queue,
MI_INTERDICT, s, SECT_HARDTARGET);
- dam += newdam;
- if (newdam)
+ if (newdam > 0) {
+ dam += newdam;
mpr(victim, "%s interdiction mission does %d damage!\n",
cname(cn), newdam);
mpr(victim, "%s interdiction mission does %d damage!\n",
cname(cn), newdam);
}
if (dam) {
collateral_damage(x, y, dam);
}
if (dam) {
collateral_damage(x, y, dam);
unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
int mission)
{
unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
int mission)
{
- int cn;
- int dam = 0, newdam;
+ int cn, newdam, osubs;
+ int dam = -1;
struct genlist mi[MAXNOC];
struct genlist mi[MAXNOC];
memset(mi, 0, sizeof(mi));
for (cn = 1; cn < MAXNOC; cn++)
memset(mi, 0, sizeof(mi));
for (cn = 1; cn < MAXNOC; cn++)
osubs = only_subs(&mi[cn].queue);
newdam = perform_mission(x, y, victim, &mi[cn].queue,
mission, s, hardtarget);
osubs = only_subs(&mi[cn].queue);
newdam = perform_mission(x, y, victim, &mi[cn].queue,
mission, s, hardtarget);
- dam += newdam;
- if (newdam) {
- /* If only subs responded, then we don't know who's
- subs they are */
+ dam = tally_dam(dam, newdam);
+ if (newdam > 0)
mpr(victim, "%s interdiction mission does %d damage!\n",
osubs ? "Enemy" : cname(cn), newdam);
mpr(victim, "%s interdiction mission does %d damage!\n",
osubs ? "Enemy" : cname(cn), newdam);
collateral_damage(x, y, dam);
collateral_damage(x, y, dam);
dosupport(struct genlist *mi, coord x, coord y, natid victim, natid actee)
{
int cn;
dosupport(struct genlist *mi, coord x, coord y, natid victim, natid actee)
{
int cn;
int dam = 0;
for (cn = 1; cn < MAXNOC; cn++) {
int dam = 0;
for (cn = 1; cn < MAXNOC; cn++) {
if (QEMPTY(&mi[cn].queue))
continue;
if (QEMPTY(&mi[cn].queue))
continue;
- dam += perform_mission(x, y, victim, &mi[cn].queue, MI_SUPPORT,
- "", SECT_HARDTARGET);
+ newdam = perform_mission(x, y, victim, &mi[cn].queue, MI_SUPPORT,
+ "", SECT_HARDTARGET);
+ if (newdam > 0)
+ dam += newdam;
struct genlist *glp;
struct plist *plp;
struct plchrstr *pcp;
struct genlist *glp;
struct plist *plp;
struct plchrstr *pcp;
int targeting_ships = *s == 's'; /* "subs" or "ships" FIXME gross! */
emp_initque(&missiles);
int targeting_ships = *s == 's'; /* "subs" or "ships" FIXME gross! */
emp_initque(&missiles);
dam = perform_mission_msl(dam, &missiles, x, y, victim, hardtarget);
dam = perform_mission_bomb(dam, &bombers, x, y, victim, mission, s,
hardtarget, targeting_ships);
dam = perform_mission_msl(dam, &missiles, x, y, victim, hardtarget);
dam = perform_mission_bomb(dam, &bombers, x, y, victim, mission, s,
hardtarget, targeting_ships);
mpr(victim, "%s %s fires at you at %s\n",
cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
mpr(victim, "%s %s fires at you at %s\n",
cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
+ return tally_dam(dam, dam2);
mpr(victim,
"Incoming torpedo sighted @ %s missed (whew)!\n",
xyas(x, y, victim));
mpr(victim,
"Incoming torpedo sighted @ %s missed (whew)!\n",
xyas(x, y, victim));
+ return tally_dam(dam, 0);
}
wu(0, sp->shp_own, "\tBOOM!...\n");
nreport(victim, N_TORP_SHIP, 0, 1);
}
wu(0, sp->shp_own, "\tBOOM!...\n");
nreport(victim, N_TORP_SHIP, 0, 1);
cname(sp->shp_own), prship(sp), xyas(x, y, victim));
}
cname(sp->shp_own), prship(sp), xyas(x, y, victim));
}
+ return tally_dam(dam, dam2);
}
static int
perform_mission_msl(int dam, struct emp_qelem *missiles, coord x, coord y,
natid victim, int hardtarget)
{
}
static int
perform_mission_msl(int dam, struct emp_qelem *missiles, coord x, coord y,
natid victim, int hardtarget)
{
+ int performed, air_dam, sublaunch, dam2;
struct emp_qelem *qp, *newqp;
struct plist *plp;
struct emp_qelem *qp, *newqp;
struct plist *plp;
/*
* Missiles, except for interdiction of ships or land units,
* because that happens elsewhere, in shp_missile_interdiction()
* and lnd_missile_interdiction().
*/
/*
* Missiles, except for interdiction of ships or land units,
* because that happens elsewhere, in shp_missile_interdiction()
* and lnd_missile_interdiction().
*/
+ performed = air_dam = 0;
for (qp = missiles->q_back; qp != missiles; qp = newqp) {
newqp = qp->q_back;
plp = (struct plist *)qp;
for (qp = missiles->q_back; qp != missiles; qp = newqp) {
newqp = qp->q_back;
plp = (struct plist *)qp;
if (msl_launch(&plp->plane, EF_SECTOR, "sector", x, y, victim,
&sublaunch) < 0)
goto use_up_msl;
if (msl_launch(&plp->plane, EF_SECTOR, "sector", x, y, victim,
&sublaunch) < 0)
goto use_up_msl;
if (!msl_hit(&plp->plane, SECT_HARDTARGET, EF_SECTOR,
N_SCT_MISS, N_SCT_SMISS, sublaunch, victim))
CANT_REACH();
if (!msl_hit(&plp->plane, SECT_HARDTARGET, EF_SECTOR,
N_SCT_MISS, N_SCT_SMISS, sublaunch, victim))
CANT_REACH();
emp_remque(qp);
free(qp);
}
emp_remque(qp);
free(qp);
}
+
+ return performed ? tally_dam(dam, air_dam) : dam;
{
struct emp_qelem *qp, *newqp, escorts, airp, b, e;
struct plist *plp;
{
struct emp_qelem *qp, *newqp, escorts, airp, b, e;
struct plist *plp;
- int plane_owner, air_dam, md;
+ int plane_owner, performed, air_dam, md;
emp_initque(&escorts);
emp_initque(&airp);
emp_initque(&escorts);
emp_initque(&airp);
add_airport(&airp, plp->plane.pln_x, plp->plane.pln_y);
}
add_airport(&airp, plp->plane.pln_x, plp->plane.pln_y);
}
+ performed = air_dam = 0;
for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
struct airport *air;
char buf[512];
for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
struct airport *air;
char buf[512];
pp = BestAirPath(buf, air->x, air->y, x, y);
if (CANT_HAPPEN(!pp))
continue;
pp = BestAirPath(buf, air->x, air->y, x, y);
if (CANT_HAPPEN(!pp))
continue;
wu(0, plane_owner, "Flying %s mission from %s to %s\n",
mission_name(mission),
xyas(air->x, air->y, plane_owner),
wu(0, plane_owner, "Flying %s mission from %s to %s\n",
mission_name(mission),
xyas(air->x, air->y, plane_owner),
+ return performed ? tally_dam(dam, air_dam) : dam;
if (msl_launch(&plp->plane, EF_SHIP, prship(&mvs->unit.ship),
newx, newy, victim, &sublaunch) < 0)
goto use_up_msl;
if (msl_launch(&plp->plane, EF_SHIP, prship(&mvs->unit.ship),
newx, newy, victim, &sublaunch) < 0)
goto use_up_msl;
if (msl_hit(&plp->plane,
shp_hardtarget(&mvs->unit.ship), EF_SHIP,
N_SHP_MISS, N_SHP_SMISS, sublaunch, victim)) {
if (msl_hit(&plp->plane,
shp_hardtarget(&mvs->unit.ship), EF_SHIP,
N_SHP_MISS, N_SHP_SMISS, sublaunch, victim)) {
"missile interdiction mission does %d damage to %s!\n",
dam, prship(&mvs->unit.ship));
shp_damage_one(mvs, dam);
"missile interdiction mission does %d damage to %s!\n",
dam, prship(&mvs->unit.ship));
shp_damage_one(mvs, dam);
}
} else {
dam = pln_damage(&plp->plane, 'p', 0);
}
} else {
dam = pln_damage(&plp->plane, 'p', 0);
struct sctstr fsect;
int trange, range;
int dam;
struct sctstr fsect;
int trange, range;
int dam;
int totdam = 0;
signed char notified[MAXNOC];
int i;
int totdam = 0;
signed char notified[MAXNOC];
int i;
putsect(&fsect);
if (dam < 0)
continue;
putsect(&fsect);
if (dam < 0)
continue;
totdam += dam;
mpr(victim, "Incoming fire does %d damage!\n", dam);
#if 0
totdam += dam;
mpr(victim, "Incoming fire does %d damage!\n", dam);
#if 0
nreport(fsect.sct_own, N_SHP_SHELL, victim, 1);
}
if (totdam > 0)
nreport(fsect.sct_own, N_SHP_SHELL, victim, 1);
}
if (totdam > 0)
- return shp_damage(list, totdam, 0, M_SUB, newx, newy);
- return 0;
+ shp_damage(list, totdam, 0, M_SUB, newx, newy);
+ return stopping;
char *what = subs ? "subs" : "ships";
int wantflags = subs ? M_SUB : 0;
int nowantflags = subs ? 0 : M_SUB;
char *what = subs ? "subs" : "ships";
int wantflags = subs ? M_SUB : 0;
int nowantflags = subs ? 0 : M_SUB;
- return shp_damage(list,
- unit_interdict(x, y, victim, what,
- shp_easiest_target(list,
- wantflags, nowantflags),
- MI_INTERDICT),
- wantflags, nowantflags, x, y);
+ dam = unit_interdict(x, y, victim, what,
+ shp_easiest_target(list, wantflags, nowantflags),
+ MI_INTERDICT);
+ if (dam >= 0)
+ shp_damage(list, dam, wantflags, nowantflags, x, y);
+ return dam >= 0;