2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
6 * Empire is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * See files README, COPYING and CREDITS in the root of the source
22 * tree for related information and legal notices. It is expected
23 * that future projects/authors will amend these files as needed.
27 * detonate.c: Detonate a nuclear device in a sector.
29 * Known contributors to this file:
30 * Steve McClure, 1998-2000
31 * Markus Armbruster, 2004-2012
48 #include "prototypes.h"
53 static void kaboom(int x, int y, int rad);
56 detonate(struct nukstr *np, coord x, coord y, int airburst)
58 int nuketype = np->nuk_type;
74 pr("Releasing RV's for %s detonation...\n",
75 airburst ? "airburst" : "groundburst");
78 ncp = &nchr[nuketype];
79 kaboom(x, y, ncp->n_blast);
83 if (sect.sct_type == SCT_WATER)
84 rad = 0; /* Nukes falling on water affect only 1 sector */
86 putnuke(np->nuk_uid, np);
88 snxtsct_dist(&ns, x, y, rad);
89 while (nxtsct(&ns, §)) {
92 if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0)
94 if (type == SCT_SANCT) {
95 pr("bounced off %s\n", xyas(ns.x, ns.y, player->cnum));
96 mpr(own, "%s nuclear device bounced off %s\n",
97 cname(player->cnum), xyas(ns.x, ns.y, own));
98 nreport(player->cnum, N_NUKE, own, 1);
101 sect_damage(§, damage);
103 fallout = sect.sct_fallout;
104 if (ncp->n_flags & N_NEUT)
105 fallout += damage * 30;
107 fallout += damage * 3;
108 sect.sct_fallout = MIN(fallout, FALLOUT_MAX);
113 if (type == SCT_WATER || type == SCT_BSPAN ||
114 type == SCT_BTOWER) {
115 if (type != SCT_WATER) {
116 pr("left nothing but water in %s\n",
117 xyas(ns.x, ns.y, player->cnum));
118 if (own != player->cnum)
120 "%s nuclear device left nothing but water in %s\n",
121 cname(player->cnum), xyas(ns.x, ns.y, own));
122 sect.sct_newtype = SCT_WATER;
123 sect.sct_type = SCT_WATER;
126 sect.sct_newtype = SCT_WASTE;
127 sect.sct_type = SCT_WASTE;
128 pr("turned %s into a radioactive wasteland\n",
129 xyas(ns.x, ns.y, player->cnum));
130 if (own != player->cnum)
132 "%s nuclear device turned %s into a radioactive wasteland\n",
133 cname(player->cnum), xyas(ns.x, ns.y, own));
135 changed |= map_set(player->cnum, sect.sct_x, sect.sct_y,
136 dchr[sect.sct_type].d_mnem, 0);
138 pr("did %d%% damage in %s\n",
139 damage, xyas(ns.x, ns.y, player->cnum));
140 if (own != player->cnum)
141 mpr(own, "%s nuclear device did %d%% damage in %s\n",
142 cname(player->cnum), damage, xyas(ns.x, ns.y, own));
144 (void)putsect(§);
145 if (type != SCT_WATER)
146 nreport(player->cnum, N_NUKE, own, 1);
150 writebmap(player->cnum);
152 snxtitem_dist(&ni, EF_PLANE, x, y, rad);
153 while (nxtitem(&ni, &plane)) {
154 if ((own = plane.pln_own) == 0)
156 if (plane.pln_flags & PLN_LAUNCHED)
158 damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden;
161 if (plane.pln_ship >= 0) {
162 /* Are we on a sub? */
163 getship(plane.pln_ship, &ship);
165 if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
168 /* Should we damage this sub? */
169 getsect(ship.shp_x, ship.shp_y, §1);
171 if (sect1.sct_type == SCT_BSPAN ||
172 sect1.sct_type == SCT_BTOWER ||
173 sect1.sct_type == SCT_WATER) {
174 /* Ok, we're not in a harbor or trapped
175 inland. Now, did we get pasted
177 if (ship.shp_x != x || ship.shp_y != y) {
178 /* Nope, so don't mess with it */
184 planedamage(&plane, damage);
185 if (own == player->cnum) {
186 pr("%s at %s reports %d%% damage\n",
188 xyas(plane.pln_x, plane.pln_y, player->cnum), damage);
190 mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
191 cname(player->cnum), damage,
192 prplane(&plane), xyas(plane.pln_x, plane.pln_y, own));
194 putplane(ni.cur, &plane);
197 snxtitem_dist(&ni, EF_LAND, x, y, rad);
198 while (nxtitem(&ni, &land)) {
199 if ((own = land.lnd_own) == 0)
201 if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
204 if (land.lnd_ship >= 0) {
205 /* Are we on a sub? */
206 getship(land.lnd_ship, &ship);
208 if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
211 /* Should we damage this sub? */
212 getsect(ship.shp_x, ship.shp_y, §1);
214 if (sect1.sct_type == SCT_BSPAN ||
215 sect1.sct_type == SCT_BTOWER ||
216 sect1.sct_type == SCT_WATER) {
217 /* Ok, we're not in a harbor or trapped
218 inland. Now, did we get pasted
220 if (ship.shp_x != x || ship.shp_y != y) {
221 /* Nope, so don't mess with it */
227 land_damage(&land, damage);
228 if (own == player->cnum) {
229 pr("%s at %s reports %d%% damage\n",
230 prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum),
233 mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
234 cname(player->cnum), damage,
235 prland(&land), xyas(land.lnd_x, land.lnd_y, own));
237 putland(land.lnd_uid, &land);
240 snxtitem_dist(&ni, EF_SHIP, x, y, rad);
241 while (nxtitem(&ni, &ship)) {
242 if ((own = ship.shp_own) == 0)
244 if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
246 if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
249 /* Should we damage this sub? */
250 getsect(ship.shp_x, ship.shp_y, §1);
252 if (sect1.sct_type == SCT_BSPAN ||
253 sect1.sct_type == SCT_BTOWER ||
254 sect1.sct_type == SCT_WATER) {
255 /* Ok, we're not in a harbor or trapped
256 inland. Now, did we get pasted
258 if (ship.shp_x != x || ship.shp_y != y) {
259 /* Nope, so don't mess with it */
264 ship_damage(&ship, damage);
265 if (own == player->cnum) {
266 pr("%s at %s reports %d%% damage\n",
267 prship(&ship), xyas(ship.shp_x, ship.shp_y, player->cnum),
270 mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
271 cname(player->cnum), damage, prship(&ship),
272 xyas(ship.shp_x, ship.shp_y, own));
274 putship(ship.shp_uid, &ship);
277 snxtitem_dist(&ni, EF_NUKE, x, y, rad);
278 while (nxtitem(&ni, &nuke)) {
279 if ((own = nuke.nuk_own) == 0)
281 if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
283 if (!pct_chance(damage))
286 if (own == player->cnum) {
287 pr("%s at %s destroyed\n",
288 prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, player->cnum));
290 mpr(own, "%s nuclear device destroyed %s at %s\n",
291 cname(player->cnum), prnuke(&nuke),
292 xyas(nuke.nuk_x, nuke.nuk_y, own));
294 putnuke(ni.cur, &nuke);
297 return nukedamage(ncp, 0, airburst);
305 kaboom(int x, int y, int rad)
307 pr("\n\nK A B O O ");
310 pr("M ! in %s\n\n", xyas(x, y, player->cnum));