1 /**
2 * @file extra_gun.c
3 * @brief Handle extra guns positioned on the sides of the spaceship
4 * @created 2006-11-25
5 * @date 2012-08-25
6 * @author Jean-Michel Martin de Santero
7 * @author Bruno Ethvignot
8 */
9 /*
10 * copyright (c) 1998-2015 TLK Games all rights reserved
11 * $Id: extra_gun.c,v 1.26 2012/08/25 15:55:00 gurumeditation Exp $
12 *
13 * Powermanga is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * Powermanga is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 * MA 02110-1301, USA.
27 */
28 #include "config.h"
29 #include "powermanga.h"
30 #include "tools.h"
31 #include "images.h"
32 #include "enemies.h"
33 #include "bonus.h"
34 #include "display.h"
35 #include "electrical_shock.h"
36 #include "energy_gauge.h"
37 #include "explosions.h"
38 #include "log_recorder.h"
39 #include "shots.h"
40 #include "extra_gun.h"
41 #include "gfx_wrapper.h"
42 #include "images.h"
43 #include "menu.h"
44 #include "options_panel.h"
45 #include "spaceship.h"
46
47 /** Maximum number guns active at any time */
48 #define GUNS_MAXOF 2
49 /** Number of types of differents guns */
50 #define GUNS_NUMOF_TYPES 5
51 /** Extra gun sprite's number of images */
52 #define GUNS_NUMOF_IMAGES 16
53
54 /**
55 * Structure io the side extra gun
56 */
57 typedef struct gun_struct
58 {
59 /** Display extra gun */
60 bool is_visible;
61 /** Display extra gun's white mask */
62 bool is_white_mask_displayed;
63 /** Power of destruction (collision) */
64 Sint16 pow_of_dest;
65 /** Damage status (<= 0 destroyed gun) */
66 Sint16 energy_level;
67 /** Number of images of the sprite */
68 Sint16 numof_images;
69 /** Current image index */
70 Sint16 current_image;
71 /** Delay before next image */
72 Sint16 anim_speed;
73 /** Delay's counter */
74 Sint16 anim_count;
75 /** Structures of images extra gun */
76 image *img[IMAGES_MAXOF];
77 /** X-coordinates */
78 Sint32 xcoord;
79 /** Y-coordinates */
80 Sint32 ycoord;
81 /** Shot delay counter */
82 Sint32 fire_rate_count;
83 Sint32 fire_rate;
84 /** 0=right side / 1=left side */
85 Sint32 position;
86 /** Previous element of the chained list */
87 struct gun_struct *previous;
88 /** Next element of the chained list */
89 struct gun_struct *next;
90 /** TRUE if the element is already chained */
91 bool is_enabled;
92 }
93 gun_struct;
94
95 /** Data structures of all extra guns */
96 static gun_struct *extra_guns = NULL;
97 static gun_struct *gun_first = NULL;
98 static gun_struct *gun_last = NULL;
99 /** Data structure of the sprites images's guns */
100 static image guns_images[GUNS_NUMOF_TYPES][GUNS_NUMOF_IMAGES];
101 static gun_struct *gun_get (void);
102 static void gun_del (gun_struct * egun);
103
104 /**
105 * Allocate buffers and initialize structure of the extras guns
106 * @return TRUE if it completed successfully or FALSE otherwise
107 */
108 bool
guns_once_init(void)109 guns_once_init (void)
110 {
111 guns_free ();
112
113 /* extract extra guns sprites images (28,450 bytes) */
114 if (!image_load
115 ("graphics/sprites/extra_guns.spr", &guns_images[0][0],
116 GUNS_NUMOF_TYPES, GUNS_NUMOF_IMAGES))
117 {
118 return FALSE;
119 }
120
121 /* allocate extra guns data structure */
122 if (extra_guns == NULL)
123 {
124 extra_guns =
125 (gun_struct *) memory_allocation (GUNS_MAXOF * sizeof (gun_struct));
126 if (extra_guns == NULL)
127 {
128 LOG_ERR ("not enough memory to allocate 'gun_struct'");
129 return FALSE;
130 }
131 }
132
133 guns_init ();
134 return TRUE;
135 }
136
137 /**
138 * Convert extra guns from data image to PNG file
139 * @return TRUE if successful
140 */
141 #ifdef PNG_EXPORT_ENABLE
142 bool
guns_extract(void)143 guns_extract (void)
144 {
145 Uint32 type, frame;
146 const char *model = EXPORT_DIR "/extra-guns/extra-gun-x/extra-gun-xx.png";
147 char *filename = memory_allocation (strlen (model) + 1);
148 if (filename == NULL)
149 {
150 LOG_ERR ("not enough memory to allocate %i bytes\n",
151 (Uint32) (strlen (model) + 1));
152 return FALSE;
153 }
154 if (!create_dir (EXPORT_DIR "/extra-guns"))
155 {
156 free_memory (filename);
157 return FALSE;
158 }
159 for (type = 0; type < GUNS_NUMOF_TYPES; type++)
160 {
161 sprintf (filename, EXPORT_DIR "/extra-guns/extra-gun-%01d", type + 1);
162 if (!create_dir (filename))
163 {
164 free_memory (filename);
165 return FALSE;
166 }
167 for (frame = 0; frame < GUNS_NUMOF_IMAGES; frame++)
168 {
169 sprintf (filename,
170 EXPORT_DIR "/extra-guns/extra-gun-%01d/extra-gun-%02d.png",
171 type + 1, frame);
172 if (!image_to_png (&guns_images[type][frame], filename))
173 {
174 free_memory (filename);
175 return FALSE;
176 }
177 }
178 }
179 free_memory (filename);
180 return TRUE;
181 }
182 #endif
183
184 /**
185 * Release memory of images and structures used for the etra guns
186 */
187 void
guns_free(void)188 guns_free (void)
189 {
190 if (extra_guns != NULL)
191 {
192 free_memory ((char *) extra_guns);
193 extra_guns = NULL;
194 }
195 images_free (&guns_images[0][0], GUNS_NUMOF_TYPES, GUNS_NUMOF_IMAGES,
196 GUNS_NUMOF_IMAGES);
197 }
198
199 /**
200 * Initialize structures of the extra guns
201 */
202 void
guns_init(void)203 guns_init (void)
204 {
205 Sint32 i;
206 gun_struct *egun;
207 spaceship_struct *ship = spaceship_get ();
208
209 /* release all extra guns */
210 for (i = 0; i < GUNS_MAXOF; i++)
211 {
212 egun = &extra_guns[i];
213 egun->is_enabled = FALSE;
214 }
215 /* clear the number of extra guns */
216 ship->num_of_extraguns = 0;
217 }
218
219 /**
220 * Handle the extra gun positioned on the sides of the player's spaceship
221 */
222 void
guns_handle(void)223 guns_handle (void)
224 {
225 Sint32 i, k, l;
226 gun_struct *egun;
227 shot_struct *bullet;
228 image *egun_img;
229 spaceship_struct *ship = spaceship_get ();
230 egun = gun_first;
231 if (egun == NULL)
232 {
233 return;
234 }
235 for (i = 0; i < ship->num_of_extraguns; i++, egun = egun->next)
236 {
237 #ifdef UNDER_DEVELOPMENT
238 if (egun == NULL && i < (ship->num_of_extraguns - 1))
239 {
240 LOG_ERR ("egun->next is null %i/%i", i, ship->num_of_extraguns);
241 break;
242 }
243 #endif
244 egun_img = egun->img[egun->current_image];
245
246 /* update vertical coordinate of the gun */
247 egun->ycoord =
248 (Sint16) (ship->spr.ycoord) +
249 ship->spr.img[ship->spr.current_image]->h - egun_img->h;
250
251 /* update horizontal coordinate of the right gun */
252 if (egun->position == 0)
253 {
254 egun->xcoord =
255 (Sint16) (ship->spr.xcoord) +
256 ship->spr.img[ship->spr.current_image]->w;
257 }
258
259 /* update horizontal coordinate of the left gun */
260 if (egun->position == 1)
261 {
262 egun->xcoord = (Sint16) (ship->spr.xcoord) - egun_img->w;
263 }
264
265 if (!player_pause && menu_status == MENU_OFF)
266 {
267 /* decrease counter of delay between two shots */
268 egun->fire_rate_count--;
269 /* check if the satellite fire or not a shot */
270 if (egun->fire_rate_count <= 0)
271 {
272 /* reset counter of delay between two shots */
273 egun->fire_rate_count = egun->fire_rate;
274 /* process each origin of the shot (location of the cannon) */
275 for (k = 0; k < egun_img->numof_cannons; k++)
276 {
277 if (num_of_shots < (MAX_OF_SHOTS - 1))
278 {
279 /* get a new shot */
280 bullet = shot_get ();
281 if (bullet == NULL)
282 {
283 break;
284 }
285 /* animated sprite (flicker shot) */
286 bullet->is_blinking = TRUE;
287 /* indicate that is friend sprite */
288 bullet->spr.type = FRIEND;
289 /* fixed trajectory */
290 bullet->spr.trajectory = 0;
291 /* set number of images of the sprite */
292 bullet->spr.numof_images = 32;
293
294 /* initialize power of the shot */
295 switch (ship->type)
296 {
297 case SPACESHIP_TYPE_1:
298 bullet->spr.pow_of_dest = 2;
299 break;
300 case SPACESHIP_TYPE_2:
301 bullet->spr.pow_of_dest = 3;
302 break;
303 case SPACESHIP_TYPE_3:
304 bullet->spr.pow_of_dest = 4;
305 break;
306 case SPACESHIP_TYPE_4:
307 bullet->spr.pow_of_dest = 3;
308 break;
309 case SPACESHIP_TYPE_5:
310 bullet->spr.pow_of_dest = 4;
311 break;
312 }
313 /* set addresses of the sprites images buffer */
314 for (l = 0; l < bullet->spr.numof_images; l++)
315 {
316 /* shot 2 force 1 */
317 bullet->spr.img[l] = (image *) & fire[V1TN1][l];
318 }
319 /* set energy level of the sprite */
320 bullet->spr.energy_level = bullet->spr.pow_of_dest;
321 /* set current image index */
322 bullet->spr.current_image = 0;
323 /* set value of delay between two images */
324 bullet->spr.anim_speed = 4;
325 /* set delay counter between two images */
326 bullet->spr.anim_count = 0;
327 bullet->img_angle = egun_img->cannons_angles[k];
328 bullet->img_old_angle = bullet->img_angle;
329 /* set x and y coordinates */
330 bullet->spr.xcoord =
331 (float) (egun->xcoord +
332 egun_img->cannons_coords[k][XCOORD] -
333 bullet->spr.img[bullet->img_angle]->x_gc);
334 bullet->spr.ycoord =
335 (float) (egun->ycoord +
336 egun_img->cannons_coords[k][YCOORD] -
337 bullet->spr.img[bullet->img_angle]->y_gc);
338 bullet->timelife = 400;
339 /* set angle of the projectile */
340 bullet->angle = PI_BY_16 * bullet->img_angle;
341 /* set speed of the displacement */
342 bullet->spr.speed = 9.0;
343 }
344 }
345 }
346 }
347
348 /* check if the sprite is visible or not */
349 if ((egun->xcoord + egun->img[0]->w) <
350 offscreen_startx
351 || (egun->ycoord + egun->img[0]->h) <
352 offscreen_starty
353 || egun->xcoord >
354 (offscreen_startx + offscreen_width_visible - 1)
355 || egun->ycoord > (offscreen_starty + offscreen_height_visible - 1))
356 {
357 /* extra gun not visible, don't perform the tests of collision */
358 egun->is_visible = FALSE;
359 }
360 else
361 {
362 /* extra gun is visible, perform the tests of collision */
363 egun->is_visible = TRUE;
364 /* increase counter delay between two images */
365 egun->anim_count++;
366 /* value of delay between two images reached? */
367 if (egun->anim_count >= egun->anim_speed)
368 {
369 /* clear counter delay between two images */
370 egun->anim_count = 0;
371 /* flip to the next image */
372 egun->current_image++;
373 /* check if last image has been reached */
374 if (egun->current_image >= egun->numof_images)
375 {
376 /* resets the animation to the first image of the animation
377 * sequence */
378 egun->current_image = 0;
379 }
380 }
381
382 /* display extra gun */
383 if (egun->is_white_mask_displayed)
384 {
385 draw_sprite_mask (coulor[WHITE], egun->img[egun->current_image],
386 egun->xcoord, egun->ycoord);
387 egun->is_white_mask_displayed = 0;
388 }
389 else
390 {
391 draw_sprite (egun->img[egun->current_image], egun->xcoord,
392 egun->ycoord);
393 }
394 }
395 }
396 }
397
398 /**
399 * Add an extra gun on the player's spaceship side
400 * @return TRUE if a extra gun was added
401 */
402 bool
gun_add(void)403 gun_add (void)
404 {
405 Sint32 i;
406 gun_struct *egun;
407 spaceship_struct *ship = spaceship_get ();
408 /* get an extra gun, cannot install more than 2 guns */
409 if (ship->num_of_extraguns >= 2)
410 {
411 return FALSE;
412 }
413 /* get new extra gun index */
414 egun = gun_get ();
415 if (egun == NULL)
416 {
417 return FALSE;
418 }
419 /* set level of energy (zero correspond to destruction of the gun) */
420 egun->energy_level = (Sint16) (100 + ship->type * 10);
421 /* set power of the gun's shot */
422 egun->pow_of_dest = (Sint16) (30 + ship->type * 5);
423 /* set number of images of the sprite */
424 egun->numof_images = GUNS_NUMOF_IMAGES;
425 /* set current image */
426 egun->current_image = 0;
427 /* value of delay between two images */
428 egun->anim_speed = 10;
429 /* counter of delay between two images */
430 egun->anim_count = 0;
431 /* set shot time-frequency */
432 egun->fire_rate = 25 - (ship->type << 1);
433 egun->fire_rate_count = egun->fire_rate;
434 /* set addresses of the images buffer */
435 for (i = 0; i < egun->numof_images; i++)
436 {
437 egun->img[i] = (image *) & guns_images[ship->type][i];
438 }
439 /* position the gun on the side of the player's spaceship */
440 switch (ship->num_of_extraguns)
441 {
442 case 1:
443 /* gun's positioned on the right */
444 egun->position = 0;
445 break;
446 case 2:
447 if (gun_first->position == 0)
448 {
449 egun->position = 1;
450 }
451 else
452 {
453 egun->position = 0;
454 }
455 break;
456 }
457 return TRUE;
458 }
459
460 /**
461 * Check validty of extra_gun chained list
462 */
463 #ifdef UNDER_DEVELOPMENT
464 static void
gun_check_chained_list(void)465 gun_check_chained_list (void)
466 {
467 Uint32 i;
468 gun_struct *egun;
469 spaceship_struct *ship = spaceship_get ();
470 Sint32 count = 0;
471 for (i = 0; i < GUNS_MAXOF; i++)
472 {
473 egun = &extra_guns[i];
474 if (egun->is_enabled)
475 {
476 count++;
477 }
478 }
479 if (count != ship->num_of_extraguns)
480 {
481 LOG_ERR ("Counting of the enabled elements failed!"
482 "count=%i, ship->num_of_extraguns=%i",
483 count, ship->num_of_extraguns);
484 }
485 count = 0;
486 egun = gun_first;
487 do
488 {
489 count++;
490 egun = egun->next;
491 }
492 while (egun != NULL && count <= (GUNS_MAXOF + 1));
493 if (count != ship->num_of_extraguns)
494 {
495 LOG_ERR ("Counting of the next elements failed!"
496 "count=%i, ship->num_of_extraguns=%i", count,
497 ship->num_of_extraguns);
498 }
499 count = 0;
500 egun = gun_last;
501 do
502 {
503 count++;
504 egun = egun->previous;
505 }
506 while (egun != NULL && count <= (GUNS_MAXOF + 1));
507 if (count != ship->num_of_extraguns)
508 {
509 LOG_ERR ("Counting of the previous elements failed!"
510 "count=%i, ship->num_of_extraguns=%i", count,
511 ship->num_of_extraguns);
512 }
513 }
514 #endif
515
516 /**
517 * Return a free extra gun element
518 * @return Pointer to a gun structure, NULL if not gun available
519 */
520 static gun_struct *
gun_get(void)521 gun_get (void)
522 {
523 Uint32 i;
524 gun_struct *egun;
525 spaceship_struct *ship = spaceship_get ();
526 for (i = 0; i < GUNS_MAXOF; i++)
527 {
528 egun = &extra_guns[i];
529 if (egun->is_enabled)
530 {
531 continue;
532 }
533 egun->is_enabled = TRUE;
534 egun->next = NULL;
535 if (ship->num_of_extraguns == 0)
536 {
537 gun_first = egun;
538 gun_last = egun;
539 gun_last->previous = NULL;
540 }
541 else
542 {
543 gun_last->next = egun;
544 egun->previous = gun_last;
545 gun_last = egun;
546 }
547 ship->num_of_extraguns++;
548 #ifdef UNDER_DEVELOPMENT
549 gun_check_chained_list ();
550 #endif
551 return egun;
552 }
553 LOG_ERR ("no more element gun is available");
554 return NULL;
555 }
556
557 /**
558 * Remove a extra gun element from list
559 * @param Pointer to a extra gun structure
560 */
561 static void
gun_del(gun_struct * egun)562 gun_del (gun_struct * egun)
563 {
564 spaceship_struct *ship = spaceship_get ();
565 egun->is_enabled = FALSE;
566 ship->num_of_extraguns--;
567 if (gun_first == egun)
568 {
569 gun_first = egun->next;
570 }
571 if (gun_last == egun)
572 {
573 gun_last = egun->previous;
574 }
575 if (egun->previous != NULL)
576 {
577 egun->previous->next = egun->next;
578 }
579 if (egun->next != NULL)
580 {
581 egun->next->previous = egun->previous;
582 }
583 }
584
585 /**
586 * Collisions between extra guns and an enemy
587 * @param foe pointer to the structure of an enemy
588 * @param num_of_fragments number of fragments to add if enemy is destroyed
589 * @return TRUE if enemy is destroyed
590 */
591 bool
guns_enemy_collisions(enemy * foe,Sint32 num_of_fragments)592 guns_enemy_collisions (enemy * foe, Sint32 num_of_fragments)
593 {
594 Sint32 i, l, m, x1, y1, x2, y2;
595 gun_struct *egun;
596 spaceship_struct *ship = spaceship_get ();
597 egun = gun_first;
598 if (egun == NULL)
599 {
600 return FALSE;
601 }
602 /* process each extra gun */
603 for (i = 0; i < ship->num_of_extraguns; i++, egun = egun->next)
604 {
605 #ifdef UNDER_DEVELOPMENT
606 if (egun == NULL && i < (ship->num_of_extraguns - 1))
607 {
608 LOG_ERR ("egun->next is null %i/%i", i, ship->num_of_extraguns);
609 break;
610 }
611 #endif
612 /* if extra gun is invisible, don't perform the tests of collision */
613 if (!egun->is_visible)
614 {
615 continue;
616 }
617 for (l = 0; l < egun->img[egun->current_image]->numof_collisions_points;
618 l++)
619 {
620 /* coordinates of the collision point of the gun */
621 x1 =
622 egun->xcoord +
623 egun->img[egun->current_image]->collisions_points[l][XCOORD];
624 y1 =
625 egun->ycoord +
626 egun->img[egun->current_image]->collisions_points[l][YCOORD];
627 /* for each collision zone of the enemy */
628 for (m = 0;
629 m <
630 foe->spr.img[foe->spr.current_image]->numof_collisions_zones;
631 m++)
632 {
633 /* coordinates of the collision zone of the enemy */
634 x2 =
635 (Sint32) foe->spr.xcoord +
636 foe->spr.img[foe->spr.current_image]->
637 collisions_coords[m][XCOORD];
638 y2 =
639 (Sint32) foe->spr.ycoord +
640 foe->spr.img[foe->spr.current_image]->
641 collisions_coords[m][YCOORD];
642 /* check if gun collision point is into enemy collision zone */
643 if (x1 >= x2 && y1 >= y2
644 && x1 <
645 (x2 +
646 foe->spr.img[foe->spr.current_image]->collisions_sizes[m]
647 [IMAGE_WIDTH])
648 && y1 <
649 (y2 +
650 foe->spr.img[foe->spr.
651 current_image]->collisions_sizes[m]
652 [IMAGE_HEIGHT]))
653 {
654 /* decrease energy level of enemy */
655 foe->spr.energy_level =
656 (Sint16) (foe->spr.energy_level - egun->pow_of_dest);
657 if (foe->type >= THANIKEE)
658 {
659 energy_gauge_guard_is_update = TRUE;
660 }
661 /* decrease energy level of gun */
662 egun->energy_level =
663 (Sint16) (egun->energy_level - foe->spr.pow_of_dest);
664 /* check if gun is destroyed */
665 if (egun->energy_level <= 0)
666 {
667 /* remove gun from the list */
668 gun_del (egun);
669 break;
670 }
671 else
672 {
673 /* gun not destroyed, display white mask */
674 egun->is_white_mask_displayed = TRUE;
675 }
676 /* check if enemy is destroyed */
677 if (foe->spr.energy_level <= 0)
678 {
679 /* check if the enemy is a meteor */
680 if ((foe->type >= BIGMETEOR && foe->type <= SMALLMETEOR)
681 || foe->type >= THANIKEE)
682 {
683 /* add a bonus gem or a lonely foe */
684 bonus_meteor_add (foe);
685 if (num_of_fragments > 0)
686 {
687 explosions_fragments_add (foe->spr.xcoord +
688 foe->spr.img[foe->spr.
689 current_image]->x_gc
690 - 8,
691 foe->spr.ycoord +
692 foe->spr.img[foe->spr.
693 current_image]->y_gc
694 - 8, 1.0,
695 num_of_fragments, 0,
696 2);
697 }
698 }
699 else
700 {
701 /* add a bonus gem or a lonely foe */
702 bonus_add (foe);
703 }
704 player_score +=
705 foe->spr.pow_of_dest << 2 << score_multiplier;
706 /* enemy destroyed! */
707 return TRUE;
708 }
709 else
710 {
711 /* enemy not destroyed, display white mask */
712 foe->is_white_mask_displayed = TRUE;
713 }
714 explosion_add ((float) x1, (float) y1, 0.3f,
715 EXPLOSION_SMALL, 0);
716 break;
717 }
718 }
719 }
720 }
721 return FALSE;
722 }
723
724 /**
725 * Collisions between extra guns and a shot
726 * @param x1 x coordinate of the collision point of the shot
727 * @param y1 y coordinate of the collision point of the shot
728 * @param bullet pointer to the structure of an shot
729 * @return TRUE if the shot touched a extra gun
730 */
731 bool
guns_shot_collisions(Sint32 x1,Sint32 y1,shot_struct * bullet)732 guns_shot_collisions (Sint32 x1, Sint32 y1, shot_struct * bullet)
733 {
734 Sint32 i, j, x2, y2;
735 gun_struct *egun;
736 spaceship_struct *ship = spaceship_get ();
737 egun = gun_first;
738 if (egun == NULL)
739 {
740 return FALSE;
741 }
742
743 /* process each extra gun */
744 for (i = 0; i < ship->num_of_extraguns; i++, egun = egun->next)
745 {
746 #ifdef UNDER_DEVELOPMENT
747 if (egun == NULL && i < (ship->num_of_extraguns - 1))
748 {
749 LOG_ERR ("egun->next is null %i/%i", i, ship->num_of_extraguns);
750 break;
751 }
752 #endif
753 /* if extra gun is invisible, don't perform the tests of collision */
754 if (!egun->is_visible)
755 {
756 continue;
757 }
758 /* for each collision zone of the gun */
759 for (j = 0; j < egun->img[egun->current_image]->numof_collisions_zones;
760 j++)
761 {
762 /* coordinates of the collision zone of the gun */
763 x2 =
764 egun->xcoord +
765 egun->img[egun->current_image]->collisions_coords[j][XCOORD];
766 y2 =
767 egun->ycoord +
768 egun->img[egun->current_image]->collisions_coords[j][YCOORD];
769 /* check if shot collision point is into gun collision zone */
770 if (x1 >= x2 &&
771 y1 >= y2 &&
772 x1 <
773 (x2 +
774 egun->img[egun->current_image]->
775 collisions_sizes[j][IMAGE_WIDTH])
776 && y1 <
777 (y2 +
778 egun->img[egun->current_image]->
779 collisions_sizes[j][IMAGE_HEIGHT]))
780 {
781 /* decrease energy level of gun */
782 egun->energy_level =
783 (Sint16) (egun->energy_level - bullet->spr.pow_of_dest);
784 /* check if gun is destroyed */
785 if (egun->energy_level <= 0)
786 {
787 gun_del (egun);
788 }
789 else
790 {
791 /* gun not destroyed, display white mask */
792 egun->is_white_mask_displayed = TRUE;
793 }
794 explosion_add (bullet->spr.xcoord, bullet->spr.ycoord, 0.35f,
795 EXPLOSION_SMALL, 0);
796 return TRUE;
797 }
798 }
799 }
800 return FALSE;
801 }
802