]> git.pond.sub.org Git - empserver/commitdiff
Limit nukes to strategic missions
authorMarkus Armbruster <armbru@pond.sub.org>
Mon, 5 Oct 2009 11:02:40 +0000 (07:02 -0400)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 13 Dec 2009 06:46:00 +0000 (07:46 +0100)
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.

14 files changed:
include/prototypes.h
info/Hitchance.t
info/bomb.t
info/launch.t
info/mission.t
src/lib/commands/arm.c
src/lib/commands/bomb.c
src/lib/commands/laun.c
src/lib/commands/miss.c
src/lib/subs/lndsub.c
src/lib/subs/mission.c
src/lib/subs/mslsub.c
src/lib/subs/plnsub.c
src/lib/subs/shpsub.c

index 0767afc42c7e8dbc368b883754c5961c43d4ec50..d2f8cb460aad7e60b35a946ffd88ce84c58a25a5 100644 (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,
                    int, int);
 extern int msl_launch_mindam(struct emp_qelem *, coord, coord, int,
 extern void msl_sel(struct emp_qelem *, coord, coord, natid, int,
                    int, int);
 extern int msl_launch_mindam(struct emp_qelem *, coord, coord, int,
-                            int, int, char *, int, int);
+                            int, int, char *, int);
 /* mtch.c */
 extern int comtch(char *, struct cmndstr *, int);
 /* natarg.c */
 /* mtch.c */
 extern int comtch(char *, struct cmndstr *, int);
 /* natarg.c */
@@ -555,7 +555,7 @@ extern void pln_put1(struct plist *);
 extern void plane_sweep(struct emp_qelem *, coord, coord);
 extern int put_plane_on_land(struct plnstr *, struct lndstr *);
 extern int pln_hitchance(struct plnstr *, int, int);
 extern void plane_sweep(struct emp_qelem *, coord, coord);
 extern int put_plane_on_land(struct plnstr *, struct lndstr *);
 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_is_in_orbit(struct plnstr *);
 extern void pln_set_tech(struct plnstr *, int);
 extern int pln_identchance(struct plnstr *, int, int);
 extern int pln_is_in_orbit(struct plnstr *);
 extern void pln_set_tech(struct plnstr *, int);
index 4f1beec4718a0fa0a13cb49cb0dd163773df4761..7485f4d9ecab0f696f3f0c1a9afe16f9c999b7c4 100644 (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
 procedure is used to calculate hitchance.
 
 a sector, then the hitchance is 100%.  Otherwise, the following
 procedure is used to calculate hitchance.
 
index da4d4d0dea8291ed399f77a52a3bcf1a63073f8d..1c6eea4def5c7a7eb4b3e9ab448c41551aa8cac3 100644 (file)
@@ -24,11 +24,10 @@ target sector.
 Strategic missions damage all commodities in the entire target sector,
 while not damaging any ships resident (similar to the
 \*Qfire\*U command).
 Strategic missions damage all commodities in the entire target sector,
 while not damaging any ships resident (similar to the
 \*Qfire\*U command).
-If a plane is armed with a nuclear warhead, then it will drop the bomb
-rather than using conventional weapons.
-Nuclear devices damage everything in the sector; planes, ships, and
-commodities.
-Only missiles in hardened silos can avoid damage from a nuclear mission.
+.s1
+Nuclear bombs can only be used for strategic bombing.  They damage
+everything in the sector; planes, ships, and commodities.
+Only missiles in hardened silos can avoid damage from a nuclear attack.
 .s1
 <SECT> represents an assembly point, where all of the planes in the
 mission meet before proceeding on to the target sector.
 .s1
 <SECT> represents an assembly point, where all of the planes in the
 mission meet before proceeding on to the target sector.
index ac5fec2b1c5d7cd746809b0cdc71d8be543808da..4ed3aee538077412ee3c061c0dfdbcc61ad44fec 100644 (file)
@@ -60,10 +60,8 @@ the launching pad instead of launching.
 Missiles launched from submarines are anonymous. The victim
 is not notified of the identity of the launching country.
 .s1
 Missiles launched from submarines are anonymous. The victim
 is not notified of the identity of the launching country.
 .s1
-Missiles on interdiction mission have the same chance of hitting and
-do the same damage as if they were launched by hand.  Also, any
-nuclear armed missiles will detonate if they launch on an interdiction
-mission.  You specify whether the nuclear warhead will airburst or
+Nuclear-tipped missiles can only be launched at sectors.
+You specify whether the nuclear warhead will airburst or
 groundburst when you arm the missiles (see info arm).
 In order to better destroy missiles on the ground (or in their silos),
 the ground-burst technique is used.
 groundburst when you arm the missiles (see info arm).
 In order to better destroy missiles on the ground (or in their silos),
 the ground-burst technique is used.
index 3f8a2443e7162faf111773a73005b686e444e7e2..0405020c920a7be974f0c93e086805158c2d3bf8 100644 (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
 their normal range. Be sure you understand this before using plane missions.)
 .s1
 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.)
 .s1
-Nukes on missiles or planes flying missions DO detonate.
+Planes armed with nukes cannot be assigned missions.
 .s1
 "marine" missiles will keep launching to interdict ships until all of
 the valuable ships in the fleet are sunk.  A "valuable" ship is one
 .s1
 "marine" missiles will keep launching to interdict ships until all of
 the valuable ships in the fleet are sunk.  A "valuable" ship is one
index a7ed90b934cb576d3ea9c064dbfa682a4bb7f019..144336cd729cf9c91bb25a50228b5f1610e9c9bf 100644 (file)
@@ -62,7 +62,7 @@ arm(void)
            && getrel(getnatp(pl.pln_own), player->cnum) != ALLIED)
            continue;
        plc = &plchr[(int)pl.pln_type];
            && getrel(getnatp(pl.pln_own), player->cnum) != ALLIED)
            continue;
        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)) {
            pr("A %s cannot carry nuclear devices!\n", plc->pl_name);
            return RET_FAIL;
            || (plc->pl_flags & (P_M | P_F)) == (P_M | P_F)) {
            pr("A %s cannot carry nuclear devices!\n", plc->pl_name);
            return RET_FAIL;
@@ -108,6 +108,7 @@ arm(void)
            pl.pln_flags |= PLN_AIRBURST;
        else
            pl.pln_flags &= ~PLN_AIRBURST;
            pl.pln_flags |= PLN_AIRBURST;
        else
            pl.pln_flags &= ~PLN_AIRBURST;
+       pl.pln_mission = 0;
 
        snprintf(buf, sizeof(buf), "armed on your %s in %s",
                 prplane(&pl), xyas(pl.pln_x, pl.pln_y, pl.pln_own));
 
        snprintf(buf, sizeof(buf), "armed on your %s in %s",
                 prplane(&pl), xyas(pl.pln_x, pl.pln_y, pl.pln_own));
index 850f0f1371cb4b89a81e37cca02ae3a15709e596..215897366cc8f240dbcc3fee89aa513217920836 100644 (file)
@@ -337,17 +337,15 @@ eff_bomb(struct emp_qelem *list, struct sctstr *target)
     struct emp_qelem *qp, *next;
     struct sctstr sect;
     int oldeff, dam = 0;
     struct emp_qelem *qp, *next;
     struct sctstr sect;
     int oldeff, dam = 0;
-    int nukedam;
 
     for (qp = list->q_forw; qp != list; qp = next) {
        next = qp->q_forw;
        plp = (struct plist *)qp;
        if (changed_plane_aborts(plp))
            continue;
 
     for (qp = list->q_forw; qp != list; qp = next) {
        next = qp->q_forw;
        plp = (struct plist *)qp;
        if (changed_plane_aborts(plp))
            continue;
-       dam += pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                         'p', &nukedam, 1);
+       dam += pln_damage(&plp->plane, 'p', 1);
     }
     }
-    if (dam <= 0)              /* dam == 0 if only nukes were delivered */
+    if (dam <= 0)
        return;
     getsect(target->sct_x, target->sct_y, &sect);
     target = &sect;
        return;
     getsect(target->sct_x, target->sct_y, &sect);
     target = &sect;
@@ -381,7 +379,6 @@ comm_bomb(struct emp_qelem *list, struct sctstr *target)
     struct emp_qelem *qp, *next;
     struct sctstr sect;
     int dam = 0;
     struct emp_qelem *qp, *next;
     struct sctstr sect;
     int dam = 0;
-    int nukedam;
 
     for (i = 0; i < nbomb; i++) {
        if (target->sct_item[bombcomm[i]] == 0)
 
     for (i = 0; i < nbomb; i++) {
        if (target->sct_item[bombcomm[i]] == 0)
@@ -421,10 +418,9 @@ comm_bomb(struct emp_qelem *list, struct sctstr *target)
        plp = (struct plist *)qp;
        if (changed_plane_aborts(plp))
            continue;
        plp = (struct plist *)qp;
        if (changed_plane_aborts(plp))
            continue;
-       dam += pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                         'p', &nukedam, 1);
+       dam += pln_damage(&plp->plane, 'p', 1);
     }
     }
-    if (dam <= 0)              /* dam == 0 if only nukes were delivered */
+    if (dam <= 0)
        return;
     getsect(target->sct_x, target->sct_y, &sect);
     target = &sect;
        return;
     getsect(target->sct_x, target->sct_y, &sect);
     target = &sect;
@@ -462,7 +458,6 @@ ship_bomb(struct emp_qelem *list, struct sctstr *target)
     char buf[1024];
     char prompt[128];
     int hitchance;
     char buf[1024];
     char prompt[128];
     int hitchance;
-    int nukedam;
     int flak;
     int gun;
 
     int flak;
     int gun;
 
@@ -535,17 +530,15 @@ ship_bomb(struct emp_qelem *list, struct sctstr *target)
        }
        if (roll(100) <= hitchance) {
            /* pinbombing is more accurate than normal bombing */
        }
        if (roll(100) <= hitchance) {
            /* pinbombing is more accurate than normal bombing */
-           dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                                'p', &nukedam, 1);
+           dam = 2 * pln_damage(&plp->plane, 'p', 1);
        } else {
            pr("splash\n");
            /* Bombs that miss have to land somewhere! */
        } else {
            pr("splash\n");
            /* Bombs that miss have to land somewhere! */
-           dam = pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                            'p', &nukedam, 0);
+           dam = pln_damage(&plp->plane, 'p', 0);
            collateral_damage(target->sct_x, target->sct_y, dam);
            dam = 0;
        }
            collateral_damage(target->sct_x, target->sct_y, dam);
            dam = 0;
        }
-       if (dam <= 0)           /* dam == 0 if only nukes were delivered */
+       if (dam <= 0)
            continue;
        if (mcp->m_flags & M_SUB)
            nreport(player->cnum, N_SUB_BOMB, ship.shp_own, 1);
            continue;
        if (mcp->m_flags & M_SUB)
            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 buf[1024];
     int hitchance;
     char prompt[128];
     char buf[1024];
     int hitchance;
-    int nukedam;
     int nplanes;
 
     for (qp = list->q_forw; qp != list; qp = next) {
     int nplanes;
 
     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) {
            /* pinbombing is more accurate than normal bombing */
        }
        if (roll(100) <= hitchance) {
            /* pinbombing is more accurate than normal bombing */
-           dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                                'p', &nukedam, 1);
+           dam = 2 * pln_damage(&plp->plane, 'p', 1);
        } else {
            pr("thud\n");
            /* Bombs that miss have to land somewhere! */
        } else {
            pr("thud\n");
            /* Bombs that miss have to land somewhere! */
-           dam = pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                            'p', &nukedam, 0);
+           dam = pln_damage(&plp->plane, 'p', 0);
            collateral_damage(target->sct_x, target->sct_y, dam);
            dam = 0;
        }
            collateral_damage(target->sct_x, target->sct_y, dam);
            dam = 0;
        }
-       if (dam <= 0)           /* dam == 0 if only nukes were delivered */
+       if (dam <= 0)
            continue;
        if (dam > 100)
            dam = 100;
            continue;
        if (dam > 100)
            dam = 100;
@@ -693,7 +683,6 @@ land_bomb(struct emp_qelem *list, struct sctstr *target)
     int unitno;
     int aaf, flak, hitchance;
     struct plist *plp;
     int unitno;
     int aaf, flak, hitchance;
     struct plist *plp;
-    int nukedam;
     int nunits;
 
     for (qp = list->q_forw; qp != list; qp = next) {
     int nunits;
 
     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);
        }
        if (roll(100) <= hitchance) {
            pr("%d%% hitchance...", hitchance);
        }
        if (roll(100) <= hitchance) {
-           dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                                'p', &nukedam, 1);
+           dam = 2 * pln_damage(&plp->plane, 'p', 1);
        } else {
            pr("thud\n");
            /* Bombs that miss have to land somewhere! */
        } else {
            pr("thud\n");
            /* Bombs that miss have to land somewhere! */
-           dam = pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                            'p', &nukedam, 0);
+           dam = pln_damage(&plp->plane, 'p', 0);
            collateral_damage(target->sct_x, target->sct_y, dam);
            dam = 0;
        }
            collateral_damage(target->sct_x, target->sct_y, dam);
            dam = 0;
        }
-       if (dam <= 0)           /* dam == 0 if only nukes were delivered */
+       if (dam <= 0)
            continue;
        if (dam > 100)
            dam = 100;
            continue;
        if (dam > 100)
            dam = 100;
@@ -790,12 +777,19 @@ strat_bomb(struct emp_qelem *list, struct sctstr *target)
     int dam = 0;
     struct emp_qelem *qp;
     struct sctstr sect;
     int dam = 0;
     struct emp_qelem *qp;
     struct sctstr sect;
-    int nukedam;
+    struct nukstr nuke;
 
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        plp = (struct plist *)qp;
 
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        plp = (struct plist *)qp;
-       dam += pln_damage(&plp->plane, target->sct_x, target->sct_y,
-                         's', &nukedam, 1);
+       if (getnuke(nuk_on_plane(&plp->plane), &nuke)) {
+           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 */
        return;
     }
     if (dam <= 0)              /* dam == 0 if only nukes were delivered */
        return;
index 32baf75eb96b7fc0636702d166bf3ff1bf2a3c27..1ea560903f4d181c508f2c63c9e17ae9cc106400 100644 (file)
@@ -40,6 +40,7 @@
 #include "damage.h"
 #include "mission.h"
 #include "news.h"
 #include "damage.h"
 #include "mission.h"
 #include "news.h"
+#include "nuke.h"
 #include "optlist.h"
 #include "path.h"
 #include "plane.h"
 #include "optlist.h"
 #include "path.h"
 #include "plane.h"
@@ -186,9 +187,9 @@ launch_missile(struct plnstr *pp, int sublaunch)
     struct mchrstr *mcp;
     struct shpstr target_ship;
     struct sctstr sect;
     struct mchrstr *mcp;
     struct shpstr target_ship;
     struct sctstr sect;
-    int nukedam;
     int rel;
     struct natstr *natp;
     int rel;
     struct natstr *natp;
+    struct nukstr nuke;
     char buf[1024];
 
     if (pcp->pl_flags & P_MAR)
     char buf[1024];
 
     if (pcp->pl_flags & P_MAR)
@@ -231,9 +232,9 @@ launch_missile(struct plnstr *pp, int sublaunch)
        pr("Range too great; try again!\n");
        return RET_FAIL;
     }
        pr("Range too great; try again!\n");
        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);
        if (opt_SLOW_WAR) {
            natp = getnatp(player->cnum);
        getsect(sx, sy, &sect);
        if (opt_SLOW_WAR) {
            natp = getnatp(player->cnum);
@@ -251,17 +252,21 @@ launch_missile(struct plnstr *pp, int sublaunch)
                     N_SCT_SMISS, "sector", sx, sy, sect.sct_own)) {
 #if 0
            /*
                     N_SCT_SMISS, "sector", sx, sy, sect.sct_own)) {
 #if 0
            /*
-            * FIXME want collateral damage on miss (which can't
-            * happen for nuclear war heads), but we get here too when
-            * launch fails or missile is intercepted
+            * FIXME want collateral damage on miss, but we get here
+            * too when 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);
 #endif
            return RET_OK;
        }
            collateral_damage(sect.sct_x, sect.sct_y, dam, 0);
 #endif
            return RET_OK;
        }
-       dam = pln_damage(pp, sect.sct_x, sect.sct_y, 's', &nukedam, 1);
-       if (!nukedam) {
+       if (getnuke(nuk_on_plane(pp), &nuke)) {
+           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),
               xyas(sx, sy, player->cnum));
            if (sect.sct_own != 0) {
            pr("did %d damage in %s\n", PERCENT_DAMAGE(dam),
               xyas(sx, sy, player->cnum));
            if (sect.sct_own != 0) {
@@ -279,23 +284,22 @@ launch_missile(struct plnstr *pp, int sublaunch)
            putsect(&sect);
        }
     } else {
            putsect(&sect);
        }
     } else {
+       if (msl_equip(pp, 'p') < 0)
+           return RET_FAIL;
        if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP,
                     N_SHP_MISS, N_SHP_SMISS, prship(&target_ship),
                     target_ship.shp_x, target_ship.shp_y,
                     target_ship.shp_own)) {
            pr("splash\n");
 #if 0 /* FIXME see above */
        if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP,
                     N_SHP_MISS, N_SHP_SMISS, prship(&target_ship),
                     target_ship.shp_x, target_ship.shp_y,
                     target_ship.shp_own)) {
            pr("splash\n");
 #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);
 #endif
            return RET_OK;
        }
            collateral_damage(target_ship.shp_x, target_ship.shp_y, dam, 0);
 #endif
            return RET_OK;
        }
-       dam = pln_damage(pp, target_ship.shp_x, target_ship.shp_y, 'p',
-                        &nukedam, 1);
-       if (!nukedam) {
-           check_retreat_and_do_shipdamage(&target_ship, dam);
-           putship(target_ship.shp_uid, &target_ship);
-       }
+       dam = pln_damage(pp, 'p', 1);
+       check_retreat_and_do_shipdamage(&target_ship, dam);
+       putship(target_ship.shp_uid, &target_ship);
        getship(target_ship.shp_uid, &target_ship);
        if (!target_ship.shp_own)
            pr("%s sunk!\n", prship(&target_ship));
        getship(target_ship.shp_uid, &target_ship);
        if (!target_ship.shp_own)
            pr("%s sunk!\n", prship(&target_ship));
index a3a72336269469da3c26331ff8429180e8a5b5c8..795674ca1b098c4fd02b01364171a869279a0498 100644 (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 == '.') {
            x = gp->x;
            y = gp->y;
        if (*p == '.') {
            x = gp->x;
            y = gp->y;
index 03b8de0d8da5ce9ab6a80a714eae217cf1a272da..04301045fd1b2b687062eed04dedbe501b4cacf7 100644 (file)
@@ -725,8 +725,7 @@ lnd_missile_interdiction(struct emp_qelem *list, coord newx, coord newy,
 
     dam = msl_launch_mindam(&msl_list, newx, newy,
                            lnd_easiest_target(list), EF_LAND,
 
     dam = msl_launch_mindam(&msl_list, newx, newy,
                            lnd_easiest_target(list), EF_LAND,
-                           lnd_count(list) * 20, "troops", victim,
-                           MI_INTERDICT);
+                           lnd_count(list) * 20, "troops", victim);
     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);
index 94d9ec31e5b55ccbe75ef29e00c375162a97e4f9..cab8182b0b5c73c0f24f00d695eb0cdb5d02c855 100644 (file)
@@ -551,7 +551,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
        /* I arbitrarily chose 100 mindam -KHS */
        dam +=
            msl_launch_mindam(&missiles, x, y, hardtarget, EF_SECTOR, 100,
        /* I arbitrarily chose 100 mindam -KHS */
        dam +=
            msl_launch_mindam(&missiles, x, y, hardtarget, EF_SECTOR, 100,
-                             "sector", victim, mission);
+                             "sector", victim);
        qp = missiles.q_forw;
        while (qp != (&missiles)) {
            newqp = qp->q_forw;
        qp = missiles.q_forw;
        while (qp != (&missiles)) {
            newqp = qp->q_forw;
@@ -902,8 +902,6 @@ mission_pln_equip(struct plist *plp, struct ichrstr *ip, char mission)
     itype = I_NONE;
     switch (mission) {
     case 'p':          /* pinpoint bomb */
     itype = I_NONE;
     switch (mission) {
     case 'p':          /* pinpoint bomb */
-       if (nuk_on_plane(pp) >= 0)
-           break;
        itype = I_SHELL;
        break;
     case 'i':          /* missile interception */
        itype = I_SHELL;
        break;
     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;
        if (needed <= 0)
            return -1;
        needed = load / ichr[itype].i_lbs;
        if (needed <= 0)
            return -1;
+       if (CANT_HAPPEN(nuk_on_plane(pp) >= 0))
+           return -1;
        if (itype == I_SHELL && item[itype] < needed) {
            if (pp->pln_ship >= 0)
                shp_supply(&ship, I_SHELL, needed);
        if (itype == I_SHELL && item[itype] < needed) {
            if (pp->pln_ship >= 0)
                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;
     int newdam, dam = 0;
     int hitchance;
     struct plnstr *pp;
     int newdam, dam = 0;
     int hitchance;
-    int nukedam;
 
     for (qp = bombers->q_forw; qp != bombers; qp = qp->q_forw) {
        plp = (struct plist *)qp;
 
     for (qp = bombers->q_forw; qp != bombers; qp = qp->q_forw) {
        plp = (struct plist *)qp;
@@ -1053,24 +1052,14 @@ air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
            hitchance = 100;
        else if (hardtarget != SECT_HARDTARGET)
            wu(0, pp->pln_own, "\t\t%d%% hitchance...", hitchance);
            hitchance = 100;
        else if (hardtarget != SECT_HARDTARGET)
            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);
-           if (nukedam) {
-               if (mission == MI_INTERDICT) {
-                   wu(0, pp->pln_own,
-                      "\t\tnuclear warhead on plane %s does %d damage to %s %s\n",
-                      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;
-           }
+           newdam = pln_damage(&plp->plane, 'p', 1);
+           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");
            if (mission == MI_SINTERDICT) {
                mpr(victim,
            wu(0, pp->pln_own, "missed\n");
            if (mission == MI_SINTERDICT) {
                mpr(victim,
index 34a91b6708ba7cfc3350d9a85597589646d29b4b..dc478bc67bc3d683788f77adb7d54114703eaeb3 100644 (file)
@@ -75,7 +75,7 @@ msl_hit(struct plnstr *pp, int hardtarget, int type, int news_item,
     struct plchrstr *pcp = plchr + pp->pln_type;
     int hitchance;
     char *from;
     struct plchrstr *pcp = plchr + pp->pln_type;
     int hitchance;
     char *from;
-    int dam, dummyi;
+    int dam;
 
     mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
        prplane(pp),
 
     mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
        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)))) {
        mpr(pp->pln_own, "KABOOOOM!  Missile explodes %s!\n", from);
        if (chance(0.33)) {
               * (1 - techfact(pp->pln_tech, 1.0)))) {
        mpr(pp->pln_own, "KABOOOOM!  Missile explodes %s!\n", from);
        if (chance(0.33)) {
-           dam = pln_damage(pp, pp->pln_x, pp->pln_y,
-                            'p', &dummyi, 1) / 2;
-           if (dam) {
-               if (pp->pln_ship >= 0) {
-                   shipdamage(&ship, dam);
-                   putship(ship.shp_uid, &ship);
-               } else {
-                   pr("Explosion damages %s %d%%",
-                      xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
-                   getsect(pp->pln_x, pp->pln_y, &sect);
-                   sectdamage(&sect, dam);
-                   putsect(&sect);
-               }
+           dam = pln_damage(pp, 'p', 1) / 2;
+           if (pp->pln_ship >= 0) {
+               shipdamage(&ship, dam);
+               putship(ship.shp_uid, &ship);
+           } else {
+               pr("Explosion damages %s %d%%",
+                  xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
+               getsect(pp->pln_x, pp->pln_y, &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 */
 int
 msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget,
 /* Keep launching missiles on list until mindam damage has been done */
 int
 msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget,
-                 int type, int mindam, char *whatp, int victim,
-                 int mission)
+                 int type, int mindam, char *whatp, int victim)
 {
     struct emp_qelem *qp;
     struct emp_qelem *next;
     struct plist *plp;
     int newdam, dam = 0;
 {
     struct emp_qelem *qp;
     struct emp_qelem *next;
     struct plist *plp;
     int newdam, dam = 0;
-    int nukedam = 0;
     int news_item;
     int snews_item;
 
     int news_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) {
        next = qp->q_back;
        plp = (struct plist *)qp;
         qp = next) {
        next = qp->q_back;
        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,
                        hardtarget, type, news_item, snews_item,
                        whatp, x, y, victim)) {
            if (msl_hit(&plp->plane,
                        hardtarget, type, news_item, snews_item,
                        whatp, x, y, victim)) {
-               newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 1);
-               if (nukedam) {
-                   if (mission == MI_INTERDICT && type == EF_SECTOR)
-                       dam += nukedam;
-               } else
-                   dam += newdam;
+               newdam = pln_damage(&plp->plane, 'p', 1);
+               dam += newdam;
 #if 0
            /*
 #if 0
            /*
-            * FIXME want collateral damage on miss (which can't
-            * happen for nuclear war heads), but we get here too when
-            * launch fails or missile is intercepted
+            * FIXME want collateral damage on miss, but we get here
+            * too when launch fails or missile is intercepted
             */
            } else {
                /* Missiles that miss have to hit somewhere! */
             */
            } else {
                /* 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);
 #endif
            }
                collateral_damage(x, y, newdam);
 #endif
            }
index fd178aa99c2ae297d81f14aef2e6b0106d0f6f30..a650deaf7dc5745ee3ade51a46410346fed8919c 100644 (file)
@@ -651,8 +651,6 @@ pln_equip(struct plist *plp, struct ichrstr *ip, char mission)
     switch (mission) {
     case 's':          /* strategic bomb */
     case 'p':          /* pinpoint bomb */
     switch (mission) {
     case 's':          /* strategic bomb */
     case 'p':          /* pinpoint bomb */
-       if (nuk_on_plane(pp) >= 0)
-           break;
        itype = I_SHELL;
        break;
     case 't':          /* transport */
        itype = I_SHELL;
        break;
     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));
            return -1;
        }
            pr("%s can't contribute to mission\n", prplane(pp));
            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) {
            pr("You don't control those civilians!\n");
            return -1;
        if (itype == I_CIVIL && pp->pln_own != own) {
            pr("You don't control those civilians!\n");
            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,
-          int noisy)
+pln_damage(struct plnstr *pp, char type, int noisy)
 {
 {
-    struct nukstr nuke;
     struct plchrstr *pcp = plchr + pp->pln_type;
     int load, i;
     int hitroll;
     struct plchrstr *pcp = plchr + pp->pln_type;
     int load, i;
     int hitroll;
@@ -982,14 +986,8 @@ pln_damage(struct plnstr *pp, coord x, coord y, char type, int *nukedamp,
     int effective = 1;
     int pinbomber = 0;
 
     int effective = 1;
     int pinbomber = 0;
 
-    if (getnuke(nuk_on_plane(pp), &nuke)) {
-       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);
+    if (CANT_HAPPEN(nuk_on_plane(pp) >= 0)) /* FIXME check uses! */
        return 0;
        return 0;
-    }
-    *nukedamp = 0;
 
     load = pln_load(pp);
     if (!load)                /* e.g. ab, blowing up on launch pad */
 
     load = pln_load(pp);
     if (!load)                /* e.g. ab, blowing up on launch pad */
index 70003f9c636a157ec6d852f10cef0d0fb0942d04..746dc411131ba8b9748fed29c37655ab4f922a8c 100644 (file)
@@ -492,7 +492,7 @@ shp_missile_interdiction(struct emp_qelem *list, coord newx, coord newy,
        sprintf(what, "%s", prship(&mvs->unit.ship));
        dam = msl_launch_mindam(&msl_list, newx, newy,
                                shp_hardtarget(&mvs->unit.ship),
        sprintf(what, "%s", prship(&mvs->unit.ship));
        dam = msl_launch_mindam(&msl_list, newx, newy,
                                shp_hardtarget(&mvs->unit.ship),
-                               EF_SHIP, 1, what, victim, MI_INTERDICT);
+                               EF_SHIP, 1, what, victim);
        if (dam) {
            mpr(victim,
                "missile interdiction mission does %d damage to %s!\n",
        if (dam) {
            mpr(victim,
                "missile interdiction mission does %d damage to %s!\n",