From 22c6fd8bf6277149dcc860d073b8dfc7e88355be Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 2 Mar 2008 11:59:56 +0100 Subject: [PATCH] Factor out common ship gun fire code into shp_fire() 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 | 1 + src/lib/commands/mfir.c | 60 ++++++++++++----------------------------- src/lib/commands/miss.c | 2 +- src/lib/commands/torp.c | 24 +++-------------- src/lib/subs/fortdef.c | 21 +++------------ src/lib/subs/landgun.c | 27 +++++++++++++++++++ src/lib/subs/mission.c | 39 +++++++++------------------ 7 files changed, 65 insertions(+), 109 deletions(-) diff --git a/include/ship.h b/include/ship.h index 99f945de..c3e24a44 100644 --- a/include/ship.h +++ b/include/ship.h @@ -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 diff --git a/src/lib/commands/mfir.c b/src/lib/commands/mfir.c index 632847f3..08185a3f 100644 --- a/src/lib/commands/mfir.c +++ b/src/lib/commands/mfir.c @@ -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); diff --git a/src/lib/commands/miss.c b/src/lib/commands/miss.c index d859d564..28161874 100644 --- a/src/lib/commands/miss.c +++ b/src/lib/commands/miss.c @@ -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; } diff --git a/src/lib/commands/torp.c b/src/lib/commands/torp.c index 9a10dbf5..8df3305b 100644 --- a/src/lib/commands/torp.c +++ b/src/lib/commands/torp.c @@ -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; diff --git a/src/lib/subs/fortdef.c b/src/lib/subs/fortdef.c index e11d7afc..591fc0f2 100644 --- a/src/lib/subs/fortdef.c +++ b/src/lib/subs/fortdef.c @@ -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) diff --git a/src/lib/subs/landgun.c b/src/lib/subs/landgun.c index bd66b7f6..7d463fd4 100644 --- a/src/lib/subs/landgun.c +++ b/src/lib/subs/landgun.c @@ -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. diff --git a/src/lib/subs/mission.c b/src/lib/subs/mission.c index 1d82a552..e45e1e2a 100644 --- a/src/lib/subs/mission.c +++ b/src/lib/subs/mission.c @@ -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