/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure
*
* This program is free software; you can redistribute it and/or modify
*
* ---
*
- * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- * related information and legal notices. It is expected that any future
- * projects/authors will amend these files as needed.
+ * See files README, COPYING and CREDITS in the root of the source
+ * tree for related information and legal notices. It is expected
+ * that future projects/authors will amend these files as needed.
*
* ---
*
* mission.c: Mission subroutines for planes/ships/units
- *
+ *
* Known contributors to this file:
* Ken Stevens, 1995
* Steve McClure, 1996-2000
#include <config.h>
+#include <stdlib.h>
+#include "empobj.h"
+#include "file.h"
+#include "item.h"
#include "misc.h"
-#include "player.h"
-#include "xy.h"
-#include "sect.h"
-#include "ship.h"
-#include "land.h"
-#include "plane.h"
-#include "nat.h"
+#include "mission.h"
#include "nsc.h"
-#include "file.h"
+#include "optlist.h"
#include "path.h"
-#include "mission.h"
-#include "genitem.h"
-#include "news.h"
-#include "item.h"
-#include <fcntl.h>
-#include "damage.h"
+#include "player.h"
#include "prototypes.h"
-#include "optlist.h"
+#include "queue.h"
+#include "xy.h"
+
+struct genlist {
+ struct emp_qelem queue; /* list of units */
+ void *cp; /* pointer to desc of thing */
+ struct empobj *thing; /* thing's struct */
+};
struct airport {
struct emp_qelem queue;
static void add_airport(struct emp_qelem *, coord, coord);
static int air_damage(struct emp_qelem *, coord, coord, int, natid,
- s_char *, int);
+ char *, int);
static void build_mission_list(struct genlist *, coord, coord, int, natid);
static void build_mission_list_type(struct genlist *, coord, coord, int,
int, natid);
static int dosupport(struct genlist *, coord, coord, natid, natid);
static int find_airport(struct emp_qelem *, coord, coord);
static int mission_pln_arm(struct emp_qelem *, coord, coord, int,
- int, struct ichrstr *, int, int, int *);
+ int, struct ichrstr *, int, int);
static void mission_pln_sel(struct emp_qelem *, int, int, int);
static int perform_mission(coord, coord, natid, struct emp_qelem *, int,
- s_char *, int);
+ char *, int);
/*
* Interdict commodities & transported planes
*/
int
-ground_interdict(coord x, coord y, natid victim, s_char *s)
+ground_interdict(coord x, coord y, natid victim, char *s)
{
int cn;
int dam = 0, newdam, rel;
cname(cn), newdam);
}
if (dam) {
- collateral_damage(x, y, dam, 0);
+ collateral_damage(x, y, dam);
}
return dam;
}
int
-collateral_damage(coord x, coord y, int dam, struct emp_qelem *list)
+collateral_damage(coord x, coord y, int dam)
{
int coll;
struct sctstr sect;
return 0;
mpr(sect.sct_own, "%s takes %d%% collateral damage\n",
xyas(x, y, sect.sct_own), coll);
- sectdamage(§, coll, list);
+ sectdamage(§, coll);
putsect(§);
return coll;
}
for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
glp = (struct genlist *)qp;
- if (glp->type != EF_SHIP)
+ if (glp->thing->ef_type != EF_SHIP)
return 0;
- mcp = (struct mchrstr *)glp->cp;
+ mcp = glp->cp;
if (!(mcp->m_flags & M_SUB))
return 0;
/* It's a sub! */
/*
* Interdict ships & land units
- *
*/
int
-unit_interdict(coord x, coord y, natid victim, s_char *s, int hardtarget,
+unit_interdict(coord x, coord y, natid victim, char *s, int hardtarget,
int mission)
{
int cn;
if (newdam) {
/* If only subs responded, then we don't know who's
subs they are */
- if (osubs) {
- mpr(victim,
- "Enemy interdiction mission does %d damage!\n",
- newdam);
- } else {
- mpr(victim,
- "%s interdiction mission does %d damage!\n",
- cname(cn), newdam);
- }
+ mpr(victim, "%s interdiction mission does %d damage!\n",
+ osubs ? "Enemy" : cname(cn), newdam);
}
}
if (dam) {
- collateral_damage(x, y, dam, 0);
+ collateral_damage(x, y, dam);
}
return dam;
}
{
struct nstr_item ni;
struct genlist *glp;
- struct genitem *gp;
- union {
- struct shpstr u_sp;
- struct lndstr u_lp;
- struct plnstr u_pp;
- } u_block;
- s_char *block;
- int dist, size;
+ struct empobj *gp;
+ union empobj_storage item;
+ int dist;
int radius;
int relat;
struct sctstr sect;
-/*
- size = max(sizeof(struct shpstr),sizeof(struct lndstr));
- size = max(size,sizeof(struct plnstr));
- block = malloc(size);
- */
- size = sizeof(u_block);
- block = (s_char *)&u_block;
-
snxtitem_all(&ni, type);
- while (nxtitem(&ni, block)) {
- gp = (struct genitem *)block;
+ while (nxtitem(&ni, &item)) {
+ gp = (struct empobj *)&item;
if (gp->own == 0)
continue;
radius = gp->radius;
if (mission != MI_RESERVE) /* XXX */
- oprange(gp, type, &radius);
+ oprange(gp, &radius);
if (dist > radius)
continue;
/* Now check from where the object actually is */
dist = mapdist(x, y, gp->x, gp->y);
radius = 999;
- oprange(gp, type, &radius);
+ oprange(gp, &radius);
if (dist > radius)
continue;
/* Ok, the object can get to where the x,y is */
if (getrel(getnatp(gp->own), sect.sct_own) > AT_WAR) {
/*
- * If the player->owner of the unit isn't at war
+ * If the owner of the unit isn't at war
* with the victim, and doesn't own the
* sect being acted upon, and isn't the
- * old player->owner of that sect, bounce them.
+ * old owner of that sect, bounce them.
*/
if (sect.sct_type != SCT_WATER &&
sect.sct_own != gp->own &&
glp = malloc(sizeof(struct genlist));
memset(glp, 0, sizeof(struct genlist));
- glp->x = gp->x;
- glp->y = gp->y;
- glp->type = type;
- switch (type) {
- case EF_LAND:
- glp->cp = (s_char *)&lchr[(int)gp->type];
- break;
- case EF_SHIP:
- glp->cp = (s_char *)&mchr[(int)gp->type];
- break;
- case EF_PLANE:
- glp->cp = (s_char *)&plchr[(int)gp->type];
- break;
- }
- glp->thing = malloc(size);
- memcpy(glp->thing, block, size);
+ glp->cp = get_empobj_chr(gp);
+ glp->thing = malloc(sizeof(item));
+ memcpy(glp->thing, &item, sizeof(item));
emp_insque(&glp->queue, &mi[gp->own].queue);
}
}
continue;
dist = mapdist(x, y, plane.pln_x, plane.pln_y);
-
- if (dist > ((int)((float)plane.pln_range / 2.0)))
+ if (dist > plane.pln_range / 2)
continue;
plp = malloc(sizeof(struct plist));
static int
perform_mission(coord x, coord y, natid victim, struct emp_qelem *list,
- int mission, s_char *s, int hardtarget)
+ int mission, char *s, int hardtarget)
{
struct emp_qelem *qp, missiles, bombers, escorts, airp, b, e;
struct emp_qelem *newqp;
struct genlist *glp;
struct plist *plp;
- struct genitem *gp;
+ struct empobj *gp;
struct lndstr *lp;
struct shpstr *sp;
struct sctstr sect;
struct mchrstr *mcp;
struct plchrstr *pcp;
- int dam = 0, dam2, mission_flags, tech;
+ int dam = 0, dam2, mission_flags;
natid plane_owner = 0;
- int gun, shell, md, air_dam = 0;
- double range2, prb, range, mobcost, hitchance;
+ int md, range, air_dam = 0;
+ double hitchance, vrange;
+ int targeting_ships = *s == 's'; /* "subs" or "ships" FIXME gross! */
getsect(x, y, §);
for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
glp = (struct genlist *)qp;
- gp = (struct genitem *)glp->thing;
+ gp = glp->thing;
md = mapdist(x, y, gp->x, gp->y);
- if (glp->type == EF_LAND) {
+ if (glp->thing->ef_type == EF_LAND) {
lp = (struct lndstr *)glp->thing;
- if (lp->lnd_effic < LAND_MINFIREEFF)
- continue;
-
if (mission == MI_SINTERDICT)
continue;
(md > land_max_interdiction_range))
continue;
- if (md > (lp->lnd_frg / 2))
- continue;
-
- if (lnd_getmil(lp) < 1)
- continue;
-
- range = techfact((int)lp->lnd_tech, (double)lp->lnd_frg / 2.0);
- range2 = (double)roundrange(range);
-
- if (md > range2)
+ range = roundrange(lnd_fire_range(lp));
+ 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) {
- double dam3 = (double)dam2;
- if (chance(((double)lp->lnd_acc) / 100.0))
- dam2 = ldround((dam3 / 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 (targeting_ships) {
+ if (chance(lnd_acc(lp) / 100.0))
+ dam2 = ldround(dam2 / 2.0, 1);
}
- } else if (glp->type == EF_SHIP) {
+ dam += dam2;
+ if (targeting_ships)
+ 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 = (struct mchrstr *)glp->cp;
+ 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))
- continue;
-*/
if (mission == MI_SINTERDICT) {
if (!(mcp->m_flags & M_SONAR))
continue;
if (!(mcp->m_flags & M_DCH) && !(mcp->m_flags & M_SUBT))
continue;
- range2 = techfact(sp->shp_tech, (double)mcp->m_vrnge);
- range2 *= (double)sp->shp_effic / 200.0;
- if (md > range2)
+ vrange = techfact(sp->shp_tech, mcp->m_vrnge);
+ vrange *= sp->shp_effic / 200.0;
+ if (md > vrange)
continue;
/* can't look all the time */
if (chance(0.5))
continue;
}
if (mcp->m_flags & M_SUB) {
-/* If we aren't shooting at "subs" or "ships" don't fire at all from
- a sub. */
- if (*s != 's')
- continue;
- if (sp->shp_mobil < 0)
- continue;
- gun = sp->shp_item[I_GUN];
- if (gun < 1)
- continue;
- shell = sp->shp_item[I_SHELL];
- if (shell < SHP_TORP_SHELLS)
- shell += supply_commod(sp->shp_own,
- sp->shp_x, sp->shp_y, I_SHELL,
- SHP_TORP_SHELLS - shell);
- if (shell < SHP_TORP_SHELLS)
- continue;
-
- range = sp->shp_effic * techfact(sp->shp_tech,
- ((double)sp->shp_frnge)) /
- 100.0;
-
- range2 = (double)roundrange(range);
+ if (!targeting_ships)
+ continue; /* subs interdict only ships */
+ range = roundrange(torprange(sp));
if (md > range)
continue;
-
if (!line_of_sight(NULL, x, y, gp->x, gp->y))
continue;
- sp->shp_item[I_SHELL] = shell - SHP_TORP_SHELLS;
- mobcost = sp->shp_effic * 0.01 * sp->shp_speed;
- mobcost = (480.0 / (mobcost +
- techfact(sp->shp_tech, mobcost)));
- sp->shp_mobil -= mobcost;
+ dam2 = shp_torp(sp, 1);
putship(sp->shp_uid, sp);
- hitchance = DTORP_HITCHANCE(md, sp->shp_visib);
+ if (dam2 < 0)
+ continue;
+ hitchance = shp_torp_hitchance(sp, md);
wu(0, sp->shp_own,
"%s locking on %s %s in %s\n",
prship(sp), cname(victim), s, xyas(x, y, sp->shp_own));
wu(0, sp->shp_own,
- "\tEffective torpedo range is %.1f\n", range);
+ "\tEffective torpedo range is %d.0\n", range);
wu(0, sp->shp_own,
"\tWhooosh... Hitchance = %d%%\n",
(int)(hitchance * 100));
- if (hitchance < 1.0 && !chance(hitchance)) {
+ if (!chance(hitchance)) {
wu(0, sp->shp_own, "\tMissed\n");
mpr(victim,
"Incoming torpedo sighted @ %s missed (whew)!\n",
continue;
}
wu(0, sp->shp_own, "\tBOOM!...\n");
- dam2 = TORP_DAMAGE();
-
dam += dam2;
nreport(victim, N_TORP_SHIP, 0, 1);
wu(0, sp->shp_own,
"Incoming torpedo sighted @ %s hits and does %d damage!\n",
xyas(x, y, victim), dam2);
} else {
- range = techfact(sp->shp_tech, (double)mcp->m_frnge / 2.0);
- range2 = (double)roundrange(range);
- if (md > range2)
- continue;
- 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)
+ range = roundrange(shp_fire_range(sp));
+ if (md > range)
continue;
- gun = max(gun, 1);
- dam2 = seagun(sp->shp_effic, gun);
- if (range2 == 0.0)
- prb = 1.0;
+ if (mission == MI_SINTERDICT)
+ dam2 = shp_dchrg(sp);
else
- prb = ((double)md) / range2;
- prb *= prb;
- if (chance(prb))
- dam2 = (int)((float)dam2 / 2.0);
+ dam2 = shp_fire(sp);
+ putship(sp->shp_uid, sp);
+ if (dam2 < 0)
+ continue;
dam += dam2;
- if (sect.sct_type == SCT_WATER)
+ if (targeting_ships)
nreport(sp->shp_own, N_SHP_SHELL, victim, 1);
else
nreport(sp->shp_own, N_SCT_SHELL, victim, 1);
mpr(victim, "%s %s fires at you at %s\n",
cname(sp->shp_own), prship(sp), xyas(x, y, victim));
-
- sp->shp_item[I_SHELL] = shell - gun;
- putship(sp->shp_uid, sp);
}
- } else if (glp->type == EF_PLANE) {
- pcp = (struct plchrstr *)glp->cp;
+ } else if (glp->thing->ef_type == EF_PLANE) {
+ pcp = glp->cp;
if (pcp->pl_flags & P_M)
/* units have their own missile interdiction */
if (hardtarget != SECT_HARDTARGET || pcp->pl_flags & P_MAR)
else
emp_insque(&plp->queue, &bombers);
plane_owner = plp->plane.pln_own;
+ } else {
+ CANT_REACH();
+ break;
}
}
if (!QEMPTY(&missiles)) {
for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
struct airport *air;
- s_char pp[512];
+ char buf[512];
+ char *pp;
air = (struct airport *)qp;
md = mapdist(x, y, air->x, air->y);
/* Split off the escorts at this base into e */
divide(&escorts, &e, air->x, air->y);
- tech = 0;
mission_flags = 0;
mission_flags |= P_X; /* stealth (shhh) */
mission_flags |= P_H; /* gets turned off if not all choppers */
mission_flags = mission_pln_arm(&b, air->x, air->y, 2 * md, 'p', 0,
- 0, mission_flags, &tech);
+ 0, mission_flags);
- if (QEMPTY(&b)) {
+ if (QEMPTY(&b))
continue;
- }
mission_flags = mission_pln_arm(&e, air->x, air->y, 2 * md, 'p', 0,
- P_F | P_ESC, mission_flags, &tech);
+ P_F | P_ESC, mission_flags);
- BestAirPath(pp, air->x, air->y, x, y);
- wu(0, plane_owner, "Flying %s mission from %s\n",
- mission_name(mission), xyas(air->x, air->y, plane_owner));
+ pp = BestAirPath(buf, air->x, air->y, x, y);
+ if (CANT_HAPPEN(!pp))
+ continue;
+ wu(0, plane_owner, "Flying %s mission from %s to %s\n",
+ mission_name(mission),
+ xyas(air->x, air->y, plane_owner),
+ xyas(x, y, plane_owner));
if (air->own && (air->own != plane_owner)) {
- wu(0, air->own, "%s is flying %s mission from %s\n",
+ wu(0, air->own, "%s is flying %s mission from %s to %s\n",
cname(plane_owner), mission_name(mission),
- xyas(air->x, air->y, air->own));
+ xyas(air->x, air->y, air->own),
+ xyas(x, y, air->own));
}
- ac_encounter(&b, &e, air->x, air->y, pp, mission_flags, 0, 0, 0);
+ ac_encounter(&b, &e, air->x, air->y, pp, mission_flags, 0);
if (!QEMPTY(&b))
air_dam +=
if (air_dam > 0) {
dam += air_dam;
- if (sect.sct_type == SCT_WATER)
+ if (targeting_ships)
nreport(plane_owner, N_SHP_BOMB, victim, 1);
else
nreport(plane_owner, N_SCT_BOMB, victim, 1);
return 0;
}
-s_char *
-nameofitem(struct genitem *gp, int type)
-{
- switch (type) {
- case EF_SHIP:
- return prship((struct shpstr *)gp);
- case EF_PLANE:
- return prplane((struct plnstr *)gp);
- case EF_LAND:
- return prland((struct lndstr *)gp);
- }
- return NULL;
-}
-
-s_char *
-mission_name(short int mission)
+char *
+mission_name(short mission)
{
switch (mission) {
case MI_INTERDICT:
case MI_SUPPORT:
return "a support";
case MI_OSUPPORT:
- return "a offensive support";
+ return "an offensive support";
case MI_DSUPPORT:
return "a defensive support";
case MI_RESERVE:
case MI_AIR_DEFENSE:
return "an air defense";
}
+ CANT_REACH();
return "a mysterious";
}
void
show_mission(int type, struct nstr_item *np)
{
- int size, first = 1, radius;
- s_char *block;
- struct genitem *gp;
-
- size = max(sizeof(struct lndstr), sizeof(struct plnstr));
- size = max(size, sizeof(struct shpstr));
- block = malloc(size);
+ int first = 1, radius;
+ union empobj_storage item;
+ struct empobj *gp;
+ struct sctstr sect;
- while (nxtitem(np, block)) {
- gp = (struct genitem *)block;
+ while (nxtitem(np, &item)) {
+ gp = (struct empobj *)&item;
if (!player->owner || gp->own == 0)
continue;
pr("Thing x,y op-sect rad mission\n");
first = 0;
}
- pr("%-25s", nameofitem(gp, type));
- pr(" %7s", xyas(gp->x, gp->y, player->cnum));
- if (gp->mission == MI_INTERDICT || gp->mission == MI_SUPPORT ||
- gp->mission == MI_OSUPPORT ||
- gp->mission == MI_DSUPPORT || gp->mission == MI_AIR_DEFENSE) {
- radius = 999;
- oprange(gp, type, &radius);
- pr(" %7s", xyas(gp->opx, gp->opy, player->cnum));
- if (radius < gp->radius)
- pr(" %4d", radius);
- else
- pr(" %4d", gp->radius);
- } else if (gp->mission == MI_RESERVE) {
- struct sctstr sect;
- int plus = 2;
-
- getsect(gp->x, gp->y, §);
- if ((sect.sct_type == SCT_HEADQ) && (sect.sct_effic >= 60))
- plus++;
-
- if (((struct lndstr *)block)->lnd_rad_max == 0)
- plus = 0;
- else
- plus += ((struct lndstr *)block)->lnd_rad_max;
- pr(" %7s", xyas(gp->x, gp->y, player->cnum));
- pr(" %4d", plus);
- } else if (gp->mission == MI_ESCORT) {
+ pr("%-25s", obj_nameof(gp));
+ prxy(" %3d,%-3d", gp->x, gp->y, player->cnum);
+ switch (gp->mission) {
+ case MI_INTERDICT:
+ case MI_SUPPORT:
+ case MI_AIR_DEFENSE:
+ case MI_DSUPPORT:
+ case MI_OSUPPORT:
+ radius = gp->radius;
+ oprange(gp, &radius);
+ prxy(" %3d,%-3d", gp->opx, gp->opy, player->cnum);
+ pr(" %4d", radius);
+ break;
+ case MI_RESERVE:
+ radius = item.land.lnd_rad_max;
+
+ if (radius) {
+ radius += 2;
+ getsect(gp->x, gp->y, §);
+ if ((sect.sct_type == SCT_HEADQ) && (sect.sct_effic >= 60))
+ radius++;
+ }
+ prxy(" %3d,%-3d", gp->x, gp->y, player->cnum);
+ pr(" %4d", radius);
+ break;
+ case MI_ESCORT:
pr(" ");
- pr(" %4d", (int)
- ((float)((struct plnstr *)block)->pln_range / 2.0)
- );
- } else
+ pr(" %4d", item.plane.pln_range / 2);
+ break;
+ default:
+ CANT_REACH();
+ /* fall through */
+ case MI_NONE:
pr(" ");
+ }
if (gp->mission)
pr(" is on %s mission\n", mission_name(gp->mission));
else
}
int
-oprange(struct genitem *gp, int type, int *radius)
+oprange(struct empobj *gp, int *radius)
{
int range;
- struct shpstr ship;
- struct lndstr land;
- struct plnstr plane;
- switch (type) {
+ switch (gp->ef_type) {
case EF_SHIP:
- getship(gp->uid, &ship);
- range = ldround(techfact(gp->tech,
- (double)ship.shp_frnge / 2.0), 1);
+ range = ldround(shp_fire_range((struct shpstr *)gp), 1);
break;
case EF_LAND:
- getland(gp->uid, &land);
- range = ldround(techfact((int)land.lnd_tech,
- (double)land.lnd_frg / 2.0), 1);
+ range = ldround(lnd_fire_range((struct lndstr *)gp), 1);
break;
case EF_PLANE:
- getplane(gp->uid, &plane);
/* missiles go one way, so we can use all the range */
- if (plchr[(int)plane.pln_type].pl_flags & P_M)
- range = plane.pln_range;
+ if (plchr[(int)gp->type].pl_flags & P_M)
+ range = ((struct plnstr *)gp)->pln_range;
else
- range = ldround((double)plane.pln_range / 2.0, 1);;
+ range = ((struct plnstr *)gp)->pln_range / 2;
break;
+ default:
+ CANT_REACH();
+ range = -1;
}
- if ((*radius) > range)
+ if (*radius > range)
*radius = range;
return range;
{
struct emp_qelem *qp, *next;
struct plnstr *pp;
- struct shpstr ship;
- struct lndstr land;
- struct sctstr sect;
struct plchrstr *pcp;
struct plist *plp;
- int y, bad, bad1;
- unsigned int x;
for (qp = list->q_forw; qp != list; qp = next) {
next = qp->q_forw;
}
if (opt_MARKET) {
- if (ontradingblock(EF_PLANE, (int *)pp)) {
+ if (ontradingblock(EF_PLANE, pp)) {
emp_remque(qp);
free(qp);
continue;
}
}
- bad = 0;
- bad1 = 0;
- if (wantflags) {
- for (x = 0; x < sizeof(wantflags) * 8; x++) {
- y = (1 << x);
- if ((wantflags & y) == y)
- if ((pcp->pl_flags & y) != y) {
- switch (y) {
- case P_F:
- case P_ESC:
- bad1 = 2;
- break;
- case P_E:
- case P_L:
- case P_K:
- bad1 = 1;
- break;
- default:
- bad = 1;
- }
- }
- }
- if (bad) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- if (bad1 == 2) {
- if ((pcp->pl_flags & P_ESC) || (pcp->pl_flags & P_F))
- bad1 = 0;
- }
- if (bad1 == 1) {
- if ((pcp->pl_flags & P_E) ||
- (pcp->pl_flags & P_K) || (pcp->pl_flags & P_L))
- bad1 = 0;
- }
- if (bad1) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- }
- bad = 0;
- bad1 = 0;
- if (nowantflags) {
- for (x = 0; x < sizeof(nowantflags) * 8; x++) {
- y = (1 << x);
- if ((nowantflags & y) == y)
- if ((pcp->pl_flags & y) == y)
- bad = 1;
- }
- if (bad) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- }
- if (pp->pln_ship >= 0) {
- if (!getship(pp->pln_ship, &ship)) {
- shipsunk:
- pp->pln_effic = 0;
- putplane(pp->pln_uid, pp);
- emp_remque(qp);
- free(qp);
- continue;
- }
- if (!can_be_on_ship(pp->pln_uid, ship.shp_uid)) {
- goto shipsunk;
- }
- if (ship.shp_effic < SHIP_MINEFF) {
- goto shipsunk;
- }
- /* Can't fly off of inefficient or non-owned, non-allied ships */
- if ((ship.shp_effic < SHP_AIROPS_EFF) ||
- ((ship.shp_own != pp->pln_own) &&
- (getrel(getnatp(ship.shp_own), pp->pln_own) != ALLIED))) {
- emp_remque(qp);
- free(qp);
- continue;
- }
+ if (!pln_capable(pp, wantflags, nowantflags)) {
+ emp_remque(qp);
+ free(qp);
+ continue;
}
- if (pp->pln_land >= 0) {
- if (!getland(pp->pln_land, &land)) {
- landdead:
- pp->pln_effic = 0;
- putplane(pp->pln_uid, pp);
- emp_remque(qp);
- free(qp);
- continue;
- }
- if (!(pcp->pl_flags & P_E))
- goto landdead;
- if (land.lnd_effic < LAND_MINEFF)
- goto landdead;
-
- /* Can't fly off of inefficient or non-owned, non-allied units */
- if ((land.lnd_effic < LND_AIROPS_EFF) ||
- ((land.lnd_own != pp->pln_own) &&
- (getrel(getnatp(land.lnd_own), pp->pln_own) != ALLIED))) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- /* Can't fly off units in ships or other units */
- if ((land.lnd_ship >= 0) || (land.lnd_land >= 0)) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- }
- /* Now, check the sector status if not on a plane or unit */
- if ((pp->pln_ship < 0) && (pp->pln_land < 0)) {
- /* If we can't get the sector, we can't check it, and can't fly */
- if (!getsect(pp->pln_x, pp->pln_y, §)) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- /* First, check allied status */
- /* Can't fly from non-owned sectors or non-allied sectors */
- if ((sect.sct_own != pp->pln_own) &&
- (getrel(getnatp(sect.sct_own), pp->pln_own) != ALLIED)) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- /* non-vtol plane */
- if ((pcp->pl_flags & P_V) == 0) {
- if ((sect.sct_type != SCT_AIRPT) || (sect.sct_effic < 40)) {
- emp_remque(qp);
- free(qp);
- continue;
- }
- }
+ if (!pln_airbase_ok(pp, 0, 0)) {
+ emp_remque(qp);
+ free(qp);
+ continue;
}
+
if (pcp->pl_flags & P_A) {
if (roll(100) > pln_identchance(pp, hardtarget, EF_SHIP)) {
emp_remque(qp);
/*
* Arm only the planes at x,y
- *
*/
static int
mission_pln_arm(struct emp_qelem *list, coord x, coord y, int dist,
int mission, struct ichrstr *ip, int flags,
- int mission_flags, int *tech)
+ int mission_flags)
{
struct emp_qelem *qp;
struct emp_qelem *next;
struct plist *plp;
+ struct plnstr *pp;
- if (*tech == 0)
- *tech = 9999;
for (qp = list->q_forw; qp != list; qp = next) {
next = qp->q_forw;
plp = (struct plist *)qp;
+ pp = &plp->plane;
- if (plp->plane.pln_x != x)
+ if (pp->pln_x != x)
continue;
- if (plp->plane.pln_y != y)
+ if (pp->pln_y != y)
continue;
- if (mission_pln_equip(plp, ip, flags, mission) < 0) {
+ if (CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED)
+ || mission_pln_equip(plp, ip, flags, mission) < 0) {
emp_remque(qp);
free(qp);
continue;
if (plp->pcp->pl_flags & P_I)
mission_flags |= P_I;
}
- if (*tech > plp->plane.pln_tech)
- *tech = plp->plane.pln_tech;
if (!(plp->pcp->pl_flags & P_H))
/* no stealth on this mission */
mission_flags &= ~P_H;
mission_flags &= ~P_MINE;
}
- /*
- * Mob costs for missions are 1/2 normal
- * Not anymore. :)
- */
-/* plp->plane.pln_mobil -= pln_mobcost(dist,&plp->plane,flags)/2;*/
- plp->plane.pln_mobil -= pln_mobcost(dist, &plp->plane, flags);
-
+ pp->pln_flags |= PLN_LAUNCHED;
+ pp->pln_mobil -= pln_mobcost(dist, pp, flags);
+ putplane(pp->pln_uid, pp);
}
return mission_flags;
}
int
mission_pln_equip(struct plist *plp, struct ichrstr *ip, int flags,
- s_char mission)
+ char mission)
{
struct plchrstr *pcp;
struct plnstr *pp;
- int needed;
+ int load, needed;
struct lndstr land;
struct shpstr ship;
struct sctstr sect;
i_type itype;
- int rval;
short *item;
pp = &plp->plane;
return -1;
}
item[I_PETROL] -= pcp->pl_fuel;
- rval = 0;
if (!(flags & P_F)) {
+ load = pln_load(pp);
itype = I_NONE;
needed = 0;
switch (mission) {
- case 's':
- case 'p':
- if (pp->pln_nuketype == -1) {
+ case 's': /* strategic bomb */
+ case 'p': /* pinpoint bomb */
+ if (nuk_on_plane(pp) < 0) {
itype = I_SHELL;
- needed = pp->pln_load;
+ needed = load;
}
break;
- case 't':
+ case 't': /* transport */
+ case 'd': /* drop */
if ((pcp->pl_flags & P_C) == 0 || ip == 0)
break;
- itype = ip->i_vtype;
- needed = (pp->pln_load * 2) / ip->i_lbs;
+ itype = ip->i_uid;
+ needed = (load * 2) / ip->i_lbs;
break;
- case 'd':
- if ((pcp->pl_flags & P_C) == 0 || ip == 0)
- break;
- itype = ip->i_vtype;
- needed = (pp->pln_load * 2) / ip->i_lbs;
- break;
- case 'a':
+ case 'a': /* paradrop */
if ((pcp->pl_flags & (P_V | P_C)) == 0)
break;
itype = I_MILIT;
- needed = pp->pln_load / ip->i_lbs;
- break;
- case 'n':
- if (pp->pln_nuketype == -1)
- rval = -1;
+ needed = load / ip->i_lbs;
break;
case 'i': /* missile interception */
- if (pp->pln_load) {
+ if (load) {
itype = I_SHELL;
- needed = pp->pln_load;
+ needed = load;
}
break;
+ case 'r': /* reconnaissance */
+ case 0: /* plane interception */
+ break;
default:
+ CANT_REACH();
break;
}
- if (rval < 0 || (itype != I_NONE && needed <= 0)) {
+ if (itype != I_NONE && needed <= 0)
return -1;
- }
if (itype != I_NONE) {
if (itype == I_SHELL && item[itype] < needed)
item[itype] += supply_commod(plp->plane.pln_own,
putland(land.lnd_uid, &land);
else
putsect(§);
- return rval;
+ return 0;
}
/*
static int
air_damage(struct emp_qelem *bombers, coord x, coord y, int mission,
- natid victim, s_char *s, int hardtarget)
+ natid victim, char *s, int hardtarget)
{
struct emp_qelem *qp;
struct plist *plp;
prplane(pp), cname(victim), s, xyas(x, y, pp->pln_own));
}
hitchance = pln_hitchance(pp, hardtarget, EF_SHIP);
- if (plp->plane.pln_nuketype != -1)
+ if (nuk_on_plane(&plp->plane) >= 0)
hitchance = 100;
else if (hardtarget != SECT_HARDTARGET)
wu(0, pp->pln_own, "\t\t%d%% hitchance...", hitchance);
"RUMBLE... your sub in %s hears a depth-charge explode nearby\n",
xyas(x, y, victim));
} else if (*s == 's') {
- mpr(victim,
- "SPLASH! Bombs miss your %s in %s\n",
+ mpr(victim, "SPLASH! Bombs miss your %s in %s\n",
s, xyas(x, y, victim));
} else {
mpr(victim, "SPLAT! Bombs miss your %s in %s\n",
}
/* Now, even though we missed, the bombs
land somewhere. */
- collateral_damage(x, y, newdam, bombers);
+ collateral_damage(x, y, newdam);
}
/* use up missiles */
- if (plp->pcp->pl_flags & P_M) {
- makelost(EF_PLANE, pp->pln_own, pp->pln_uid, pp->pln_x,
- pp->pln_y);
- pp->pln_own = 0;
- }
+ if (plp->pcp->pl_flags & P_M)
+ pp->pln_effic = 0;
}
return dam;
struct emp_qelem *esc_list)
{
int dam = 0, cn;
- int mission_flags, tech, combat = 0, rel, dist, z;
+ int mission_flags, combat = 0, rel, dist, z;
struct emp_qelem *qp, interceptors, airp, i, empty, *next;
struct plist *plp;
struct genlist *glp;
- struct genitem *gp;
+ struct empobj *gp;
struct genlist mi[MAXNOC];
- s_char path[512];
+ char buf[512];
+ char *path;
int count;
int tcount;
emp_initque(&interceptors);
for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) {
next = qp->q_forw;
-
glp = (struct genlist *)qp;
- gp = (struct genitem *)glp->thing;
- plp = (struct plist *)qp;
+ gp = glp->thing;
+ if (CANT_HAPPEN(gp->ef_type != EF_PLANE))
+ break;
dist = mapdist(x, y, gp->x, gp->y);
plp = malloc(sizeof(struct plist));
memset(plp, 0, sizeof(struct plist));
- plp->pcp = (struct plchrstr *)glp->cp;
+ plp->pcp = glp->cp;
memcpy(&plp->plane, glp->thing, sizeof(struct plnstr));
/* missiles go one way, so we can use all the range */
for (qp = interceptors.q_forw; qp != (&interceptors);
qp = qp->q_forw)
tcount++;
- tcount -= (count * 2);
+ tcount -= count * 2;
/* Just in case there are more incoming than we have */
if (tcount < 0)
tcount = 0;
/* Split off the interceptors at this base into i */
divide(&interceptors, &i, air->x, air->y);
- tech = 0;
mission_flags = 0;
mission_flags |= P_X; /* stealth (shhh) */
/* gets turned off if not all choppers */
continue;
}
mission_flags =
- mission_pln_arm(&i, air->x, air->y, 2 * dist, 'r', 0, P_F,
- mission_flags, &tech);
+ mission_pln_arm(&i, air->x, air->y, 2 * dist, 0, 0, P_F,
+ mission_flags);
/* Did we run out of interceptors? */
if (QEMPTY(&i))
continue;
}
- BestAirPath(path, air->x, air->y, x, y);
- wu(0, cn, "Flying %s mission from %s\n",
- mission_name(MI_AIR_DEFENSE), xyas(air->x, air->y, cn));
+ path = BestAirPath(buf, air->x, air->y, x, y);
+ if (CANT_HAPPEN(!path)) {
+ pln_put(&i);
+ continue;
+ }
+ wu(0, cn, "Flying %s mission from %s to %s\n",
+ mission_name(MI_AIR_DEFENSE),
+ xyas(air->x, air->y, cn),
+ xyas(x, y, cn));
if (air->own && (air->own != cn)) {
- wu(0, air->own, "%s is flying %s mission from %s\n",
+ wu(0, air->own, "%s is flying %s mission from %s to %s\n",
cname(cn), mission_name(MI_AIR_DEFENSE),
- xyas(air->x, air->y, air->own));
+ xyas(air->x, air->y, air->own),
+ xyas(x, y, air->own));
}
/* Now, fly the planes to the sector */
emp_initque(&empty);
ac_encounter(&i, &empty, air->x, air->y,
- path, mission_flags, 1, bomb_list, esc_list);
+ path, mission_flags, 1);
/* If none made it, continue */
if (QEMPTY(&i))
pln_put(&i);
}
+ if (CANT_HAPPEN(!QEMPTY(&interceptors)))
+ pln_put(&interceptors);
}
/* We have to free all of these, if they are still there, otherwise they get