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 = pct_chance(hitchance); mpr(pp->pln_own, "\t%d%% hitchance...%s\n", hitchance, hit ? "HIT!" : "miss"); } if (type != EF_PLANE) mpr(victim, "...Incoming %s missile %s\n", sublaunch ? "" : cname(pp->pln_own), hit ? "HIT!\n" : "missed\n"); if (hit && news_item) { if (sublaunch) nreport(victim, snews_item, 0, 1); else nreport(pp->pln_own, news_item, victim, 1); } return hit; }
int pdump(void) { int nplanes; struct nstr_item np; struct plnstr plane; struct nukstr nuke; int field[128]; struct natstr *natp; int n, i; time_t now; if (!snxtitem(&np, EF_PLANE, player->argp[1], NULL)) return RET_SYN; prdate(); if (!player->argp[2]) { for (n = 1; n <= 32; n++) field[n - 1] = n; field[n - 1] = 0; } else { n = 2; i = 0; while (player->argp[n]) { if (!strcmp("type", player->argp[n])) { field[i++] = 1; } else if (!strcmp("x", player->argp[n])) { field[i++] = 2; } else if (!strcmp("y", player->argp[n])) { field[i++] = 3; } else if (!strcmp("wing", player->argp[n])) { field[i++] = 4; } else if (!strcmp("eff", player->argp[n])) { field[i++] = 5; } else if (!strcmp("mob", player->argp[n])) { field[i++] = 6; } else if (!strcmp("tech", player->argp[n])) { field[i++] = 7; } else if (!strcmp("att", player->argp[n])) { field[i++] = 8; } else if (!strcmp("def", player->argp[n])) { field[i++] = 9; } else if (!strcmp("acc", player->argp[n])) { field[i++] = 10; } else if (!strcmp("react", player->argp[n])) { field[i++] = 11; } else if (!strcmp("range", player->argp[n])) { field[i++] = 12; } else if (!strcmp("load", player->argp[n])) { field[i++] = 13; } else if (!strcmp("fuel", player->argp[n])) { field[i++] = 14; } else if (!strcmp("hard", player->argp[n])) { field[i++] = 15; } else if (!strcmp("ship", player->argp[n])) { field[i++] = 16; } else if (!strcmp("land", player->argp[n])) { field[i++] = 17; } else if (!strcmp("laun", player->argp[n])) { field[i++] = 18; } else if (!strcmp("orb", player->argp[n])) { field[i++] = 19; } else if (!strcmp("nuke", player->argp[n])) { field[i++] = 20; } else if (!strcmp("grd", player->argp[n])) { field[i++] = 21; } else { pr("Unrecognized field %s\n", player->argp[n]); } if (n++ > 100) { pr("Too many fields\n"); return RET_FAIL; } } field[i] = 0; } if (player->god) pr(" "); time(&now); pr("DUMP PLANES %ld\n", (long)now); if (player->god) pr("own "); pr("id"); n = 0; while (field[n]) { switch (field[n]) { case 1: pr(" type"); break; case 2: pr(" x"); break; case 3: pr(" y"); break; case 4: pr(" wing"); break; case 5: pr(" eff"); break; case 6: pr(" mob"); break; case 7: pr(" tech"); break; case 8: pr(" att"); break; case 9: pr(" def"); break; case 10: pr(" acc"); break; case 11: pr(" react"); break; case 12: pr(" range"); break; case 13: pr(" load"); break; case 14: pr(" fuel"); break; case 15: pr(" hard"); break; case 16: pr(" ship"); break; case 17: pr(" land"); break; case 18: pr(" laun"); break; case 19: pr(" orb"); break; case 20: pr(" nuke"); break; case 21: pr(" grd"); break; } n++; } pr("\n"); nplanes = 0; natp = getnatp(player->cnum); while (nxtitem(&np, &plane)) { if (!player->owner || plane.pln_own == 0) continue; nplanes++; if (player->god) pr("%d ", plane.pln_own); pr("%d", np.cur); n = 0; while (field[n]) { switch (field[n++]) { case 1: pr(" %.4s", plchr[(int)plane.pln_type].pl_name); break; case 2: pr(" %d", xrel(natp, plane.pln_x)); break; case 3: pr(" %d", yrel(natp, plane.pln_y)); break; case 4: pr(" %c", plane.pln_wing ? plane.pln_wing : '~'); break; case 5: pr(" %d", plane.pln_effic); break; case 6: pr(" %d", plane.pln_mobil); break; case 7: pr(" %d", plane.pln_tech); break; case 8: pr(" %d", pln_att(&plane)); break; case 9: pr(" %d", pln_def(&plane)); break; case 10: pr(" %d", pln_acc(&plane)); break; case 11: pr(" %d", plane.pln_range); break; case 12: pr(" %d", pln_range_max(&plane)); break; case 13: pr(" %d", pln_load(&plane)); break; case 14: pr(" %d", plchr[(int)plane.pln_type].pl_fuel); break; case 15: pr(" %d", plane.pln_harden); break; case 16: pr(" %d", plane.pln_ship); break; case 17: pr(" %d", plane.pln_land); break; case 18: pr(pln_is_in_orbit(&plane) ? " Y" : " N"); break; case 19: pr(pln_is_in_orbit(&plane) && (plane.pln_flags & PLN_SYNCHRONOUS) ? " Y" : " N"); break; case 20: if (getnuke(nuk_on_plane(&plane), &nuke)) { pr(" %.5s", nchr[nuke.nuk_type].n_name); break; } else pr(" N/A"); break; case 21: pr(" %c", plane.pln_flags & PLN_AIRBURST ? 'A' : 'G'); break; } } pr("\n"); } if (nplanes == 0) { if (player->argp[1]) pr("%s: No plane(s)\n", player->argp[1]); else pr("%s: No plane(s)\n", ""); return RET_FAIL; } else pr("%d plane%s\n", nplanes, splur(nplanes)); return RET_OK; }
/* * Describe an item up for sale. "tgp" is a union containing * the details of the generic item. * Return 1 on success, 0 on error */ int trade_desc(struct empobj *tgp) { i_type it; struct sctstr sect; struct nukstr *np; struct shpstr *sp; struct plnstr *pp; struct lndstr *lp; struct nstr_item ni; struct plnstr plane; struct lndstr land; struct nukstr nuke; switch (tgp->ef_type) { case EF_NUKE: np = (struct nukstr *)tgp; pr("(%3d) tech %d %d%% %s #%d", np->nuk_own, np->nuk_tech, np->nuk_effic, nchr[(int)np->nuk_type].n_name, np->nuk_uid); break; case EF_SHIP: sp = (struct shpstr *)tgp; pr("(%3d) tech %d %d%% %s [", sp->shp_own, sp->shp_tech, sp->shp_effic, prship(sp)); for (it = I_NONE + 1; it <= I_MAX; ++it) { if (sp->shp_item[it]) pr("%c:%d ", ichr[it].i_mnem, sp->shp_item[it]); } pr("] #%d", sp->shp_uid); snxtitem_cargo(&ni, EF_PLANE, EF_SHIP, sp->shp_uid); while (nxtitem(&ni, &plane)) { pr("\n\t\t\t\t tech %3d %3d%% %s #%d", plane.pln_tech, plane.pln_effic, plchr[(int)plane.pln_type].pl_name, plane.pln_uid); if (getnuke(nuk_on_plane(&plane), &nuke)) pr("(%s)", nchr[nuke.nuk_type].n_name); } snxtitem_cargo(&ni, EF_LAND, EF_SHIP, sp->shp_uid); while (nxtitem(&ni, &land)) { pr("\n\t\t\t\t tech %3d %3d%% %s #%d", land.lnd_tech, land.lnd_effic, lchr[(int)land.lnd_type].l_name, land.lnd_uid); if (pln_first_on_land(&land) >= 0) { snxtitem_cargo(&ni, EF_PLANE, EF_LAND, land.lnd_uid); while (nxtitem(&ni, &plane)) { pr("\n\t\t\t\t tech %3d %3d%% %s #%d", plane.pln_tech, plane.pln_effic, plchr[(int)plane.pln_type].pl_name, plane.pln_uid); if (getnuke(nuk_on_plane(&plane), &nuke)) pr("(%s)", nchr[nuke.nuk_type].n_name); } } } getsect(sp->shp_x, sp->shp_y, §); if (sect.sct_type != SCT_WATER) pr(" in a %s %s", cname(sect.sct_own), dchr[sect.sct_type].d_name); else pr(" at sea"); break; case EF_LAND: lp = (struct lndstr *)tgp; pr("(%3d) tech %d %d%% %s [", lp->lnd_own, lp->lnd_tech, lp->lnd_effic, lchr[(int)lp->lnd_type].l_name); for (it = I_NONE + 1; it <= I_MAX; ++it) { if (lp->lnd_item[it]) pr("%c:%d ", ichr[it].i_mnem, lp->lnd_item[it]); } pr("] #%d", lp->lnd_uid); break; case EF_PLANE: pp = (struct plnstr *)tgp; pr("(%3d) tech %d %d%% %s #%d", pp->pln_own, pp->pln_tech, pp->pln_effic, plchr[(int)pp->pln_type].pl_name, pp->pln_uid); if (getnuke(nuk_on_plane(pp), &nuke)) pr("(%s)", nchr[nuke.nuk_type].n_name); break; default: pr("flaky unit type %d", tgp->uid); break; } return 1; }
int msl_launch(struct plnstr *pp, int type, char *what, coord x, coord y, natid victim, int *sublaunchp) { struct shpstr ship; struct nukstr nuke; int sublaunch = 0; 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_SECTOR ? "in " : "", xyas(x, y, pp->pln_own)); if (pp->pln_ship >= 0) { getship(pp->pln_ship, &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"; } else { if (pp->pln_harden > 0) { base = "missile silo"; in_or_at = " at "; from = "in silo"; } else { base = in_or_at = ""; from = "on launch pad"; } } 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)) { 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 { 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(§); } } #endif return -1; } mpr(pp->pln_own, "\tSHWOOOOOSH! Missile launched!\n"); 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 (type == EF_SECTOR || type == EF_LAND) { if (msl_abm_intercept(pp, x, y, sublaunch)) return -1; } if (type == EF_SHIP) { if (shp_missile_defense(x, y, pp->pln_own, pln_def(pp))) { return -1; } } if (sublaunchp) *sublaunchp = sublaunch; return 0; }
int pln_equip(struct plist *plp, struct ichrstr *ip, char mission) { struct plchrstr *pcp; struct plnstr *pp; int load, needed; struct lndstr land; struct shpstr ship; struct sctstr sect; i_type itype; short *item; int own; int abandon_needed; pp = &plp->plane; pcp = plp->pcp; if (pp->pln_ship >= 0) { getship(pp->pln_ship, &ship); plp->pstage = ship.shp_pstage; item = ship.shp_item; own = ship.shp_own; } else if (pp->pln_land >= 0) { getland(pp->pln_land, &land); plp->pstage = land.lnd_pstage; item = land.lnd_item; own = land.lnd_own; } else { getsect(pp->pln_x, pp->pln_y, §); plp->pstage = sect.sct_pstage; item = sect.sct_item; own = sect.sct_oldown; } if (pcp->pl_fuel > item[I_PETROL]) { pr("%s not enough petrol there!\n", prplane(pp)); return -1; } item[I_PETROL] -= pcp->pl_fuel; load = pln_load(pp); itype = I_NONE; switch (mission) { case 's': /* strategic bomb */ case 'p': /* pinpoint bomb */ itype = I_SHELL; break; case 't': /* transport */ if (!(pcp->pl_flags & P_C) || !ip) break; itype = ip->i_uid; load *= 2; break; case 'm': /* mine */ if ((pcp->pl_flags & P_MINE) == 0) break; itype = I_SHELL; load *= 2; break; case 'd': /* drop */ if (!(pcp->pl_flags & P_C) || CANT_HAPPEN(!ip)) break; itype = ip->i_uid; if (pcp->pl_flags & P_V) load *= 2; break; case 'a': /* paradrop */ if (!(pcp->pl_flags & P_P)) break; itype = I_MILIT; if (pcp->pl_flags & P_V) load *= 2; break; case 'r': /* reconnaissance */ case 'e': /* escort */ load = 0; break; case 'i': /* missile interception */ if (CANT_HAPPEN(!(pcp->pl_flags & P_M) || !(pcp->pl_flags & (P_N | P_O)))) break; if (load) itype = I_SHELL; break; default: CANT_REACH(); load = 0; } if (itype != I_NONE) { needed = load / ichr[itype].i_lbs; if (needed <= 0) { pr("%s can't contribute to mission\n", prplane(pp)); return -1; } if (nuk_on_plane(pp) >= 0) { if (mission == 's' || mission == 't') needed = 0; else { pr("%s can't fly this mission" " while it is carrying a nuclear weapon", prplane(pp)); return -1; } } if (itype == I_CIVIL && pp->pln_own != own) { pr("You don't control those civilians!\n"); return -1; } #if 0 /* Supply is broken somewhere, so don't use it for now */ if (itype == I_SHELL && item[itype] < needed) item[itype] += supply_commod(plp->plane.pln_own, plp->plane.pln_x, plp->plane.pln_y, I_SHELL, needed); #endif if (pp->pln_ship >= 0 || pp->pln_land >= 0) abandon_needed = 0; else abandon_needed = !!would_abandon(§, itype, needed, NULL); if (item[itype] < needed + abandon_needed) { pr("Not enough %s for %s\n", ichr[itype].i_name, prplane(pp)); return -1; } item[itype] -= needed; plp->load = needed; } if (pp->pln_ship >= 0) { if (pp->pln_own != ship.shp_own) { wu(0, ship.shp_own, "%s %s prepares for takeoff from ship %s\n", cname(pp->pln_own), prplane(pp), prship(&ship)); } putship(ship.shp_uid, &ship); } else if (pp->pln_land >= 0) { if (pp->pln_own != land.lnd_own) { wu(0, land.lnd_own, "%s %s prepares for takeoff from unit %s\n", cname(pp->pln_own), prplane(pp), prland(&land)); } putland(land.lnd_uid, &land); } else { if (pp->pln_own != sect.sct_own) { wu(0, sect.sct_own, "%s %s prepares for takeoff from %s\n", cname(pp->pln_own), prplane(pp), xyas(sect.sct_x, sect.sct_y, sect.sct_own)); } putsect(§); } return 0; }
int pln_damage(struct plnstr *pp, char type, int noisy) { struct plchrstr *pcp = plchr + pp->pln_type; int load, i, hitroll, aim, len; int dam = 0; int effective = 1; int pinbomber = 0; char buf[80]; if (CANT_HAPPEN(nuk_on_plane(pp) >= 0)) return 0; load = pln_load(pp); if (!load) /* e.g. ab, blowing up on launch pad */ return 0; i = roll(load) + 1; if (i > load) i = load; if (pcp->pl_flags & P_M) { if (pcp->pl_flags & P_MAR) pinbomber = 1; } else if (pcp->pl_flags & P_T) pinbomber = 1; aim = pln_acc(pp); if (type == 's') { effective = !pinbomber; aim = 30 + (pinbomber ? aim : 100 - aim); } else { effective = pinbomber; aim = 100 - aim; } len = 0; while (i--) { dam += roll(6); hitroll = roll(100); if (hitroll >= 90) { dam += 8; if (noisy) len += sprintf(buf + len, "BLAM"); } else if (hitroll < aim) { dam += 5; if (noisy) len += sprintf(buf + len, "Blam"); } else { dam += 1; if (noisy) len += sprintf(buf + len, "blam"); } if (noisy) { if (len > 75) { mpr(pp->pln_own, "%s\n", buf); len = 0; } if (i) len += sprintf(buf + len, "-"); } } if (noisy && len) mpr(pp->pln_own, "%s\n", buf); if (effective) dam *= 2; return dam; }