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
00036
00037 #include <config.h>
00038
00039 #include "file.h"
00040 #include "land.h"
00041 #include "map.h"
00042 #include "misc.h"
00043 #include "nat.h"
00044 #include "news.h"
00045 #include "nsc.h"
00046 #include "optlist.h"
00047 #include "path.h"
00048 #include "plane.h"
00049 #include "player.h"
00050 #include "prototypes.h"
00051 #include "sect.h"
00052 #include "ship.h"
00053 #include "xy.h"
00054
00055 #define FLAK_GUN_MAX 14
00056
00057 static void ac_intercept(struct emp_qelem *, struct emp_qelem *,
00058 struct emp_qelem *, natid, coord, coord);
00059 static int all_missiles(struct emp_qelem *);
00060 static void ac_dog(struct plist *, struct plist *);
00061 static void ac_planedamage(struct plist *, natid, int, natid, int,
00062 int, char *);
00063 static void ac_doflak(struct emp_qelem *, struct sctstr *);
00064 static void ac_landflak(struct emp_qelem *, coord, coord);
00065 static void ac_shipflak(struct emp_qelem *, coord, coord);
00066 static void ac_fireflak(struct emp_qelem *, natid, int);
00067 static void getilist(struct emp_qelem *, natid,
00068 struct emp_qelem *, struct emp_qelem *,
00069 struct emp_qelem *, struct emp_qelem *);
00070 static int do_evade(struct emp_qelem *, struct emp_qelem *);
00071
00072 void
00073 ac_encounter(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
00074 coord x, coord y, char *path, int mission_flags,
00075 int no_air_defense, struct emp_qelem *obomb,
00076 struct emp_qelem *oesc)
00077 {
00078 int val, non_missiles;
00079 int rel;
00080 int dir;
00081 int nats[MAXNOC];
00082 int lnats[MAXNOC];
00083 int gotilist[MAXNOC];
00084 int unfriendly[MAXNOC];
00085 int overfly[MAXNOC];
00086 struct emp_qelem ilist[MAXNOC], *qp;
00087 char mypath[1024];
00088 int myp;
00089 int civ, mil;
00090 natid plane_owner;
00091 struct sctstr sect;
00092 struct shpstr ship;
00093 struct lndstr land;
00094 struct nstr_item ni;
00095 natid cn;
00096 struct natstr *over, *mynatp;
00097 struct plist *plp;
00098 int evaded;
00099 struct shiplist *head = NULL;
00100 int changed = 0;
00101 int intown = 0;
00102
00103
00104
00105
00106 plp = (struct plist *)bomb_list->q_forw;
00107 plane_owner = plp->plane.pln_own;
00108
00109 strncpy(mypath, path, sizeof(mypath));
00110 myp = 0;
00111
00112 memset(overfly, 0, sizeof(overfly));
00113 memset(gotilist, 0, sizeof(gotilist));
00114 memset(unfriendly, 0, sizeof(unfriendly));
00115 for (cn = 1; cn < MAXNOC; cn++) {
00116 if ((mynatp = getnatp(cn)) == 0)
00117 continue;
00118 rel = getrel(mynatp, plane_owner);
00119 if (rel > HOSTILE)
00120 continue;
00121 if (plane_owner == cn)
00122 continue;
00123 unfriendly[cn]++;
00124 }
00125 if (mission_flags & PM_R) {
00126 if (mission_flags & P_S) {
00127 PR(plane_owner, "\nSPY Plane report\n");
00128 PRdate(plane_owner);
00129 sathead();
00130 } else if (mission_flags & P_A) {
00131 PR(plane_owner, "\nAnti-Sub Patrol report\n");
00132 } else {
00133 PR(plane_owner, "\nReconnaissance report\n");
00134 PRdate(plane_owner);
00135 }
00136 }
00137
00138 pln_removedupes(bomb_list, esc_list);
00139 while ((dir = mypath[myp++]) && !QEMPTY(bomb_list)) {
00140 if ((val = diridx(dir)) == DIR_STOP)
00141 break;
00142
00143 x = xnorm(x + diroff[val][0]);
00144 y = ynorm(y + diroff[val][1]);
00145 getsect(x, y, §);
00146 over = getnatp(sect.sct_own);
00147
00148 if (mission_flags & PM_R) {
00149 if (opt_HIDDEN)
00150 setcont(plane_owner, sect.sct_own, FOUND_FLY);
00151 if (sect.sct_type == SCT_WATER) {
00152 PR(plane_owner, "flying over %s at %s\n",
00153 dchr[sect.sct_type].d_name, xyas(x, y, plane_owner));
00154 if (mission_flags & PM_S)
00155 plane_sweep(bomb_list, x, y);
00156 if (mission_flags & P_A) {
00157 plane_sona(bomb_list, x, y, &head);
00158 }
00159 changed += map_set(plane_owner,
00160 sect.sct_x, sect.sct_y,
00161 dchr[sect.sct_type].d_mnem, 0);
00162 } else if (mission_flags & P_S) {
00163 satdisp_sect(§, (mission_flags & P_I) ? 10 : 50);
00164 } else {
00165
00166 if (sect.sct_own == plane_owner)
00167 PR(plane_owner, "Your ");
00168 else
00169 PR(plane_owner, "%s (#%d) ",
00170 cname(sect.sct_own), sect.sct_own);
00171 PR(plane_owner, "%s", dchr[sect.sct_type].d_name);
00172 changed += map_set(plane_owner,
00173 sect.sct_x, sect.sct_y,
00174 dchr[sect.sct_type].d_mnem, 0);
00175 PR(plane_owner, " %d%% efficient ",
00176 (sect.sct_own == plane_owner) ?
00177 sect.sct_effic : roundintby((int)sect.sct_effic, 25));
00178 civ = sect.sct_item[I_CIVIL];
00179 mil = sect.sct_item[I_MILIT];
00180 if (civ)
00181 PR(plane_owner, "with %s%d civ ",
00182 (sect.sct_own == plane_owner) ?
00183 "" : "approx ",
00184 (sect.sct_own == plane_owner) ?
00185 civ : roundintby(civ, 25));
00186 if (mil)
00187 PR(plane_owner, "with %s%d mil ",
00188 (sect.sct_own == plane_owner) ?
00189 "" : "approx ",
00190 (sect.sct_own == plane_owner) ?
00191 mil : roundintby(mil, 25));
00192 PR(plane_owner, "@ %s\n", xyas(x, y, plane_owner));
00193 }
00194 if (mission_flags & P_S)
00195 satdisp_units(sect.sct_x, sect.sct_y);
00196 } else {
00197 PR(plane_owner, "flying over %s at %s\n",
00198 dchr[sect.sct_type].d_name, xyas(x, y, plane_owner));
00199 changed += map_set(plane_owner, sect.sct_x, sect.sct_y,
00200 dchr[sect.sct_type].d_mnem, 0);
00201 }
00202 if ((rel = getrel(over, plane_owner)) == ALLIED)
00203 continue;
00204
00205 evaded = do_evade(bomb_list, esc_list);
00206
00207 if (sect.sct_own != 0 && sect.sct_own != plane_owner && !evaded) {
00208
00209
00210 overfly[sect.sct_own]++;
00211 PR(sect.sct_own, "%s planes spotted over %s\n",
00212 cname(plane_owner), xyas(x, y, sect.sct_own));
00213 if (opt_HIDDEN)
00214 setcont(cn, plane_owner, FOUND_FLY);
00215 }
00216
00217 if (!evaded) {
00218
00219 if (unfriendly[sect.sct_own])
00220 ac_doflak(bomb_list, §);
00221
00222 if (!QEMPTY(bomb_list))
00223 ac_landflak(bomb_list, x, y);
00224 if (!QEMPTY(bomb_list))
00225 ac_shipflak(bomb_list, x, y);
00226 }
00227
00228 if (QEMPTY(bomb_list))
00229 break;
00230 if (!no_air_defense && !evaded)
00231 air_defense(x, y, plane_owner, bomb_list, esc_list);
00232
00233 if (sect.sct_own == 0 || sect.sct_own == plane_owner)
00234 continue;
00235
00236 if (evaded)
00237 continue;
00238
00239 non_missiles = 0;
00240 for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw) {
00241 struct plist *ip = (struct plist *)qp;
00242 if (!(plchr[(int)ip->plane.pln_type].pl_flags & P_M))
00243 non_missiles = 1;
00244 }
00245
00246 if (!non_missiles)
00247 continue;
00248
00249 if (unfriendly[sect.sct_own] && !gotilist[sect.sct_own]) {
00250 getilist(&ilist[sect.sct_own], sect.sct_own,
00251 bomb_list, esc_list, obomb, oesc);
00252 gotilist[sect.sct_own]++;
00253 }
00254 if (rel > HOSTILE)
00255 continue;
00256 ac_intercept(bomb_list, esc_list, &ilist[sect.sct_own],
00257 sect.sct_own, x, y);
00258 intown = sect.sct_own;
00259 }
00260
00261
00262 for (cn = 1; cn < MAXNOC; cn++) {
00263 if (plane_owner == cn)
00264 continue;
00265 if (overfly[cn] > 0)
00266 nreport(plane_owner, N_OVFLY_SECT, cn, overfly[cn]);
00267 }
00268
00269 if (changed)
00270 writemap(player->cnum);
00271
00272 if (QEMPTY(bomb_list) && QEMPTY(esc_list)) {
00273 if (mission_flags & P_A)
00274 free_shiplist(&head);
00275 return;
00276 }
00277
00278
00279
00280 memset(nats, 0, sizeof(nats));
00281 snxtitem_xy(&ni, EF_SHIP, x, y);
00282 while (nxtitem(&ni, &ship)) {
00283 if (mchr[(int)ship.shp_type].m_flags & M_SUB)
00284 continue;
00285 nats[ship.shp_own]++;
00286 }
00287
00288 memset(lnats, 0, sizeof(lnats));
00289 snxtitem_xy(&ni, EF_LAND, x, y);
00290 while (nxtitem(&ni, &land)) {
00291 if (land.lnd_ship >= 0 || land.lnd_land >= 0)
00292 continue;
00293 lnats[land.lnd_own]++;
00294 }
00295
00296
00297 for (cn = 1; cn < MAXNOC && !QEMPTY(bomb_list); cn++) {
00298 if (plane_owner == cn)
00299 continue;
00300 intown = -1;
00301
00302 if (nats[cn] != 0) {
00303
00304 if (cn != 0) {
00305 PR(cn, "%s planes spotted over ships in %s\n",
00306 cname(plane_owner), xyas(x, y, cn));
00307 if (opt_HIDDEN)
00308 setcont(cn, plane_owner, FOUND_FLY);
00309 }
00310 if (unfriendly[cn]) {
00311
00312 if (!gotilist[cn]) {
00313 getilist(&ilist[cn], cn, bomb_list, esc_list, obomb,
00314 oesc);
00315 gotilist[cn]++;
00316 }
00317 PR(plane_owner, "Flying over %s ships in %s\n",
00318 cname(cn), xyas(x, y, plane_owner));
00319
00320 if (!evaded) {
00321
00322
00323 intown = 1;
00324
00325 ac_intercept(bomb_list, esc_list, &ilist[cn],
00326 cn, x, y);
00327 }
00328 }
00329 }
00330
00331 if (lnats[cn] != 0) {
00332
00333 if (cn != 0) {
00334 PR(cn, "%s planes spotted over land units in %s\n",
00335 cname(plane_owner), xyas(x, y, cn));
00336 if (opt_HIDDEN)
00337 setcont(cn, plane_owner, FOUND_FLY);
00338 }
00339 if (unfriendly[cn]) {
00340
00341 if (!gotilist[cn]) {
00342 getilist(&ilist[cn], cn, bomb_list, esc_list, obomb,
00343 oesc);
00344 gotilist[cn]++;
00345 }
00346 PR(plane_owner, "Flying over %s land units in %s\n",
00347 cname(cn), xyas(x, y, plane_owner));
00348 if (!evaded) {
00349 if (intown == -1) {
00350
00351 ac_intercept(bomb_list, esc_list, &ilist[cn],
00352 cn, x, y);
00353 }
00354 }
00355 }
00356 }
00357 }
00358 if (mission_flags & P_A)
00359 free_shiplist(&head);
00360 }
00361
00362 static int
00363 count_non_missiles(struct emp_qelem *list)
00364 {
00365 struct emp_qelem *qp;
00366 struct plist *plp;
00367 int att_count = 0;
00368
00369
00370 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
00371 plp = (struct plist *)qp;
00372 if (!(plp->pcp->pl_flags & P_M))
00373 att_count++;
00374 }
00375 return att_count;
00376 }
00377
00378 void
00379 sam_intercept(struct emp_qelem *att_list, struct emp_qelem *def_list,
00380 natid def_own, natid plane_owner, coord x, coord y,
00381 int delete_missiles)
00382 {
00383 struct emp_qelem *aqp;
00384 struct emp_qelem *anext;
00385 struct emp_qelem *dqp;
00386 struct emp_qelem *dnext;
00387 struct plist *aplp;
00388 struct plist *dplp;
00389 int first = 1;
00390
00391 for (aqp = att_list->q_forw,
00392 dqp = def_list->q_forw;
00393 aqp != att_list && dqp != def_list; aqp = anext) {
00394 anext = aqp->q_forw;
00395 aplp = (struct plist *)aqp;
00396 if (aplp->pcp->pl_flags & P_M)
00397 continue;
00398 if (aplp->pcp->pl_cost < 1000)
00399 continue;
00400 for (; dqp != def_list; dqp = dnext) {
00401 dnext = dqp->q_forw;
00402 dplp = (struct plist *)dqp;
00403 if (!(dplp->pcp->pl_flags & P_M))
00404 continue;
00405
00406 if (dplp->plane.pln_range <
00407 mapdist(x, y, dplp->plane.pln_x, dplp->plane.pln_y)) {
00408 emp_remque(dqp);
00409 free(dqp);
00410 continue;
00411 }
00412 if (mission_pln_equip(dplp, 0, P_F, 0) < 0) {
00413 emp_remque(dqp);
00414 free(dqp);
00415 continue;
00416 }
00417 if (first) {
00418 first = 0;
00419 PR(plane_owner, "%s launches SAMs!\n", cname(def_own));
00420 PR(def_own, "Launching SAMs at %s planes!\n",
00421 cname(plane_owner));
00422 ac_combat_headers(plane_owner, def_own);
00423 }
00424 ac_dog(aplp, dplp);
00425 dqp = dnext;
00426 break;
00427 }
00428 }
00429 if (!first) {
00430 PR(plane_owner, "\n");
00431 PR(def_own, "\n");
00432 }
00433 if (delete_missiles) {
00434 for (; dqp != def_list; dqp = dnext) {
00435 dnext = dqp->q_forw;
00436 dplp = (struct plist *)dqp;
00437 if (!(dplp->pcp->pl_flags & P_M))
00438 continue;
00439 emp_remque(dqp);
00440 free(dqp);
00441 continue;
00442 }
00443 }
00444 }
00445
00446 static void
00447 ac_intercept(struct emp_qelem *bomb_list, struct emp_qelem *esc_list,
00448 struct emp_qelem *def_list, natid def_own, coord x, coord y)
00449 {
00450 struct plnstr *pp;
00451 struct plist *plp;
00452 int icount;
00453 struct emp_qelem *next;
00454 struct emp_qelem *qp;
00455 struct emp_qelem int_list;
00456 int att_count;
00457 natid plane_owner;
00458 int dist;
00459
00460 plp = (struct plist *)bomb_list->q_forw;
00461 plane_owner = plp->plane.pln_own;
00462
00463 icount = 0;
00464
00465 sam_intercept(bomb_list, def_list, def_own, plane_owner, x, y, 0);
00466 sam_intercept(esc_list, def_list, def_own, plane_owner, x, y, 1);
00467 if (!(att_count = count_non_missiles(bomb_list) +
00468 count_non_missiles(esc_list)))
00469 return;
00470
00471 emp_initque(&int_list);
00472 for (qp = def_list->q_forw; qp != def_list; qp = next) {
00473 next = qp->q_forw;
00474 plp = (struct plist *)qp;
00475 pp = &plp->plane;
00476
00477 if (plp->pcp->pl_flags & P_M)
00478 continue;
00479 dist = mapdist(x, y, pp->pln_x, pp->pln_y) * 2;
00480 if (pp->pln_range < dist)
00481 continue;
00482 if (mission_pln_equip(plp, 0, P_F, 0) < 0) {
00483 emp_remque(qp);
00484 free(qp);
00485 continue;
00486 }
00487
00488 emp_remque(qp);
00489 emp_insque(qp, &int_list);
00490 pp->pln_mobil -= pln_mobcost(dist, pp, P_F);
00491 putplane(pp->pln_uid, pp);
00492 icount++;
00493 if (icount > att_count)
00494 break;
00495 }
00496 if (icount == 0)
00497 return;
00498 PR(plane_owner, "%d %s fighter%s rising to intercept!\n",
00499 icount, cname(def_own), icount == 1 ? " is" : "s are");
00500 PR(def_own, "%d fighter%s intercepting %s planes!\n",
00501 icount, icount == 1 ? " is" : "s are", cname(plane_owner));
00502 ac_combat_headers(plane_owner, def_own);
00503 ac_airtoair(esc_list, &int_list);
00504 ac_airtoair(bomb_list, &int_list);
00505 PR(plane_owner, "\n");
00506 PR(def_own, "\n");
00507 }
00508
00509 void
00510 ac_combat_headers(natid plane_owner, natid def_own)
00511 {
00512 PR(plane_owner,
00513 " %-10.10s %-10.10s strength int odds damage results\n",
00514 cname(plane_owner), cname(def_own));
00515 PR(def_own,
00516 " %-10.10s %-10.10s strength int odds damage results\n",
00517 cname(def_own), cname(plane_owner));
00518 }
00519
00520
00521
00522
00523 void
00524 ac_airtoair(struct emp_qelem *att_list, struct emp_qelem *int_list)
00525 {
00526 struct plist *attacker;
00527 struct plist *interceptor;
00528 struct emp_qelem *att;
00529 struct emp_qelem *in;
00530 int nplanes;
00531 int more_att;
00532 int more_int;
00533 struct emp_qelem *att_next;
00534 struct emp_qelem *in_next;
00535
00536 att = att_list->q_forw;
00537 in = int_list->q_forw;
00538 more_att = 1;
00539 more_int = 1;
00540 if (QEMPTY(att_list) || QEMPTY(int_list)) {
00541 more_att = 0;
00542 more_int = 0;
00543 }
00544 while (more_att || more_int) {
00545 in_next = in->q_forw;
00546 att_next = att->q_forw;
00547 attacker = (struct plist *)att;
00548
00549
00550 if (plchr[(int)attacker->plane.pln_type].pl_flags & P_M) {
00551 att = att_next;
00552 if (att == att_list) {
00553 more_att = 0;
00554 if (QEMPTY(att_list))
00555 more_int = 0;
00556 else
00557 att = att->q_forw;
00558 }
00559 if (all_missiles(att_list))
00560 more_att = 0;
00561 continue;
00562 }
00563 interceptor = (struct plist *)in;
00564 nplanes = attacker->plane.pln_effic;
00565 if (nplanes > interceptor->plane.pln_effic)
00566 nplanes = interceptor->plane.pln_effic;
00567 ac_dog(attacker, interceptor);
00568 in = in_next;
00569 att = att_next;
00570 if (att == att_list) {
00571 more_att = 0;
00572 if (QEMPTY(att_list))
00573 more_int = 0;
00574 else
00575 att = att->q_forw;
00576 }
00577 if (in == int_list) {
00578 more_int = 0;
00579 if (QEMPTY(int_list))
00580 more_att = 0;
00581 else
00582 in = in->q_forw;
00583 }
00584 }
00585 }
00586
00587 static int
00588 all_missiles(struct emp_qelem *att_list)
00589 {
00590 struct emp_qelem *qp;
00591 struct plist *p;
00592
00593 qp = att_list->q_forw;
00594 while (qp != att_list) {
00595 p = (struct plist *)qp;
00596 if (!(plchr[(int)p->plane.pln_type].pl_flags & P_M))
00597 return 0;
00598
00599 qp = qp->q_forw;
00600 }
00601 return 1;
00602 }
00603
00604 static void
00605 ac_dog(struct plist *ap, struct plist *dp)
00606 {
00607 int att, def;
00608 double odds;
00609 int intensity;
00610 natid att_own, def_own;
00611 int adam, ddam;
00612 char mesg[1024];
00613 char temp[14];
00614
00615 att_own = ap->plane.pln_own;
00616 def_own = dp->plane.pln_own;
00617
00618 PR(att_own, " %3.3s #%-4d %3.3s #%-4d",
00619 ap->pcp->pl_name,
00620 ap->plane.pln_uid, dp->pcp->pl_name, dp->plane.pln_uid);
00621 if (def_own)
00622 PR(def_own, " %3.3s #%-4d %3.3s #%-4d",
00623 dp->pcp->pl_name,
00624 dp->plane.pln_uid, ap->pcp->pl_name, ap->plane.pln_uid);
00625 if (ap->plane.pln_att == 0) {
00626 att = ap->plane.pln_def * ap->plane.pln_effic / 100;
00627 att = MAX(att, ap->pcp->pl_def / 2);
00628 } else {
00629 att = ap->plane.pln_att * ap->plane.pln_effic / 100;
00630 att = MAX(att, ap->pcp->pl_att / 2);
00631 }
00632
00633 def = dp->plane.pln_def * dp->plane.pln_effic / 100;
00634 def = MAX(def, dp->pcp->pl_def / 2);
00635
00636 if ((ap->pcp->pl_flags & P_F) && ap->bombs != 0)
00637 att -= 2;
00638 if ((dp->pcp->pl_flags & P_F) && dp->bombs != 0)
00639 def -= 2;
00640 att += ap->pcp->pl_stealth / 25.0;
00641 def += dp->pcp->pl_stealth / 25.0;
00642 if (att < 1) {
00643 def += 1 - att;
00644 att = 1;
00645 }
00646 if (def < 1) {
00647 att += 1 - def;
00648 def = 1;
00649 }
00650 odds = ((double)att / ((double)def + (double)att));
00651 if (odds <= 0.05)
00652 odds = 0.05;
00653 intensity = roll(20) + roll(20) + roll(20) + roll(20) + 1;
00654
00655 PR(att_own, " %3d/%-3d %3d %3.2f ", att, def, intensity, odds);
00656 PR(def_own, " %3d/%-3d %3d %3.2f ", def, att, intensity, odds);
00657
00658 adam = 0;
00659 ddam = 0;
00660 while ((intensity--) > 0) {
00661
00662 if (chance(odds)) {
00663 ddam += 1;
00664 if ((dp->plane.pln_effic - ddam) < PLANE_MINEFF)
00665 intensity = 0;
00666 } else {
00667 adam += 1;
00668 if ((ap->plane.pln_effic - adam) < PLANE_MINEFF)
00669 intensity = 0;
00670 }
00671 }
00672
00673 if (dp->pcp->pl_flags & P_M)
00674 ddam = 100;
00675
00676 PR(att_own, "%3d/%-3d", adam, ddam);
00677 PR(def_own, "%3d/%-3d", ddam, adam);
00678 ac_planedamage(ap, def_own, adam, def_own, 1, 0, mesg);
00679 strncpy(temp, mesg, 14);
00680 ac_planedamage(dp, att_own, ddam, att_own, 1, 0, mesg);
00681 PR(att_own, "%-13.13s %-13.13s\n", temp, mesg);
00682 PR(def_own, "%-13.13s %-13.13s\n", mesg, temp);
00683
00684 if (opt_HIDDEN) {
00685 setcont(att_own, def_own, FOUND_FLY);
00686 setcont(def_own, att_own, FOUND_FLY);
00687 }
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 static void
00703 ac_planedamage(struct plist *plp, natid from, int dam, natid other,
00704 int checkabort, int show, char *mesg)
00705 {
00706 struct plnstr *pp;
00707 int disp;
00708 char dmess[255];
00709 int eff;
00710 struct shpstr ship;
00711 struct lndstr land;
00712 natid plane_owner;
00713
00714 disp = 0;
00715 pp = &plp->plane;
00716 plane_owner = pp->pln_own;
00717 eff = pp->pln_effic;
00718 sprintf(dmess, " no damage");
00719 if (dam <= 0) {
00720 strcpy(mesg, dmess);
00721 return;
00722 }
00723 memset(dmess, 0, sizeof(dmess));
00724 eff -= dam;
00725 if (eff < 0)
00726 eff = 0;
00727 if (eff < PLANE_MINEFF) {
00728 sprintf(dmess, " shot down");
00729 disp = 1;
00730 } else if (eff < 80 && chance((80 - eff) / 100.0) && checkabort) {
00731 sprintf(dmess, " aborted @%2d%%", eff);
00732 disp = 2;
00733 } else if (show == 0) {
00734 sprintf(dmess, " cleared");
00735 }
00736
00737 if ((plp->pcp->pl_flags & P_M) == 0) {
00738 if (show) {
00739 PR(plane_owner, " %s %s takes %d%s.\n",
00740 cname(pp->pln_own), prplane(pp), dam, dmess);
00741 if (other)
00742 PR(other, " %s %s takes %d%s.\n",
00743 cname(pp->pln_own), prplane(pp), dam, dmess);
00744 }
00745 }
00746 if (show && checkabort == 1) {
00747 PR(plane_owner, "\n");
00748 if (other)
00749 PR(other, "\n");
00750 }
00751
00752 pp->pln_effic = eff;
00753 pp->pln_mobil -= MIN(32 + pp->pln_mobil, dam / 2);
00754 if (disp == 1) {
00755 if (from != 0 && (plp->pcp->pl_flags & P_M) == 0)
00756 nreport(from, N_DOWN_PLANE, pp->pln_own, 1);
00757 if (pp->pln_ship >= 0) {
00758 getship(pp->pln_ship, &ship);
00759 take_plane_off_ship(pp, &ship);
00760 }
00761 if (pp->pln_land >= 0) {
00762 getland(pp->pln_land, &land);
00763 take_plane_off_land(pp, &land);
00764 }
00765 pp->pln_effic = 0;
00766 putplane(pp->pln_uid, pp);
00767 emp_remque(&plp->queue);
00768 free(plp);
00769 } else if (disp == 2) {
00770 putplane(pp->pln_uid, pp);
00771 emp_remque(&plp->queue);
00772 free(plp);
00773 } else
00774 putplane(pp->pln_uid, pp);
00775 strcpy(mesg, dmess);
00776 }
00777
00778 static void
00779 ac_doflak(struct emp_qelem *list, struct sctstr *from)
00780 {
00781 int shell;
00782 int gun;
00783 natid plane_owner;
00784 struct plist *plp;
00785
00786 plp = (struct plist *)list->q_forw;
00787 plane_owner = plp->plane.pln_own;
00788
00789 gun = MIN(FLAK_GUN_MAX, from->sct_item[I_GUN]);
00790 shell = from->sct_item[I_SHELL];
00791 if (gun > shell * 2) {
00792 shell += supply_commod(from->sct_own, from->sct_x, from->sct_y,
00793 I_SHELL, (gun + 1) / 2 - shell);
00794 from->sct_item[I_SHELL] = shell;
00795 putsect(from);
00796 }
00797 if (gun > shell * 2)
00798 gun = shell * 2;
00799
00800 gun = roundavg(tfact(from->sct_own, 2.0 * gun));
00801 if (gun > 0) {
00802 PR(plane_owner, "firing %d flak guns in %s...\n",
00803 gun, xyas(from->sct_x, from->sct_y, plane_owner));
00804 if (from->sct_own != 0)
00805 PR(from->sct_own, "firing %d flak guns in %s...\n",
00806 gun, xyas(from->sct_x, from->sct_y, from->sct_own));
00807 ac_fireflak(list, from->sct_own, gun);
00808 }
00809 }
00810
00811 static void
00812 ac_shipflak(struct emp_qelem *list, coord x, coord y)
00813 {
00814 struct nstr_item ni;
00815 struct shpstr ship;
00816 struct mchrstr *mcp;
00817 double flak, total, ngun;
00818 int gun, shell;
00819 int rel;
00820 struct plist *plp;
00821 natid plane_owner;
00822 natid from;
00823 int nats[MAXNOC];
00824
00825 plp = (struct plist *)list->q_forw;
00826 plane_owner = plp->plane.pln_own;
00827
00828 memset(nats, 0, sizeof(nats));
00829 total = ngun = 0;
00830 snxtitem_xy(&ni, EF_SHIP, x, y);
00831 while (!QEMPTY(list) && nxtitem(&ni, &ship)) {
00832 if (ship.shp_own == 0 || ship.shp_own == plane_owner)
00833 continue;
00834 mcp = &mchr[(int)ship.shp_type];
00835 if (mcp->m_flags & M_SUB)
00836 continue;
00837 rel = getrel(getnatp(ship.shp_own), plane_owner);
00838 if (rel > HOSTILE)
00839 continue;
00840 shell = gun = 0;
00841 gun = MIN(ship.shp_item[I_GUN], ship.shp_glim);
00842 if (gun) {
00843 shell = ship.shp_item[I_SHELL];
00844 if (shell <= 0) {
00845 shell = supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
00846 I_SHELL, 1);
00847 ship.shp_item[I_SHELL] = shell;
00848 putship(ship.shp_uid, &ship);
00849 }
00850 }
00851 if (gun == 0 || shell == 0)
00852 continue;
00853 flak = gun * (ship.shp_effic / 100.0);
00854 ngun += flak;
00855 total += techfact(ship.shp_tech, flak * 2.0);
00856
00857 if (!nats[ship.shp_own]) {
00858
00859 PR(ship.shp_own, "%s planes spotted over ships in %s\n",
00860 cname(plane_owner), xyas(x, y, ship.shp_own));
00861 PR(plane_owner, "Flying over %s ships in %s\n",
00862 cname(ship.shp_own), xyas(x, y, plane_owner));
00863 nats[ship.shp_own] = 1;
00864 }
00865 PR(ship.shp_own, "firing %.0f flak guns from %s...\n",
00866 flak, prship(&ship));
00867 from = ship.shp_own;
00868 }
00869
00870
00871 if (ngun > FLAK_GUN_MAX)
00872 total *= FLAK_GUN_MAX / ngun;
00873
00874 gun = roundavg(total);
00875 if (gun > 0) {
00876 PR(plane_owner, "Flak! Ships firing %d flak guns...\n", gun);
00877 ac_fireflak(list, from, gun);
00878 }
00879 }
00880
00881 static void
00882 ac_landflak(struct emp_qelem *list, coord x, coord y)
00883 {
00884 struct nstr_item ni;
00885 struct lndstr land;
00886 struct lchrstr *lcp;
00887 double flak, total, ngun;
00888 int gun;
00889 int rel;
00890 struct plist *plp;
00891 natid plane_owner;
00892 natid from;
00893 int nats[MAXNOC];
00894
00895 plp = (struct plist *)list->q_forw;
00896 plane_owner = plp->plane.pln_own;
00897
00898 memset(nats, 0, sizeof(nats));
00899 total = ngun = 0;
00900 snxtitem_xy(&ni, EF_LAND, x, y);
00901 while (!QEMPTY(list) && nxtitem(&ni, &land)) {
00902 if (land.lnd_own == 0 || land.lnd_own == plane_owner)
00903 continue;
00904 lcp = &lchr[(int)land.lnd_type];
00905 if ((lcp->l_flags & L_FLAK) == 0 || land.lnd_aaf == 0)
00906 continue;
00907 if (land.lnd_ship >= 0 || land.lnd_land >= 0)
00908 continue;
00909 rel = getrel(getnatp(land.lnd_own), plane_owner);
00910 if (rel > HOSTILE)
00911 continue;
00912 flak = land.lnd_aaf * 1.5 * land.lnd_effic / 100.0;
00913 ngun += flak;
00914 total += techfact(land.lnd_tech, flak * 2.0);
00915
00916 if (!nats[land.lnd_own]) {
00917
00918 PR(land.lnd_own, "%s planes spotted over land units in %s\n",
00919 cname(plane_owner), xyas(x, y, land.lnd_own));
00920 PR(plane_owner, "Flying over %s land units in %s\n",
00921 cname(land.lnd_own), xyas(x, y, plane_owner));
00922 nats[land.lnd_own] = 1;
00923 }
00924 PR(land.lnd_own, "firing flak guns from unit %s (aa rating %d)\n",
00925 prland(&land), land.lnd_aaf);
00926 from = land.lnd_own;
00927 }
00928
00929
00930 if (ngun > FLAK_GUN_MAX)
00931 total *= FLAK_GUN_MAX / ngun;
00932
00933 gun = roundavg(total);
00934 if (gun > 0) {
00935 PR(plane_owner, "Flak! Land units firing %d flak guns...\n", gun);
00936 ac_fireflak(list, from, gun);
00937 }
00938 }
00939
00940
00941
00942
00943 static void
00944 ac_fireflak(struct emp_qelem *list, natid from, int guns)
00945 {
00946 struct plist *plp;
00947 int n;
00948 struct emp_qelem *qp;
00949 struct emp_qelem *next;
00950 char msg[255];
00951
00952 plp = (struct plist *)list->q_forw;
00953
00954 for (qp = list->q_forw; qp != list; qp = next) {
00955 next = qp->q_forw;
00956 plp = (struct plist *)qp;
00957 n = ac_flak_dam(guns, plp->plane.pln_def, plp->pcp->pl_flags);
00958 ac_planedamage(plp, from, n, 0, 2, 1, msg);
00959 }
00960 }
00961
00962
00963
00964
00965 int
00966 ac_flak_dam(int guns, int def, int pl_flags)
00967 {
00968 int flak, dam;
00969 float mult;
00970
00971 static float flaktable[18] = { 0.132f, 0.20f, 0.20f, 0.25f, 0.30f,
00972
00973 0.35f, 0.40f, 0.45f, 0.50f, 0.50f, 0.55f, 0.60f, 0.65f,
00974
00975 0.70f,0.75f, 0.80f, 0.85f, 1.1305f };
00976 enum { FLAK_MAX = sizeof(flaktable)/sizeof(flaktable[0]) - 1 };
00977
00978 flak = guns - def;
00979 if ((pl_flags & P_T) == 0)
00980 flak--;
00981 if (pl_flags & P_X)
00982 flak -= 2;
00983 if (pl_flags & P_H)
00984 flak -= 1;
00985
00986 if (flak > 8)
00987 mult = flaktable[FLAK_MAX];
00988 else if (flak < -7)
00989 mult = flaktable[0];
00990 else {
00991 flak += 8;
00992 mult = flaktable[flak];
00993 }
00994 mult *= flakscale;
00995 dam = (int)((roll(8) + 2) * mult);
00996 if (dam > 100)
00997 dam = 100;
00998 return dam;
00999 }
01000
01001
01002
01003
01004 int
01005 ac_isflying(struct plnstr *plane, struct emp_qelem *list)
01006 {
01007 struct emp_qelem *qp;
01008 struct emp_qelem *next;
01009 struct plnstr *pp;
01010 struct plist *plp;
01011
01012 if (!list)
01013 return 0;
01014 for (qp = list->q_forw; qp != list; qp = next) {
01015 next = qp->q_forw;
01016 plp = (struct plist *)qp;
01017 pp = &plp->plane;
01018 if (plane->pln_uid == pp->pln_uid)
01019 return 1;
01020 }
01021 return 0;
01022 }
01023
01024
01025
01026
01027
01028 static void
01029 getilist(struct emp_qelem *list, natid own, struct emp_qelem *a,
01030 struct emp_qelem *b, struct emp_qelem *c, struct emp_qelem *d)
01031 {
01032 struct plchrstr *pcp;
01033 struct plnstr plane;
01034 struct nstr_item ni;
01035 struct plist *ip;
01036
01037 emp_initque(list);
01038 snxtitem_all(&ni, EF_PLANE);
01039 while (nxtitem(&ni, &plane)) {
01040 if (plane.pln_own != own)
01041 continue;
01042 pcp = &plchr[(int)plane.pln_type];
01043 if ((pcp->pl_flags & P_F) == 0)
01044 continue;
01045 if (plane.pln_mission != 0)
01046 continue;
01047 if (plane.pln_mobil <= 0)
01048 continue;
01049 if (plane.pln_effic < 40)
01050 continue;
01051 if (!pln_airbase_ok(&plane, 0, 0))
01052 continue;
01053
01054
01055 if (ac_isflying(&plane, a))
01056 continue;
01057 if (ac_isflying(&plane, b))
01058 continue;
01059 if (ac_isflying(&plane, c))
01060 continue;
01061 if (ac_isflying(&plane, d))
01062 continue;
01063
01064 ip = malloc(sizeof(*ip));
01065 ip->bombs = 0;
01066 ip->misc = 0;
01067 ip->pcp = &plchr[(int)plane.pln_type];
01068 ip->plane = plane;
01069 emp_insque(&ip->queue, list);
01070 }
01071 }
01072
01073 static int
01074 do_evade(struct emp_qelem *bomb_list, struct emp_qelem *esc_list)
01075 {
01076 struct emp_qelem *qp;
01077 double evade;
01078 struct plist *plp;
01079
01080 evade = 100.0;
01081 for (qp = bomb_list->q_forw; qp != bomb_list; qp = qp->q_forw) {
01082 plp = (struct plist *)qp;
01083 if (evade > plp->pcp->pl_stealth / 100.0)
01084 evade = plp->pcp->pl_stealth / 100.0;
01085 }
01086 for (qp = esc_list->q_forw; qp != esc_list; qp = qp->q_forw) {
01087 plp = (struct plist *)qp;
01088 if (evade > plp->pcp->pl_stealth / 100.0)
01089 evade = plp->pcp->pl_stealth / 100.0;
01090 }
01091
01092 if (chance(evade))
01093 return 1;
01094
01095 return 0;
01096 }