]> git.pond.sub.org Git - empserver/commitdiff
Factor out common ship gun fire code into shp_fire()
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 2 Mar 2008 10:59:56 +0000 (11:59 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Fri, 14 Mar 2008 19:25:37 +0000 (20:25 +0100)
This takes care of a number of bugs / inconsistencies:

* Ships with zero firing range could return fire and fire support, but
  not fire actively or interdict.  Fix by testing for gun limit
  instead in multifire() and mission().  No ships in the stock game
  are affected.

* Required gun crew was inconsistent: multifire() let N military fire
  max(1,floor(N/2)) guns for active fire.  Ditto perform_mission() for
  interdiction.  quiet_bigdef() let them fire N guns for returning gun
  fire.  Ditto sd() for firing support and firing at boarding parties.
  fire_dchrg() let them fire floor(N/2) for returning fire to
  torpedoes.  Unify to let N military fire floor((N+1)/2) guns.

* Shell use was inconsistent: sd() and perform_mission() used one
  shell per gun, everything else one per two guns.  Unify to one shell
  per two guns.

* Shell resupply bugs: multifire() got two shells regardless of actual
  ammo use.  quiet_bigdef() got one shell (but use_ammo() uses only
  one, which is a bug).  sd() and perform_mission() resupplied before
  checking all other requirements and could thus get more shells than
  actually needed.

include/ship.h
src/lib/commands/mfir.c
src/lib/commands/miss.c
src/lib/commands/torp.c
src/lib/subs/fortdef.c
src/lib/subs/landgun.c
src/lib/subs/mission.c

index 99f945deeca30082f1788cea4f5f700b0c63ac8d..c3e24a44ecfc9af059711e85d30141a7b61e3fd9 100644 (file)
@@ -184,5 +184,6 @@ extern int m_frnge(struct mchrstr *, int);
 extern int m_glim(struct mchrstr *, int);
 
 extern int shp_dchrg(struct shpstr *);
+extern int shp_fire(struct shpstr *);
 
 #endif
index 632847f3f4279d4ea15ac1884ef31ee75e6ffdb8..08185a3f5297784fde1e1464e54a351b2a3505ec 100644 (file)
@@ -82,7 +82,6 @@ multifire(void)
     int gun;
     int shell;
     int shots;
-    double guneff;
     int dam;
     int totaldefdam = 0;
     int fshipno;
@@ -189,13 +188,11 @@ multifire(void)
                pr("Not enough mil on ship #%d\n", item.ship.shp_uid);
                continue;
            }
-           gun = item.ship.shp_item[I_GUN];
-           gun = MIN(gun, item.ship.shp_glim);
-           if (item.ship.shp_frnge == 0) {
+           if (item.ship.shp_glim == 0) {
                pr("Ships %d cannot fire guns!\n", item.ship.shp_uid);
                continue;
            }
-           if (gun == 0) {
+           if (item.ship.shp_item[I_GUN] == 0) {
                pr("Not enough guns on ship #%d\n", item.ship.shp_uid);
                continue;
            }
@@ -328,29 +325,16 @@ multifire(void)
                if (target == targ_sub)
                    /* Don't tell it's a sub */
                    range2 = -1;
-               gun = fship.shp_item[I_GUN];
-               gun = MIN(gun, fship.shp_glim);
-               if (fship.shp_frnge == 0 || gun == 0) {
+               if (fship.shp_item[I_GUN] == 0) {
                    pr("Insufficient arms.\n");
                    continue;
                }
-               shell = fship.shp_item[I_SHELL];
-               shell += supply_commod(fship.shp_own,
-                                      fship.shp_x, fship.shp_y,
-                                      I_SHELL, 2 - shell);
-               if (shell <= 0) {
+               dam = shp_fire(&fship);
+               putship(fship.shp_uid, &fship);
+               if (dam <= 0) {
                    pr("Klick!     ...\n");
                    continue;
                }
-               gun = MIN(gun, shell * 2);
-               gun = MIN(gun, mil / 2);
-               gun = MAX(gun, 1);
-               shots = gun;
-               guneff = seagun(fship.shp_effic, shots);
-               dam = (int)guneff;
-               shell -= ldround(shots / 2.0, 1);
-               fship.shp_item[I_SHELL] = shell;
-               putship(fship.shp_uid, &fship);
            }
            if (opt_NOMOBCOST == 0) {
                fship.shp_mobil = MAX(fship.shp_mobil - 15, -100);
@@ -723,7 +707,7 @@ static int
 quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
             coord ax, coord ay, int *nfiring)
 {
-    int nshot, range;
+    int range;
     double erange, hitchance;
     struct shpstr ship;
     struct lndstr land;
@@ -753,16 +737,13 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
        /* Don't shoot yourself */
        if (ship.shp_own == aown)
            continue;
-       if (ship.shp_effic < 60)
-           continue;
-
-       gun = ship.shp_item[I_GUN];
-       shell = ship.shp_item[I_SHELL];
-
-       if (ship.shp_item[I_MILIT] < 1)
-           continue;
-
        if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
+           if (ship.shp_effic < 60)
+               continue;
+           gun = ship.shp_item[I_GUN];
+           shell = ship.shp_item[I_SHELL];
+           if (ship.shp_item[I_MILIT] < 1)
+               continue;
            if (shell < SHP_TORP_SHELLS)
                shell += supply_commod(ship.shp_own,
                                       ship.shp_x, ship.shp_y,
@@ -800,16 +781,9 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
            erange = effrange(ship.shp_frnge, ship.shp_tech);
            if (roundrange(erange) < ni.curdist)
                continue;
-           /* must have gun, shell, and milit to fire */
-           if (shell < 1)
-               shell += supply_commod(ship.shp_own,
-                                      ship.shp_x, ship.shp_y, I_SHELL, 1);
-           /* only need 1 shell, so don't check that */
-           if (shell < 1)
-               continue;
-           nshot = MIN(gun, ship.shp_item[I_MILIT]);
-           nshot = MIN(nshot, ship.shp_glim);
-           if (nshot == 0)
+           dam2 = shp_fire(&ship);
+           /* no putship(&ship) because ammo is charged in use_ammo() */
+           if (dam2 < 0)
                continue;
            (*nfiring)++;
            fp = malloc(sizeof(struct flist));
@@ -818,7 +792,7 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
            fp->uid = ship.shp_uid;
            add_to_fired_queue(&fp->queue, list);
            nreport(ship.shp_own, N_FIRE_BACK, player->cnum, 1);
-           dam += seagun(ship.shp_effic, nshot);
+           dam += dam2;
        }
     }
     snxtitem_dist(&ni, EF_LAND, ax, ay, 8);
index d859d564f1f1800428e6087950be5fbaca5507a9..281618740e832eeb3450e9a64c1a6b53cc9d1427 100644 (file)
@@ -221,7 +221,7 @@ mission(void)
            radius = desired_radius;
 
        if ((mission == MI_INTERDICT) && (type == EF_SHIP))
-           if (mchr[(int)gp->type].m_frnge < 1) {
+           if (mchr[(int)gp->type].m_glim == 0) {
                pr("%s: cannot fire at range!\n", obj_nameof(gp));
                continue;
            }
index 9a10dbf556dd452c369f3c7761b145c77d332ecb..8df3305bbb5ddd4ccbb5ed8aa7021c934ea8373c 100644 (file)
@@ -319,30 +319,12 @@ static void
 fire_dchrg(struct shpstr *sp, struct shpstr *targ, int ntargets)
 {
     int dam;
-    int shells;
-    int gun;
-    double guneff;
 
     if ((mchr[(int)targ->shp_type].m_flags & M_SUB) == 0) {
-       shells = sp->shp_item[I_SHELL];
-       gun = sp->shp_item[I_GUN];
-       gun = MIN(gun, sp->shp_glim);
-       gun = MIN(gun, sp->shp_item[I_MILIT] / 2);
-
-       shells += supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
-                               I_SHELL, (gun + 1) / 2 - shells);
-
-       gun = MIN(gun, shells * 2);
-       if (gun == 0)
-           return;
-
-       /* ok, all set.. now, we shoot */
-       shells -= ldround(gun / 2.0, 1);
-       sp->shp_item[I_SHELL] = shells;
+       dam = shp_fire(sp);
        putship(sp->shp_uid, sp);
-
-       guneff = seagun(sp->shp_effic, gun);
-       dam = (int)guneff;
+       if (dam < 0)
+           return;
        if (ntargets > 2)
            dam /= ntargets / 2;
 
index e11d7afca172c0ff4bc132558c274b5284d35100..591fc0f2ba87f4c9d3a7f258e2329d9a6b500256 100644 (file)
@@ -67,12 +67,10 @@ int
 sd(natid att, natid own, coord x, coord y, int noisy, int defending,
    int usesubs)
 {
-    int nshot;
     int range;
     double eff;
     struct shpstr ship;
     struct nstr_item ni;
-    int shell;
     int dam, rel, rel2;
 
     if (own == 0)
@@ -91,34 +89,23 @@ sd(natid att, natid own, coord x, coord y, int noisy, int defending,
        rel2 = getrel(getnatp(ship.shp_own), att);
        if ((ship.shp_own != own) && ((rel != ALLIED) || (rel2 != AT_WAR)))
            continue;
-       if (ship.shp_effic < 60)
-           continue;
        if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && !usesubs)
            continue;
        range = roundrange(effrange(ship.shp_frnge, ship.shp_tech));
        if (range < ni.curdist)
            continue;
-       /* must have gun, shell, and milit to fire */
-       shell = ship.shp_item[I_SHELL];
-       if (shell < ship.shp_glim)
-           shell += supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
-                                  I_SHELL, shell - ship.shp_glim);
-       nshot = MIN(MIN(ship.shp_item[I_GUN], shell), ship.shp_item[I_MILIT]);
-       nshot = MIN(nshot, ship.shp_glim);
-       if (nshot <= 0)
-           continue;
-       ship.shp_item[I_SHELL] = shell - nshot;
+       dam = shp_fire(&ship);
        putship(ship.shp_uid, &ship);
+       if (dam < 0)
+           continue;
        if (defending)
            nreport(ship.shp_own, N_FIRE_BACK, att, 1);
        else
            nreport(ship.shp_own, N_FIRE_S_ATTACK, att, 1);
-       dam = seagun(ship.shp_effic, nshot);
        eff *= (1.0 - (0.01 * dam));
        if (noisy) {
            pr_beep();
-           pr("Incoming shell%s %d damage!\n",
-              nshot == 1 ? " does" : "s do", dam);
+           pr("Incoming shells do %d damage!\n", dam);
        }
        if (noisy || (ship.shp_own != own)) {
            if (ship.shp_own == own)
index bd66b7f631d4bfebbe4e94c40009e9242531c179..7d463fd450d40ca79e7962237f231951afd81fc0 100644 (file)
@@ -101,6 +101,33 @@ fort_fire(struct sctstr *sp)
     return (int)fortgun(sp->sct_effic, guns);
 }
 
+/*
+ * Fire from ship SP.
+ * Use ammo, resupply if necessary.
+ * Return damage if the ship fires, else -1.
+ */
+int
+shp_fire(struct shpstr *sp)
+{
+    int guns, shells;
+
+    if (sp->shp_effic < 60)
+       return -1;
+    guns = sp->shp_glim;
+    guns = MIN(guns, sp->shp_item[I_GUN]);
+    guns = MIN(guns, (sp->shp_item[I_MILIT] + 1) / 2);
+    if (guns == 0)
+       return -1;
+    shells = sp->shp_item[I_SHELL];
+    shells += supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
+                           I_SHELL, (guns + 1) / 2 - shells);
+    guns = MIN(guns, shells * 2);
+    if (guns == 0)
+       return -1;
+    sp->shp_item[I_SHELL] = shells - (guns + 1) / 2;
+    return (int)seagun(sp->shp_effic, guns);
+}
+
 /*
  * Drop depth-charges from ship SP.
  * Use ammo, resupply if necessary.
index 1d82a55238f262479b873e8f8887dfc568c52f15..e45e1e2a545401e6e974d261ef6082fbce4c6636 100644 (file)
@@ -480,16 +480,10 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
            sp = (struct shpstr *)glp->thing;
            mcp = glp->cp;
 
-           if (sp->shp_effic < 60)
-               continue;
-           if (sp->shp_frnge == 0)
-               continue;
            if (((mission == MI_INTERDICT) ||
                 (mission == MI_SINTERDICT)) &&
                (md > ship_max_interdiction_range))
                continue;
-           if (sp->shp_item[I_MILIT] < 1)
-               continue;
 /*
   if ((mcp->m_flags & M_SUB) &&
   (sect.sct_type != SCT_WATER))
@@ -513,6 +507,12 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
    a sub. */
                if (*s != 's')
                    continue;
+               if (sp->shp_effic < 60)
+                   continue;
+               if (sp->shp_frnge == 0)
+                   continue;
+               if (sp->shp_item[I_MILIT] < 1)
+                   continue;
                if (sp->shp_mobil < 0)
                    continue;
                gun = sp->shp_item[I_GUN];
@@ -569,28 +569,13 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                range = roundrange(effrange(sp->shp_frnge, sp->shp_tech));
                if (md > range)
                    continue;
-               if (mission == MI_SINTERDICT) {
+               if (mission == MI_SINTERDICT)
                    dam2 = shp_dchrg(sp);
-                   putship(sp->shp_uid, sp);
-                   if (dam2 < 0)
-                       continue;
-               } else {
-                   gun = sp->shp_item[I_GUN];
-                   gun = MIN(gun, sp->shp_glim);
-                   shell = sp->shp_item[I_SHELL];
-                   if (shell < gun)
-                       shell += supply_commod(sp->shp_own,
-                                              sp->shp_x, sp->shp_y, I_SHELL,
-                                              gun - shell);
-                   gun = MIN(gun, shell);
-                   gun = MIN(gun, sp->shp_item[I_MILIT] / 2.0);
-                   if (gun == 0)
-                       continue;
-                   gun = MAX(gun, 1);
-                   dam2 = seagun(sp->shp_effic, gun);
-                   sp->shp_item[I_SHELL] = shell - gun;
-                   putship(sp->shp_uid, sp);
-               }
+               else
+                   dam2 = shp_fire(sp);
+               putship(sp->shp_uid, sp);
+               if (dam2 < 0)
+                   continue;
                if (range == 0.0)
                    prb = 1.0;
                else