1 /*
2  * Triplane Classic - a side-scrolling dogfighting game.
3  * Copyright (C) 1996,1997,2009  Dodekaedron Software Creations Oy
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * tjt@users.sourceforge.net
19  */
20 
21 /* Triplane Turmoil flying objects code */
22 
23 #include "world/constants.h"
24 #include "triplane.h"
25 #include "tripai.h"
26 #include "util/wutil.h"
27 #include "world/plane.h"
28 #include "io/sound.h"
29 #include "world/tripaudio.h"
30 
31 void do_shots(void);
32 void start_shot(int player);
33 void start_shot(int x, int y, int angle, int speed, int infan = -1);
34 void do_fobjects(void);
35 void start_smoke(int player);
36 void start_ssmoke(int x, int y);
37 void detect_damage(void);
38 void start_parts(int player);
39 void start_rifle(int x, int y);
40 void start_gun_wave(int x);
41 void drop_bomb(int player, int target = -1);
42 void do_bombs(void);
43 void start_bomb_explo(int l, int hitted = 0);
44 void start_explox(int x, int y);
45 void start_wave(int x);
46 void start_flame(int x, int y, int width);
47 void do_flames(void);
48 void start_one_flame(int x, int y);
49 
50 int flame_x[MAX_FLAMES];
51 int flame_y[MAX_FLAMES];
52 int flame_width[MAX_FLAMES];
53 int flame_age[MAX_FLAMES];
54 
55 /******************************************************************************/
56 
start_flame(int x,int y,int width)57 void start_flame(int x, int y, int width) {
58     int l;
59 
60     for (l = 0; l < MAX_FLAMES; l++)
61         if (!flame_x[l])
62             break;
63 
64     if (l == MAX_FLAMES)
65         return;
66 
67     flame_x[l] = x + 3;
68     flame_y[l] = y - 7;
69     flame_width[l] = width - 6;
70     flame_age[l] = FLAME_AGE;
71 }
72 
do_flames(void)73 void do_flames(void) {
74     int l;
75 
76     for (l = 0; l < MAX_FLAMES; l++) {
77         if (!flame_x[l])
78             continue;
79 
80         if (!(--flame_age[l])) {
81             flame_x[l] = 0;
82             continue;
83 
84         }
85 
86 
87         start_one_flame(flame_x[l] + wrandom(flame_width[l]), flame_y[l]);
88 
89     }
90 
91 }
92 
start_one_flame(int x,int y)93 void start_one_flame(int x, int y) {
94     int l;
95 
96     for (l = 0; l < MAX_FLYING_OBJECTS; l++)
97         if (!fobjects[l].x)
98             break;
99 
100     if (l != MAX_FLYING_OBJECTS) {
101         fobjects[l].x = x << 8;
102         fobjects[l].y = y << 8;
103 
104         fobjects[l].x_speed = 0;
105         fobjects[l].y_speed = 0;
106         fobjects[l].hit_plane = 0;
107         fobjects[l].width = 7;
108         fobjects[l].height = 14;
109         fobjects[l].type = FOBJECTS_FLAME;
110         fobjects[l].phase = 0;
111     }
112 
113 }
114 
115 
do_shots(void)116 void do_shots(void) {
117     int l, l2;
118     unsigned char kohta;
119 
120     for (l = 0; l < MAX_SHOTS; l++) {
121         if (shots_flying_x[l]) {
122 
123             shots_flying_y_speed[l] -= SHOTS_GRAVITY;
124             shots_flying_x[l] += shots_flying_x_speed[l] >> 9;
125             shots_flying_y[l] -= shots_flying_y_speed[l] >> 9;
126 
127             if ((shots_flying_x[l] < 0) || ((shots_flying_x[l] >> 8) >= NUMBER_OF_SCENES * 160) || shots_flying_y[l] < 0 || (shots_flying_y[l] >> 8) >= 200)
128                 shots_flying_x[l] = 0;
129             else {
130                 kohta = level_bitmap[(shots_flying_x[l] >> 8) + (shots_flying_y[l] >> 8) * 2400];
131                 if (kohta < 112 || kohta > 119) {
132                     if (kohta >= 224 && kohta <= 231)
133                         start_gun_wave(shots_flying_x[l] >> 8);
134 
135                     shots_flying_x[l] = 0;
136                 }
137             }
138 
139             if ((shots_flying_age[l]++) > SHOTS_RANGE)
140                 shots_flying_x[l] = 0;
141 
142             for (l2 = 0; l2 < 16; l2++) {
143                 if (plane_present[l2])
144                     if (((player_x[l2] + 2304) > shots_flying_x[l]) &&
145                         ((player_x[l2] - 2304) < shots_flying_x[l]) &&
146                         ((player_y[l2] + 2304) > shots_flying_y[l]) && ((player_y[l2] - 2304) < shots_flying_y[l]))
147                         if (plane_p[l2][(player_angle[l2] >> 8) / 6][player_rolling[l2]][player_upsidedown[l2]]
148                             [(shots_flying_x[l] >> 8) - (player_x_8[l2]) + 10 + ((shots_flying_y[l] >> 8) - (player_y_8[l2]) + 10) * 20] != 255) {
149 
150                             if (config.sound_on && config.sfx_on)
151                                 play_2d_sample(sample_hit[wrandom(4)], player_x_8[solo_country], player_x_8[l2]);
152 
153                             shots_flying_x[l] = 0;
154 
155                             if (shots_flying_owner[l] != -1) {
156                                 player_hits[shots_flying_owner[l]]++;
157                                 player_endurance[l2] -= wrandom(12);
158                             } else
159                                 player_endurance[l2] -= wrandom(6);
160 
161                             if (player_endurance[l2] < 1) {
162                                 if (!player_spinning[l2] && !in_closing[l2]) {
163                                     if (shots_flying_owner[l] != -1) {
164                                         if (player_sides[l2] != player_sides[shots_flying_owner[l]]) {
165                                             player_points[shots_flying_owner[l]]++;
166 
167                                         } else {
168                                             player_points[shots_flying_owner[l]]--;
169                                         }
170 
171                                         player_shots_down[shots_flying_owner[l]][l2]++;
172                                     }
173                                 }
174                                 if (wrandom(4) && (!player_on_airfield[l2]))
175                                     player_spinning[l2] = 1;
176                                 else {
177                                     in_closing[l2] = 2;
178                                     plane_present[l2] = 0;
179                                     start_parts(l2);
180                                 }
181                             }
182                             break;
183                         }
184             }
185         }
186 
187 
188     }
189 
190 }
191 
start_shot(int x,int y,int angle,int speed,int infan)192 void start_shot(int x, int y, int angle, int speed, int infan) {
193     int l;
194 
195     for (l = 0; l < MAX_SHOTS; l++)
196         if (!shots_flying_x[l])
197             break;
198 
199     if (l != MAX_SHOTS) {
200         shots_flying_age[l] = 0;
201         shots_flying_x[l] = (x << 8);
202         shots_flying_y[l] = (y << 8);
203         shots_flying_x_speed[l] = (cosinit[angle] * speed) >> 2;
204         shots_flying_y_speed[l] = (sinit[angle] * speed) >> 2;
205         shots_flying_x[l] += shots_flying_x_speed[l] >> 6;
206         shots_flying_y[l] -= shots_flying_y_speed[l] >> 6;
207         shots_flying_owner[l] = -1;
208         shots_flying_infan[l] = infan;
209     }
210 
211 }
212 
213 
start_shot(int player)214 void start_shot(int player) {
215     int l;
216     int plane_type = player;
217 
218     player_last_shot[player] = 0;
219 
220     if (in_closing[player])
221         return;
222 
223     player_fired[player]++;
224     player_ammo[player]--;
225     for (l = 0; l < MAX_SHOTS; l++)
226         if (!shots_flying_x[l])
227             break;
228 
229     if (l != MAX_SHOTS) {
230         shots_flying_age[l] = 0;
231         shots_flying_x[l] = player_x[player] + 12 * cosinit[player_angle[player] >> 8];
232         shots_flying_y[l] = player_y[player] - 12 * sinit[player_angle[player] >> 8];
233         shots_flying_x_speed[l] = (cosinit[player_angle[player] >> 8] * (player_speed[player] + SHOTS_SPEED)) >> 2;
234         shots_flying_y_speed[l] = (sinit[player_angle[player] >> 8] * (player_speed[player] + SHOTS_SPEED)) >> 2;
235         shots_flying_owner[l] = player;
236         shots_flying_infan[l] = -1;
237     }
238     if (config.gunshot_sounds && config.sound_on && config.sfx_on) {
239         if (plane_type == 0 || plane_type > 3)
240             plane_type = 1;
241         play_2d_sample(sample_konsu[plane_type], player_x_8[solo_country], player_x_8[player]);
242     }
243 }
244 
do_fobjects(void)245 void do_fobjects(void) {
246     int l, l2;
247 
248     for (l = 0; l < MAX_FLYING_OBJECTS; l++) {
249         if (fobjects[l].x) {
250 
251             fobjects[l].x += fobjects[l].x_speed >> 8;
252             fobjects[l].y -= fobjects[l].y_speed >> 8;
253 
254             if ((fobjects[l].y < 0) || (fobjects[l].x < 0) || ((fobjects[l].x >> 8) >= NUMBER_OF_SCENES * 160) || (fobjects[l].y >> 8) >= 200) {
255                 fobjects[l].x = 0;
256                 continue;
257             }
258 
259             if ((level_bitmap[(fobjects[l].x >> 8) + (fobjects[l].y >> 8) * 2400]) < 112
260                 || ((level_bitmap[(fobjects[l].x >> 8) + (fobjects[l].y >> 8) * 2400])) > 119) {
261                 fobjects[l].x = 0;
262                 continue;
263             }
264 
265             if (fobjects[l].hit_plane && part_collision_detect)
266                 for (l2 = 0; l2 < 16; l2++) {
267                     if (plane_present[l2]) {
268                         if (((player_x[l2] + 2304) > fobjects[l].x) &&
269                             ((player_x[l2] - 2304) < fobjects[l].x) && ((player_y[l2] + 2304) > fobjects[l].y) && ((player_y[l2] - 2304) < fobjects[l].y))
270                             if (plane_p[l2][(player_angle[l2] >> 8) / 6][player_rolling[l2]][player_upsidedown[l2]]
271                                 [(fobjects[l].x >> 8) - (player_x_8[l2]) + 10 + ((fobjects[l].y >> 8) - (player_y_8[l2]) + 10) * 20] != 255) {
272                                 fobjects[l].x = 0;
273                                 player_endurance[l2] -= wrandom(FOBJECTS_DAMAGE);
274                                 if (player_endurance[l2] < 1) {
275                                     if ((fobjects[l].owner != -1) && (!player_spinning[l2])) {
276                                         player_shots_down[fobjects[l].owner][l2]++;
277                                         if (player_sides[fobjects[l].owner] != player_sides[l2])
278                                             player_points[fobjects[l].owner]++;
279                                         else
280                                             player_points[fobjects[l].owner]--;
281                                     }
282 
283                                     if (wrandom(2) == 1 && (!player_on_airfield[l2]))
284                                         player_spinning[l2] = 1;
285                                     else {
286                                         in_closing[l2] = 2;
287                                         plane_present[l2] = 0;
288                                         start_parts(l2);
289                                     }
290                                 }
291                                 break;
292                             }
293                     }
294                 }
295 
296 
297 
298             switch (fobjects[l].type) {
299             case FOBJECTS_SMOKE:
300                 fobjects[l].phase++;
301                 if (fobjects[l].phase == SMOKE_FRAMES)
302                     fobjects[l].x = 0;
303                 break;
304 
305             case FOBJECTS_SSMOKE:
306                 fobjects[l].phase++;
307                 if (fobjects[l].phase == 17)
308                     fobjects[l].x = 0;
309                 break;
310 
311 
312             case FOBJECTS_RIFLE:
313                 fobjects[l].phase++;
314                 if (fobjects[l].phase == 12)
315                     fobjects[l].phase = 0;
316                 fobjects[l].y_speed -= FOBJECTS_GRAVITY;
317                 break;
318 
319 
320             case FOBJECTS_WAVE1:
321                 fobjects[l].phase++;
322                 if (fobjects[l].phase == WAVE1_FRAMES)
323                     fobjects[l].x = 0;
324                 break;
325 
326             case FOBJECTS_WAVE2:
327                 fobjects[l].phase++;
328                 if (fobjects[l].phase == WAVE2_FRAMES)
329                     fobjects[l].x = 0;
330                 break;
331 
332 
333             case FOBJECTS_ITEXPLOSION:
334                 fobjects[l].phase++;
335                 if (fobjects[l].phase == ITEXPLOSION_FRAMES)
336                     fobjects[l].x = 0;
337                 break;
338 
339 
340             case FOBJECTS_PARTS:
341                 fobjects[l].y_speed -= FOBJECTS_GRAVITY;
342                 break;
343 
344             case FOBJECTS_EXPLOX:
345                 fobjects[l].phase++;
346                 if (fobjects[l].phase == EXPLOX_FRAMES)
347                     fobjects[l].x = 0;
348                 break;
349 
350             case FOBJECTS_FLAME:
351                 fobjects[l].phase++;
352                 if (fobjects[l].phase == NUMBER_OF_FLAMES)
353                     fobjects[l].x = 0;
354 
355                 if (config.structure_smoke)
356                     if (fobjects[l].phase & 3)
357                         start_ssmoke(fobjects[l].x, fobjects[l].y - 256);
358                 break;
359             }
360         }
361     }
362 }
363 
364 
start_wave(int x)365 void start_wave(int x) {
366     int l;
367 
368     for (l = 0; l < MAX_FLYING_OBJECTS; l++)
369         if (!fobjects[l].x)
370             break;
371 
372     if (l != MAX_FLYING_OBJECTS) {
373         fobjects[l].x = (x) << 8;
374         fobjects[l].y = (terrain_level[x] - 11) << 8;
375         fobjects[l].x_speed = 0;
376         fobjects[l].y_speed = 0;
377         fobjects[l].hit_plane = 0;
378         fobjects[l].width = 23;
379         fobjects[l].height = 23;
380         fobjects[l].type = FOBJECTS_WAVE1;
381         fobjects[l].phase = 0;
382     }
383 
384 }
385 
start_gun_wave(int x)386 void start_gun_wave(int x) {
387     int l;
388 
389     for (l = 0; l < MAX_FLYING_OBJECTS; l++)
390         if (!fobjects[l].x)
391             break;
392 
393     if (l != MAX_FLYING_OBJECTS) {
394         fobjects[l].x = (x) << 8;
395         fobjects[l].y = (terrain_level[x] - 2) << 8;
396         fobjects[l].x_speed = 0;
397         fobjects[l].y_speed = 0;
398         fobjects[l].hit_plane = 0;
399         fobjects[l].width = 3;
400         fobjects[l].height = 5;
401         fobjects[l].type = FOBJECTS_WAVE2;
402         fobjects[l].phase = 0;
403     }
404 
405 }
406 
407 
start_smoke(int player)408 void start_smoke(int player) {
409     int l;
410 
411     for (l = 0; l < MAX_FLYING_OBJECTS; l++)
412         if (!fobjects[l].x)
413             break;
414 
415     if (l != MAX_FLYING_OBJECTS) {
416         fobjects[l].x = player_x[player] - 12 * cosinit[player_angle[player] >> 8];
417         fobjects[l].y = player_y[player] + 12 * sinit[player_angle[player] >> 8];
418 
419         fobjects[l].x_speed = 0;
420         fobjects[l].y_speed = 0;
421         fobjects[l].hit_plane = 0;
422         fobjects[l].width = 20;
423         fobjects[l].height = 20;
424         fobjects[l].type = FOBJECTS_SMOKE;
425         fobjects[l].phase = 0;
426     }
427 
428 }
429 
start_ssmoke(int x,int y)430 void start_ssmoke(int x, int y) {
431     int l;
432 
433     for (l = 0; l < MAX_FLYING_OBJECTS; l++)
434         if (!fobjects[l].x)
435             break;
436 
437     if (l != MAX_FLYING_OBJECTS) {
438 
439         fobjects[l].x = x;
440         fobjects[l].y = y - 1024 + wrandom(2048);
441 
442         fobjects[l].x_speed = 0;
443         fobjects[l].y_speed = 256 * 256 * 3;
444         fobjects[l].hit_plane = 0;
445         fobjects[l].width = 9;
446         fobjects[l].height = 9;
447         fobjects[l].type = FOBJECTS_SSMOKE;
448         fobjects[l].phase = 0;
449     }
450 
451 }
452 
453 
start_explox(int x,int y)454 void start_explox(int x, int y) {
455     int l;
456     int l2;
457     int number_of_exps;
458 
459     number_of_exps = wrandom(EXPLOX_RANDOM) + EXPLOX_CONST;
460 
461     for (l2 = 0; l2 < number_of_exps; l2++) {
462 
463 
464         for (l = 0; l < MAX_FLYING_OBJECTS; l++)
465             if (!fobjects[l].x)
466                 break;
467 
468         if (l != MAX_FLYING_OBJECTS) {
469             fobjects[l].x = x + wrandom(EXPLOX_VARIETY) - (EXPLOX_VARIETY / 2);
470             fobjects[l].y = y + wrandom(EXPLOX_VARIETY) - (EXPLOX_VARIETY / 2);
471 
472             fobjects[l].x_speed = 0;
473             fobjects[l].y_speed = 0;
474             fobjects[l].hit_plane = 0;
475             fobjects[l].width = 9;
476             fobjects[l].height = 9;
477             fobjects[l].type = FOBJECTS_EXPLOX;
478             fobjects[l].subtype = wrandom(4);
479             fobjects[l].phase = 0 - wrandom(EXPLOX_PHASE_DIFF);
480 
481         }
482     }
483 }
484 
detect_damage(void)485 void detect_damage(void) {
486     int l;
487 
488     for (l = 0; l < 16; l++) {
489         if (!player_exists[l])
490             continue;
491 
492         if (wrandom(plane_mass[l] >> 4) >= player_endurance[l])
493             if (wrandom(2))
494                 start_smoke(l);
495 
496     }
497 }
498 
start_parts(int player)499 void start_parts(int player) {
500     int l, l2, limit;
501     int xxx, yyy;
502     int xsss;
503 
504     limit = wrandom(NUMBER_OF_EXPLOSION_PARTS);
505 
506     start_explox(player_x[player], player_y[player]);
507 
508     xxx = player_x[player] - 12 * cosinit[player_angle[player] >> 8];
509     yyy = player_y[player] + 12 * sinit[player_angle[player] >> 8];
510     xsss = (cosinit[player_angle[player] >> 8] * (player_speed[player])) >> 2;
511 
512     for (l2 = 0; l2 < limit; l2++) {
513         for (l = 0; l < MAX_FLYING_OBJECTS; l++)
514             if (!fobjects[l].x)
515                 break;
516 
517         if (l != MAX_FLYING_OBJECTS) {
518             fobjects[l].x = xxx;
519             fobjects[l].y = yyy;
520             fobjects[l].x_speed = xsss + wrandom(PARTS_SPEED) - (PARTS_SPEED >> 1);
521             fobjects[l].y_speed = (wrandom(PARTS_SPEED) - (PARTS_SPEED >> 1));
522             fobjects[l].hit_plane = 1;
523             fobjects[l].width = 10;
524             fobjects[l].height = 10;
525             fobjects[l].type = FOBJECTS_PARTS;
526             fobjects[l].phase = wrandom(NUMBER_OF_BITES);
527             fobjects[l].owner = -1;
528         }
529     }
530 }
531 
start_rifle(int x,int y)532 void start_rifle(int x, int y) {
533     int l;
534 
535     for (l = 0; l < MAX_FLYING_OBJECTS; l++)
536         if (!fobjects[l].x)
537             break;
538 
539     if (l != MAX_FLYING_OBJECTS) {
540         fobjects[l].x = x << 8;
541         fobjects[l].y = y << 8;
542         fobjects[l].x_speed = 256 * 128 * 5 - wrandom(2560 * 128);
543         fobjects[l].y_speed = wrandom(256 * 5 * 128);
544         fobjects[l].hit_plane = 0;
545         fobjects[l].width = 8;
546         fobjects[l].height = 8;
547         fobjects[l].type = FOBJECTS_RIFLE;
548         fobjects[l].phase = 0;
549         fobjects[l].owner = -1;
550     }
551 
552 }
553 
554 
drop_bomb(int player,int target)555 void drop_bomb(int player, int target) {
556     int l;
557 
558     for (l = 0; l < MAX_BOMBS; l++)
559         if (!bomb_x[l])
560             break;
561 
562     if (l == MAX_BOMBS)
563         return;
564 
565     if (target != -1)
566         bombs_going[target] = l;
567 
568     player_bombed[player]++;
569 
570     bomb_speed[l] = player_speed[player];
571     bomb_angle[l] = player_angle[player];
572     bomb_x_speed[l] = (cosinit[bomb_angle[l] >> 8] * bomb_speed[l]) >> 2;
573     bomb_y_speed[l] = (sinit[bomb_angle[l] >> 8] * bomb_speed[l]) >> 2;
574     bomb_x[l] = player_x[player] + (9 - player_upsidedown[player] * 18) * sinit[player_angle[player] >> 8];
575     bomb_y[l] = player_y[player] + (9 - player_upsidedown[player] * 18) * cosinit[player_angle[player] >> 8];
576 
577     bomb_owner[l] = player;
578 }
579 
do_bombs(void)580 void do_bombs(void) {
581     int l2, l, tempero;
582 
583     for (l = 0; l < MAX_BOMBS; l++) {
584         if (!bomb_x[l])
585             continue;
586 
587         bomb_y_speed[l] -= BOMB_GRAVITY;
588         bomb_x[l] += bomb_x_speed[l] >> 9;
589         bomb_y[l] -= bomb_y_speed[l] >> 9;
590 
591 
592 
593         if (bomb_y_speed[l] == 0) {
594             if (bomb_x_speed[l] > 0)
595                 bomb_angle[l] = 0;
596             else
597                 bomb_angle[l] = 46080;
598         } else {
599             if (bomb_x_speed[l] == 0) {
600                 if (bomb_y_speed[l] > 0)
601                     bomb_angle[l] = 23040;
602                 else
603                     bomb_angle[l] = 69120;
604             } else {
605                 tempero = ((bomb_y_speed[l] << 7) / bomb_x_speed[l]);
606                 if (tempero > 512)
607                     tempero = 512;
608                 if (tempero < (-512))
609                     tempero = -512;
610 
611                 if (bomb_x_speed[l] > 0)
612                     bomb_angle[l] = tempero * 45;
613                 else
614                     bomb_angle[l] = 46080 + tempero * 45;
615 
616             }
617         }
618 
619 
620 
621         if (bomb_angle[l] >= 92160)
622             bomb_angle[l] -= 92160;
623 
624         if (bomb_angle[l] < 0)
625             bomb_angle[l] += 92160;
626 
627 
628         if ((bomb_x[l] < 0) || (bomb_x[l] >> 8) >= 2400 || (bomb_y[l] >> 8) > 199) {
629             bomb_x[l] = 0;
630             continue;
631         }
632 
633         if (bomb_y[l] >= 0)
634             if ((level_bitmap[(bomb_x[l] >> 8) + (bomb_y[l] >> 8) * 2400]) < 112 || ((level_bitmap[(bomb_x[l] >> 8) + (bomb_y[l] >> 8) * 2400])) > 119
635                 || ((bomb_y[l] >> 8) >= 200)) {
636                 start_bomb_explo(l);
637 
638                 bomb_x[l] = 0;
639                 continue;
640             }
641 
642 
643         for (l2 = 0; l2 < 16; l2++) {
644             if (plane_present[l2]) {
645                 if (((player_x[l2] + 2304) > bomb_x[l]) &&
646                     ((player_x[l2] - 2304) < bomb_x[l]) && ((player_y[l2] + 2304) > bomb_y[l]) && ((player_y[l2] - 2304) < bomb_y[l]))
647                     if (plane_p[l2][(player_angle[l2] >> 8) / 6][player_rolling[l2]][player_upsidedown[l2]]
648                         [(bomb_x[l] >> 8) - (player_x_8[l2]) + 10 + ((bomb_y[l] >> 8) - (player_y_8[l2]) + 10) * 20] != 255) {
649                         bomb_x[l] = 0;
650                         player_endurance[l2] = 0;
651                         if (player_endurance[l2] < 1) {
652                             if ((!player_spinning[l2]) && (!in_closing[l2])) {
653                                 if (player_sides[bomb_owner[l]] != player_sides[l2])
654                                     player_points[bomb_owner[l]]++;
655                                 else
656                                     player_points[bomb_owner[l]]--;
657 
658                                 player_shots_down[bomb_owner[l]][l2]++;
659                             }
660 
661                             in_closing[l2] = 2;
662                             plane_present[l2] = 0;
663                             start_parts(l2);
664                             start_bomb_explo(l, 1);
665 
666                         }
667                         break;
668                     }
669             }
670         }
671 
672 
673     }
674 
675 
676 }
677 
start_bomb_explo(int bb,int hitted)678 void start_bomb_explo(int bb, int hitted) {
679     int l, l2, limit;
680     int palasia = 0;
681 
682     if (playing_solo) {
683         if (bomb_owner[bb] != solo_country) {
684             for (l = 0; l < 100; l++) {
685                 if (bombs_going[l] == bb) {
686                     bombs_going[l] = -1;
687                     break;
688 
689                 }
690 
691             }
692 
693         }
694 
695     } else {
696         if (computer_active[bomb_owner[bb]]) {
697             for (l = 0; l < 100; l++) {
698                 if (bombs_going[l] == bb) {
699                     bombs_going[l] = -1;
700                     break;
701 
702                 }
703 
704             }
705 
706         }
707 
708     }
709 
710 
711     limit = wrandom(MAX_BOMB_PARTS - MIN_BOMB_PARTS);
712     limit += MIN_BOMB_PARTS;
713 
714 
715     if ((level_bitmap[(bomb_x[bb] >> 8) + (bomb_y[bb] >> 8) * 2400] >= 224)
716         && (level_bitmap[(bomb_x[bb] >> 8) + (bomb_y[bb] >> 8) * 2400] <= 231)) {
717         start_wave(bomb_x[bb] >> 8);
718         if (config.splash && config.sound_on && config.sfx_on)
719             play_2d_sample(sample_splash[wrandom(3)], player_x_8[solo_country], bomb_x[bb] >> 8);
720     } else {
721         start_explox(bomb_x[bb], bomb_y[bb]);
722         if (config.explosion_sounds && config.sound_on && config.sfx_on)
723             play_2d_sample(sample_bomb[wrandom(3) + 1], player_x_8[solo_country], bomb_x[bb] >> 8);
724 
725     }
726 
727     for (l = 0; l < MAX_AA_GUNS; l++)
728         if (kkbase_x[l] && kkbase_status[l] != 2) {
729             if ((bomb_x[bb] >> 8) >= kkbase_x[l] && (bomb_x[bb] >> 8) <= (kkbase_x[l] + 25) &&
730                 (bomb_y[bb] >> 8) >= (kkbase_y[l] - 5) && (bomb_y[bb] >> 8) <= (kkbase_y[l] + 30)) {
731                 if (kkbase_country[l] == player_sides[bomb_owner[bb]])
732                     hitted = -1;
733 
734                 if (config.flames)
735                     start_flame(kkbase_x[l], kkbase_y[l] + 21, 26);
736 
737                 if (playing_solo) {
738                     if (leveldata.struct_type[kkbase_number[l]] == 1)
739                         solo_dest_remaining--;
740 
741                     if (leveldata.struct_type[kkbase_number[l]] == 2)
742                         solo_failed = 1;
743 
744                 }
745 
746                 kkbase_status[l] = 2;
747                 kkbase_frame[l] = 0;
748                 struct_state[kkbase_number[l]] = 1;
749 
750                 if (hitted != -1)
751                     hitted = 1;
752             }
753         }
754 
755     for (l = 0; l < MAX_STRUCTURES; l++)
756         if ((structures[l][1] != NULL) && (!struct_state[l])) {
757             if ((bomb_x[bb] >> 8) >= leveldata.struct_x[l] && (bomb_x[bb] >> 8) <= (leveldata.struct_x[l] + struct_width[l]) &&
758                 (bomb_y[bb] >> 8) >= (leveldata.struct_y[l] - 5) && (bomb_y[bb] >> 8) <= (leveldata.struct_y[l] + 5 + struct_heigth[l])) {
759                 if (config.flames)
760                     start_flame(leveldata.struct_x[l], leveldata.struct_y[l] + struct_heigth[l], struct_width[l]);
761 
762 
763 
764                 struct_state[l] = 1;
765 
766                 if (playing_solo) {
767                     if (leveldata.struct_type[l] == 1)
768                         solo_dest_remaining--;
769 
770                     if (leveldata.struct_type[l] == 2)
771                         solo_failed = 1;
772 
773                 }
774 
775                 if (player_sides[leveldata.struct_owner[l]] == player_sides[bomb_owner[bb]])
776                     hitted = -1;
777 
778                 if (hitted != -1)
779                     hitted = 1;
780 
781                 if (current_mode == SVGA_MODE) {
782 
783                     structures[l][1]->blit_to_bitmap(standard_background, leveldata.struct_x[l] - (leveldata.struct_x[l] / 800) * 800,
784                                                      leveldata.struct_y[l] + (leveldata.struct_x[l] / 800) * 196 - 4);
785 
786                     structures[l][1]->blit(leveldata.struct_x[l] - (leveldata.struct_x[l] / 800) * 800,
787                                            leveldata.struct_y[l] + (leveldata.struct_x[l] / 800) * 196 - 4);
788 
789                     if ((leveldata.struct_x[l] - (leveldata.struct_x[l] / 800) * 800) + struct_width[l] > 800)
790                         structures[l][1]->blit(leveldata.struct_x[l] - (leveldata.struct_x[l] / 800) * 800 - 800,
791                                                leveldata.struct_y[l] + (leveldata.struct_x[l] / 800 + 1) * 196 - 4);
792                 }
793 
794                 if (leveldata.struct_hit[l]) {
795                     structures[l][1]->blit_to_bitmap(maisema, leveldata.struct_x[l], leveldata.struct_y[l]);
796                 }
797 
798 
799 
800             }
801         }
802 
803     for (l = 0; l < MAX_INFANTRY; l++) {
804         if (infan_x[l] && infan_state[l] < 3) {
805             if ((bomb_x[bb] >> 8) >= (infan_x[l] - 30) && (bomb_x[bb] >> 8) <= (infan_x[l] + 44) &&
806                 (bomb_y[bb] >> 8) >= (infan_y[l] - 20) && (bomb_y[bb] >> 8) <= (infan_y[l] + 30)) {
807                 if (player_sides[infan_country[l]] == player_sides[bomb_owner[bb]])
808                     hitted = -1;
809 
810                 if (hitted != -1)
811                     hitted = 1;
812 
813                 if (playing_solo) {
814                     if (leveldata.struct_type[l] == 1)
815                         solo_dest_remaining--;
816 
817                     if (leveldata.struct_type[l] == 2)
818                         solo_failed = 1;
819 
820                 }
821 
822                 start_rifle(infan_x[l], infan_y[l]);
823 
824                 if (infan_x[l] == (bomb_x[bb] >> 8)) {
825                     infan_x[l] = 0;
826 
827                 }
828 
829                 if (infan_x[l] > (bomb_x[bb] >> 8)) {
830 
831                     infan_direction[l] = 1;
832                     infan_frame[l] = 0;
833                     infan_state[l] = 4;
834                     infan_x_speed[l] = 2;
835                 }
836 
837                 if (infan_x[l] < (bomb_x[bb] >> 8)) {
838 
839                     infan_direction[l] = 0;
840                     infan_frame[l] = 0;
841                     infan_state[l] = 4;
842                     infan_x_speed[l] = -2;
843                 }
844 
845 
846             }
847 
848         }
849     }
850 
851 
852     if (hitted == 1) {
853         player_bomb_hits[bomb_owner[bb]]++;
854     }
855 
856     if (palasia)
857         for (l2 = 0; l2 < limit; l2++) {
858             for (l = 0; l < MAX_FLYING_OBJECTS; l++)
859                 if (!fobjects[l].x)
860                     break;
861 
862             if (l != MAX_FLYING_OBJECTS) {
863                 fobjects[l].x = bomb_x[bb];
864                 fobjects[l].y = bomb_y[bb];
865                 fobjects[l].x_speed = wrandom(PARTS_SPEED) - PARTS_SPEED / 2;
866                 fobjects[l].y_speed = (wrandom(PARTS_SPEED) - PARTS_SPEED / 2);
867                 fobjects[l].hit_plane = 1;
868                 fobjects[l].width = 10;
869                 fobjects[l].height = 10;
870                 fobjects[l].type = FOBJECTS_PARTS;
871                 fobjects[l].phase = wrandom(NUMBER_OF_BITES);
872                 fobjects[l].owner = bomb_owner[bb];
873             }
874         }
875 }
876