/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
- * Ken Stevens, Steve McClure
+ * Copyright (C) 1986-2021, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Ken Stevens, Steve McClure, Markus Armbruster
*
- * This program is free software; you can redistribute it and/or modify
+ * Empire is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ---
*
* Known contributors to this file:
* Ken Stevens, 1995
* Steve McClure, 1996-2000
+ * Markus Armbruster, 2004-2021
*/
#include <config.h>
#include <stdlib.h>
-#include "file.h"
-#include "land.h"
+#include "chance.h"
#include "misc.h"
-#include "mission.h"
#include "nat.h"
#include "news.h"
#include "nsc.h"
#include "nuke.h"
#include "optlist.h"
-#include "path.h"
+#include "plague.h"
#include "plane.h"
-#include "player.h"
#include "prototypes.h"
#include "queue.h"
#include "sect.h"
#include "xy.h"
int
-msl_hit(struct plnstr *pp, int hardtarget, int type, int news_item,
- int snews_item, char *what, coord x, coord y, int victim)
+msl_launch(struct plnstr *pp, int type, char *what, coord x, coord y,
+ natid victim, int *sublaunchp)
{
- int hit;
struct shpstr ship;
- struct sctstr sect;
+ struct nukstr nuke;
int sublaunch = 0;
- struct plchrstr *pcp = plchr + pp->pln_type;
- int hitchance;
- char *from;
- int dam;
+ char *base, *in_or_at, *from;
mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
prplane(pp),
cname(victim),
what,
- (type == EF_SHIP || type == EF_PLANE) ? "in " : "",
+ type != EF_SECTOR ? "in " : "",
xyas(x, y, pp->pln_own));
- mpr(pp->pln_own, "\tLaunching from ");
if (pp->pln_ship >= 0) {
getship(pp->pln_ship, &ship);
- mpr(pp->pln_own, "%s in ", prship(&ship));
+ base = prship(&ship);
+ in_or_at = " in ";
if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
sublaunch = 1;
from = "in hatch";
} else
from = "on deck";
- mpr(pp->pln_own, "%s\n",
- xyas(ship.shp_x, ship.shp_y, pp->pln_own));
} else {
if (pp->pln_harden > 0) {
- mpr(pp->pln_own, "missile silo at ");
+ base = "missile silo";
+ in_or_at = " at ";
from = "in silo";
- } else
+ } else {
+ base = in_or_at = "";
from = "on launch pad";
- mpr(pp->pln_own, "%s\n", xyas(pp->pln_x, pp->pln_y, pp->pln_own));
+ }
}
+ mpr(pp->pln_own, "\tLaunching from %s%s%s\n",
+ base, in_or_at, xyas(pp->pln_x, pp->pln_y, pp->pln_own));
+
+ CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED);
+ pp->pln_flags |= PLN_LAUNCHED;
+ putplane(pp->pln_uid, pp);
if (chance((0.05 + (100 - pp->pln_effic) / 100.0)
* (1 - techfact(pp->pln_tech, 1.0)))) {
mpr(pp->pln_own, "KABOOOOM! Missile explodes %s!\n", from);
+ if (getnuke(nuk_on_plane(pp), &nuke)) {
+ mpr(pp->pln_own, "%s lost!\n", prnuke(&nuke));
+ nuke.nuk_effic = 0;
+ putnuke(nuke.nuk_uid, &nuke);
+ }
+#if 0
+ /*
+ * Disabled for now, because it breaks callers that call
+ * msl_launch() for each member of a list of planes, created
+ * by msl_sel() or perform_mission(). Damage to the base can
+ * damage other planes. Any copies of them in the list become
+ * stale. When msl_launch() modifies and writes back such a
+ * stale copy, the damage gets wiped out, triggering a seqno
+ * oops.
+ */
if (chance(0.33)) {
- dam = pln_damage(pp, 'p', 1) / 2;
+ struct sctstr sect;
+ int dam;
+
+ dam = pln_damage(pp, 'p', NULL) / 2;
if (pp->pln_ship >= 0) {
shipdamage(&ship, dam);
putship(ship.shp_uid, &ship);
} else {
- pr("Explosion damages %s %d%%",
- xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
+ mpr(pp->pln_own, "Explosion damages %s %d%%\n",
+ xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
getsect(pp->pln_x, pp->pln_y, §);
sectdamage(§, dam);
putsect(§);
}
}
- return 0;
+#endif
+ return -1;
}
- CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED);
- pp->pln_flags |= PLN_LAUNCHED;
- putplane(pp->pln_uid, pp);
mpr(pp->pln_own, "\tSHWOOOOOSH! Missile launched!\n");
- if (pcp->pl_flags & P_T)
+ if (type != EF_PLANE)
mpr(victim, "Incoming %s missile sighted at %s...\n",
sublaunch ? "sub-launched" : cname(pp->pln_own),
xyas(x, y, victim));
- if ((pcp->pl_flags & P_T && !(pcp->pl_flags & P_MAR))) {
+ if (type == EF_SECTOR || type == EF_LAND) {
if (msl_abm_intercept(pp, x, y, sublaunch))
- return 0;
+ return -1;
}
- if (pcp->pl_flags & P_MAR) {
+ if (type == EF_SHIP) {
if (shp_missile_defense(x, y, pp->pln_own, pln_def(pp))) {
- return 0;
+ return -1;
}
}
+ if (sublaunchp)
+ *sublaunchp = sublaunch;
+ return 0;
+}
+
+int
+msl_hit(struct plnstr *pp, int hardtarget, int type,
+ int news_item, int snews_item, int sublaunch, natid victim)
+{
+ int hitchance, hit;
+
if (nuk_on_plane(pp) >= 0) {
mpr(pp->pln_own, "\tArming nuclear warheads...\n");
hit = 1;
} else {
hitchance = pln_hitchance(pp, hardtarget, type);
- hit = (roll(100) <= hitchance);
- mpr(pp->pln_own, "\t%d%% hitchance...%s\n", hitchance,
+ hit = pct_chance(hitchance);
+ mpr(pp->pln_own, "\t%d%% hit chance...%s\n", hitchance,
hit ? "HIT!" : "miss");
}
- if (pcp->pl_flags & P_T)
+ if (type != EF_PLANE)
mpr(victim, "...Incoming %s missile %s\n",
sublaunch ? "" : cname(pp->pln_own),
hit ? "HIT!\n" : "missed\n");
if (mission &&
plane.pln_radius < mapdist(x, y, plane.pln_opx, plane.pln_opy))
continue;
- if (getrel(getnatp(plane.pln_own), victim) >= NEUTRAL)
+ if (relations_with(plane.pln_own, victim) >= NEUTRAL)
continue;
/* missiles go one way, so we can use all the range */
if (plane.pln_range < mapdist(x, y, plane.pln_x, plane.pln_y))
continue;
if (plane.pln_effic < 100)
continue;
+ if (opt_MARKET) {
+ if (ontradingblock(EF_PLANE, &plane))
+ continue;
+ }
if (!pln_airbase_ok(&plane, 1, 0))
continue;
/* got a valid interceptor */
irv = malloc(sizeof(*irv));
irv->load = 0;
+ irv->pstage = PLG_HEALTHY;
irv->pcp = &plchr[(int)plane.pln_type];
irv->plane = plane;
emp_insque(&irv->queue, list);
int news_item)
{
struct plnstr *pp;
- struct plchrstr *pcp;
struct emp_qelem *intlist;
struct emp_qelem intfoo;
struct emp_qelem *qp;
pp = &ip->plane;
if (pp->pln_own != sp->sct_own)
continue;
- pcp = ip->pcp;
- if (mission_pln_equip(ip, NULL, 'i') < 0) {
+ if (mission_pln_equip(ip, NULL, 0) < 0) {
emp_remque(qp);
free(qp);
continue;
next = qp->q_forw;
ip = (struct plist *)qp;
pp = &ip->plane;
- pcp = ip->pcp;
- if (mission_pln_equip(ip, NULL, 'i') < 0) {
+ if (mission_pln_equip(ip, NULL, 0) < 0) {
emp_remque(qp);
free(qp);
continue;
qp = intlist->q_forw;
ip = (struct plist *)qp;
pp = &ip->plane;
- pcp = ip->pcp;
mpr(msl->pln_own, "%s %s launched in defense!\n",
cname(pp->pln_own), def_name);
def_name, who, att_name, cname(sp->sct_own));
}
- if (msl_hit(pp, pln_def(msl), EF_PLANE, news_item, news_item,
- att_name, sp->sct_x, sp->sct_y, msl->pln_own)) {
+ if (msl_launch(pp, EF_PLANE, att_name, sp->sct_x, sp->sct_y,
+ msl->pln_own, NULL) >= 0
+ && msl_hit(pp, pln_def(msl), EF_PLANE, 0, 0, 0, msl->pln_own)) {
mpr(msl->pln_own, "%s destroyed by %s %s!\n",
att_name, cname(pp->pln_own), def_name);
mpr(sp->sct_own, "%s %s intercepted!\n", who, att_name);
if (sp->sct_own != pp->pln_own)
mpr(pp->pln_own, "%s %s intercepted!\n", who, att_name);
+ if (sublaunch)
+ nreport(pp->pln_own, news_item, 0, 1);
+ else
+ nreport(pp->pln_own, news_item, msl->pln_own, 1);
destroyed = 1;
}
/* zap the missile */