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"; }
/* 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 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); }
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; }