Factor out common land unit fire code into lnd_fire()
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.
This commit is contained in:
parent
652afa12de
commit
f6c87d21ff
6 changed files with 92 additions and 124 deletions
|
@ -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 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);
|
||||
|
|
|
@ -460,7 +460,7 @@ extern int lnd_prewrite(int, void *);
|
|||
/* 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 *);
|
||||
|
|
|
@ -79,8 +79,6 @@ multifire(void)
|
|||
coord x;
|
||||
coord y;
|
||||
int mil;
|
||||
int gun;
|
||||
int shell;
|
||||
int shots;
|
||||
int dam;
|
||||
int totaldefdam = 0;
|
||||
|
@ -173,8 +171,6 @@ multifire(void)
|
|||
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;
|
||||
|
@ -361,13 +357,11 @@ multifire(void)
|
|||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -376,21 +370,16 @@ multifire(void)
|
|||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
@ -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;
|
||||
int gun, shell;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
@ -803,27 +781,17 @@ quiet_bigdef(int attacker, struct emp_qelem *list, natid own, natid aown,
|
|||
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;
|
||||
|
||||
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);
|
||||
use_supply(&land);
|
||||
putland(land.lnd_uid, &land);
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "damage.h"
|
||||
#include "file.h"
|
||||
#include "land.h"
|
||||
#include "nat.h"
|
||||
#include "optlist.h"
|
||||
#include "prototypes.h"
|
||||
|
@ -65,16 +66,14 @@ seagun(int effic, int guns)
|
|||
}
|
||||
|
||||
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;
|
||||
if (shells < ammo && ammo != 0)
|
||||
d *= (double)shells / (double)ammo;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -179,6 +178,45 @@ shp_torp(struct shpstr *sp, int usemob)
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
double dam = 0.0;
|
||||
int dam, dam2;
|
||||
int dist;
|
||||
int shell;
|
||||
int gun;
|
||||
int range;
|
||||
|
||||
dam = 0;
|
||||
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_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;
|
||||
|
||||
/* do we have supplies? */
|
||||
if (!has_supply(&land))
|
||||
continue;
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
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 (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));
|
||||
}
|
||||
return (int)dam;
|
||||
return dam;
|
||||
}
|
||||
|
||||
int
|
||||
lnd_can_attack(struct lndstr *lp)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
int gun, shell, md, range, air_dam = 0;
|
||||
int md, range, air_dam = 0;
|
||||
double prb, hitchance, vrange;
|
||||
|
||||
getsect(x, y, §);
|
||||
|
@ -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 (lp->lnd_effic < LAND_MINFIREEFF)
|
||||
continue;
|
||||
|
||||
if (mission == MI_SINTERDICT)
|
||||
continue;
|
||||
|
||||
|
@ -440,26 +437,15 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
(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;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
@ -475,7 +461,6 @@ perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
|
|||
|
||||
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue