int sabo(void) { struct nstr_item ni; struct lndstr land, tmp; struct sctstr sect; double odds; int dam; if (!snxtitem(&ni, EF_LAND, player->argp[1], NULL)) return RET_SYN; while (nxtitem(&ni, &land)) { if (!player->owner) continue; if (!(lchr[(int)land.lnd_type].l_flags & L_SPY)) { pr("%s is not a spy.\n", prland(&land)); continue; } if (land.lnd_ship >= 0) { pr("%s is on ship %d.\n", prland(&land), land.lnd_ship); continue; } if (land.lnd_land >= 0) { pr("%s is on unit %d.\n", prland(&land), land.lnd_land); continue; } if (!getsect(land.lnd_x, land.lnd_y, §)) continue; if (land.lnd_item[I_SHELL] == 0) { pr("%s has no shells.\n", prland(&land)); continue; } odds = LND_SPY_DETECT_CHANCE(land.lnd_effic); if (chance(odds)) { wu(0, sect.sct_own, "%s spy shot in %s during sabotage attempt.\n", cname(player->cnum), xyas(sect.sct_x, sect.sct_y, sect.sct_own)); pr("%s was shot and killed.\n", prland(&land)); land.lnd_effic = 0; putland(land.lnd_uid, &land); continue; } dam = lnd_sabo(&land, sect.sct_item); if (dam < 0) continue; pr("Explosion in %s causes %d damage.\n", xyas(land.lnd_x, land.lnd_y, player->cnum), dam); if (sect.sct_own) { wu(0, sect.sct_own, "Sabotage in sector %s caused %d damage.\n", xyas(sect.sct_x, sect.sct_y, sect.sct_own), dam); } /* hack: hide the spy so it don't gets blasted by sectdamage() */ tmp = land; tmp.lnd_own = 0; putland(land.lnd_uid, &tmp); land.lnd_seqno = tmp.lnd_seqno; sectdamage(§, dam); putsect(§); if (chance(odds)) { pr("%s dies in explosion.\n", prland(&land)); land.lnd_effic = 0; } putland(land.lnd_uid, &land); } return RET_OK; }
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; }