]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/aquaBoss.cpp
Prevent a segmentation fault when using the -map option without specifying a map.
[quix0rs-blobwars.git] / src / aquaBoss.cpp
1 /*
2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (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.
13
14 See the 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 #include "aquaBoss.h"
23
24 void aquaBossAttack();
25
26 void leachParticles(Entity *enemy)
27 {
28         float dx, dy;
29         
30         Sprite *blood = graphics.getSprite("RedBloodParticle", true);
31         
32         Math::calculateSlope(self->x, self->y, enemy->x, enemy->y, &dx, &dy);
33         
34         dx *= Math::rrand(1, 2);
35         dy *= Math::rrand(1, 2);
36
37         for (int i = 0 ; i < 25 ; i++)
38         {
39                 map.addParticle(enemy->x + 10 + Math::rrand(-2, 2), enemy->y + 10 + Math::rrand(-2, 2), dx, dy, Math::rrand(1, 60), graphics.red, blood, PAR_WEIGHTLESS);
40         }
41         
42         addBlood(enemy, 0, 0, 1);
43 }
44
45 void aquaBossRecharge()
46 {
47         debug(("aquaBossRecharge\n"));
48         
49         if (self->health == self->maxHealth)
50         {
51                 self->think = aquaBossAttack;
52                 Math::removeBit(&self->flags, ENT_IMMUNE);
53                 self->setSprites(graphics.getSprite("AquaBossRight", true), graphics.getSprite("AquaBossLeft", true), graphics.getSprite("AquaBossLeft", true));
54                 return;
55         }
56         
57         bool leachedEnemy = false;
58         int diffX, diffY;
59         
60         Entity *enemy = (Entity*)map.enemyList.getHead();
61         
62         while (enemy->next != NULL)
63         {
64                 enemy = (Entity*)enemy->next;
65                 
66                 // don't leach enemies not in the pool!!
67                 if (enemy->x >= 1490)
68                         continue;
69                 
70                 diffX = abs((int)(enemy->x - self->x));
71                 diffY = abs((int)(enemy->y - self->y));
72                 
73                 if ((diffX <= 160) && (diffY <= 120))
74                 {
75                         if (enemy->health > -100)
76                         {
77                                 enemy->dx = enemy->dy = 0;
78                                 enemy->health = -1;
79                                 if (enemy->health % 10)
80                                 {
81                                         audio.playSound(SND_DEATH1 + Math::prand() % 3, CH_DEATH);
82                                 }
83                                 
84                                 Math::limitInt(&(++self->health), 0, self->maxHealth);
85                                 self->setActionFinished(25);
86                                 leachParticles(enemy);
87                                 leachedEnemy = true;
88                         }
89                 }
90         }
91         
92         self->setActionFinished(5);
93         
94         if (!leachedEnemy)
95         {
96                 self->think = aquaBossAttack;
97                 Math::removeBit(&self->flags, ENT_IMMUNE);
98                 self->setSprites(graphics.getSprite("AquaBossRight", true), graphics.getSprite("AquaBossLeft", true), graphics.getSprite("AquaBossLeft", true));
99         }
100 }
101
102 void aquaBossCircleStrafe()
103 {
104         debug(("aquaBossCircleStrafe\n"));
105         
106         self->think = &aquaBossAttack;
107 }
108
109 void aquaBossRapidLaserFire()
110 {
111         debug(("aquaBossRapidLaserFire\n"));
112         
113         (self->x < player.x) ? self->face = 0 : self->face = 1;
114         
115         self->setThinkTime(2);
116         self->setActionFinished(5);
117         
118         addBullet((Entity*)self, self->currentWeapon->getSpeed(self->face), 0);
119         self->think = &aquaBossRapidLaserFire;
120         
121         self->custom--;
122         
123         if (self->custom == 0)
124         {
125                 self->think = &aquaBossAttack;
126                 self->setActionFinished(90);
127         }
128 }
129
130 void aquaBossRapidPreLaserFire()
131 {
132         (self->x < player.x) ? self->face = 0 : self->face = 1;
133         
134         self->dx = 0;
135         if (self->x < 1150) self->dx = 3;
136         if (self->x > 1170) self->dx = -3;
137         
138         if (self->custom == 0)
139         {
140                 if (self->y > 490)
141                         self->dy = -2;
142                 
143                 if (self->y <= 490)
144                 {
145                         self->think = &aquaBossRapidLaserFire;
146                         self->dy = 3;
147                         self->custom = Math::rrand(8, 16);
148                 }
149         }
150         else
151         {
152                 if (self->y < 940)
153                         self->dy = 2;
154                 
155                 if (self->y >= 940)
156                 {
157                         self->think = &aquaBossRapidLaserFire;
158                         self->dy = -3;
159                         self->custom = Math::rrand(8, 16);
160                 }
161         }
162 }
163
164 void aquaBossFire()
165 {
166         debug(("aquaBossFire\n"));
167         
168         (self->x < player.x) ? self->face = 0 : self->face = 1;
169         
170         self->setActionFinished(5);
171         self->setThinkTime(2);
172         self->think = &aquaBossFire;
173         
174         addBullet((Entity*)self, 0, 0);
175         
176         self->custom--;
177         
178         if (self->custom == 0)
179         {
180                 Math::removeBit(&self->flags, ENT_AIMS);
181                 self->currentWeapon = &weapon[WP_ALIENLASER];
182                 self->think = &aquaBossAttack;
183         }
184 }
185
186 void aquaBossUnProtect()
187 {
188         debug(("aquaBossUnProtect\n"));
189         
190         Math::removeBit(&self->flags, ENT_IMMUNE);
191         self->think = &aquaBossAttack;
192         
193         self->setSprites(graphics.getSprite("AquaBossRight", true), graphics.getSprite("AquaBossLeft", true), graphics.getSprite("AquaBossLeft", true));
194 }
195
196 void aquaBossProtect()
197 {
198         debug(("aquaBossProtect\n"));
199         
200         Math::addBit(&self->flags, ENT_IMMUNE);
201         self->think = &aquaBossUnProtect;
202         self->setThinkTime(Math::rrand(90, 120));
203         
204         self->setSprites(graphics.getSprite("AquaBossProtectRight", true), graphics.getSprite("AquaBossProtectLeft", true), graphics.getSprite("AquaBossProtectLeft", true));
205 }
206
207 void aquaBossReact()
208 {
209         // They can keep firing as much as they want, but it won't drop its shield now!
210         if (self->flags & ENT_IMMUNE)
211         {
212                 self->setThinkTime(Math::rrand(90, 120));
213                 return;
214         }
215         
216         if ((Math::prand() % 12) == 0)
217                 aquaBossProtect();
218 }
219
220 void aquaBossDie()
221 {
222         self->health -= Math::rrand(1, 2);
223         self->setActionFinished(30);
224         self->setThinkTime(2);
225         
226         self->dx = Math::rrand(-3, 3);
227         self->dy = Math::rrand(-3, 3);
228         
229         addExplosion(self->x, self->y, 50, &player);
230         addSmokeAndFire(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 2);
231         addBlood(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 3);
232         
233         if (self->health <= -100)
234         {
235                 checkObjectives(self->name, false);
236                 
237                 map.mainBossPart = NULL;
238         }
239 }
240
241 void aquaBossAttack()
242 {
243         if (player.health < 1)
244         {
245                 self->dx = 0;
246                 return;
247         }
248         
249         debug(("aquaBossAttack\n"));
250         
251         (self->x < player.x) ? self->face = 0 : self->face = 1;
252         
253         int r = Math::prand() % (15 + game.skill);
254         
255         if (r < 5)
256         {
257                 self->dx = Math::rrand(-2, 2);
258                 self->dy = Math::rrand(-2, 2);
259                 self->setThinkTime(Math::rrand(60, 120));
260                 self->think = &aquaBossAttack;
261         }
262         else if (r < 8)
263         {
264                 self->dx = self->dy = 0;
265                 self->custom = Math::rrand(5, 8);
266                 self->currentWeapon = &weapon[WP_AIMEDPISTOL];
267                 Math::addBit(&self->flags, ENT_AIMS);
268                 self->think = &aquaBossFire;
269         }
270         else if (r == 8)
271         {
272                 self->think = &aquaBossRapidPreLaserFire;
273                 self->custom = Math::prand() % 2;
274         }
275         else if (r == 9)
276         {
277                 //self->think = &aquaBossCircleStrafe;
278         }
279         else
280         {
281                 self->think = &aquaBossRecharge;
282                 self->custom = Math::rrand(10, 25) * game.skill;
283         }
284 }
285
286 void aquaBossMainInit()
287 {
288         debug(("aquaBossMainInit\n"));
289         
290         map.boss[0] = new Boss();
291         strlcpy(map.boss[0]->name, "BioMech Aqua Blob", sizeof map.boss[0]->name);
292         map.boss[0]->health = 45 * game.skill;
293         map.boss[0]->maxHealth = 45 * game.skill;
294         map.boss[0]->setSprites(graphics.getSprite("AquaBossRight", true), graphics.getSprite("AquaBossLeft", true), graphics.getSprite("AquaBossLeft", true));
295         map.boss[0]->currentWeapon = &weapon[WP_ALIENLASER];
296         map.boss[0]->face = 0;
297         map.boss[0]->active = false;
298         map.boss[0]->x = 1072;
299         map.boss[0]->y = 740;
300         map.boss[0]->immune = 0;
301         map.boss[0]->setThinkTime(1);
302         map.boss[0]->setActionFinished(1);
303         map.boss[0]->think = &aquaBossAttack;
304         map.boss[0]->react = &aquaBossReact;
305         map.boss[0]->die = &aquaBossDie;
306         
307         Math::addBit(&map.boss[0]->flags, ENT_SWIMS);
308         
309         map.setMainBossPart(map.boss[0]);
310         
311         debug(("aquaBossMainInit: Done\n"));
312 }
313
314 void aquaBossInit()
315 {
316         aquaBossMainInit();
317 }