Limit nukes to strategic missions

Before Empire 2, nukes could be delivered only with bomb (special
mission 'n', airburst only) and launch (targeting sectors or
satellites only).

Empire 2 made nukes available for any kind of bombing, and for any
missile strike on sectors or ships.  This included interdiction and
support missions.  Nuclear-tipped anti-sats and bomb mission n were
removed.

Unfortunately, this was done in a messy way, which led to
inconsistencies and bugs.  The problem is that ordinary damage affects
just the target, while nuke damage affects an area.  Code dealing with
plane damage was designed for the former.  Instead of rewriting it to
cope with area damage cleanly, nuke damage got shoehorned into
pln_damage(), the function to compute conventional plane damage, as a
side effect: computing damage blasted sectors in the area.

If the plane carried a nuke, pln_damage() returned zero (conventional)
damage.  Without further logic, this simply bypassed the code to apply
damage to the target.  This worked out okay when the target already
got damaged correctly by the side effect.

However, some targets are immune to the side effect: when interdicting
a move or explore command, the commodities being moved are not in any
sector.

For other targets, damage has effects other than damaging the target:
offensive and defensive support don't apply the (conventional) damage
to the target sector.  Instead, they turn it into a combat bonus.
Without further logic, nuclear damage doesn't contribute to that.

To make all that work, pln_damage() returned the nuclear damage for
ground zero as well.  Because a plane does either conventional or
nuclear damage, one of them is always zero.

Most callers simply ignored the nuclear damage, and applied only the
conventional damage.

Bug: land units and ships failed to retreat when pin-bombed or
missiled with a nuke.  That's because they received zero conventional
damage.

The mission code flies planes and missiles and tallies their damage.
This mission damage included nuclear damage at ground zero (except for
missiles sometimes, see below), to make support and commodity
interdiction work.  Unfortunately, this broke other things.

Bug: when bombers interdicted ships or land units, nukes first damaged
the ships or land units by the side effect, then again through mission
damage.  Interdicting missiles had a special case to avoid this.

Bug: when interdicting move, explore or transport, nukes first damaged
the sector by the side effect, then again through mission damage's
collateral damage.

There may well be more bugs hiding in this mess.

The mess is not worth fixing.  While the idea of interdicting and
supporting with nukes sounds kind of cool, I believe it's pretty
irrelevant in actual play.

Instead, go back to a variation of the original rules: nukes can be
delivered only through bomb mission 's' and launch at sectors.

Make arm reject marine missiles in addition to satellites, ABMs and
SAMs, and clear the mission.  Make mission reject planes armed with
nukes.  Oops when they show up in mission_pln_equip() anyway.

Make pln_equip() allow planes with nukes only for missions 's' and
't'.

Clean up pln_damage() to just compute damage, without side effect.
Change strat_bomb() and launch_missile() to detonate nukes.  Simplify
the other callers.  Parameter mission of msl_launch_mindam() is now
unused, remove it.

Missiles exploding on launch no longer set off their nukes.  That was
pretty ridiculous anyway.
This commit is contained in:
Markus Armbruster 2009-10-05 07:02:40 -04:00
parent b0ba9022dc
commit a269cdd7e9
14 changed files with 102 additions and 124 deletions

View file

@ -499,7 +499,7 @@ extern int msl_hit(struct plnstr *, int, int, int, int, char *,
extern void msl_sel(struct emp_qelem *, coord, coord, natid, int, extern void msl_sel(struct emp_qelem *, coord, coord, natid, int,
int, int); int, int);
extern int msl_launch_mindam(struct emp_qelem *, coord, coord, int, extern int msl_launch_mindam(struct emp_qelem *, coord, coord, int,
int, int, char *, int, int); int, int, char *, int);
/* mtch.c */ /* mtch.c */
extern int comtch(char *, struct cmndstr *, int); extern int comtch(char *, struct cmndstr *, int);
/* natarg.c */ /* natarg.c */
@ -555,7 +555,7 @@ extern void pln_put1(struct plist *);
extern void plane_sweep(struct emp_qelem *, coord, coord); extern void plane_sweep(struct emp_qelem *, coord, coord);
extern int put_plane_on_land(struct plnstr *, struct lndstr *); extern int put_plane_on_land(struct plnstr *, struct lndstr *);
extern int pln_hitchance(struct plnstr *, int, int); extern int pln_hitchance(struct plnstr *, int, int);
extern int pln_damage(struct plnstr *, coord, coord, char, int *, int); extern int pln_damage(struct plnstr *, char, int);
extern int pln_identchance(struct plnstr *, int, int); extern int pln_identchance(struct plnstr *, int, int);
extern int pln_is_in_orbit(struct plnstr *); extern int pln_is_in_orbit(struct plnstr *);
extern void pln_set_tech(struct plnstr *, int); extern void pln_set_tech(struct plnstr *, int);

View file

@ -62,7 +62,7 @@ where
Plane and missile hitchance Plane and missile hitchance
If the plane or missile is carrying a nuclear warhead or the target is If the target is
a sector, then the hitchance is 100%. Otherwise, the following a sector, then the hitchance is 100%. Otherwise, the following
procedure is used to calculate hitchance. procedure is used to calculate hitchance.

View file

@ -24,11 +24,10 @@ target sector.
Strategic missions damage all commodities in the entire target sector, Strategic missions damage all commodities in the entire target sector,
while not damaging any ships resident (similar to the while not damaging any ships resident (similar to the
\*Qfire\*U command). \*Qfire\*U command).
If a plane is armed with a nuclear warhead, then it will drop the bomb .s1
rather than using conventional weapons. Nuclear bombs can only be used for strategic bombing. They damage
Nuclear devices damage everything in the sector; planes, ships, and everything in the sector; planes, ships, and commodities.
commodities. Only missiles in hardened silos can avoid damage from a nuclear attack.
Only missiles in hardened silos can avoid damage from a nuclear mission.
.s1 .s1
<SECT> represents an assembly point, where all of the planes in the <SECT> represents an assembly point, where all of the planes in the
mission meet before proceeding on to the target sector. mission meet before proceeding on to the target sector.

View file

@ -60,10 +60,8 @@ the launching pad instead of launching.
Missiles launched from submarines are anonymous. The victim Missiles launched from submarines are anonymous. The victim
is not notified of the identity of the launching country. is not notified of the identity of the launching country.
.s1 .s1
Missiles on interdiction mission have the same chance of hitting and Nuclear-tipped missiles can only be launched at sectors.
do the same damage as if they were launched by hand. Also, any You specify whether the nuclear warhead will airburst or
nuclear armed missiles will detonate if they launch on an interdiction
mission. You specify whether the nuclear warhead will airburst or
groundburst when you arm the missiles (see info arm). groundburst when you arm the missiles (see info arm).
In order to better destroy missiles on the ground (or in their silos), In order to better destroy missiles on the ground (or in their silos),
the ground-burst technique is used. the ground-burst technique is used.

View file

@ -49,7 +49,7 @@ planes flying in their op-area, in accordance with the air-defense mission,
but will not intercept one outside their op-area, even if it is within but will not intercept one outside their op-area, even if it is within
their normal range. Be sure you understand this before using plane missions.) their normal range. Be sure you understand this before using plane missions.)
.s1 .s1
Nukes on missiles or planes flying missions DO detonate. Planes armed with nukes cannot be assigned missions.
.s1 .s1
"marine" missiles will keep launching to interdict ships until all of "marine" missiles will keep launching to interdict ships until all of
the valuable ships in the fleet are sunk. A "valuable" ship is one the valuable ships in the fleet are sunk. A "valuable" ship is one

View file

@ -62,7 +62,7 @@ arm(void)
&& getrel(getnatp(pl.pln_own), player->cnum) != ALLIED) && getrel(getnatp(pl.pln_own), player->cnum) != ALLIED)
continue; continue;
plc = &plchr[(int)pl.pln_type]; plc = &plchr[(int)pl.pln_type];
if ((plc->pl_flags & (P_O | P_N)) if ((plc->pl_flags & (P_O | P_N | P_MAR))
|| (plc->pl_flags & (P_M | P_F)) == (P_M | P_F)) { || (plc->pl_flags & (P_M | P_F)) == (P_M | P_F)) {
pr("A %s cannot carry nuclear devices!\n", plc->pl_name); pr("A %s cannot carry nuclear devices!\n", plc->pl_name);
return RET_FAIL; return RET_FAIL;
@ -108,6 +108,7 @@ arm(void)
pl.pln_flags |= PLN_AIRBURST; pl.pln_flags |= PLN_AIRBURST;
else else
pl.pln_flags &= ~PLN_AIRBURST; pl.pln_flags &= ~PLN_AIRBURST;
pl.pln_mission = 0;
snprintf(buf, sizeof(buf), "armed on your %s in %s", snprintf(buf, sizeof(buf), "armed on your %s in %s",
prplane(&pl), xyas(pl.pln_x, pl.pln_y, pl.pln_own)); prplane(&pl), xyas(pl.pln_x, pl.pln_y, pl.pln_own));

View file

@ -337,17 +337,15 @@ eff_bomb(struct emp_qelem *list, struct sctstr *target)
struct emp_qelem *qp, *next; struct emp_qelem *qp, *next;
struct sctstr sect; struct sctstr sect;
int oldeff, dam = 0; int oldeff, dam = 0;
int nukedam;
for (qp = list->q_forw; qp != list; qp = next) { for (qp = list->q_forw; qp != list; qp = next) {
next = qp->q_forw; next = qp->q_forw;
plp = (struct plist *)qp; plp = (struct plist *)qp;
if (changed_plane_aborts(plp)) if (changed_plane_aborts(plp))
continue; continue;
dam += pln_damage(&plp->plane, target->sct_x, target->sct_y, dam += pln_damage(&plp->plane, 'p', 1);
'p', &nukedam, 1);
} }
if (dam <= 0) /* dam == 0 if only nukes were delivered */ if (dam <= 0)
return; return;
getsect(target->sct_x, target->sct_y, &sect); getsect(target->sct_x, target->sct_y, &sect);
target = &sect; target = &sect;
@ -381,7 +379,6 @@ comm_bomb(struct emp_qelem *list, struct sctstr *target)
struct emp_qelem *qp, *next; struct emp_qelem *qp, *next;
struct sctstr sect; struct sctstr sect;
int dam = 0; int dam = 0;
int nukedam;
for (i = 0; i < nbomb; i++) { for (i = 0; i < nbomb; i++) {
if (target->sct_item[bombcomm[i]] == 0) if (target->sct_item[bombcomm[i]] == 0)
@ -421,10 +418,9 @@ comm_bomb(struct emp_qelem *list, struct sctstr *target)
plp = (struct plist *)qp; plp = (struct plist *)qp;
if (changed_plane_aborts(plp)) if (changed_plane_aborts(plp))
continue; continue;
dam += pln_damage(&plp->plane, target->sct_x, target->sct_y, dam += pln_damage(&plp->plane, 'p', 1);
'p', &nukedam, 1);
} }
if (dam <= 0) /* dam == 0 if only nukes were delivered */ if (dam <= 0)
return; return;
getsect(target->sct_x, target->sct_y, &sect); getsect(target->sct_x, target->sct_y, &sect);
target = &sect; target = &sect;
@ -462,7 +458,6 @@ ship_bomb(struct emp_qelem *list, struct sctstr *target)
char buf[1024]; char buf[1024];
char prompt[128]; char prompt[128];
int hitchance; int hitchance;
int nukedam;
int flak; int flak;
int gun; int gun;
@ -535,17 +530,15 @@ ship_bomb(struct emp_qelem *list, struct sctstr *target)
} }
if (roll(100) <= hitchance) { if (roll(100) <= hitchance) {
/* pinbombing is more accurate than normal bombing */ /* pinbombing is more accurate than normal bombing */
dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y, dam = 2 * pln_damage(&plp->plane, 'p', 1);
'p', &nukedam, 1);
} else { } else {
pr("splash\n"); pr("splash\n");
/* Bombs that miss have to land somewhere! */ /* Bombs that miss have to land somewhere! */
dam = pln_damage(&plp->plane, target->sct_x, target->sct_y, dam = pln_damage(&plp->plane, 'p', 0);
'p', &nukedam, 0);
collateral_damage(target->sct_x, target->sct_y, dam); collateral_damage(target->sct_x, target->sct_y, dam);
dam = 0; dam = 0;
} }
if (dam <= 0) /* dam == 0 if only nukes were delivered */ if (dam <= 0)
continue; continue;
if (mcp->m_flags & M_SUB) if (mcp->m_flags & M_SUB)
nreport(player->cnum, N_SUB_BOMB, ship.shp_own, 1); nreport(player->cnum, N_SUB_BOMB, ship.shp_own, 1);
@ -589,7 +582,6 @@ plane_bomb(struct emp_qelem *list, struct sctstr *target)
char prompt[128]; char prompt[128];
char buf[1024]; char buf[1024];
int hitchance; int hitchance;
int nukedam;
int nplanes; int nplanes;
for (qp = list->q_forw; qp != list; qp = next) { for (qp = list->q_forw; qp != list; qp = next) {
@ -641,17 +633,15 @@ plane_bomb(struct emp_qelem *list, struct sctstr *target)
} }
if (roll(100) <= hitchance) { if (roll(100) <= hitchance) {
/* pinbombing is more accurate than normal bombing */ /* pinbombing is more accurate than normal bombing */
dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y, dam = 2 * pln_damage(&plp->plane, 'p', 1);
'p', &nukedam, 1);
} else { } else {
pr("thud\n"); pr("thud\n");
/* Bombs that miss have to land somewhere! */ /* Bombs that miss have to land somewhere! */
dam = pln_damage(&plp->plane, target->sct_x, target->sct_y, dam = pln_damage(&plp->plane, 'p', 0);
'p', &nukedam, 0);
collateral_damage(target->sct_x, target->sct_y, dam); collateral_damage(target->sct_x, target->sct_y, dam);
dam = 0; dam = 0;
} }
if (dam <= 0) /* dam == 0 if only nukes were delivered */ if (dam <= 0)
continue; continue;
if (dam > 100) if (dam > 100)
dam = 100; dam = 100;
@ -693,7 +683,6 @@ land_bomb(struct emp_qelem *list, struct sctstr *target)
int unitno; int unitno;
int aaf, flak, hitchance; int aaf, flak, hitchance;
struct plist *plp; struct plist *plp;
int nukedam;
int nunits; int nunits;
for (qp = list->q_forw; qp != list; qp = next) { for (qp = list->q_forw; qp != list; qp = next) {
@ -755,17 +744,15 @@ land_bomb(struct emp_qelem *list, struct sctstr *target)
pr("%d%% hitchance...", hitchance); pr("%d%% hitchance...", hitchance);
} }
if (roll(100) <= hitchance) { if (roll(100) <= hitchance) {
dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y, dam = 2 * pln_damage(&plp->plane, 'p', 1);
'p', &nukedam, 1);
} else { } else {
pr("thud\n"); pr("thud\n");
/* Bombs that miss have to land somewhere! */ /* Bombs that miss have to land somewhere! */
dam = pln_damage(&plp->plane, target->sct_x, target->sct_y, dam = pln_damage(&plp->plane, 'p', 0);
'p', &nukedam, 0);
collateral_damage(target->sct_x, target->sct_y, dam); collateral_damage(target->sct_x, target->sct_y, dam);
dam = 0; dam = 0;
} }
if (dam <= 0) /* dam == 0 if only nukes were delivered */ if (dam <= 0)
continue; continue;
if (dam > 100) if (dam > 100)
dam = 100; dam = 100;
@ -790,12 +777,19 @@ strat_bomb(struct emp_qelem *list, struct sctstr *target)
int dam = 0; int dam = 0;
struct emp_qelem *qp; struct emp_qelem *qp;
struct sctstr sect; struct sctstr sect;
int nukedam; struct nukstr nuke;
for (qp = list->q_forw; qp != list; qp = qp->q_forw) { for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
plp = (struct plist *)qp; plp = (struct plist *)qp;
dam += pln_damage(&plp->plane, target->sct_x, target->sct_y, if (getnuke(nuk_on_plane(&plp->plane), &nuke)) {
's', &nukedam, 1); mpr(plp->plane.pln_own,
"Releasing RV's for %s detonation...\n",
plp->plane.pln_flags & PLN_AIRBURST
? "airburst" : "groundburst");
detonate(&nuke, target->sct_x, target->sct_y,
plp->plane.pln_flags & PLN_AIRBURST);
} else
dam += pln_damage(&plp->plane, 's', 1);
} }
if (dam <= 0) /* dam == 0 if only nukes were delivered */ if (dam <= 0) /* dam == 0 if only nukes were delivered */
return; return;

View file

@ -40,6 +40,7 @@
#include "damage.h" #include "damage.h"
#include "mission.h" #include "mission.h"
#include "news.h" #include "news.h"
#include "nuke.h"
#include "optlist.h" #include "optlist.h"
#include "path.h" #include "path.h"
#include "plane.h" #include "plane.h"
@ -186,9 +187,9 @@ launch_missile(struct plnstr *pp, int sublaunch)
struct mchrstr *mcp; struct mchrstr *mcp;
struct shpstr target_ship; struct shpstr target_ship;
struct sctstr sect; struct sctstr sect;
int nukedam;
int rel; int rel;
struct natstr *natp; struct natstr *natp;
struct nukstr nuke;
char buf[1024]; char buf[1024];
if (pcp->pl_flags & P_MAR) if (pcp->pl_flags & P_MAR)
@ -231,9 +232,9 @@ launch_missile(struct plnstr *pp, int sublaunch)
pr("Range too great; try again!\n"); pr("Range too great; try again!\n");
return RET_FAIL; return RET_FAIL;
} }
if (msl_equip(pp, 'p') < 0)
return RET_FAIL;
if (!(pcp->pl_flags & P_MAR)) { if (!(pcp->pl_flags & P_MAR)) {
if (msl_equip(pp, 's') < 0)
return RET_FAIL;
getsect(sx, sy, &sect); getsect(sx, sy, &sect);
if (opt_SLOW_WAR) { if (opt_SLOW_WAR) {
natp = getnatp(player->cnum); natp = getnatp(player->cnum);
@ -251,17 +252,21 @@ launch_missile(struct plnstr *pp, int sublaunch)
N_SCT_SMISS, "sector", sx, sy, sect.sct_own)) { N_SCT_SMISS, "sector", sx, sy, sect.sct_own)) {
#if 0 #if 0
/* /*
* FIXME want collateral damage on miss (which can't * FIXME want collateral damage on miss, but we get here
* happen for nuclear war heads), but we get here too when * too when launch fails or missile is intercepted
* launch fails or missile is intercepted
*/ */
dam = pln_damage(pp, sect.sct_x, sect.sct_y, 's', &nukedam, 0); dam = pln_damage(pp, 's', 0);
collateral_damage(sect.sct_x, sect.sct_y, dam, 0); collateral_damage(sect.sct_x, sect.sct_y, dam, 0);
#endif #endif
return RET_OK; return RET_OK;
} }
dam = pln_damage(pp, sect.sct_x, sect.sct_y, 's', &nukedam, 1); if (getnuke(nuk_on_plane(pp), &nuke)) {
if (!nukedam) { mpr(pp->pln_own,
"Releasing RV's for %s detonation...\n",
pp->pln_flags & PLN_AIRBURST ? "airburst" : "groundburst");
detonate(&nuke, sx, sy, pp->pln_flags & PLN_AIRBURST);
} else {
dam = pln_damage(pp, 's', 1);
pr("did %d damage in %s\n", PERCENT_DAMAGE(dam), pr("did %d damage in %s\n", PERCENT_DAMAGE(dam),
xyas(sx, sy, player->cnum)); xyas(sx, sy, player->cnum));
if (sect.sct_own != 0) { if (sect.sct_own != 0) {
@ -279,23 +284,22 @@ launch_missile(struct plnstr *pp, int sublaunch)
putsect(&sect); putsect(&sect);
} }
} else { } else {
if (msl_equip(pp, 'p') < 0)
return RET_FAIL;
if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP, if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP,
N_SHP_MISS, N_SHP_SMISS, prship(&target_ship), N_SHP_MISS, N_SHP_SMISS, prship(&target_ship),
target_ship.shp_x, target_ship.shp_y, target_ship.shp_x, target_ship.shp_y,
target_ship.shp_own)) { target_ship.shp_own)) {
pr("splash\n"); pr("splash\n");
#if 0 /* FIXME see above */ #if 0 /* FIXME see above */
dam = pln_damage(pp,target_ship.shp_x,target_ship.shp_y,'p',&nukedam, 0); dam = pln_damage(pp, 'p', 0);
collateral_damage(target_ship.shp_x, target_ship.shp_y, dam, 0); collateral_damage(target_ship.shp_x, target_ship.shp_y, dam, 0);
#endif #endif
return RET_OK; return RET_OK;
} }
dam = pln_damage(pp, target_ship.shp_x, target_ship.shp_y, 'p', dam = pln_damage(pp, 'p', 1);
&nukedam, 1); check_retreat_and_do_shipdamage(&target_ship, dam);
if (!nukedam) { putship(target_ship.shp_uid, &target_ship);
check_retreat_and_do_shipdamage(&target_ship, dam);
putship(target_ship.shp_uid, &target_ship);
}
getship(target_ship.shp_uid, &target_ship); getship(target_ship.shp_uid, &target_ship);
if (!target_ship.shp_own) if (!target_ship.shp_own)
pr("%s sunk!\n", prship(&target_ship)); pr("%s sunk!\n", prship(&target_ship));

View file

@ -246,6 +246,12 @@ mission(void)
} }
} }
if (type == EF_PLANE && nuk_on_plane((struct plnstr *)gp) >= 0) {
pr("%s can't perform a mission while it carries a nuclear weapon",
obj_nameof(gp));
continue;
}
if (*p == '.') { if (*p == '.') {
x = gp->x; x = gp->x;
y = gp->y; y = gp->y;

View file

@ -725,8 +725,7 @@ lnd_missile_interdiction(struct emp_qelem *list, coord newx, coord newy,
dam = msl_launch_mindam(&msl_list, newx, newy, dam = msl_launch_mindam(&msl_list, newx, newy,
lnd_easiest_target(list), EF_LAND, lnd_easiest_target(list), EF_LAND,
lnd_count(list) * 20, "troops", victim, lnd_count(list) * 20, "troops", victim);
MI_INTERDICT);
if (dam) { if (dam) {
mpr(victim, "missile interdiction mission does %d damage!\n", dam); mpr(victim, "missile interdiction mission does %d damage!\n", dam);
collateral_damage(newx, newy, dam); collateral_damage(newx, newy, dam);

View file

@ -551,7 +551,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
/* I arbitrarily chose 100 mindam -KHS */ /* I arbitrarily chose 100 mindam -KHS */
dam += dam +=
msl_launch_mindam(&missiles, x, y, hardtarget, EF_SECTOR, 100, msl_launch_mindam(&missiles, x, y, hardtarget, EF_SECTOR, 100,
"sector", victim, mission); "sector", victim);
qp = missiles.q_forw; qp = missiles.q_forw;
while (qp != (&missiles)) { while (qp != (&missiles)) {
newqp = qp->q_forw; newqp = qp->q_forw;
@ -902,8 +902,6 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, char mission)
itype = I_NONE; itype = I_NONE;
switch (mission) { switch (mission) {
case 'p': /* pinpoint bomb */ case 'p': /* pinpoint bomb */
if (nuk_on_plane(pp) >= 0)
break;
itype = I_SHELL; itype = I_SHELL;
break; break;
case 'i': /* missile interception */ case 'i': /* missile interception */
@ -923,6 +921,8 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, char mission)
needed = load / ichr[itype].i_lbs; needed = load / ichr[itype].i_lbs;
if (needed <= 0) if (needed <= 0)
return -1; return -1;
if (CANT_HAPPEN(nuk_on_plane(pp) >= 0))
return -1;
if (itype == I_SHELL && item[itype] < needed) { if (itype == I_SHELL && item[itype] < needed) {
if (pp->pln_ship >= 0) if (pp->pln_ship >= 0)
shp_supply(&ship, I_SHELL, needed); shp_supply(&ship, I_SHELL, needed);
@ -1014,7 +1014,6 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
struct plnstr *pp; struct plnstr *pp;
int newdam, dam = 0; int newdam, dam = 0;
int hitchance; int hitchance;
int nukedam;
for (qp = bombers->q_forw; qp != bombers; qp = qp->q_forw) { for (qp = bombers->q_forw; qp != bombers; qp = qp->q_forw) {
plp = (struct plist *)qp; plp = (struct plist *)qp;
@ -1053,24 +1052,14 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
hitchance = 100; hitchance = 100;
else if (hardtarget != SECT_HARDTARGET) else if (hardtarget != SECT_HARDTARGET)
wu(0, pp->pln_own, "\t\t%d%% hitchance...", hitchance); wu(0, pp->pln_own, "\t\t%d%% hitchance...", hitchance);
/* Always calculate damage */
if (roll(100) <= hitchance) { if (roll(100) <= hitchance) {
newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 1); newdam = pln_damage(&plp->plane, 'p', 1);
if (nukedam) { wu(0, pp->pln_own,
if (mission == MI_INTERDICT) { "\t\thit %s %s for %d damage\n",
wu(0, pp->pln_own, cname(victim), s, newdam);
"\t\tnuclear warhead on plane %s does %d damage to %s %s\n", dam += newdam;
prplane(pp), nukedam, cname(victim), s);
dam += nukedam;
}
} else {
wu(0, pp->pln_own,
"\t\thit %s %s for %d damage\n",
cname(victim), s, newdam);
dam += newdam;
}
} else { } else {
newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 0); newdam = pln_damage(&plp->plane, 'p', 0);
wu(0, pp->pln_own, "missed\n"); wu(0, pp->pln_own, "missed\n");
if (mission == MI_SINTERDICT) { if (mission == MI_SINTERDICT) {
mpr(victim, mpr(victim,

View file

@ -75,7 +75,7 @@ msl_hit(struct plnstr *pp, int hardtarget, int type, int news_item,
struct plchrstr *pcp = plchr + pp->pln_type; struct plchrstr *pcp = plchr + pp->pln_type;
int hitchance; int hitchance;
char *from; char *from;
int dam, dummyi; int dam;
mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n", mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
prplane(pp), prplane(pp),
@ -107,19 +107,16 @@ msl_hit(struct plnstr *pp, int hardtarget, int type, int news_item,
* (1 - techfact(pp->pln_tech, 1.0)))) { * (1 - techfact(pp->pln_tech, 1.0)))) {
mpr(pp->pln_own, "KABOOOOM! Missile explodes %s!\n", from); mpr(pp->pln_own, "KABOOOOM! Missile explodes %s!\n", from);
if (chance(0.33)) { if (chance(0.33)) {
dam = pln_damage(pp, pp->pln_x, pp->pln_y, dam = pln_damage(pp, 'p', 1) / 2;
'p', &dummyi, 1) / 2; if (pp->pln_ship >= 0) {
if (dam) { shipdamage(&ship, dam);
if (pp->pln_ship >= 0) { putship(ship.shp_uid, &ship);
shipdamage(&ship, dam); } else {
putship(ship.shp_uid, &ship); pr("Explosion damages %s %d%%",
} else { xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
pr("Explosion damages %s %d%%", getsect(pp->pln_x, pp->pln_y, &sect);
xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam); sectdamage(&sect, dam);
getsect(pp->pln_x, pp->pln_y, &sect); putsect(&sect);
sectdamage(&sect, dam);
putsect(&sect);
}
} }
} }
return 0; return 0;
@ -373,14 +370,12 @@ msl_intercept(coord x, coord y, natid bombown, int hardtarget,
/* Keep launching missiles on list until mindam damage has been done */ /* Keep launching missiles on list until mindam damage has been done */
int int
msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget, msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget,
int type, int mindam, char *whatp, int victim, int type, int mindam, char *whatp, int victim)
int mission)
{ {
struct emp_qelem *qp; struct emp_qelem *qp;
struct emp_qelem *next; struct emp_qelem *next;
struct plist *plp; struct plist *plp;
int newdam, dam = 0; int newdam, dam = 0;
int nukedam = 0;
int news_item; int news_item;
int snews_item; int snews_item;
@ -395,7 +390,7 @@ msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget,
snews_item = N_SCT_SMISS; snews_item = N_SCT_SMISS;
} }
for (qp = list->q_back; qp != list && dam < mindam && !nukedam; for (qp = list->q_back; qp != list && dam < mindam;
qp = next) { qp = next) {
next = qp->q_back; next = qp->q_back;
plp = (struct plist *)qp; plp = (struct plist *)qp;
@ -404,21 +399,16 @@ msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget,
if (msl_hit(&plp->plane, if (msl_hit(&plp->plane,
hardtarget, type, news_item, snews_item, hardtarget, type, news_item, snews_item,
whatp, x, y, victim)) { whatp, x, y, victim)) {
newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 1); newdam = pln_damage(&plp->plane, 'p', 1);
if (nukedam) { dam += newdam;
if (mission == MI_INTERDICT && type == EF_SECTOR)
dam += nukedam;
} else
dam += newdam;
#if 0 #if 0
/* /*
* FIXME want collateral damage on miss (which can't * FIXME want collateral damage on miss, but we get here
* happen for nuclear war heads), but we get here too when * too when launch fails or missile is intercepted
* launch fails or missile is intercepted
*/ */
} else { } else {
/* Missiles that miss have to hit somewhere! */ /* Missiles that miss have to hit somewhere! */
newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 0); newdam = pln_damage(&plp->plane, 'p', 0);
collateral_damage(x, y, newdam); collateral_damage(x, y, newdam);
#endif #endif
} }

View file

@ -651,8 +651,6 @@ pln_equip(struct plist *plp, struct ichrstr *ip, char mission)
switch (mission) { switch (mission) {
case 's': /* strategic bomb */ case 's': /* strategic bomb */
case 'p': /* pinpoint bomb */ case 'p': /* pinpoint bomb */
if (nuk_on_plane(pp) >= 0)
break;
itype = I_SHELL; itype = I_SHELL;
break; break;
case 't': /* transport */ case 't': /* transport */
@ -701,6 +699,16 @@ pln_equip(struct plist *plp, struct ichrstr *ip, char mission)
pr("%s can't contribute to mission\n", prplane(pp)); pr("%s can't contribute to mission\n", prplane(pp));
return -1; return -1;
} }
if (nuk_on_plane(pp) >= 0) {
if (mission == 's' || mission == 't')
needed = 0;
else {
pr("%s can't fly this mission"
" while it is carrying a nuclear weapon",
prplane(pp));
return -1;
}
}
if (itype == I_CIVIL && pp->pln_own != own) { if (itype == I_CIVIL && pp->pln_own != own) {
pr("You don't control those civilians!\n"); pr("You don't control those civilians!\n");
return -1; return -1;
@ -967,13 +975,9 @@ pln_hitchance(struct plnstr *pp, int hardtarget, int type)
return hitchance; return hitchance;
} }
/* return 0 if there was a nuclear detonation */
int int
pln_damage(struct plnstr *pp, coord x, coord y, char type, int *nukedamp, pln_damage(struct plnstr *pp, char type, int noisy)
int noisy)
{ {
struct nukstr nuke;
struct plchrstr *pcp = plchr + pp->pln_type; struct plchrstr *pcp = plchr + pp->pln_type;
int load, i; int load, i;
int hitroll; int hitroll;
@ -982,14 +986,8 @@ pln_damage(struct plnstr *pp, coord x, coord y, char type, int *nukedamp,
int effective = 1; int effective = 1;
int pinbomber = 0; int pinbomber = 0;
if (getnuke(nuk_on_plane(pp), &nuke)) { if (CANT_HAPPEN(nuk_on_plane(pp) >= 0)) /* FIXME check uses! */
mpr(pp->pln_own, "Releasing RV's for %s detonation...\n",
pp->pln_flags & PLN_AIRBURST ? "airburst" : "groundburst");
*nukedamp = detonate(&nuke, x, y,
pp->pln_flags & PLN_AIRBURST);
return 0; return 0;
}
*nukedamp = 0;
load = pln_load(pp); load = pln_load(pp);
if (!load) /* e.g. ab, blowing up on launch pad */ if (!load) /* e.g. ab, blowing up on launch pad */

View file

@ -492,7 +492,7 @@ shp_missile_interdiction(struct emp_qelem *list, coord newx, coord newy,
sprintf(what, "%s", prship(&mvs->unit.ship)); sprintf(what, "%s", prship(&mvs->unit.ship));
dam = msl_launch_mindam(&msl_list, newx, newy, dam = msl_launch_mindam(&msl_list, newx, newy,
shp_hardtarget(&mvs->unit.ship), shp_hardtarget(&mvs->unit.ship),
EF_SHIP, 1, what, victim, MI_INTERDICT); EF_SHIP, 1, what, victim);
if (dam) { if (dam) {
mpr(victim, mpr(victim,
"missile interdiction mission does %d damage to %s!\n", "missile interdiction mission does %d damage to %s!\n",