]> git.pond.sub.org Git - empserver/commitdiff
Factor out common land unit fire code into lnd_fire()
authorMarkus Armbruster <armbru@pond.sub.org>
Mon, 3 Mar 2008 07:29:52 +0000 (08:29 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Fri, 14 Mar 2008 19:25:38 +0000 (20:25 +0100)
This takes care of a number of bugs / inconsistencies:

* Resupply before fire: fire command did not require unit to be in
  supply, and resupplied shells.  Everywhere else (return fire,
  support and interdiction) the land unit had to be in supply after
  resupply of everything.  Unify not to resupply anything and not to
  require being in supply.  This is consistent with ships and sectors.

* Resupply after fire: fire command resupplied shells after active
  fire.  Unify not to do that.  This is consistent with ships and
  sectors.

* When a land unit returned fire to multiple attackers, quiet_bigdef()
  charged it ammo for each one.  Finally, it was charged one shell
  more by use_ammo().  Except only the first land unit got charged
  there in fact, because buggy add_to_fired_queue() entered only the
  first land unit into the defender list.  Fix add_to_fired_queue()
  and change quiet_bigdef() not to charge ammo, just like for ships
  and sectors.  This charges only one shell instead of the true ammo
  use, which is wrong, but consistent with ships.

* lnd_support() tallied support damage unrounded.  Unify to round
  before tally.

include/land.h
include/prototypes.h
src/lib/commands/mfir.c
src/lib/subs/landgun.c
src/lib/subs/lndsub.c
src/lib/subs/mission.c

index f01d58f2d19ffc992ce48696b807293973554ae3..caf730621e496425bc786750553e240f36362dc6 100644 (file)
@@ -167,6 +167,8 @@ extern int l_acc(struct lchrstr *, int);
 extern int l_dam(struct lchrstr *, int);
 extern int l_aaf(struct lchrstr *, int);
 
 extern int l_dam(struct lchrstr *, int);
 extern int l_aaf(struct lchrstr *, int);
 
+extern int lnd_fire(struct lndstr *);
+
 /* src/lib/subs/lndsub.c */
 extern void lnd_sweep(struct emp_qelem *, int, int, natid);
 extern int lnd_interdict(struct emp_qelem *, coord, coord, natid);
 /* src/lib/subs/lndsub.c */
 extern void lnd_sweep(struct emp_qelem *, int, int, natid);
 extern int lnd_interdict(struct emp_qelem *, coord, coord, natid);
index c1b5948f109ec3254736e7fee3e3cd85a2411e9e..4a10d416eaa99f86cd52c100479084a6be092880 100644 (file)
@@ -460,7 +460,7 @@ extern int lnd_prewrite(int, void *);
 /* landgun.c */
 extern double seagun(int, int);
 extern double fortgun(int, int);
 /* landgun.c */
 extern double seagun(int, int);
 extern double fortgun(int, int);
-extern double landunitgun(int, int, int, int, int);
+extern double landunitgun(int, int);
 extern double effrange(int, double);
 extern double torprange(struct shpstr *);
 extern double fortrange(struct sctstr *);
 extern double effrange(int, double);
 extern double torprange(struct shpstr *);
 extern double fortrange(struct sctstr *);
index 19f1885c5bd9997cfeaef1b8258be2da84244713..ca52e15aa1b2232acd787e0bae91a27d994fcc83 100644 (file)
@@ -79,8 +79,6 @@ multifire(void)
     coord x;
     coord y;
     int mil;
     coord x;
     coord y;
     int mil;
-    int gun;
-    int shell;
     int shots;
     int dam;
     int totaldefdam = 0;
     int shots;
     int dam;
     int totaldefdam = 0;
@@ -173,8 +171,6 @@ multifire(void)
                   fland.lnd_uid, LAND_MINFIREEFF);
                continue;
            }
                   fland.lnd_uid, LAND_MINFIREEFF);
                continue;
            }
-           resupply_commod(&fland, I_SHELL);   /* Get more shells */
-           putland(fland.lnd_uid, &fland);
            if (fland.lnd_item[I_SHELL] == 0) {
                pr("%s -- not enough shells\n", prland(&fland));
                continue;
            if (fland.lnd_item[I_SHELL] == 0) {
                pr("%s -- not enough shells\n", prland(&fland));
                continue;
@@ -361,13 +357,11 @@ multifire(void)
                pr("Unit %d cannot fire!\n", fland.lnd_uid);
                continue;
            }
                pr("Unit %d cannot fire!\n", fland.lnd_uid);
                continue;
            }
-           if (fland.lnd_item[I_SHELL] == 0) {
-               pr("%s -- not enough shells\n", prland(&fland));
+           if (fland.lnd_item[I_GUN] == 0) {
+               pr("%s -- not enough guns\n", prland(&fland));
                continue;
            }
 
                continue;
            }
 
-           shell = fland.lnd_item[I_SHELL];
-
            range = effrange(fland.lnd_frg, fland.lnd_tech);
            range2 = roundrange(range);
            pr("range is %d.00 (%.2f)\n", range2, range);
            range = effrange(fland.lnd_frg, fland.lnd_tech);
            range2 = roundrange(range);
            pr("range is %d.00 (%.2f)\n", range2, range);
@@ -376,21 +370,16 @@ multifire(void)
                range2 = -1;
            }
 
                range2 = -1;
            }
 
-           gun = fland.lnd_item[I_GUN];
-           if (gun <= 0) {
-               pr("%s -- not enough guns\n", prland(&fland));
+           dam = lnd_fire(&fland);
+           putland(fland.lnd_uid, &fland);
+           if (dam < 0) {
+               pr("Klick!     ...\n");
                continue;
            }
                continue;
            }
-
-           dam = (int)landunitgun(fland.lnd_effic, fland.lnd_dam, gun,
-                                  fland.lnd_ammo, shell);
            if (target == targ_ship) {
                if (chance(fland.lnd_acc / 100.0))
                    dam = ldround(dam / 2.0, 1);
            }
            if (target == targ_ship) {
                if (chance(fland.lnd_acc / 100.0))
                    dam = ldround(dam / 2.0, 1);
            }
-           use_supply(&fland);
-           resupply_commod(&fland, I_SHELL);   /* Get more shells */
-           putland(fland.lnd_uid, &fland);
        } else {
            fx = fsect.sct_x;
            fy = fsect.sct_y;
        } else {
            fx = fsect.sct_x;
            fy = fsect.sct_y;
@@ -716,7 +705,6 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
     struct sctstr firing;
     struct nstr_sect ns;
     struct flist *fp;
     struct sctstr firing;
     struct nstr_sect ns;
     struct flist *fp;
-    int gun, shell;
 
     if (own == 0)
        return 0;
 
     if (own == 0)
        return 0;
@@ -779,16 +767,6 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
     while (nxtitem(&ni, &land)) {
        if (land.lnd_own == 0)
            continue;
     while (nxtitem(&ni, &land)) {
        if (land.lnd_own == 0)
            continue;
-       if (land.lnd_effic < LAND_MINFIREEFF)
-           continue;
-       /* Can't fire if on a ship */
-       if (land.lnd_ship >= 0)
-           continue;
-       if (land.lnd_land >= 0)
-           continue;
-       /* Gotta have military */
-       if (land.lnd_item[I_MILIT] < 1)
-           continue;
        /* Don't shoot yourself */
        if (land.lnd_own == aown)
            continue;
        /* Don't shoot yourself */
        if (land.lnd_own == aown)
            continue;
@@ -803,27 +781,17 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
        if (roundrange(erange) < ni.curdist)
            continue;
 
        if (roundrange(erange) < ni.curdist)
            continue;
 
-       resupply_all(&land);
-       if (!has_supply(&land))
+       dam2 = lnd_fire(&land);
+       /* no putland(&land) because ammo is charged in use_ammo() */
+       if (dam2 < 0)
            continue;
 
            continue;
 
-       gun = land.lnd_item[I_GUN];
-       shell = land.lnd_item[I_SHELL];
-
-       if (land.lnd_item[I_MILIT] == 0 || shell == 0 || gun == 0)
-           continue;
-
-       dam2 = (int)landunitgun(land.lnd_effic, land.lnd_dam, gun,
-                               land.lnd_ammo, shell);
-
        (*nfiring)++;
        fp = malloc(sizeof(struct flist));
        memset(fp, 0, sizeof(struct flist));
        fp->type = targ_unit;
        fp->uid = land.lnd_uid;
        add_to_fired_queue(&fp->queue, list);
        (*nfiring)++;
        fp = malloc(sizeof(struct flist));
        memset(fp, 0, sizeof(struct flist));
        fp->type = targ_unit;
        fp->uid = land.lnd_uid;
        add_to_fired_queue(&fp->queue, list);
-       use_supply(&land);
-       putland(land.lnd_uid, &land);
        nreport(land.lnd_own, N_FIRE_BACK, player->cnum, 1);
        dam += dam2;
     }
        nreport(land.lnd_own, N_FIRE_BACK, player->cnum, 1);
        dam += dam2;
     }
@@ -929,21 +897,17 @@ static void
 add_to_fired_queue(struct emp_qelem *elem, struct emp_qelem *list)
 {
     struct emp_qelem *qp;
 add_to_fired_queue(struct emp_qelem *elem, struct emp_qelem *list)
 {
     struct emp_qelem *qp;
-    struct flist *fp, *ep;
-    int bad = 0;
-
-    ep = (struct flist *)elem;
+    struct flist *fp;
+    struct flist *ep = (struct flist *)elem;
 
     /* Don't put them on the list if they're already there */
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        fp = (struct flist *)qp;
 
     /* Don't put them on the list if they're already there */
     for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
        fp = (struct flist *)qp;
-       if ((fp->type == targ_ship) && (fp->uid == ep->uid))
-           bad = 1;
-       if ((fp->type != targ_ship) && (fp->x == ep->x) &&
-           (fp->y == ep->y))
-           bad = 1;
+       if (fp->type != targ_land && fp->uid == ep->uid)
+           return;
+       if (fp->type != targ_land
+           && fp->x == ep->x && fp->y == ep->y)
+           return;
     }
     }
-
-    if (!bad)
-       emp_insque(elem, list);
+    emp_insque(elem, list);
 }
 }
index 1cca07cd5a1692da7839d5479e5fc6fb86694382..fbaed6c50be7a52f834ba6bbe372ebad30c25325 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "damage.h"
 #include "file.h"
 
 #include "damage.h"
 #include "file.h"
+#include "land.h"
 #include "nat.h"
 #include "optlist.h"
 #include "prototypes.h"
 #include "nat.h"
 #include "optlist.h"
 #include "prototypes.h"
@@ -65,16 +66,14 @@ seagun(int effic, int guns)
 }
 
 double
 }
 
 double
-landunitgun(int effic, int shots, int guns, int ammo, int shells)
+landunitgun(int effic, int guns)
 {
 {
-    double d = 0.0;
+    double d;
 
 
-    shots = MIN(shots, guns);
-    while (shots-- > 0)
+    d = 0.0;
+    while (guns--)
        d += 5.0 + random() % 6;
     d *= effic * 0.01;
        d += 5.0 + random() % 6;
     d *= effic * 0.01;
-    if (shells < ammo && ammo != 0)
-       d *= (double)shells / (double)ammo;
     return d;
 }
 
     return d;
 }
 
@@ -179,6 +178,45 @@ shp_torp(struct shpstr *sp, int usemob)
     return TORP_DAMAGE();
 }
 
     return TORP_DAMAGE();
 }
 
+/*
+ * Fire from land unit LP.
+ * Use ammo, resupply if necessary.
+ * Return damage if the land unit fires, else -1.
+ */
+int
+lnd_fire(struct lndstr *lp)
+{
+    int guns, shells;
+    double d;
+    int ammo = lchr[lp->lnd_type].l_ammo;
+
+    if (CANT_HAPPEN(ammo == 0))
+       ammo = 1;
+
+    if (lp->lnd_effic < LAND_MINFIREEFF)
+       return -1;
+    if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
+       return -1;
+    if (lp->lnd_item[I_MILIT] == 0)
+       return -1;
+    guns = lp->lnd_dam;
+    guns = MIN(guns, lp->lnd_item[I_GUN]);
+    if (guns == 0)
+       return -1;
+    shells = lp->lnd_item[I_SHELL];
+    shells += supply_commod(lp->lnd_own, lp->lnd_x, lp->lnd_y,
+                           I_SHELL, ammo - shells);
+    if (shells == 0)
+       return -1;
+    d = landunitgun(lp->lnd_effic, guns);
+    if (shells < ammo) {
+       d *= (double)shells / (double)ammo;
+       ammo = shells;
+    }
+    lp->lnd_item[I_SHELL] = shells - ammo;
+    return d;
+}
+
 /*
  * Return effective firing range for range factor RNG at tech TLEV.
  */
 /*
  * Return effective firing range for range factor RNG at tech TLEV.
  */
index a3ba6e90c338a5a079c6b6e621cf6e1811ba0b3b..a6b4636e5132814e11cc729bde6404a181a53925 100644 (file)
@@ -1128,37 +1128,21 @@ lnd_support(natid victim, natid attacker, coord x, coord y, int defending)
     struct nstr_item ni;
     struct lndstr land;
     int rel, rel2;
     struct nstr_item ni;
     struct lndstr land;
     int rel, rel2;
-    double dam = 0.0;
+    int dam, dam2;
     int dist;
     int dist;
-    int shell;
-    int gun;
     int range;
 
     int range;
 
+    dam = 0;
     snxtitem_all(&ni, EF_LAND);
     while (nxtitem(&ni, &land)) {
     snxtitem_all(&ni, EF_LAND);
     while (nxtitem(&ni, &land)) {
-       if (land.lnd_dam == 0)
-           continue;
        if ((land.lnd_x == x) && (land.lnd_y == y))
            continue;
        if ((land.lnd_x == x) && (land.lnd_y == y))
            continue;
-       if (land.lnd_ship >= 0)
-           continue;
-       if (land.lnd_land >= 0)
-           continue;
-       if (land.lnd_effic < LAND_MINFIREEFF)
-           continue;
-       /* Do we have mil? */
-       if (land.lnd_item[I_MILIT] <= 0)
-           continue;
        rel = getrel(getnatp(land.lnd_own), attacker);
        rel2 = getrel(getnatp(land.lnd_own), victim);
        if ((land.lnd_own != attacker) &&
            ((rel != ALLIED) || (rel2 != AT_WAR)))
            continue;
 
        rel = getrel(getnatp(land.lnd_own), attacker);
        rel2 = getrel(getnatp(land.lnd_own), victim);
        if ((land.lnd_own != attacker) &&
            ((rel != ALLIED) || (rel2 != AT_WAR)))
            continue;
 
-       /* do we have supplies? */
-       if (!has_supply(&land))
-           continue;
-
        /* are we in range? */
        dist = mapdist(land.lnd_x, land.lnd_y, x, y);
 
        /* are we in range? */
        dist = mapdist(land.lnd_x, land.lnd_y, x, y);
 
@@ -1166,31 +1150,26 @@ lnd_support(natid victim, natid attacker, coord x, coord y, int defending)
        if (dist > range)
            continue;
 
        if (dist > range)
            continue;
 
-       shell = land.lnd_item[I_SHELL];
-       gun = land.lnd_item[I_GUN];
-
-       if (shell == 0 || gun == 0)
+       dam2 = lnd_fire(&land);
+       putland(land.lnd_uid, &land);
+       if (dam2 < 0)
            continue;
 
            continue;
 
-       use_supply(&land);
        if (defending)
            nreport(land.lnd_own, N_FIRE_BACK, victim, 1);
        else
            nreport(land.lnd_own, N_FIRE_L_ATTACK, victim, 1);
        if (defending)
            nreport(land.lnd_own, N_FIRE_BACK, victim, 1);
        else
            nreport(land.lnd_own, N_FIRE_L_ATTACK, victim, 1);
-       if (roll(100) < land.lnd_acc) {
-           dam += landunitgun(land.lnd_effic, land.lnd_dam, gun,
-                              land.lnd_ammo, shell) / 2;
-       } else {
-           dam += landunitgun(land.lnd_effic, land.lnd_dam, gun,
-                              land.lnd_ammo, shell);
-       }
+       if (roll(100) < land.lnd_acc)
+           dam2 /= 2;
+       dam += dam2;
        if (land.lnd_own != attacker)
            wu(0, land.lnd_own,
               "%s supported %s at %s\n",
               prland(&land), cname(attacker), xyas(x, y, land.lnd_own));
     }
        if (land.lnd_own != attacker)
            wu(0, land.lnd_own,
               "%s supported %s at %s\n",
               prland(&land), cname(attacker), xyas(x, y, land.lnd_own));
     }
-    return (int)dam;
+    return dam;
 }
 }
+
 int
 lnd_can_attack(struct lndstr *lp)
 {
 int
 lnd_can_attack(struct lndstr *lp)
 {
index 1f8e9d7366acbc6654f50a248a244c4dd13fe460..1e92f77c2ac4276b04c9f49ac496a4608bfac903 100644 (file)
@@ -411,7 +411,7 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
     struct plchrstr *pcp;
     int dam = 0, dam2, mission_flags, tech;
     natid plane_owner = 0;
     struct plchrstr *pcp;
     int dam = 0, dam2, mission_flags, tech;
     natid plane_owner = 0;
-    int gun, shell, md, range, air_dam = 0;
+    int md, range, air_dam = 0;
     double prb, hitchance, vrange;
 
     getsect(x, y, &sect);
     double prb, hitchance, vrange;
 
     getsect(x, y, &sect);
@@ -430,9 +430,6 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
        if (glp->thing->ef_type == EF_LAND) {
            lp = (struct lndstr *)glp->thing;
 
        if (glp->thing->ef_type == EF_LAND) {
            lp = (struct lndstr *)glp->thing;
 
-           if (lp->lnd_effic < LAND_MINFIREEFF)
-               continue;
-
            if (mission == MI_SINTERDICT)
                continue;
 
            if (mission == MI_SINTERDICT)
                continue;
 
@@ -440,42 +437,30 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
                (md > land_max_interdiction_range))
                continue;
 
                (md > land_max_interdiction_range))
                continue;
 
-           if ((lp->lnd_ship != -1) || (lp->lnd_land != -1))
-               continue;
-
-           if (lp->lnd_item[I_MILIT] < 1)
-               continue;
-
            range = roundrange(effrange(lp->lnd_frg, lp->lnd_tech));
            if (md > range)
                continue;
 
            range = roundrange(effrange(lp->lnd_frg, lp->lnd_tech));
            if (md > range)
                continue;
 
-           shell = lp->lnd_item[I_SHELL];
-           gun = lp->lnd_item[I_GUN];
-           if (shell == 0 || gun == 0)
+           dam2 = lnd_fire(lp);
+           putland(lp->lnd_uid, lp);
+           if (dam2 < 0)
                continue;
 
                continue;
 
-           if (has_supply(lp)) {
-               use_supply(lp);
-               putland(lp->lnd_uid, lp);
-               dam2 = ldround(landunitgun(lp->lnd_effic, lp->lnd_dam, gun,
-                                          lp->lnd_ammo, shell), 1);
-               if (sect.sct_type == SCT_WATER) {
-                   if (chance(lp->lnd_acc / 100.0))
-                       dam2 = ldround(dam2 / 2.0, 1);
-               }
-               dam += dam2;
-               if (sect.sct_type == SCT_WATER)
-                   nreport(lp->lnd_own, N_SHP_SHELL, victim, 1);
-               else
-                   nreport(lp->lnd_own, N_SCT_SHELL, victim, 1);
-               wu(0, lp->lnd_own,
-                  "%s fires at %s %s at %s\n",
-                  prland(lp), cname(victim), s, xyas(x, y, lp->lnd_own));
-
-               mpr(victim, "%s %s fires at you at %s\n",
-                   cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
+           if (sect.sct_type == SCT_WATER) {
+               if (chance(lp->lnd_acc / 100.0))
+                   dam2 = ldround(dam2 / 2.0, 1);
            }
            }
+           dam += dam2;
+           if (sect.sct_type == SCT_WATER)
+               nreport(lp->lnd_own, N_SHP_SHELL, victim, 1);
+           else
+               nreport(lp->lnd_own, N_SCT_SHELL, victim, 1);
+           wu(0, lp->lnd_own,
+              "%s fires at %s %s at %s\n",
+              prland(lp), cname(victim), s, xyas(x, y, lp->lnd_own));
+
+           mpr(victim, "%s %s fires at you at %s\n",
+               cname(lp->lnd_own), prland(lp), xyas(x, y, victim));
        } else if (glp->thing->ef_type == EF_SHIP) {
            sp = (struct shpstr *)glp->thing;
            mcp = glp->cp;
        } else if (glp->thing->ef_type == EF_SHIP) {
            sp = (struct shpstr *)glp->thing;
            mcp = glp->cp;