void takeover_plane(struct plnstr *pp, natid newown) { int n; if ((pp->pln_own == newown) || (pp->pln_own == 0)) return; if (pp->pln_flags & PLN_LAUNCHED) return; if (pp->pln_ship >= 0 || pp->pln_land >= 0) return; /* * XXX If this was done right, planes could escape, * flying to a nearby friendly airport. */ n = pp->pln_effic - (29 + roll(100)); if (n < 0) n = 0; pp->pln_effic = n; if (pp->pln_effic < PLANE_MINEFF || pp->pln_harden > 0) { pp->pln_effic = 0; mpr(newown, "%s blown up by the crew!\n", prplane(pp)); wu(0, pp->pln_own, "%s blown up by the crew to avoid capture by %s at %s!\n", prplane(pp), cname(newown), xyas(pp->pln_x, pp->pln_y, pp->pln_own)); } else { mpr(newown, "We have captured %s!\n", prplane(pp)); wu(0, pp->pln_own, "%s captured by %s at %s!\n", prplane(pp), cname(newown), xyas(pp->pln_x, pp->pln_y, pp->pln_own)); } takeover_unit((struct empobj *)pp, newown); }
int sate(void) { static int sct_shp_or_lnd[] = { EF_SECTOR, EF_SHIP, EF_LAND, EF_BAD }; double tech; int pln_uid; struct plnstr plane; int type = EF_BAD; if (!player->argp[1] || !*player->argp[1] || !isdigit(*player->argp[1]) || (pln_uid = atoi(player->argp[1])) < 0) return RET_SYN; if (!getplane(pln_uid, &plane)) { pr("No such plane\n"); return RET_FAIL; } if (plane.pln_own != player->cnum && !player->god) { pr("You don't own plane #%d\n", pln_uid); return RET_FAIL; } if (!pln_is_in_orbit(&plane)) { pr("%s isn't in orbit\n", prplane(&plane)); return RET_FAIL; } if (plane.pln_mobil < plane_mob_max) { pr("%s doesn't have enough mobility (needs %d)\n", prplane(&plane), plane_mob_max); return RET_FAIL; } if (player->argp[2]) { type = ef_byname_from(player->argp[2], sct_shp_or_lnd); if (type < 0) { return RET_SYN; } } if (plchr[(int)plane.pln_type].pl_flags & P_S) pr("Satellite Spy Report:\n"); else pr("Satellite Map Report:\n"); pr("%s at ", prplane(&plane)); tech = techfact(plane.pln_tech, 20.0); return satmap(plane.pln_x, plane.pln_y, plane.pln_effic, (int)tech, plchr[(int)plane.pln_type].pl_flags, type); }
void pln_arm(struct emp_qelem *list, int dist, char mission, struct ichrstr *ip) { struct emp_qelem *qp; struct emp_qelem *next; struct plist *plp; struct plnstr *pp; for (qp = list->q_forw; qp != list; qp = next) { next = qp->q_forw; plp = (struct plist *)qp; pp = &plp->plane; getplane(pp->pln_uid, pp); if ((pp->pln_flags & PLN_LAUNCHED) || pln_equip(plp, ip, mission) < 0) { emp_remque(qp); free(qp); continue; } pp->pln_flags |= PLN_LAUNCHED; pp->pln_mobil -= pln_mobcost(dist, pp, mission); putplane(pp->pln_uid, pp); pr("%s equipped\n", prplane(pp)); } }
static void upd_plane(struct plnstr *pp, int etus, struct natstr *np, struct bp *bp, int build) { struct plchrstr *pcp = &plchr[(int)pp->pln_type]; int mult, cost, eff_lost; if (build == 1) { if (!pp->pln_off && np->nat_money >= 0) planerepair(pp, np, bp, etus); if (!player->simulation) pp->pln_off = 0; } else { mult = 1; if (np->nat_level[NAT_TLEV] < pp->pln_tech * 0.85) mult = 2; cost = -(mult * etus * MIN(0.0, pcp->pl_cost * money_plane)); if (np->nat_money < cost && !player->simulation) { eff_lost = etus / 5; if (pp->pln_effic - eff_lost < PLANE_MINEFF) eff_lost = pp->pln_effic - PLANE_MINEFF; if (eff_lost > 0) { wu(0, pp->pln_own, "%s lost %d%% to lack of maintenance\n", prplane(pp), eff_lost); pp->pln_effic -= eff_lost; } } else { np->nat_money -= cost; } /* flight pay is 5x the pay received by other military */ np->nat_money += etus * pcp->pl_crew * money_mil * 5; } }
void pln_newlanding(struct emp_qelem *list, coord tx, coord ty, int cno) { struct emp_qelem *qp; struct plist *plp; struct shpstr ship; struct sctstr sect; if (cno >= 0) getship(cno, &ship); for (qp = list->q_forw; qp != list; qp = qp->q_forw) { plp = (struct plist *)qp; if (cno >= 0) { if (!could_be_on_ship(&plp->plane, &ship)) pr("\t%s cannot land on ship #%d! %s aborts!\n", prplane(&plp->plane), cno, prplane(&plp->plane)); else if (!put_plane_on_ship(&plp->plane, &ship)) pr("\tNo room on ship #%d! %s aborts!\n", cno, prplane(&plp->plane)); else { if (plp->plane.pln_own != ship.shp_own) { wu(0, ship.shp_own, "%s %s lands on your %s\n", cname(player->cnum), prplane(&plp->plane), prship(&ship)); } if (plp->pcp->pl_crew && plp->pstage == PLG_INFECT && ship.shp_pstage == PLG_HEALTHY) ship.shp_pstage = PLG_EXPOSED; } } else { plp->plane.pln_x = tx; plp->plane.pln_y = ty; getsect(tx, ty, §); if (plp->plane.pln_own != sect.sct_own) { wu(0, sect.sct_own, "%s %s lands at your sector %s\n", cname(player->cnum), prplane(&plp->plane), xyas(tx, ty, sect.sct_own)); } if (plp->pcp->pl_crew && plp->pstage == PLG_INFECT && sect.sct_pstage == PLG_HEALTHY) sect.sct_pstage = PLG_EXPOSED; plp->plane.pln_ship = cno; } } }
char * unit_nameof(struct empobj *gp) { switch (gp->ef_type) { case EF_SHIP: return prship((struct shpstr *)gp); case EF_PLANE: return prplane((struct plnstr *)gp); case EF_LAND: return prland((struct lndstr *)gp); case EF_NUKE: return prnuke((struct nukstr *)gp); } CANT_REACH(); return "The Beast #666"; }
static int showsat(struct sky **skypp, int x, int y) { struct sky *skyp; struct sky *todelete = NULL; struct sky **prev; int nsat = 0; prev = NULL; skyp = *skypp; prev = skypp; do { /* we delete it, we free it. */ if (todelete) { free(todelete); todelete = NULL; } if (skyp->s_sat.pln_x != x || skyp->s_sat.pln_y != y) { prev = &(*prev)->s_next; continue; } pr(" %12.12s (#%3d) %s @ %s\n", cname(skyp->s_sat.pln_own), skyp->s_sat.pln_own, prplane(&skyp->s_sat), xyas(x, y, player->cnum)); if (opt_HIDDEN) { /* FOUND_COAST should probably be changed to FOUND_SKY -KHS */ setcont(player->cnum, skyp->s_sat.pln_own, FOUND_COAST); } *prev = skyp->s_next; todelete = skyp; nsat++; } while (NULL != (skyp = skyp->s_next)); /* check that last one! */ if (todelete) free(todelete); return nsat; }
static int load_plane_ship(struct sctstr *sectp, struct shpstr *sp, int noisy, int load_unload, int *nshipsp) { struct nstr_item ni; struct plnstr pln; int loaded = 0; char buf[1024]; char *p; char prompt[512]; struct mchrstr *mcp = mchr + sp->shp_type; if (mcp->m_nplanes + mcp->m_nchoppers + mcp->m_nxlight == 0) { if (noisy) pr("%s cannot carry planes\n", prship(sp)); return 0; } if (load_unload == LOAD && shp_nplane(sp, NULL, NULL, NULL) >= mcp->m_nchoppers + mcp->m_nxlight + mcp->m_nplanes) { if (noisy) pr("%s doesn't have room for any more planes\n", prship(sp)); return 0; } sprintf(prompt, "Plane(s) to %s %s? ", load_unload == LOAD ? "load onto" : "unload from", prship(sp)); p = getstarg(player->argp[3], prompt, buf); if (!p) return RET_SYN; if (!snxtitem(&ni, EF_PLANE, p, NULL)) return RET_SYN; if (!still_ok_ship(sectp, sp)) return RET_SYN; if (noisy && p && *p) noisy = isdigit(*p); while (nxtitem(&ni, &pln)) { if (!player->owner) continue; if (!(plchr[(int)pln.pln_type].pl_flags & P_L) && !(plchr[(int)pln.pln_type].pl_flags & P_E) && !(plchr[(int)pln.pln_type].pl_flags & P_K) && !(plchr[(int)pln.pln_type].pl_flags & P_M) ) { if (noisy) pr("You can only load light planes, helos, xtra-light, or missiles onto ships.\n"); continue; } if (load_unload == LOAD && pln.pln_ship > -1) { if (noisy) pr("%s is already on ship #%d!\n", prplane(&pln), pln.pln_ship); continue; } if (load_unload == LOAD && pln.pln_land > -1) { if (noisy) pr("%s is already on land unit #%d!\n", prplane(&pln), pln.pln_land); continue; } if (pln.pln_harden != 0) { if (noisy) pr("%s has been hardened and can't be loaded\n", prplane(&pln)); continue; } if (load_unload == UNLOAD) { if (pln.pln_ship != sp->shp_uid) continue; } else if (sp->shp_x != pln.pln_x || sp->shp_y != pln.pln_y) continue; if (!could_be_on_ship(&pln, sp)) { if (noisy) { if (plchr[(int)pln.pln_type].pl_flags & P_K) p = "choppers"; else if (plchr[(int)pln.pln_type].pl_flags & P_E) p = "extra light planes"; else if (plchr[(int)pln.pln_type].pl_flags & P_M) p = "missiles"; else p = "planes"; pr("%s cannot carry %s.\n", prship(sp), p); } continue; } /* Fit plane on ship */ if (load_unload == LOAD) { if (!put_plane_on_ship(&pln, sp)) { if (noisy) pr("Can't put plane %d on this ship!\n", pln.pln_uid); continue; } sprintf(buf, "loaded on your %s at %s", prship(sp), xyas(sp->shp_x, sp->shp_y, sp->shp_own)); gift(sp->shp_own, player->cnum, &pln, buf); putplane(pln.pln_uid, &pln); } else { pln.pln_ship = -1; sprintf(buf, "unloaded in your %s at %s", dchr[sectp->sct_type].d_name, xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own)); gift(sectp->sct_own, player->cnum, &pln, buf); putplane(pln.pln_uid, &pln); } pr("%s %s %s at %s.\n", prplane(&pln), (load_unload == UNLOAD) ? "unloaded from" : "loaded onto", prship(sp), xyas(sp->shp_x, sp->shp_y, player->cnum)); loaded = 1; } *nshipsp += loaded; return 0; }
int scra(void) { struct nstr_item ni; union empobj_storage item; int type, n; struct sctstr sect; struct mchrstr *mp; struct plchrstr *pp; struct lchrstr *lp; char *p; i_type i; char prompt[128]; char buf[1024]; float eff; short *mvec; int amt; if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf))) return RET_SYN; switch (*p) { case 's': type = EF_SHIP; break; case 'p': type = EF_PLANE; break; case 'l': type = EF_LAND; break; default: pr("Ships, land units, or planes only! (s, l, p)\n"); return RET_SYN; } if (!snxtitem(&ni, type, player->argp[2], NULL)) return RET_SYN; n = 0; while (nxtitem(&ni, &item)) { if (!player->owner) continue; n++; } snprintf(prompt, sizeof(prompt), "Really scrap %d %s%s [n]? ", n, ef_nameof(type), splur(n)); if (!confirm(prompt)) return RET_FAIL; snxtitem_rewind(&ni); while (nxtitem(&ni, &item)) { if (!player->owner) continue; if (opt_MARKET) { if (ontradingblock(type, &item.ship)) { pr("You cannot scrap an item on the trading block!\n"); continue; } } getsect(item.gen.x, item.gen.y, §); if (type == EF_SHIP) { if (!player->owner && relations_with(sect.sct_own, player->cnum) < FRIENDLY) { pr("%s is not in a friendly harbor!\n", prship(&item.ship)); continue; } if (sect.sct_type != SCT_HARBR || sect.sct_effic < 60) { pr("%s is not in a 60%% efficient harbor!\n", prship(&item.ship)); continue; } if (mchr[item.ship.shp_type].m_flags & M_TRADE) { pr("WARNING: You only collect money from trade ships if you \"scuttle\" them!\n"); sprintf(prompt, "Are you really sure that you want to scrap %s (n)? ", prship(&item.ship)); if (!confirm(prompt)) { pr("%s not scrapped\n", prship(&item.ship)); continue; } } } else { if (!player->owner && relations_with(sect.sct_own, player->cnum) != ALLIED) { pr("%s is not in an allied sector!\n", unit_nameof(&item.gen)); continue; } if (type == EF_PLANE && (sect.sct_type != SCT_AIRPT || sect.sct_effic < 60)) { pr("%s is not in a 60%% efficient airfield!\n", prplane(&item.plane)); continue; } } pr("%s scrapped in %s\n", unit_nameof(&item.gen), xyas(item.gen.x, item.gen.y, player->cnum)); unit_drop_cargo(&item.gen, sect.sct_own); if (type == EF_SHIP) { eff = item.ship.shp_effic / 100.0; mp = &mchr[(int)item.ship.shp_type]; for (i = I_NONE + 1; i <= I_MAX; i++) { if (load_comm_ok(§, item.ship.shp_own, i, -item.ship.shp_item[i])) sect.sct_item[i] += item.ship.shp_item[i]; } mvec = mp->m_mat; if (item.ship.shp_pstage == PLG_INFECT && sect.sct_pstage == PLG_HEALTHY) sect.sct_pstage = PLG_EXPOSED; } else if (type == EF_LAND) { eff = item.land.lnd_effic / 100.0; lp = &lchr[(int)item.land.lnd_type]; for (i = I_NONE + 1; i <= I_MAX; i++) { if (load_comm_ok(§, item.land.lnd_own, i, -item.land.lnd_item[i])) sect.sct_item[i] += item.land.lnd_item[i]; } mvec = lp->l_mat; if (item.land.lnd_pstage == PLG_INFECT && sect.sct_pstage == PLG_HEALTHY) sect.sct_pstage = PLG_EXPOSED; } else { eff = item.land.lnd_effic / 100.0; pp = &plchr[(int)item.plane.pln_type]; mvec = pp->pl_mat; } item.gen.effic = 0; put_empobj(type, item.gen.uid, &item.gen); for (i = I_NONE + 1; i <= I_MAX; i++) { if (i == I_CIVIL || i == I_MILIT || i == I_UW) amt = sect.sct_item[i] + mvec[i] * eff; else amt = sect.sct_item[i] + mvec[i] * 2 / 3 * eff; if (amt > ITEM_MAX) amt = ITEM_MAX; sect.sct_item[i] = amt; } putsect(§); } return RET_OK; }
static int pupgr(void) { struct sctstr sect; struct natstr *natp; struct nstr_item ni; struct plnstr plane; struct plchrstr *pp; int n; int tlev; int avail, cost; int cash; if (!snxtitem(&ni, EF_PLANE, player->argp[2], NULL)) return RET_SYN; natp = getnatp(player->cnum); cash = natp->nat_money; tlev = (int)natp->nat_level[NAT_TLEV]; n = 0; while (nxtitem(&ni, &plane)) { if (plane.pln_own == 0) continue; getsect(plane.pln_x, plane.pln_y, §); if (sect.sct_own != player->cnum) continue; if (sect.sct_type != SCT_AIRPT || sect.sct_effic < 60) continue; if (relations_with(plane.pln_own, sect.sct_own) < FRIENDLY) { pr("You are not on friendly terms with the owner of plane %d!\n", plane.pln_uid); continue; } if (pln_is_in_orbit(&plane)) { pr("Plane %s is in orbit!\n", prplane(&plane)); continue; } if (plane.pln_flags & PLN_LAUNCHED) continue; n++; pp = &plchr[(int)plane.pln_type]; avail = (PLN_BLD_WORK(pp->pl_lcm, pp->pl_hcm) * UPGR_COST + 99) / 100; if (sect.sct_avail < avail) { pr("Not enough available work in %s to upgrade a %s\n", xyas(sect.sct_x, sect.sct_y, player->cnum), pp->pl_name); pr(" (%d available work required)\n", avail); continue; } if (plane.pln_effic < 60) { pr("%s is too damaged to upgrade!\n", prplane(&plane)); continue; } if (plane.pln_tech >= tlev) { pr("%s tech: %d, yours is only %d\n", prplane(&plane), plane.pln_tech, tlev); continue; } cost = pp->pl_cost * UPGR_COST / 100; if (cost + player->dolcost > cash) { pr("You don't have enough money to upgrade %s!\n", prplane(&plane)); continue; } sect.sct_avail -= avail; plane.pln_effic -= UPGR_EFF; pln_set_tech(&plane, tlev); plane.pln_harden = 0; plane.pln_mission = 0; putplane(plane.pln_uid, &plane); putsect(§); player->dolcost += cost; pr("%s upgraded to tech %d, at a cost of %d\n", prplane(&plane), plane.pln_tech, cost); if (plane.pln_own != player->cnum) wu(0, plane.pln_own, "%s upgraded by %s to tech %d, at a cost of %d\n", prplane(&plane), cname(player->cnum), plane.pln_tech, cost); } if (n == 0) { pr("No planes.\n"); return RET_SYN; } return RET_OK; }
/* Knock down a bridge span. Note that this does NOT write the * sector out to the database, it's up to the caller to do that. */ static void knockdown(struct sctstr *sp) { struct lndstr land; struct plnstr plane; struct nukstr nuke; struct nstr_item ni; mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge%s falls at %s!\n", sp->sct_type == SCT_BTOWER ? " tower" : "", xyas(sp->sct_x, sp->sct_y, sp->sct_own)); if (!SCT_MINES_ARE_SEAMINES(sp)) sp->sct_mines = 0; sp->sct_type = SCT_WATER; sp->sct_newtype = SCT_WATER; sp->sct_own = 0; sp->sct_oldown = 0; sp->sct_mobil = 0; sp->sct_effic = 0; /* Sink all the units */ snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &land)) { if (land.lnd_own == 0) continue; if (land.lnd_ship >= 0) continue; mpr(land.lnd_own, " AARGH! %s tumbles to its doom!\n", prland(&land)); land.lnd_effic = 0; putland(land.lnd_uid, &land); } /* Sink all the planes */ snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &plane)) { if (plane.pln_own == 0) continue; if (plane.pln_flags & PLN_LAUNCHED) continue; if (plane.pln_ship >= 0) continue; mpr(plane.pln_own, " AARGH! %s tumbles to its doom!\n", prplane(&plane)); plane.pln_effic = 0; putplane(plane.pln_uid, &plane); } /* Sink all the nukes */ snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y); while (nxtitem(&ni, &nuke)) { if (nuke.nuk_own == 0) continue; if (nuke.nuk_plane >= 0) continue; mpr(nuke.nuk_own, " %s sinks to the bottom of the sea!\n", prnuke(&nuke)); nuke.nuk_effic = 0; putnuke(nuke.nuk_uid, &nuke); } memset(sp->sct_item, 0, sizeof(sp->sct_item)); memset(sp->sct_del, 0, sizeof(sp->sct_del)); memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); sp->sct_pstage = PLG_HEALTHY; sp->sct_ptime = 0; sp->sct_che = 0; sp->sct_che_target = 0; }
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; }
void pln_sel(struct nstr_item *ni, struct emp_qelem *list, struct sctstr *ap, int ap_to_target, int rangemult, int wantflags, int nowantflags) { struct plnstr plane; int range; struct plchrstr *pcp; struct plist *plp; emp_initque(list); while (nxtitem(ni, &plane)) { /* * It would be nice to let deities fly foreign planes, but * much of the code assumes that only the plane's owner can * fly it. */ if (!plane.pln_own || plane.pln_own != player->cnum) continue; if (plane.pln_mobil <= 0) continue; if (plane.pln_effic < 40) { pr("%s not efficient enough (must be 40%%)\n", prplane(&plane)); continue; } if (!pln_capable(&plane, wantflags, nowantflags)) continue; if (opt_MARKET) { if (ontradingblock(EF_PLANE, &plane)) { pr("plane #%d inelligible - it's for sale.\n", plane.pln_uid); continue; } } range = mapdist(plane.pln_x, plane.pln_y, ap->sct_x, ap->sct_y); if (range > 4) { pr("%s too far from assembly point\n", prplane(&plane)); continue; } range += ap_to_target; range *= rangemult; pcp = &plchr[(int)plane.pln_type]; if (plane.pln_range < range) { pr("%s out of range (%d:%d)\n", prplane(&plane), plane.pln_range, range); continue; } if (!pln_airbase_ok(&plane, rangemult != 2, 1)) continue; pr("%s standing by\n", prplane(&plane)); plane.pln_mission = 0; putplane(plane.pln_uid, &plane); plp = malloc(sizeof(struct plist)); plp->load = 0; plp->pstage = PLG_HEALTHY; plp->pcp = pcp; plp->plane = plane; emp_insque(&plp->queue, list); } }
int pln_airbase_ok(struct plnstr *pp, int oneway, int noisy) { struct shpstr ship; struct lndstr land; struct sctstr sect; struct plchrstr *pcp = plchr + pp->pln_type; if (CANT_HAPPEN(noisy && pp->pln_own != player->cnum)) noisy = 0; if (pp->pln_ship >= 0) { /* ship: needs to be own or allied, efficient */ if (!getship(pp->pln_ship, &ship)) { CANT_REACH(); return 0; } if (relations_with(ship.shp_own, pp->pln_own) != ALLIED) { if (noisy) pr("(note) An ally does not own the ship %s is on\n", prplane(pp)); return 0; } if (!(carrier_planes(&ship, pcp->pl_flags & P_M) & pcp->pl_flags)) return 0; } else if (pp->pln_land >= 0) { /* land: needs to be own or allied, efficient, not embarked */ if (!getland(pp->pln_land, &land)) { CANT_REACH(); return 0; } if (relations_with(land.lnd_own, pp->pln_own) != ALLIED) { if (noisy) pr("(note) An ally does not own the unit %s is on\n", prplane(pp)); return 0; } if (land.lnd_effic < LND_AIROPS_EFF || !(pcp->pl_flags & P_E)) return 0; if (land.lnd_ship >= 0 || land.lnd_land >= 0) return 0; } else { /* sector: needs to be own or allied, efficient airfield */ if (!getsect(pp->pln_x, pp->pln_y, §)) { CANT_REACH(); return 0; } if (relations_with(sect.sct_own, pp->pln_own) != ALLIED) { if (noisy) pr("(note) An ally does not own the sector %s is in\n", prplane(pp)); return 0; } /* need airfield unless VTOL */ if ((pcp->pl_flags & P_V) == 0) { if (sect.sct_type != SCT_AIRPT) { if (noisy) pr("%s not at airport\n", prplane(pp)); return 0; } if (sect.sct_effic < 40) { if (noisy) pr("%s is not 40%% efficient, %s can't take off from there.\n", xyas(sect.sct_x, sect.sct_y, player->cnum), prplane(pp)); return 0; } if (!oneway && sect.sct_effic < 60) { if (noisy) pr("%s is not 60%% efficient, %s can't land there.\n", xyas(sect.sct_x, sect.sct_y, player->cnum), prplane(pp)); return 0; } } } return 1; }
static int load_plane_land(struct sctstr *sectp, struct lndstr *lp, int noisy, int load_unload, int *nunitsp) { struct nstr_item ni; struct plnstr pln; int loaded = 0; char *p; char prompt[512]; char buf[1024]; struct lchrstr *lcp = lchr + lp->lnd_type; if (!lcp->l_nxlight) { if (noisy) pr("%s cannot carry extra-light planes.\n", prland(lp)); return 0; } if (load_unload == LOAD && lnd_nxlight(lp) >= lcp->l_nxlight) { if (noisy) pr("%s doesn't have room for any more extra-light planes\n", prland(lp)); return 0; } sprintf(prompt, "Plane(s) to %s %s? ", load_unload == LOAD ? "load onto" : "unload from", prland(lp)); p = getstarg(player->argp[3], prompt, buf); if (!p) return RET_SYN; if (!snxtitem(&ni, EF_PLANE, p, NULL)) return RET_SYN; if (!still_ok_land(sectp, lp)) return RET_SYN; if (noisy && p && *p) noisy = isdigit(*p); while (nxtitem(&ni, &pln)) { if (!player->owner) continue; if (!(plchr[(int)pln.pln_type].pl_flags & P_E)) { if (noisy) pr("You can only load xlight planes onto units.\n"); continue; } if (load_unload == LOAD && pln.pln_ship > -1) { if (noisy) pr("%s is already on ship #%d!\n", prplane(&pln), pln.pln_ship); continue; } if (load_unload == LOAD && pln.pln_land > -1) { if (noisy) pr("%s is already on unit #%d!\n", prplane(&pln), pln.pln_land); continue; } if (pln.pln_harden != 0) { if (noisy) pr("%s has been hardened and can't be loaded\n", prplane(&pln)); continue; } /* Plane sanity done */ /* Find the right unit */ if (load_unload == UNLOAD) { if (pln.pln_land != lp->lnd_uid) continue; } else if (lp->lnd_x != pln.pln_x || lp->lnd_y != pln.pln_y) continue; /* Fit plane on unit */ if (load_unload == LOAD) { if (!put_plane_on_land(&pln, lp)) { if (noisy) pr("Can't put plane %d on this unit!\n", pln.pln_uid); continue; } sprintf(buf, "loaded on %s at %s", prland(lp), xyas(lp->lnd_x, lp->lnd_y, lp->lnd_own)); gift(lp->lnd_own, player->cnum, &pln, buf); putplane(pln.pln_uid, &pln); } else { pln.pln_land = -1; sprintf(buf, "unloaded at your sector at %s", xyas(sectp->sct_x, sectp->sct_y, sectp->sct_own)); gift(sectp->sct_own, player->cnum, &pln, buf); putplane(pln.pln_uid, &pln); } pr("%s %s %s at %s.\n", prplane(&pln), (load_unload == UNLOAD) ? "unloaded from" : "loaded onto", prland(lp), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); loaded = 1; } *nunitsp += loaded; return 0; }
int detonate(struct nukstr *np, coord x, coord y, int airburst) { int nuketype = np->nuk_type; struct nchrstr *ncp; struct plnstr plane; struct sctstr sect; struct shpstr ship; struct lndstr land; struct nukstr nuke; natid own; int type; int damage; int fallout; int rad; struct nstr_sect ns; struct nstr_item ni; int changed = 0; pr("Releasing RV's for %s detonation...\n", airburst ? "airburst" : "groundburst"); getsect(x, y, §); ncp = &nchr[nuketype]; kaboom(x, y, ncp->n_blast); rad = ncp->n_blast; if (!airburst) rad = rad * 2 / 3; if (sect.sct_type == SCT_WATER) rad = 0; /* Nukes falling on water affect only 1 sector */ np->nuk_effic = 0; putnuke(np->nuk_uid, np); snxtsct_dist(&ns, x, y, rad); while (nxtsct(&ns, §)) { own = sect.sct_own; type = sect.sct_type; if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0) continue; if (type == SCT_SANCT) { pr("bounced off %s\n", xyas(ns.x, ns.y, player->cnum)); mpr(own, "%s nuclear device bounced off %s\n", cname(player->cnum), xyas(ns.x, ns.y, own)); nreport(player->cnum, N_NUKE, own, 1); continue; } sect_damage(§, damage); if (opt_FALLOUT) { fallout = sect.sct_fallout; if (ncp->n_flags & N_NEUT) fallout += damage * 30; else fallout += damage * 3; sect.sct_fallout = MIN(fallout, FALLOUT_MAX); } if (damage > 100) { sect.sct_oldown = 0; sect.sct_own = 0; if (type == SCT_WATER || type == SCT_BSPAN || type == SCT_BTOWER) { if (type != SCT_WATER) { pr("left nothing but water in %s\n", xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device left nothing but water in %s\n", cname(player->cnum), xyas(ns.x, ns.y, own)); sect.sct_newtype = SCT_WATER; sect.sct_type = SCT_WATER; } } else { sect.sct_newtype = SCT_WASTE; sect.sct_type = SCT_WASTE; pr("turned %s into a radioactive wasteland\n", xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device turned %s into a radioactive wasteland\n", cname(player->cnum), xyas(ns.x, ns.y, own)); } changed |= map_set(player->cnum, sect.sct_x, sect.sct_y, dchr[sect.sct_type].d_mnem, 0); } else { pr("did %d%% damage in %s\n", damage, xyas(ns.x, ns.y, player->cnum)); if (own != player->cnum) mpr(own, "%s nuclear device did %d%% damage in %s\n", cname(player->cnum), damage, xyas(ns.x, ns.y, own)); } (void)putsect(§); if (type != SCT_WATER) nreport(player->cnum, N_NUKE, own, 1); } if (changed) writebmap(player->cnum); snxtitem_dist(&ni, EF_PLANE, x, y, rad); while (nxtitem(&ni, &plane)) { if ((own = plane.pln_own) == 0) continue; if (plane.pln_flags & PLN_LAUNCHED) continue; damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden; if (damage <= 0) continue; if (plane.pln_ship >= 0) { /* Are we on a sub? */ getship(plane.pln_ship, &ship); if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } } planedamage(&plane, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prplane(&plane), xyas(plane.pln_x, plane.pln_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prplane(&plane), xyas(plane.pln_x, plane.pln_y, own)); } putplane(ni.cur, &plane); } snxtitem_dist(&ni, EF_LAND, x, y, rad); while (nxtitem(&ni, &land)) { if ((own = land.lnd_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (land.lnd_ship >= 0) { /* Are we on a sub? */ getship(land.lnd_ship, &ship); if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } } land_damage(&land, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prland(&land), xyas(land.lnd_x, land.lnd_y, own)); } putland(land.lnd_uid, &land); } snxtitem_dist(&ni, EF_SHIP, x, y, rad); while (nxtitem(&ni, &ship)) { if ((own = ship.shp_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (mchr[(int)ship.shp_type].m_flags & M_SUB) { struct sctstr sect1; /* Should we damage this sub? */ getsect(ship.shp_x, ship.shp_y, §1); if (sect1.sct_type == SCT_BSPAN || sect1.sct_type == SCT_BTOWER || sect1.sct_type == SCT_WATER) { /* Ok, we're not in a harbor or trapped inland. Now, did we get pasted directly? */ if (ship.shp_x != x || ship.shp_y != y) { /* Nope, so don't mess with it */ continue; } } } ship_damage(&ship, damage); if (own == player->cnum) { pr("%s at %s reports %d%% damage\n", prship(&ship), xyas(ship.shp_x, ship.shp_y, player->cnum), damage); } else { mpr(own, "%s nuclear device did %d%% damage to %s at %s\n", cname(player->cnum), damage, prship(&ship), xyas(ship.shp_x, ship.shp_y, own)); } putship(ship.shp_uid, &ship); } snxtitem_dist(&ni, EF_NUKE, x, y, rad); while (nxtitem(&ni, &nuke)) { if ((own = nuke.nuk_own) == 0) continue; if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0) continue; if (!pct_chance(damage)) continue; nuke.nuk_effic = 0; if (own == player->cnum) { pr("%s at %s destroyed\n", prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, player->cnum)); } else { mpr(own, "%s nuclear device destroyed %s at %s\n", cname(player->cnum), prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, own)); } putnuke(ni.cur, &nuke); } return nukedamage(ncp, 0, airburst); }
static void look_land(struct lndstr *lookland) { struct plnstr *pp; struct lndstr *lp; double drange; int range; int vrange; int i; int dist; drange = techfact(lookland->lnd_tech, lchr[lookland->lnd_type].l_spy); drange *= lookland->lnd_effic / 100.0; range = ldround(drange, 1); if (range == 0) return; for (i = 0; NULL != (lp = getlandp(i)); i++) { if (lp->lnd_own == player->cnum || lp->lnd_own == 0) continue; if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; /* Don't always see spies */ if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { /* If it's on a ship or unit, assume it's hidden enough not to be seen */ if (lp->lnd_ship >= 0 || lp->lnd_land >= 0) continue; if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic)))) continue; } vrange = ldround((lnd_vis(lp) * range) / 20.0, 1); dist = mapdist(lp->lnd_x, lp->lnd_y, lookland->lnd_x, lookland->lnd_y); if (dist > vrange) continue; pr("%s %s (approx %d mil) @ %s\n", prnatid(lp->lnd_own), prland(lp), roundintby(lp->lnd_item[I_MILIT], 20), xyas(lp->lnd_x, lp->lnd_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, lp->lnd_own, FOUND_LOOK); } for (i = 0; NULL != (pp = getplanep(i)); i++) { if (pp->pln_own == player->cnum || pp->pln_own == 0) continue; if (pp->pln_ship >= 0 || pp->pln_land >= 0) continue; if (pp->pln_flags & PLN_LAUNCHED) continue; vrange = ldround((10 * range) / 20.0, 1); dist = mapdist(pp->pln_x, pp->pln_y, lookland->lnd_x, lookland->lnd_y); if (dist > vrange) continue; pr("%s %s @ %s\n", prnatid(pp->pln_own), prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum)); if (opt_HIDDEN) setcont(player->cnum, pp->pln_own, FOUND_LOOK); } }