]> git.pond.sub.org Git - empserver/blob - src/lib/subs/detonate.c
Import of Empire 4.2.12
[empserver] / src / lib / subs / detonate.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program 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 2 of the License, or
9  *  (at your option) any later version.
10  *
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.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  detonate.c: Detonate a nuclear device in a sector.
29  * 
30  *  Known contributors to this file:
31  *     Steve McClure, 1998-2000
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "xy.h"
37 #include "nat.h"
38 #include "file.h"
39 #include "sect.h"
40 #include "nuke.h"
41 #include "ship.h"
42 #include "land.h"
43 #include "news.h"
44 #include "plane.h"
45 #include "nsc.h"
46 #include "var.h"
47 #include "optlist.h"
48 #include "prototypes.h"
49
50 void kaboom(int x, int y, int rad, natid cn);
51
52 int
53 detonate(struct plnstr *pp, int x, int y)
54 {
55         int     nuketype = pp->pln_nuketype;
56         natid   bombown = pp->pln_own;
57         int     airburst = (pp->pln_flags & PLN_AIRBURST);
58         struct  nchrstr *ncp;
59         struct  plnstr plane;
60         struct  sctstr sect;
61         struct  shpstr ship;
62         struct  lndstr land;
63         struct  nukstr nuke;
64         s_char  *bp;
65         s_char  buf[128];
66         s_char  buf2[128];
67         natid   own;
68         int     type;
69         int     damage;
70         int     fallout;
71         int     rad;
72         struct  nstr_sect ns;
73         struct  nstr_item ni;
74         int     issea = 0;
75         int     retval;
76
77         pp->pln_nuketype = -1;
78         getsect(x,y,&sect);
79         if (sect.sct_type == SCT_WATER)
80                 issea = 1;
81         ncp = &nchr[nuketype];
82         kaboom(x, y, ncp->n_blast, bombown);
83         rad = ncp->n_blast;
84         if (!airburst)
85                 rad = rad * 2 / 3;
86         snxtsct_dist(&ns, x, y, rad);
87         while (nxtsct(&ns, &sect)) {
88             /* Nukes falling on water affect only 1 sector */
89             if ((sect.sct_x != x) && issea)
90                 continue;
91             if ((sect.sct_y != y) && issea)
92                 continue;
93             own = sect.sct_own;
94             type = sect.sct_type;
95             if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0)
96                 continue;
97             if (type == SCT_SANCT) {
98                 mpr(bombown,"bounced off %s\n", xyas(ns.x, ns.y, bombown));
99                 if(own != 0)
100                     mpr(own, "%s nuclear device bounced off %s\n",
101                         cname(bombown), xyas(ns.x, ns.y, bombown));
102                 nreport(bombown, N_NUKE, own, 1);
103                 continue;
104             }
105             if (opt_FALLOUT)
106                 fallout = getvar(V_FALLOUT,(s_char *)&sect,EF_SECTOR);
107             sect_damage(&sect, damage, 0);
108             if (sect.sct_x == x && sect.sct_y == y)
109                 retval = damage;
110             if (opt_FALLOUT) {
111                 if (opt_NEUTRON && (ncp->n_flags & N_NEUT))
112                     fallout += damage*30;
113                 else
114                     fallout += damage*3;
115                 putvar(V_FALLOUT,fallout,(s_char *)&sect,EF_SECTOR);
116             }
117             if (damage > 100) {
118                 makelost(EF_SECTOR, sect.sct_own, 0, sect.sct_x, sect.sct_y);
119                 sect.sct_oldown = 0;
120                 sect.sct_own = 0;
121                 if (type == SCT_WATER || type == SCT_BSPAN ||
122                     type == SCT_BTOWER) {
123                     bp = "left nothing but water in %s\n";
124                     if (type != SCT_WATER) {
125                         sect.sct_newtype = SCT_WATER;
126                         sect.sct_type = SCT_WATER;
127                     }
128                 } else {
129                     sect.sct_newtype = SCT_WASTE;
130                     sect.sct_type = SCT_WASTE;
131                     bp = "turned %s into a radioactive wasteland\n";
132                 }
133             } else {
134                 sprintf(buf, "did %d%%%% damage in %%s\n", damage);
135                 bp = buf;
136             }
137             if ((type == SCT_CAPIT || type == SCT_MOUNT) && damage >= 100)
138                 caploss(&sect, own, "\n%s lost its capital!\n\n");
139             (void) putsect(&sect);
140             if (type != SCT_WATER)
141                 nreport(bombown, N_NUKE, own, 1);
142             mpr(bombown,bp, xyas(ns.x, ns.y, bombown));
143             if (own != bombown && own != 0) {
144                 (void) sprintf(buf2, bp, xyas(ns.x, ns.y, own));
145                 mpr(own, "%s nuclear device %s\n",
146                     cname(bombown), buf2);
147             }
148         }
149         snxtitem_dist(&ni, EF_PLANE, x, y, rad);
150         while (nxtitem(&ni, (caddr_t)&plane)) {
151                 /* Nukes falling on water affect only 1 sector */
152                 if ((plane.pln_x != x) && issea)
153                         continue;
154                 if ((plane.pln_y != y) && issea)
155                         continue;
156                 if ((own = plane.pln_own) == 0)
157                         continue;
158                 if ((plane.pln_flags & PLN_LAUNCHED) && (airburst != 2))
159                         continue;
160                 damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden;
161                 if (damage <= 0)
162                         continue;
163                 if (plane.pln_ship >= 0) {
164                   /* Are we on a sub? */
165                   getship(plane.pln_ship, &ship);
166
167                   if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
168                     struct sctstr       sect1;
169                     
170                     /* Should we damage this sub? */
171                     getsect(ship.shp_x,ship.shp_y,&sect1);
172                     
173                     if (sect1.sct_type == SCT_BSPAN ||
174                         sect1.sct_type == SCT_BTOWER ||
175                         sect1.sct_type == SCT_WATER) {
176                       /* Ok, we're not in a harbor or trapped
177                          inland.  Now, did we get pasted
178                          directly? */
179                       if (ship.shp_x != x || ship.shp_y != y) {
180                         /* Nope, so don't mess with it */
181                         continue;
182                       }
183                     }
184                   }
185                 }
186                 planedamage(&plane, damage);
187                 if (own == bombown) {
188                         mpr(bombown,"%s at %s reports %d%% damage\n",
189                             prplane(&plane),
190                             xyas(plane.pln_x, plane.pln_y, own),
191                             damage);
192                 } else {
193                         if(own != 0)
194                         mpr(own,
195                             "%s nuclear device did %d%% damage to %s at %s\n",
196                             cname(bombown), damage,
197                             prplane(&plane),
198                             xyas(plane.pln_x, plane.pln_y, own));
199                 }
200                 putplane(ni.cur, &plane);
201         }
202         snxtitem_dist(&ni, EF_LAND, x, y, rad);
203         while (nxtitem(&ni, (caddr_t)&land)) {
204                 /* Nukes falling on water affect only 1 sector */
205                 if ((land.lnd_x != x) && issea)
206                         continue;
207                 if ((land.lnd_y != y) && issea)
208                         continue;
209                 if ((own = land.lnd_own) == 0)
210                         continue;
211                 if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
212                         continue;
213
214                 if (land.lnd_ship >= 0) {
215                   /* Are we on a sub? */
216                   getship(land.lnd_ship, &ship);
217
218                   if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
219                     struct sctstr       sect1;
220                     
221                     /* Should we damage this sub? */
222                     getsect(ship.shp_x,ship.shp_y,&sect1);
223                     
224                     if (sect1.sct_type == SCT_BSPAN ||
225                         sect1.sct_type == SCT_BTOWER ||
226                         sect1.sct_type == SCT_WATER) {
227                       /* Ok, we're not in a harbor or trapped
228                          inland.  Now, did we get pasted
229                          directly? */
230                       if (ship.shp_x != x || ship.shp_y != y) {
231                         /* Nope, so don't mess with it */
232                         continue;
233                       }
234                     }
235                   }
236                 }
237                 land_damage(&land, damage);
238                 if (own == bombown) {
239                         mpr(bombown,"%s at %s reports %d%% damage\n",
240                             prland(&land),
241                             xyas(land.lnd_x, land.lnd_y, own), damage);
242                 } else {
243                         if(own != 0)
244                                 mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
245                                     cname(bombown), damage,
246                                     prland(&land),
247                                     xyas(land.lnd_x, land.lnd_y, own));
248                 }
249                 putland(land.lnd_uid, &land);
250         }
251         snxtitem_dist(&ni, EF_SHIP, x, y, rad);
252         while (nxtitem(&ni, (caddr_t)&ship)) {
253                 /* Nukes falling on water affect only 1 sector */
254                 if ((ship.shp_x != x) && issea)
255                         continue;
256                 if ((ship.shp_y != y) && issea)
257                         continue;
258                 if ((own = ship.shp_own) == 0)
259                         continue;
260                 if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
261                         continue;
262                 if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
263                   struct sctstr sect1;
264
265                   /* Should we damage this sub? */
266                   getsect(ship.shp_x,ship.shp_y,&sect1);
267                   
268                   if (sect1.sct_type == SCT_BSPAN ||
269                       sect1.sct_type == SCT_BTOWER ||
270                       sect1.sct_type == SCT_WATER) {
271                     /* Ok, we're not in a harbor or trapped
272                        inland.  Now, did we get pasted
273                        directly? */
274                     if (ship.shp_x != x || ship.shp_y != y) {
275                       /* Nope, so don't mess with it */
276                       continue;
277                     }
278                   }
279                 }
280                 ship_damage(&ship, damage);
281                 if (own == bombown) {
282                         mpr(bombown,"%s at %s reports %d%% damage\n",
283                             prship(&ship),
284                             xyas(ship.shp_x, ship.shp_y, own), damage);
285                 } else {
286                         if(own != 0)
287                                 mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
288                                     cname(bombown), damage, prship(&ship),
289                                     xyas(ship.shp_x, ship.shp_y, own));
290                 }
291                 putship(ship.shp_uid, &ship);
292         }
293         snxtitem_dist(&ni, EF_NUKE, x, y, rad);
294         while (nxtitem(&ni, (caddr_t)&nuke)) {
295                 /* Nukes falling on water affect only 1 sector */
296                 if ((nuke.nuk_x != x) && issea)
297                         continue;
298                 if ((nuke.nuk_y != y) && issea)
299                         continue;
300                 if ((own = nuke.nuk_own) == 0)
301                         continue;
302                 if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
303                         continue;
304                 if (roll(100) >= damage)
305                         continue;
306                 makelost(EF_NUKE, nuke.nuk_own, nuke.nuk_uid, nuke.nuk_x, nuke.nuk_y);
307                 nuke.nuk_own = 0;
308                 if (own == bombown) {
309                         mpr(bombown,"nuclear stockpile #%d at %s destroyed\n",
310                                 ni.cur, xyas(nuke.nuk_x, nuke.nuk_y, own));
311                 } else {
312                         if(own != 0)
313                         mpr(own, "nuclear stockpile #%d at %s destroyed\n",
314                                 ni.cur, xyas(nuke.nuk_x, nuke.nuk_y, own));
315                 }
316                 putnuke(ni.cur, &nuke);
317         }
318         return retval;
319 }
320
321
322 /*
323  * silly to be sure.
324  */
325 void
326 kaboom(int x, int y, int rad, natid cn)
327 {
328         mpr(cn,"\n\nK A B ");
329         while (rad-- > 0)
330                 mpr(cn,"O O ");
331         mpr(cn,"M ! in %s\n\n", xyas(x, y, cn));
332 }