extern int pln_next_on_unit(int);
/* src/lib/subs/aircombat.c */
-extern void ac_combat_headers(natid, natid);
-extern void ac_airtoair(struct emp_qelem *, struct emp_qelem *);
extern int ac_flak_dam(int, int, int);
extern void ac_encounter(struct emp_qelem *, struct emp_qelem *, coord,
- coord, char *, int, int);
-extern void sam_intercept(struct emp_qelem *, struct emp_qelem *,
- natid, natid, coord, coord, int);
+ coord, char *, int);
/* src/lib/subs/aswplnsubs.c */
extern int on_shiplist(short, struct shiplist *);
extern int oprange(struct empobj *);
extern int in_oparea(struct empobj *, coord, coord);
extern int cando(int, int);
-extern int air_defense(coord, coord, natid, struct emp_qelem *,
- struct emp_qelem *);
/* move.c */
extern int check_lmines(coord, coord, double);
extern int move_ground(struct sctstr *, struct sctstr *,
.s1
Artillery units less than 40% efficient will not fire.
.s1
-Planes flying missions will be intercepted normally. (i.e. if you fly
-over enemy territory, you'll get intercepted. Any mission except air
-missions may also be intercepted by planes on air defense missions)
+Planes flying missions other than air defense will be intercepted
+normally. (i.e. if you fly over enemy territory, you'll get
+intercepted.
.s1
-Planes of less than 40% efficiency will not fly missions.
-.s1
-Planes assigned to missions are \*QNOT\*U eligible to intercept
-normally. For example, if a fighter is assigned to an escort or air-defense
+Planes assigned to missions other than air defense are \*QNOT\*U
+eligible to intercept normally. For example, if a fighter is assigned
+to an escort
or interdiction or support mission, it will \*QNOT\*U rise to intercept
an intruding enemy plane. (planes on air-defense missions will intercept
planes flying in their op-area, in accordance with the air-defense mission,
Only planes with the 'escort' or 'intercept' abilities can fly escort missions.
.s1
AIR DEFENSE MISSIONS (planes only)
-When given an air defense mission, an intercept capable plane will attempt
-to intercept any enemy plane (defined as any plane belonging to a country
-you re at war with) flying into its operations area, irregardless
-of whether the enemy planes are flying over owned sectors. For example, if
-a plane is given an air defense mission with an op area covering some
-owned sectors, some sea, some allied sectors, and some enemy sectors, it
-would try to intercept over any of them.
-.s1
-When a plane enters a sector, any planes with air defense missions that are
-at war with the owner of the plane will fly there to fight it.
-The air defense planes
-encounter normal interception along the way (but do \*QNOT\*U trigger
-more air defense missions, but \*QMAY\*U be intercepted normally).
-Once the air defense planes get to the sector,
-they fight the plane. Then, if the owner of the sector
-is hostile to the plane, still more planes may intercept it.
+.s1
+Putting a plane on an air defense mission modifies where the plane
+intercepts. Without a mission, it intercepts over own sectors,
+surface ships and land units. With an air defense mission, it
+intercepts over any sector in its op area.
.s1
.L Example
Groonland wants to run a recon flight over Bannannarama. Joeland has a
It takes the shortest path there, and fights the Groonland plane.
Let's say that both take 20 points of damage, and neither aborts.
.s1
-Next, the Groonland plane overflies a Bannannarama sector. The Joeland
-plane flies there, and is intercepted by the Bannannarama plane. Let's
-say that it comes through the fight without being aborted. It then fights
-the Groonland plane. After this combat, if the Groonland plane is not
-aborted, it may be intercepted again by the busy Bannannarama fighter,
-assuming that that plane is still efficient enough, has mob enough, etc.
+Next, the Groonland plane overflies a Bannannarama sector. It gets
+intercepted by Joeland's fighter, because the sector is in its
+op-area, and by Bannannarama's fighter, because the sector belongs to
+Bannannarama. And so forth.
.s1
A good use of this mission is to provide a wider CAP around a carrier,
so that enemy planes get intercepted several times on the way to the
return RET_FAIL;
}
pln_arm(&esc_list, 2 * ap_to_target, mission, ip, P_F | P_ESC);
- ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0, 0);
+ ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
if (QEMPTY(&bomb_list)) {
pr("No planes got through fighter defenses\n");
} else if (target.sct_type == SCT_SANCT) {
return RET_FAIL;
}
pln_arm(&esc_list, 2 * ap_to_target, 'd', ip, P_ESC | P_F);
- ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0, 0);
+ ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
if (QEMPTY(&bomb_list)) {
pr("No planes got through fighter defenses\n");
} else {
return RET_FAIL;
}
pln_arm(&esc_list, ap_to_target, 't', ip, P_ESC | P_F);
- ac_encounter(&bomb_list, &esc_list, ax, ay,
- flightpath, 0, 0);
+ ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
if (QEMPTY(&bomb_list)) {
pr("No planes got through fighter defenses\n");
} else {
return RET_FAIL;
}
pln_arm(&esc_list, 2 * ap_to_target, 'a', &ichr[I_MILIT], P_ESC | P_F);
- ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0, 0);
+ ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, 0);
if (QEMPTY(&bomb_list)) {
pr("No planes got through fighter defenses\n");
} else {
}
pln_arm(&esc_list, ap_to_target, 'r', 0, P_F | P_ESC);
ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath,
- *player->argp[0] == 's' ? PM_R | PM_S : PM_R,
- 0);
+ *player->argp[0] == 's' ? PM_R | PM_S : PM_R);
if (QEMPTY(&bomb_list)) {
pr("No planes got through fighter defenses\n");
} else {
#include "land.h"
#include "map.h"
#include "misc.h"
+#include "mission.h"
#include "nat.h"
#include "news.h"
#include "nsc.h"
#define FLAK_GUN_MAX 14
static int plane_caps(struct emp_qelem *);
+static void sam_intercept(struct emp_qelem *, struct emp_qelem *,
+ natid, natid, coord, coord, int);
static void ac_intercept(struct emp_qelem *, struct emp_qelem *,
- struct emp_qelem *, natid, coord, coord);
+ struct emp_qelem *, natid, coord, coord, int);
+static void ac_combat_headers(natid, natid);
+static void ac_airtoair(struct emp_qelem *, struct emp_qelem *);
static void ac_dog(struct plist *, struct plist *);
static void ac_planedamage(struct plist *, natid, int, natid, int,
int, char *);
static void ac_landflak(struct emp_qelem *, coord, coord);
static void ac_shipflak(struct emp_qelem *, coord, coord);
static void ac_fireflak(struct emp_qelem *, natid, int);
-static void getilist(struct emp_qelem *, natid);
+static void getilists(struct emp_qelem *, unsigned char *, natid);
static int do_evade(struct emp_qelem *, struct emp_qelem *);
void
ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
- coord x, coord y, char *path, int mission_flags,
- int no_air_defense)
+ coord x, coord y, char *path, int mission_flags)
{
int val;
int dir;
unsigned char gotships[MAXNOC];
unsigned char gotlands[MAXNOC];
- int gotilist[MAXNOC];
unsigned char rel[MAXNOC];
int overfly[MAXNOC];
int flags;
plane_owner = plp->plane.pln_own;
memset(overfly, 0, sizeof(overfly));
- memset(gotilist, 0, sizeof(gotilist));
- for (cn = 0; cn < MAXNOC; cn++)
- rel[cn] = getrel(getnatp(cn), plane_owner);
+ getilists(ilist, rel, plane_owner);
if (mission_flags & PM_R) {
flags = plane_caps(bomb_list);
if (QEMPTY(bomb_list))
break;
- if (!no_air_defense)
- air_defense(x, y, plane_owner, bomb_list, esc_list);
-
for (cn = 1; cn < MAXNOC && !QEMPTY(bomb_list); cn++) {
if (rel[cn] > HOSTILE)
continue;
- if (cn != sect.sct_own && !gotships[cn] && !gotlands[cn])
- continue;
- if (!gotilist[cn]) {
- getilist(&ilist[cn], cn);
- gotilist[cn]++;
- }
- ac_intercept(bomb_list, esc_list, &ilist[cn], cn, x, y);
+ ac_intercept(bomb_list, esc_list, &ilist[cn], cn, x, y,
+ !(cn == sect.sct_own
+ || gotships[cn] || gotlands[cn]));
}
}
writemap(player->cnum);
free_shiplist(&head);
- for (cn = 1; cn < MAXNOC; cn++) {
- if (gotilist[cn])
- pln_put(&ilist[cn]);
- }
+ for (cn = 1; cn < MAXNOC; cn++)
+ pln_put(&ilist[cn]);
}
static int
return fl;
}
-void
+static void
sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
natid def_own, natid plane_owner, coord x, coord y,
- int delete_missiles)
+ int only_mission)
{
struct emp_qelem *aqp;
struct emp_qelem *anext;
struct emp_qelem *dnext;
struct plist *aplp;
struct plist *dplp;
+ struct plnstr *pp;
int first = 1;
for (aqp = att_list->q_forw,
for (; dqp != def_list; dqp = dnext) {
dnext = dqp->q_forw;
dplp = (struct plist *)dqp;
+ pp = &dplp->plane;
if (!(dplp->pcp->pl_flags & P_M))
continue;
-
- if (dplp->plane.pln_range <
- mapdist(x, y, dplp->plane.pln_x, dplp->plane.pln_y))
+ if (only_mission && !pp->pln_mission)
continue;
- if (CANT_HAPPEN(dplp->plane.pln_flags & PLN_LAUNCHED)
+ if (pp->pln_range < mapdist(x, y, pp->pln_x, pp->pln_y))
+ continue;
+ if (pp->pln_mission
+ && pp->pln_radius < mapdist(x, y, pp->pln_opx, pp->pln_opy))
+ continue;
+ if (CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED)
|| mission_pln_equip(dplp, 0, P_F, 0) < 0) {
emp_remque(dqp);
free(dqp);
continue;
}
- dplp->plane.pln_flags |= PLN_LAUNCHED;
- putplane(dplp->plane.pln_uid, &dplp->plane);
+ pp->pln_flags |= PLN_LAUNCHED;
+ putplane(pp->pln_uid, pp);
if (first) {
first = 0;
PR(plane_owner, "%s launches SAMs!\n", cname(def_own));
PR(plane_owner, "\n");
PR(def_own, "\n");
}
- if (delete_missiles) {
- for (; dqp != def_list; dqp = dnext) {
- dnext = dqp->q_forw;
- dplp = (struct plist *)dqp;
- if (!(dplp->pcp->pl_flags & P_M))
- continue;
- emp_remque(dqp);
- free(dqp);
- continue;
- }
- }
}
static void
ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
- struct emp_qelem *def_list, natid def_own, coord x, coord y)
+ struct emp_qelem *def_list, natid def_own, coord x, coord y,
+ int only_mission)
{
struct plnstr *pp;
struct plist *plp;
plp = (struct plist *)bomb_list->q_forw;
plane_owner = plp->plane.pln_own;
- sam_intercept(bomb_list, def_list, def_own, plane_owner, x, y, 0);
- sam_intercept(esc_list, def_list, def_own, plane_owner, x, y, 0);
+ sam_intercept(bomb_list, def_list, def_own, plane_owner, x, y,
+ only_mission);
+ sam_intercept(esc_list, def_list, def_own, plane_owner, x, y,
+ only_mission);
att_count = 0;
for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw)
/* SAMs interdict separately */
if (plp->pcp->pl_flags & P_M)
continue;
+ if (only_mission && !pp->pln_mission)
+ continue;
dist = mapdist(x, y, pp->pln_x, pp->pln_y) * 2;
if (pp->pln_range < dist)
continue;
+ if (pp->pln_mission
+ && pp->pln_radius < mapdist(x, y, pp->pln_opx, pp->pln_opy))
+ continue;
if (CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED)
|| mission_pln_equip(plp, 0, P_F, 0) < 0) {
emp_remque(qp);
}
/*
- * Get a list of planes available for interception duties.
+ * Get planes available for interception duties.
*/
static void
-getilist(struct emp_qelem *list, natid own)
+getilists(struct emp_qelem *list, unsigned char *rel, natid intruder)
{
+ natid cn;
struct plchrstr *pcp;
struct plnstr plane;
struct nstr_item ni;
struct plist *ip;
- emp_initque(list);
+ rel[0] = NEUTRAL;
+ for (cn = 1; cn < MAXNOC; cn++) {
+ rel[cn] = getrel(getnatp(cn), intruder);
+ emp_initque(&list[cn]);
+ }
+
snxtitem_all(&ni, EF_PLANE);
while (nxtitem(&ni, &plane)) {
- if (plane.pln_own != own)
+ if (rel[plane.pln_own] > HOSTILE)
continue;
pcp = &plchr[(int)plane.pln_type];
if ((pcp->pl_flags & P_F) == 0)
continue;
if (plane.pln_flags & PLN_LAUNCHED)
continue;
- if (plane.pln_mission != 0)
+ if (plane.pln_mission && plane.pln_mission != MI_AIR_DEFENSE)
continue;
if (plane.pln_mobil <= 0)
continue;
ip->misc = 0;
ip->pcp = &plchr[(int)plane.pln_type];
ip->plane = plane;
- emp_insque(&ip->queue, list);
+ emp_insque(&ip->queue, &list[plane.pln_own]);
}
}
xyas(x, y, air->own));
}
- ac_encounter(&b, &e, air->x, air->y, pp, 0, 0);
+ ac_encounter(&b, &e, air->x, air->y, pp, 0);
if (!QEMPTY(&b))
air_dam +=
return dam;
}
-
-/*
- * Check to see if anyone hostile to the victim
- * is running an air defense mission on this
- * sector. If so, do air combat
- */
-int
-air_defense(coord x, coord y, natid victim, struct emp_qelem *bomb_list,
- struct emp_qelem *esc_list)
-{
- int dam = 0, cn;
- int combat = 0, rel, dist, z;
- struct emp_qelem *qp, interceptors, airp, i, empty, *next;
- struct plist *plp;
- struct genlist *glp;
- struct empobj *gp;
- struct genlist mi[MAXNOC];
- char buf[512];
- char *path;
- int count;
- int tcount;
-
- count = 0;
- for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw)
- count++;
- for (qp = esc_list->q_forw; qp != esc_list; qp = qp->q_forw)
- count++;
-
- memset(mi, 0, sizeof(mi));
- for (z = 1; z < MAXNOC; z++)
- emp_initque((struct emp_qelem *)&mi[z]);
-
- build_mission_list_type(mi, x, y, MI_AIR_DEFENSE, EF_PLANE, victim);
-
- for (cn = 1; cn < MAXNOC; cn++) {
- /* Check our relations */
- rel = getrel(getnatp(cn), victim);
-
- if (rel > HOSTILE)
- continue;
-
- if (QEMPTY(&mi[cn].queue))
- continue;
-
- /* Ok, make a list of all the interceptors. Note that this *copies* the
- * list from the mission creation. This list must be deleted later. */
- 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 = 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 = glp->cp;
- memcpy(&plp->plane, glp->thing, sizeof(struct plnstr));
-
- /* missiles go one way, so we can use all the range */
- if (!(plp->pcp->pl_flags & P_M))
- dist *= 2;
- /* If it's out of range, free it and continue on */
- if (dist > plp->plane.pln_range) {
- free(plp);
- continue;
- }
- emp_insque(&plp->queue, &interceptors);
- }
-
- /* Remove those who cannot go */
- mission_pln_sel(&interceptors, P_F, 0, SECT_HARDTARGET);
-
- if (QEMPTY(&interceptors))
- continue;
-
- /* Now, delete all the extras, but delete the first ones, not the last ones, so
- * that the higher numbered planes go into battle (they should be the better ones
- * at fighting, if all went well.) */
- tcount = 0;
- for (qp = interceptors.q_forw; qp != (&interceptors);
- qp = qp->q_forw)
- tcount++;
- tcount -= count * 2;
- /* Just in case there are more incoming than we have */
- if (tcount < 0)
- tcount = 0;
- for (qp = interceptors.q_forw; qp != (&interceptors); qp = next) {
- next = qp->q_forw;
- if (tcount) {
- tcount--;
- /* Free it up and continue */
- emp_remque(qp);
- glp = (struct genlist *)qp;
- free(glp);
- }
- }
-
- /* Now, make a list of all the airports these planes are coming from */
- emp_initque(&airp);
- for (qp = interceptors.q_forw; qp != (&interceptors);
- qp = qp->q_forw) {
- plp = (struct plist *)qp;
- if (!find_airport(&airp, plp->plane.pln_x, plp->plane.pln_y))
- add_airport(&airp, plp->plane.pln_x, plp->plane.pln_y);
- }
-
- /* Now, fly them out one airport at a time */
- for (qp = airp.q_forw; qp != (&airp); qp = qp->q_forw) {
- struct airport *air;
-
- air = (struct airport *)qp;
- dist = mapdist(x, y, air->x, air->y);
-
- emp_initque(&i);
-
- /* Split off the interceptors at this base into i */
- divide(&interceptors, &i, air->x, air->y);
-
- sam_intercept(bomb_list, &i, cn, victim, x, y, 0);
- sam_intercept(esc_list, &i, cn, victim, x, y, 1);
-
- /* Did we run out of interceptors? */
- if (QEMPTY(&i))
- continue;
- /* Did we run out of bombers? */
- if (QEMPTY(bomb_list)) {
- /* Yes, so we have to put the rest of the interceptors back, and
- then continue, or we leak memory */
- pln_put(&i);
- continue;
- }
- mission_pln_arm(&i, air->x, air->y, 2 * dist, 0, 0, P_F);
-
- /* Did we run out of interceptors? */
- if (QEMPTY(&i))
- continue;
- /* Did we run out of bombers? */
- if (QEMPTY(bomb_list)) {
- /* Yes, so we have to put the rest of the interceptors back, and
- then continue, or we leak memory */
- pln_put(&i);
- continue;
- }
-
- 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 to %s\n",
- cname(cn), mission_name(MI_AIR_DEFENSE),
- 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, 0, 1);
-
- /* If none made it, continue */
- if (QEMPTY(&i))
- continue;
-
- /* Some made it, so now they get to try to fight. */
- /* Intercept the escorts first */
- combat = 0;
- if (!QEMPTY(esc_list)) {
- mpr(victim, "%s air defense planes intercept!\n",
- cname(cn));
- ac_combat_headers(victim, cn);
- ac_airtoair(esc_list, &i);
- combat = 1;
- }
- /* Now intercept the bombers */
- if (!QEMPTY(bomb_list)) {
- if (!combat) {
- mpr(victim, "%s air defense planes intercept!\n",
- cname(cn));
- ac_combat_headers(victim, cn);
- }
- ac_airtoair(bomb_list, &i);
- PR(cn, "\n");
- PR(victim, "\n");
- }
-
- 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
- lost and we leak memory all over the place. */
- for (cn = 1; cn < MAXNOC; cn++) {
- /* free up all this memory if it's still there */
- for (qp = mi[cn].queue.q_forw; qp != (&mi[cn].queue); qp = next) {
- next = qp->q_forw;
- glp = (struct genlist *)qp;
- free(glp->thing);
- free(glp);
- }
- }
-
- return dam;
-}