00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <config.h>
00036
00037 #include <stdlib.h>
00038 #include "file.h"
00039 #include "land.h"
00040 #include "misc.h"
00041 #include "mission.h"
00042 #include "nat.h"
00043 #include "news.h"
00044 #include "nsc.h"
00045 #include "optlist.h"
00046 #include "path.h"
00047 #include "plane.h"
00048 #include "player.h"
00049 #include "prototypes.h"
00050 #include "queue.h"
00051 #include "sect.h"
00052 #include "ship.h"
00053 #include "xy.h"
00054
00055 int
00056 msl_equip(struct plnstr *pp)
00057 {
00058 struct plist pl;
00059
00060 memset(&pl, 0, sizeof(struct plist));
00061 pl.pcp = plchr + pp->pln_type;
00062 pl.plane = *pp;
00063 return mission_pln_equip(&pl, 0, 0, 'p');
00064 }
00065
00066 int
00067 msl_hit(struct plnstr *pp, int hardtarget, int type, int news_item,
00068 int snews_item, char *what, coord x, coord y, int victim)
00069 {
00070 int hit;
00071 struct shpstr ship;
00072 struct sctstr sect;
00073 int sublaunch = 0;
00074 struct plchrstr *pcp = plchr + pp->pln_type;
00075 int hitchance = pln_hitchance(pp, hardtarget, type);
00076 char *from;
00077 int dam, dummyi;
00078
00079 mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
00080 prplane(pp),
00081 cname(victim),
00082 what,
00083 (type == EF_SHIP || type == EF_PLANE) ? "in " : "",
00084 xyas(x, y, pp->pln_own));
00085 mpr(pp->pln_own, "\tLaunching from ");
00086 if (pp->pln_ship >= 0) {
00087 getship(pp->pln_ship, &ship);
00088 mpr(pp->pln_own, "%s in ", prship(&ship));
00089 if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
00090 sublaunch = 1;
00091 from = "in hatch";
00092 } else
00093 from = "on deck";
00094 mpr(pp->pln_own, "%s\n",
00095 xyas(ship.shp_x, ship.shp_y, pp->pln_own));
00096 } else {
00097 if (pp->pln_harden > 0) {
00098 mpr(pp->pln_own, "missile silo at ");
00099 from = "in silo";
00100 } else
00101 from = "on launch pad";
00102 mpr(pp->pln_own, "%s\n", xyas(pp->pln_x, pp->pln_y, pp->pln_own));
00103 }
00104
00105 if (chance((0.05 + (100 - pp->pln_effic) / 100.0)
00106 * (1 - techfact(pp->pln_tech, 1.0)))) {
00107 mpr(pp->pln_own, "KABOOOOM! Missile explodes %s!\n", from);
00108 if (chance(0.33)) {
00109 dam = pln_damage(pp, pp->pln_x, pp->pln_y,
00110 'p', &dummyi, 1) / 2;
00111 if (dam) {
00112 if (pp->pln_ship >= 0) {
00113 shipdamage(&ship, dam);
00114 putship(ship.shp_uid, &ship);
00115 } else {
00116 pr("Explosion damages %s %d%%",
00117 xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
00118 getsect(pp->pln_x, pp->pln_y, §);
00119 sectdamage(§, dam, 0);
00120 putsect(§);
00121 }
00122 }
00123 }
00124 return 0;
00125 }
00126
00127 mpr(pp->pln_own, "\tSHWOOOOOSH! Missile launched!\n");
00128
00129 if (pp->pln_nuketype != -1)
00130 mpr(pp->pln_own, "\tArming nuclear warheads...\n");
00131
00132 if (pcp->pl_flags & P_T)
00133 mpr(victim, "Incoming %s missile sighted at %s...\n",
00134 sublaunch ? "sub-launched" : cname(pp->pln_own),
00135 xyas(x, y, victim));
00136
00137 if (opt_PINPOINTMISSILE == 0 ||
00138 (pcp->pl_flags & P_T && !(pcp->pl_flags & P_MAR))) {
00139 if (msl_intercept(x, y, pp->pln_own, pcp->pl_def,
00140 sublaunch, P_N, P_O)) {
00141 return 0;
00142 }
00143 }
00144 if (pcp->pl_flags & P_MAR) {
00145 if (shp_missile_defense(x, y, pp->pln_own, pcp->pl_def)) {
00146 return 0;
00147 }
00148 }
00149
00150 if (pp->pln_nuketype != -1)
00151 hitchance = 100;
00152
00153 mpr(pp->pln_own, "\t%d%% hitchance...", hitchance);
00154 hit = (roll(100) <= hitchance);
00155
00156 mpr(pp->pln_own, hit ? "HIT!\n" : "miss\n");
00157 if (pcp->pl_flags & P_T)
00158 mpr(victim, "...Incoming %s missile %s\n",
00159 sublaunch ? "" : cname(pp->pln_own),
00160 hit ? "HIT!\n" : "missed\n");
00161 if (hit && news_item) {
00162 if (sublaunch)
00163 nreport(victim, snews_item, 0, 1);
00164 else
00165 nreport(pp->pln_own, news_item, victim, 1);
00166 }
00167 return hit;
00168 }
00169
00170 void
00171 msl_sel(struct emp_qelem *list, coord x, coord y, natid victim,
00172 int wantflags, int nowantflags, int mission)
00173 {
00174 struct plchrstr *pcp;
00175 struct plnstr plane;
00176 struct plist *irv;
00177 struct nstr_item ni;
00178
00179 emp_initque(list);
00180 snxtitem_all(&ni, EF_PLANE);
00181 while (nxtitem(&ni, &plane)) {
00182 if (!plane.pln_own)
00183 continue;
00184
00185 pcp = &plchr[(int)plane.pln_type];
00186 if (!(pcp->pl_flags & P_M))
00187 continue;
00188 if (wantflags && (pcp->pl_flags & wantflags) != wantflags)
00189 continue;
00190 if (nowantflags && pcp->pl_flags & nowantflags)
00191 continue;
00192 if (mission && plane.pln_mission != mission)
00193 continue;
00194 if (getrel(getnatp(plane.pln_own), victim) >= NEUTRAL)
00195 continue;
00196
00197 if (plane.pln_range < mapdist(x, y, plane.pln_x, plane.pln_y))
00198 continue;
00199 if (plane.pln_mobil <= 0)
00200 continue;
00201 if (plane.pln_effic < 100)
00202 continue;
00203
00204 irv = malloc(sizeof(*irv));
00205 irv->bombs = 0;
00206 irv->misc = 0;
00207 irv->pcp = &plchr[(int)plane.pln_type];
00208 irv->plane = plane;
00209 emp_insque(&irv->queue, list);
00210 }
00211 }
00212
00213 int
00214 msl_intercept(coord x, coord y, natid bombown, int hardtarget,
00215 int sublaunch, int wantflags, int nowantflags)
00216 {
00217 struct plnstr *pp;
00218 struct plchrstr *pcp;
00219 struct sctstr sect;
00220 struct emp_qelem *irvlist;
00221 struct emp_qelem foo;
00222 struct emp_qelem *intlist;
00223 struct emp_qelem intfoo;
00224 struct emp_qelem *qp;
00225 struct emp_qelem *next;
00226 struct plist *ip;
00227 int icount = 0;
00228 short destroyed = 0;
00229 char *att_name;
00230 char *def_name;
00231 int news_item;
00232 char *who = sublaunch ? "" : cname(bombown);
00233
00234 getsect(x, y, §);
00235 if (wantflags == P_O && !nowantflags) {
00236 att_name = "satellite";
00237 def_name = "a-sat missile";
00238 news_item = N_SAT_KILL;
00239 if (sect.sct_own) {
00240 mpr(sect.sct_own, "%s has positioned a satellite over %s\n",
00241 sublaunch ? "someone" : cname(bombown),
00242 xyas(x, y, sect.sct_own));
00243 }
00244 } else if (wantflags == P_N && nowantflags == P_O) {
00245 att_name = "warhead";
00246 def_name = "abm";
00247 news_item = sublaunch ? N_NUKE_SSTOP : N_NUKE_STOP;
00248 } else {
00249 att_name = "elephant";
00250 def_name = "tomato";
00251 news_item = N_NUKE_STOP;
00252 }
00253 irvlist = &foo;
00254
00255
00256 msl_sel(irvlist, x, y, bombown, wantflags, nowantflags, 0);
00257 intlist = &intfoo;
00258 emp_initque(intlist);
00259
00260
00261 for (qp = irvlist->q_forw; qp != irvlist && icount < 2; qp = next) {
00262 next = qp->q_forw;
00263 ip = (struct plist *)qp;
00264 pp = &ip->plane;
00265 if (pp->pln_own != sect.sct_own)
00266 continue;
00267 pcp = ip->pcp;
00268 if (mission_pln_equip(ip, 0, 0, 'i') < 0) {
00269 emp_remque(qp);
00270 free(qp);
00271 continue;
00272 }
00273
00274
00275
00276 emp_remque(qp);
00277 emp_insque(qp, intlist);
00278 putplane(pp->pln_uid, pp);
00279 icount++;
00280 }
00281
00282 for (qp = irvlist->q_forw; qp != irvlist && icount < 2; qp = next) {
00283 next = qp->q_forw;
00284 ip = (struct plist *)qp;
00285 pp = &ip->plane;
00286 pcp = ip->pcp;
00287 if (mission_pln_equip(ip, 0, 0, 'i') < 0) {
00288 emp_remque(qp);
00289 free(qp);
00290 continue;
00291 }
00292
00293
00294
00295 emp_remque(qp);
00296 emp_insque(qp, intlist);
00297 putplane(pp->pln_uid, pp);
00298 icount++;
00299 }
00300
00301 while (!QEMPTY(irvlist)) {
00302 qp = irvlist->q_forw;
00303 emp_remque(qp);
00304 free(qp);
00305 }
00306 if (icount == 0) {
00307 if (sect.sct_own != 0)
00308 mpr(sect.sct_own, "No %ss launched to intercept.\n", def_name);
00309 return destroyed;
00310 }
00311
00312
00313
00314 while (!QEMPTY(intlist)) {
00315 qp = intlist->q_forw;
00316 ip = (struct plist *)qp;
00317 pp = &ip->plane;
00318 pcp = ip->pcp;
00319
00320 mpr(bombown, "%s %s launched in defense!\n",
00321 cname(pp->pln_own), def_name);
00322 if (sect.sct_own == pp->pln_own) {
00323 mpr(sect.sct_own, "%s launched to intercept %s %s!\n",
00324 def_name, who, att_name);
00325 } else {
00326 if (sect.sct_own)
00327 mpr(sect.sct_own,
00328 "%s launched an %s to intercept the %s %s!\n",
00329 cname(pp->pln_own), def_name, who, att_name);
00330 mpr(pp->pln_own,
00331 "%s launched to intercept %s %s arcing towards %s territory!\n",
00332 def_name, who, att_name, cname(sect.sct_own));
00333 }
00334
00335 if (!destroyed &&
00336 msl_hit(pp, hardtarget, EF_PLANE, news_item, news_item,
00337 att_name, x, y, bombown)) {
00338 mpr(bombown, "%s destroyed by %s %s!\n",
00339 att_name, cname(pp->pln_own), def_name);
00340 if (sect.sct_own)
00341 mpr(sect.sct_own, "%s %s intercepted!\n", who, att_name);
00342 if (sect.sct_own != pp->pln_own)
00343 mpr(pp->pln_own, "%s %s intercepted!\n", who, att_name);
00344 destroyed = 1;
00345 }
00346
00347 pp->pln_effic = 0;
00348 putplane(pp->pln_uid, pp);
00349 emp_remque(qp);
00350 free(qp);
00351 if (destroyed)
00352 break;
00353 }
00354
00355 while (!QEMPTY(intlist)) {
00356 qp = intlist->q_forw;
00357 emp_remque(qp);
00358 free(qp);
00359 }
00360 if (destroyed)
00361 return destroyed;
00362 if (icount) {
00363 mpr(bombown, "%s made it through %s defenses!\n",
00364 att_name, def_name);
00365 if (sect.sct_own)
00366 mpr(sect.sct_own, "%s made it through %s defenses!\n",
00367 att_name, def_name);
00368 }
00369 return destroyed;
00370 }
00371
00372
00373 int
00374 msl_launch_mindam(struct emp_qelem *list, coord x, coord y, int hardtarget,
00375 int type, int mindam, char *whatp, int victim,
00376 int mission)
00377 {
00378 struct emp_qelem *qp;
00379 struct emp_qelem *next;
00380 struct plist *plp;
00381 int newdam, dam = 0;
00382 int nukedam = 0;
00383 int news_item;
00384 int snews_item;
00385
00386 if (type == EF_SHIP) {
00387 news_item = N_SHP_MISS;
00388 snews_item = N_SHP_SMISS;
00389 } else if (type == EF_LAND) {
00390 news_item = N_LND_MISS;
00391 snews_item = N_LND_SMISS;
00392 } else {
00393 news_item = N_SCT_MISS;
00394 snews_item = N_SCT_SMISS;
00395 }
00396
00397 for (qp = list->q_back; qp != list && dam < mindam && !nukedam;
00398 qp = next) {
00399 next = qp->q_back;
00400 plp = (struct plist *)qp;
00401
00402 if (mission_pln_equip(plp, 0, 0, 'p') >= 0) {
00403 if (msl_hit(&plp->plane,
00404 hardtarget, type, news_item, snews_item,
00405 whatp, x, y, victim)) {
00406 newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 1);
00407 if (nukedam) {
00408 if (mission == MI_INTERDICT && type == EF_SECTOR)
00409 dam += nukedam;
00410 } else
00411 dam += newdam;
00412 } else {
00413
00414 newdam = pln_damage(&plp->plane, x, y, 'p', &nukedam, 0);
00415 collateral_damage(x, y, newdam, 0);
00416 }
00417 plp->plane.pln_effic = 0;
00418 putplane(plp->plane.pln_uid, &plp->plane);
00419 emp_remque(qp);
00420 free(qp);
00421 }
00422 }
00423 return dam;
00424 }