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 #include <config.h>
00037
00038 #include <ctype.h>
00039 #include "commands.h"
00040 #include "damage.h"
00041 #include "item.h"
00042 #include "land.h"
00043 #include "news.h"
00044 #include "optlist.h"
00045 #include "path.h"
00046 #include "plane.h"
00047 #include "retreat.h"
00048 #include "ship.h"
00049
00050 static void pin_bomb(struct emp_qelem *list, struct sctstr *target);
00051 static void strat_bomb(struct emp_qelem *list, struct sctstr *target);
00052 static void comm_bomb(struct emp_qelem *list, struct sctstr *target);
00053 static void eff_bomb(struct emp_qelem *list, struct sctstr *target);
00054 static int pinflak_planedamage(struct plnstr *pp, struct plchrstr *pcp,
00055 natid from, int flak);
00056 static void plane_bomb(struct emp_qelem *list, struct sctstr *target);
00057 static void land_bomb(struct emp_qelem *list, struct sctstr *target);
00058 static void ship_bomb(struct emp_qelem *list, struct sctstr *target);
00059
00060 static i_type bombcomm[] = {
00061 I_CIVIL,
00062 I_MILIT,
00063 I_SHELL,
00064 I_GUN,
00065 I_PETROL,
00066 I_IRON,
00067 I_DUST,
00068 I_BAR,
00069 I_FOOD,
00070 I_OIL,
00071 I_LCM,
00072 I_HCM,
00073 I_UW,
00074 I_RAD
00075 };
00076 static int nbomb = sizeof(bombcomm) / sizeof(*bombcomm);
00077
00078 int
00079 bomb(void)
00080 {
00081 char *p;
00082 int mission_flags;
00083 coord tx, ty;
00084 coord ax, ay;
00085 int ap_to_target;
00086 struct ichrstr *ip;
00087 char flightpath[MAX_PATH_LEN];
00088 struct nstr_item ni_bomb;
00089 struct nstr_item ni_esc;
00090 struct sctstr target;
00091 struct emp_qelem bomb_list;
00092 struct emp_qelem esc_list;
00093 int wantflags;
00094 struct sctstr ap_sect;
00095 char mission;
00096 int rel;
00097 struct natstr *natp;
00098 char buf[1024];
00099
00100 wantflags = 0;
00101 if (!snxtitem(&ni_bomb, EF_PLANE, player->argp[1]))
00102 return RET_SYN;
00103 if (!snxtitem(&ni_esc, EF_PLANE,
00104 getstarg(player->argp[2], "escort(s)? ", buf)))
00105 pr("No escorts...\n");
00106 p = getstarg(player->argp[3], "pinpoint, or strategic? ", buf);
00107 if (!p)
00108 return RET_SYN;
00109 mission = *p;
00110 if (strchr("ps", mission) == 0)
00111 return RET_SYN;
00112 if (!get_assembly_point(player->argp[4], &ap_sect, buf))
00113 return RET_SYN;
00114 ax = ap_sect.sct_x;
00115 ay = ap_sect.sct_y;
00116 if (getpath(flightpath, player->argp[5], ax, ay, 0, 0, P_FLYING) == 0
00117 || *flightpath == 0)
00118 return RET_SYN;
00119 tx = ax;
00120 ty = ay;
00121 (void)pathtoxy(flightpath, &tx, &ty, fcost);
00122 pr("target sector is %s\n", xyas(tx, ty, player->cnum));
00123 getsect(tx, ty, &target);
00124 ip = 0;
00125 ap_to_target = strlen(flightpath);
00126 if (flightpath[ap_to_target - 1] == 'h')
00127 ap_to_target--;
00128 pr("range to target is %d\n", ap_to_target);
00129
00130
00131
00132 mission_flags = 0;
00133 pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target,
00134 2, wantflags, P_M | P_O);
00135 pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target,
00136 2, wantflags | P_F | P_ESC, P_M | P_O);
00137
00138
00139
00140 mission_flags |= P_X;
00141 mission_flags |= P_H;
00142 mission_flags = pln_arm(&bomb_list, 2 * ap_to_target, mission,
00143 ip, 0, mission_flags);
00144 if (QEMPTY(&bomb_list)) {
00145 pr("No planes could be equipped for the mission.\n");
00146 return RET_FAIL;
00147 }
00148 mission_flags = pln_arm(&esc_list, 2 * ap_to_target, mission,
00149 ip, P_F | P_ESC, mission_flags);
00150 ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, mission_flags,
00151 0, 0, 0);
00152 if (QEMPTY(&bomb_list)) {
00153 pr("No planes got through fighter defenses\n");
00154 } else if (target.sct_type == SCT_SANCT) {
00155 pr("You can't bomb that sector!\n");
00156 } else {
00157 switch (mission) {
00158 case 'p':
00159 pin_bomb(&bomb_list, &target);
00160 break;
00161 case 's':
00162 if (opt_SLOW_WAR) {
00163 natp = getnatp(player->cnum);
00164 if (target.sct_own) {
00165 rel = getrel(natp, target.sct_own);
00166 if ((rel != AT_WAR) && (player->cnum != target.sct_own)
00167 && (target.sct_own) &&
00168 (target.sct_oldown != player->cnum)) {
00169 pr("You're not at war with them!\n");
00170 pln_put(&bomb_list);
00171 pln_put(&esc_list);
00172 return RET_FAIL;
00173 }
00174 }
00175 }
00176 nreport(player->cnum, N_SCT_BOMB, target.sct_own, 1);
00177 strat_bomb(&bomb_list, &target);
00178 break;
00179 default:
00180 pr("Bad mission %c\n", mission);
00181 break;
00182 }
00183 }
00184 pln_put(&bomb_list);
00185 pln_put(&esc_list);
00186 return RET_OK;
00187 }
00188
00189 static void
00190 pin_bomb(struct emp_qelem *list, struct sctstr *target)
00191 {
00192 struct dchrstr *dcp;
00193 int nplanes;
00194 int nships;
00195 int type;
00196 int bad;
00197 char *p;
00198 struct plist *plp;
00199 int nsubs;
00200 int nunits;
00201 struct natstr *natp;
00202 int rel;
00203 char buf[1024];
00204 int i;
00205
00206 bad = 0;
00207 type = target->sct_type;
00208 dcp = &dchr[type];
00209 pr("Target sector is a %s constructed %s\n",
00210 effadv((int)target->sct_effic), dcp->d_name);
00211 nsubs = 0;
00212 plp = (struct plist *)list->q_forw;
00213 if (plp->pcp->pl_flags & P_A) {
00214 nships = num_shipsatxy(target->sct_x, target->sct_y, 0, 0);
00215 nsubs = nships - shipsatxy(target->sct_x, target->sct_y, 0, M_SUB);
00216 if (nsubs > 0)
00217 pr("Some subs are present in the sector.\n");
00218 } else {
00219 nships = shipsatxy(target->sct_x, target->sct_y, 0, M_SUB);
00220 }
00221 nplanes = planesatxy(target->sct_x, target->sct_y, 0, 0, list);
00222 nunits = unitsatxy(target->sct_x, target->sct_y, 0, 0);
00223 retry:
00224 p = getstring("Bomb what? (ship, plane, land unit, efficiency, commodities) ",
00225 buf);
00226 if (p == 0 || *p == 0) {
00227 if (player->aborted)
00228 return;
00229 bad++;
00230 if (bad > 2)
00231 return;
00232 goto retry;
00233 }
00234 switch (*p) {
00235 case 'l':
00236 if (opt_SLOW_WAR) {
00237 natp = getnatp(player->cnum);
00238 if (target->sct_own) {
00239 rel = getrel(natp, target->sct_own);
00240 if ((rel != AT_WAR) && (player->cnum != target->sct_own)
00241 && (target->sct_own) &&
00242 (target->sct_oldown != player->cnum)) {
00243 pr("You're not at war with them!\n");
00244 goto retry;
00245 }
00246 }
00247 }
00248 if (nunits == 0) {
00249 pr("no units there\n");
00250 goto retry;
00251 }
00252 land_bomb(list, target);
00253 break;
00254 case 'p':
00255 if (opt_SLOW_WAR) {
00256 natp = getnatp(player->cnum);
00257 if (target->sct_own) {
00258 rel = getrel(natp, target->sct_own);
00259 if ((rel != AT_WAR) && (player->cnum != target->sct_own)
00260 && (target->sct_own) &&
00261 (target->sct_oldown != player->cnum)) {
00262 pr("You're not at war with them!\n");
00263 goto retry;
00264 }
00265 }
00266 }
00267 if (nplanes == 0) {
00268 pr("no planes there\n");
00269 goto retry;
00270 }
00271 plane_bomb(list, target);
00272 break;
00273 case 's':
00274 if (nships == 0) {
00275 if (((struct plist *)list->q_forw)->pcp->pl_flags & P_A) {
00276 if (nsubs == 0) {
00277 pr("no ships there\n");
00278 goto retry;
00279 }
00280 } else {
00281 pr("no ships there\n");
00282 goto retry;
00283 }
00284 }
00285 ship_bomb(list, target);
00286 break;
00287 case 'c':
00288 if (opt_SLOW_WAR) {
00289 natp = getnatp(player->cnum);
00290 if (target->sct_own) {
00291 rel = getrel(natp, target->sct_own);
00292 if ((rel != AT_WAR) && (player->cnum != target->sct_own)
00293 && (target->sct_own) &&
00294 (target->sct_oldown != player->cnum)) {
00295 pr("You're not at war with them!\n");
00296 goto retry;
00297 }
00298 }
00299 }
00300
00301 for (i = 0; i < nbomb; i++) {
00302 if (!target->sct_item[bombcomm[i]])
00303 continue;
00304 break;
00305 }
00306 if (i >= nbomb) {
00307 pr("No bombable commodities in %s\n",
00308 xyas(target->sct_x, target->sct_y, player->cnum));
00309 goto retry;
00310 }
00311 comm_bomb(list, target);
00312 break;
00313 case 'e':
00314 if (opt_SLOW_WAR) {
00315 natp = getnatp(player->cnum);
00316 if (target->sct_own) {
00317 rel = getrel(natp, target->sct_own);
00318 if ((rel != AT_WAR) && (player->cnum != target->sct_own)
00319 && (target->sct_own) &&
00320 (target->sct_oldown != player->cnum)) {
00321 pr("You're not at war with them!\n");
00322 goto retry;
00323 }
00324 }
00325 }
00326 eff_bomb(list, target);
00327 break;
00328 case 'q':
00329 pr("Aborting mission.\n");
00330 return;
00331 default:
00332 pr("Bad target type.\n");
00333 goto retry;
00334 }
00335 }
00336
00337 static void
00338 eff_bomb(struct emp_qelem *list, struct sctstr *target)
00339 {
00340 struct plist *plp;
00341 struct emp_qelem *qp;
00342 struct sctstr sect;
00343 int oldeff, dam = 0;
00344 int nukedam;
00345
00346 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
00347 plp = (struct plist *)qp;
00348 if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T)))
00349 continue;
00350 if (plp->bombs || plp->plane.pln_nuketype != -1)
00351 dam += pln_damage(&plp->plane, target->sct_x, target->sct_y,
00352 'p', &nukedam, 1);
00353 }
00354 if (dam <= 0)
00355 return;
00356 getsect(target->sct_x, target->sct_y, §);
00357 target = §
00358 oldeff = target->sct_effic;
00359 target->sct_effic = effdamage(target->sct_effic, dam);
00360 target->sct_avail = effdamage(target->sct_avail, dam);
00361 target->sct_road = effdamage(target->sct_road, dam);
00362 target->sct_rail = effdamage(target->sct_rail, dam);
00363 target->sct_defense = effdamage(target->sct_defense, dam);
00364 pr("did %d%% damage to efficiency in %s\n",
00365 oldeff - target->sct_effic,
00366 xyas(target->sct_x, target->sct_y, player->cnum));
00367 if (target->sct_own)
00368 wu(0, target->sct_own,
00369 "%s bombing raid did %d%% damage in %s\n",
00370 cname(player->cnum), oldeff - target->sct_effic,
00371 xyas(target->sct_x, target->sct_y, target->sct_own));
00372 if (target->sct_effic < SCT_MINEFF) {
00373 if (target->sct_type == SCT_BSPAN)
00374 knockdown(target, list);
00375 else if (target->sct_type == SCT_BTOWER) {
00376 knockdown(target, list);
00377 bridgefall(target, list);
00378 }
00379 }
00380 putsect(§);
00381 collateral_damage(target->sct_x, target->sct_y, dam, list);
00382 }
00383
00384 static void
00385 comm_bomb(struct emp_qelem *list, struct sctstr *target)
00386 {
00387 struct plist *plp;
00388 double b;
00389 int i;
00390 int amt, before;
00391 struct ichrstr *ip;
00392 struct emp_qelem *qp;
00393 struct sctstr sect;
00394 int dam = 0;
00395 int nukedam;
00396
00397 for (i = 0; i < nbomb; i++) {
00398 if (target->sct_item[bombcomm[i]] == 0)
00399 continue;
00400 if (opt_SUPER_BARS && bombcomm[i] == I_BAR)
00401 continue;
00402 ip = &ichr[bombcomm[i]];
00403 pr("some %s\n", ip->i_name);
00404 }
00405 for (;;) {
00406 ip = whatitem(NULL, "commodity to bomb? ");
00407 if (player->aborted)
00408 return;
00409 if (!ip)
00410 continue;
00411
00412 for (i = 0; i < nbomb; i++) {
00413 if (opt_SUPER_BARS && bombcomm[i] == I_BAR)
00414 continue;
00415 if (&ichr[bombcomm[i]] == ip)
00416 break;
00417 }
00418 if (i == nbomb) {
00419 pr("You can't bomb %s!\n", ip->i_name);
00420 for (i = 0; i < nbomb; i++) {
00421 if (opt_SUPER_BARS && bombcomm[i] == I_BAR)
00422 continue;
00423 pr("%s%s", i == 0 ? "Bombable: " : ", ",
00424 ichr[bombcomm[i]].i_name);
00425 }
00426 pr("\n");
00427 } else
00428 break;
00429 }
00430 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
00431 plp = (struct plist *)qp;
00432 if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T)))
00433 continue;
00434 if (plp->bombs || plp->plane.pln_nuketype != -1)
00435 dam += pln_damage(&plp->plane, target->sct_x, target->sct_y,
00436 'p', &nukedam, 1);
00437 }
00438 if (dam <= 0)
00439 return;
00440 getsect(target->sct_x, target->sct_y, §);
00441 target = §
00442 before = target->sct_item[ip->i_uid];
00443 target->sct_item[ip->i_uid] = amt = commdamage(before, dam, ip->i_uid);
00444 if (before > 0.0)
00445 b = 100.0 * (1.0 - (double)amt / (double)before);
00446 else
00447 b = 0.0;
00448 pr("did %.2f%% damage to %s in %s\n",
00449 b, ip->i_name, xyas(target->sct_x, target->sct_y, player->cnum));
00450 nreport(player->cnum, N_SCT_BOMB, target->sct_own, 1);
00451 if (target->sct_own != 0)
00452 wu(0, target->sct_own,
00453 "%s precision bombing raid did %.2f%% damage to %s in %s\n",
00454 cname(player->cnum), b, ip->i_name,
00455 xyas(target->sct_x, target->sct_y, target->sct_own));
00456 putsect(§);
00457 collateral_damage(target->sct_x, target->sct_y, dam, list);
00458 }
00459
00460 static void
00461 ship_bomb(struct emp_qelem *list, struct sctstr *target)
00462 {
00463 struct plist *plp;
00464 struct mchrstr *mcp;
00465 int dam;
00466 char *q;
00467 int n;
00468 struct emp_qelem *qp;
00469 int shipno;
00470 int ignore;
00471 struct shpstr ship;
00472 int nships = 0;
00473 struct shiplist *head = NULL;
00474 char buf[1024];
00475 char prompt[128];
00476 int hitchance;
00477 int nukedam;
00478 int flak;
00479 int gun;
00480 int shell;
00481
00482 for (qp = list->q_forw; qp != list && !player->aborted;
00483 qp = qp->q_forw) {
00484 free_shiplist(&head);
00485 plp = (struct plist *)qp;
00486 if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T)))
00487 continue;
00488 if (plp->pcp->pl_flags & P_A)
00489 nships = asw_shipsatxy(target->sct_x, target->sct_y, 0, 0,
00490 &plp->plane, &head);
00491 else
00492 nships = shipsatxy(target->sct_x, target->sct_y, 0, M_SUB);
00493 if (nships == 0) {
00494 pr("%s could not find any ships!\n", prplane(&plp->plane));
00495 continue;
00496 }
00497 (void)sprintf(prompt, "%s, %d bombs. Target ('~' to skip)? ",
00498 prplane(&plp->plane), plp->bombs);
00499 ignore = 0;
00500 shipno = -1;
00501 while (shipno < 0 && !player->aborted && !ignore) {
00502 if ((q = getstring(prompt, buf)) == 0 || *q == 0)
00503 continue;
00504 if (*q == '~') {
00505 ignore = 1;
00506 continue;
00507 }
00508 if (*q == '?') {
00509 if (plp->pcp->pl_flags & P_A)
00510 print_shiplist(head);
00511 else
00512 shipsatxy(target->sct_x, target->sct_y, 0, M_SUB);
00513 continue;
00514 }
00515 if (*q == 'd')
00516 goto next;
00517 if (!isdigit(*q))
00518 continue;
00519 n = atoi(q);
00520 if (n < 0)
00521 continue;
00522 if ((plp->pcp->pl_flags & P_A) && !on_shiplist(n, head))
00523 continue;
00524 if (getship(n, &ship) && ship.shp_x == target->sct_x &&
00525 ship.shp_y == target->sct_y)
00526 shipno = n;
00527 }
00528 if (shipno < 0)
00529 continue;
00530 if ((plp->pcp->pl_flags & P_A) && !on_shiplist(shipno, head))
00531 continue;
00532
00533 shell = gun = 0;
00534 gun = MIN(ship.shp_item[I_GUN], ship.shp_glim);
00535 if (gun > 0) {
00536 shell = ship.shp_item[I_SHELL];
00537 if (shell <= 0)
00538 shell = supply_commod(ship.shp_own,
00539 ship.shp_x, ship.shp_y, I_SHELL, 1);
00540 }
00541 mcp = &mchr[(int)ship.shp_type];
00542 if (gun > 0 && shell > 0 && !(mcp->m_flags & M_SUB)) {
00543 flak = (int)(techfact(ship.shp_tech, gun) * 2.0);
00544 ship.shp_item[I_SHELL] = shell;
00545 putship(ship.shp_uid, &ship);
00546 PR(ship.shp_own, "Flak! Firing %d guns from ship %s\n",
00547 flak, prship(&ship));
00548 if (pinflak_planedamage(&plp->plane, plp->pcp, ship.shp_own, flak))
00549 continue;
00550 }
00551
00552 dam = 0;
00553 if (plp->plane.pln_nuketype != -1)
00554 hitchance = 100;
00555 else {
00556 hitchance = pln_hitchance(&plp->plane,
00557 shp_hardtarget(&ship), EF_SHIP);
00558 pr("%d%% hitchance...", hitchance);
00559 }
00560 if (roll(100) <= hitchance) {
00561
00562 dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y,
00563 'p', &nukedam, 1);
00564 } else {
00565 pr("splash\n");
00566
00567 dam = pln_damage(&plp->plane, target->sct_x, target->sct_y,
00568 'p', &nukedam, 0);
00569 collateral_damage(target->sct_x, target->sct_y, dam, list);
00570 dam = 0;
00571 }
00572 if (dam <= 0)
00573 continue;
00574 if (mcp->m_flags & M_SUB)
00575 nreport(player->cnum, N_SUB_BOMB, ship.shp_own, 1);
00576 else
00577 nreport(player->cnum, N_SHP_BOMB, ship.shp_own, 1);
00578 if (ship.shp_own) {
00579 wu(0, ship.shp_own, "%s bombs did %d damage to %s at %s\n",
00580 cname(player->cnum), dam,
00581 prship(&ship),
00582 xyas(target->sct_x, target->sct_y, ship.shp_own));
00583 }
00584 pr("\n");
00585 check_retreat_and_do_shipdamage(&ship, dam);
00586 if (ship.shp_rflags & RET_BOMBED)
00587 if (((ship.shp_rflags & RET_INJURED) == 0) || !dam)
00588 retreat_ship(&ship, 'b');
00589 putship(ship.shp_uid, &ship);
00590 getship(ship.shp_uid, &ship);
00591 if (!ship.shp_own) {
00592 pr("%s at %s sunk!\n",
00593 prship(&ship),
00594 xyas(target->sct_x, target->sct_y, player->cnum));
00595 }
00596 collateral_damage(target->sct_x, target->sct_y, dam / 2, list);
00597 next:
00598 ;
00599 }
00600 free_shiplist(&head);
00601 }
00602
00603 static void
00604 plane_bomb(struct emp_qelem *list, struct sctstr *target)
00605 {
00606 int dam;
00607 char *q;
00608 int n;
00609 natid own;
00610 struct plnstr plane;
00611 struct emp_qelem *qp;
00612 int planeno;
00613 int ignore;
00614 struct plist *plp;
00615 char prompt[128];
00616 char buf[1024];
00617 int hitchance;
00618 int nukedam;
00619 int nplanes;
00620
00621 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
00622 plp = (struct plist *)qp;
00623 if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T)))
00624 continue;
00625 nplanes = planesatxy(target->sct_x, target->sct_y, 0, 0, list);
00626 if (nplanes == 0) {
00627 pr("%s could not find any planes!\n", prplane(&plp->plane));
00628 continue;
00629 }
00630 (void)sprintf(prompt, "%s, %d bombs. Target ('~' to skip)? ",
00631 prplane(&plp->plane), plp->bombs);
00632 planeno = -1;
00633 ignore = 0;
00634 while (planeno < 0 && !player->aborted && !ignore) {
00635 if ((q = getstring(prompt, buf)) == 0 || *q == 0)
00636 continue;
00637 if (*q == '~') {
00638 ignore = 1;
00639 continue;
00640 }
00641 if (*q == '?') {
00642 planesatxy(target->sct_x, target->sct_y, 0, 0, list);
00643 continue;
00644 }
00645 if (*q == 'd')
00646 goto next;
00647 n = atoi(q);
00648 if (n < 0)
00649 continue;
00650 if (getplane(n, &plane) &&
00651 plane.pln_x == target->sct_x &&
00652 plane.pln_y == target->sct_y &&
00653 ((plane.pln_flags & PLN_LAUNCHED) == 0) &&
00654 (!ac_isflying(&plane, list)))
00655 planeno = n;
00656 else
00657 pr("Plane #%d not spotted\n", n);
00658 }
00659 if (planeno < 0)
00660 continue;
00661 dam = 0;
00662 if (plp->plane.pln_nuketype != -1)
00663 hitchance = 100;
00664 else {
00665 hitchance = pln_hitchance(&plp->plane, 0, EF_PLANE);
00666 pr("%d%% hitchance...", hitchance);
00667 }
00668 if (roll(100) <= hitchance) {
00669
00670 dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y,
00671 'p', &nukedam, 1);
00672 } else {
00673 pr("thud\n");
00674
00675 dam = pln_damage(&plp->plane, target->sct_x, target->sct_y,
00676 'p', &nukedam, 0);
00677 collateral_damage(target->sct_x, target->sct_y, dam, list);
00678 dam = 0;
00679 }
00680 if (dam <= 0)
00681 continue;
00682 if (dam > 100)
00683 dam = 100;
00684 own = plane.pln_own;
00685 if (dam > plane.pln_effic)
00686 plane.pln_effic = 0;
00687 else
00688 plane.pln_effic -= dam;
00689 plane.pln_mobil = (dam * plane.pln_mobil / 100.0);
00690 if (own == player->cnum) {
00691 pr("%s reports %d%% damage\n", prplane(&plane), dam);
00692 } else {
00693 if (own != 0)
00694 wu(0, own,
00695 "%s pinpoint bombing raid did %d%% damage to %s\n",
00696 cname(player->cnum), dam, prplane(&plane));
00697 }
00698 nreport(player->cnum, N_DOWN_PLANE, own, 1);
00699 if (own != 0)
00700 wu(0, own, "%s bombs did %d%% damage to %s at %s\n",
00701 cname(player->cnum), dam, prplane(&plane),
00702 xyas(target->sct_x, target->sct_y, own));
00703 putplane(plane.pln_uid, &plane);
00704 collateral_damage(target->sct_x, target->sct_y, dam, list);
00705 next:
00706 ;
00707 }
00708 }
00709
00710 static void
00711 land_bomb(struct emp_qelem *list, struct sctstr *target)
00712 {
00713 int dam;
00714 char *q;
00715 int n;
00716 natid own;
00717 char prompt[128];
00718 char buf[1024];
00719 struct lndstr land;
00720 struct emp_qelem *qp;
00721 int unitno;
00722 int ignore, flak, hitchance;
00723 struct plist *plp;
00724 int nukedam;
00725 int nunits;
00726
00727 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
00728 plp = (struct plist *)qp;
00729 if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T)))
00730 continue;
00731 nunits = unitsatxy(target->sct_x, target->sct_y, 0, 0);
00732 if (nunits == 0) {
00733 pr("%s could not find any units!\n", prplane(&plp->plane));
00734 continue;
00735 }
00736 (void)sprintf(prompt, "%s, %d bombs. Target ('~' to skip)? ",
00737 prplane(&plp->plane), plp->bombs);
00738 unitno = -1;
00739 ignore = 0;
00740 while (unitno < 0 && !player->aborted && !ignore) {
00741 if ((q = getstring(prompt, buf)) == 0 || *q == 0)
00742 continue;
00743 if (*q == '~') {
00744 ignore = 1;
00745 continue;
00746 }
00747 if (*q == '?') {
00748 unitsatxy(target->sct_x, target->sct_y, 0, 0);
00749 continue;
00750 }
00751 if (*q == 'd')
00752 goto next;
00753 n = atoi(q);
00754 if (n < 0)
00755 continue;
00756 if (getland(n, &land) &&
00757 land.lnd_x == target->sct_x && land.lnd_y == target->sct_y)
00758 unitno = n;
00759 else
00760 pr("Unit #%d not spotted\n", n);
00761 }
00762 if (unitno < 0)
00763 continue;
00764
00765 flak = (int)(techfact(land.lnd_tech, land.lnd_aaf) * 3.0);
00766 if (flak) {
00767 PR(land.lnd_own,
00768 "Flak! Firing flak guns from unit %s (aa rating %d)\n",
00769 prland(&land), land.lnd_aaf);
00770 if (pinflak_planedamage(&plp->plane, plp->pcp, land.lnd_own, flak))
00771 continue;
00772 }
00773
00774 dam = 0;
00775 if (plp->plane.pln_nuketype != -1)
00776 hitchance = 100;
00777 else {
00778 hitchance = pln_hitchance(&plp->plane,
00779 lnd_hardtarget(&land), EF_LAND);
00780 pr("%d%% hitchance...", hitchance);
00781 }
00782 if (roll(100) <= hitchance) {
00783 dam = 2 * pln_damage(&plp->plane, target->sct_x, target->sct_y,
00784 'p', &nukedam, 1);
00785 } else {
00786 pr("thud\n");
00787
00788 dam = pln_damage(&plp->plane, target->sct_x, target->sct_y,
00789 'p', &nukedam, 0);
00790 collateral_damage(target->sct_x, target->sct_y, dam, list);
00791 dam = 0;
00792 }
00793 if (dam <= 0)
00794 continue;
00795 if (dam > 100)
00796 dam = 100;
00797 own = land.lnd_own;
00798 if (own != 0)
00799 mpr(own, "%s pinpoint bombing raid did %d damage to %s\n",
00800 cname(player->cnum), dam, prland(&land));
00801 check_retreat_and_do_landdamage(&land, dam);
00802
00803 if (land.lnd_rflags & RET_BOMBED)
00804 if (((land.lnd_rflags & RET_INJURED) == 0) || !dam)
00805 retreat_land(&land, 'b');
00806 nreport(player->cnum, N_UNIT_BOMB, own, 1);
00807 putland(land.lnd_uid, &land);
00808 collateral_damage(target->sct_x, target->sct_y, dam, list);
00809 next:
00810 ;
00811 }
00812 }
00813
00814 static void
00815 strat_bomb(struct emp_qelem *list, struct sctstr *target)
00816 {
00817 struct plist *plp;
00818 int dam = 0;
00819 struct emp_qelem *qp;
00820 struct sctstr sect;
00821 int nukedam;
00822
00823 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
00824 plp = (struct plist *)qp;
00825 if ((plp->pcp->pl_flags & P_C) && (!(plp->pcp->pl_flags & P_T)))
00826 continue;
00827 if (plp->bombs || plp->plane.pln_nuketype != -1)
00828 dam += pln_damage(&plp->plane, target->sct_x, target->sct_y,
00829 's', &nukedam, 1);
00830 }
00831 if (dam <= 0)
00832 return;
00833 getsect(target->sct_x, target->sct_y, §);
00834 target = §
00835 if (target->sct_own)
00836 wu(0, target->sct_own, "%s bombing raid did %d damage in %s\n",
00837 cname(player->cnum), PERCENT_DAMAGE(dam),
00838 xyas(target->sct_x, target->sct_y, target->sct_own));
00839
00840 sectdamage(target, dam, list);
00841
00842 pr("did %d damage in %s\n", PERCENT_DAMAGE(dam),
00843 xyas(target->sct_x, target->sct_y, player->cnum));
00844 putsect(§);
00845 }
00846
00847 static int
00848 pinflak_planedamage(struct plnstr *pp, struct plchrstr *pcp, natid from,
00849 int flak)
00850 {
00851 int disp;
00852 char dmess[255];
00853 int eff;
00854 struct shpstr ship;
00855 struct lndstr land;
00856 natid plane_owner;
00857 int dam;
00858
00859 dam = ac_flak_dam(flak, pp->pln_def, pcp->pl_flags);
00860 disp = 0;
00861 plane_owner = pp->pln_own;
00862 eff = pp->pln_effic;
00863 if (dam <= 0)
00864 return 0;
00865 memset(dmess, 0, sizeof(dmess));
00866 eff -= dam;
00867 if (eff < 0)
00868 eff = 0;
00869 if (eff < PLANE_MINEFF) {
00870 sprintf(dmess, " -- shot down");
00871 disp = 1;
00872 } else if (chance((100 - eff) / 100.0)) {
00873 sprintf(dmess, " -- aborted with %d%% damage", 100 - eff);
00874 disp = 2;
00875 }
00876 PR(plane_owner, " Flak! %s %s takes %d%s.\n",
00877 cname(pp->pln_own), prplane(pp), dam, dmess);
00878
00879 pp->pln_effic = eff;
00880 if (disp == 1) {
00881 if (from != 0)
00882 nreport(from, N_DOWN_PLANE, pp->pln_own, 1);
00883 if (pp->pln_ship >= 0) {
00884 getship(pp->pln_ship, &ship);
00885 take_plane_off_ship(pp, &ship);
00886 }
00887 if (pp->pln_land >= 0) {
00888 getland(pp->pln_land, &land);
00889 take_plane_off_land(pp, &land);
00890 }
00891 }
00892 putplane(pp->pln_uid, pp);
00893
00894 if (disp > 0)
00895 return 1;
00896 return 0;
00897 }