]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/droidBoss.cpp
e468c29a9e056571a507ff72d44fcd8faabad715
[quix0rs-blobwars.git] / src / droidBoss.cpp
1 /*
2 Copyright (C) 2004 Parallel Realities
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "droidBoss.h"
22
23 void droidBossAttack();
24
25 void droidBossChangeParticles()
26 {
27         (self->x < player.x) ? self->face = 0 : self->face = 1;
28         
29         int color = 0;
30         float dx, dy;
31         
32         dx = 0;
33         
34         switch (self->shieldFrequency)
35         {
36                 case 0:
37                         color = graphics.red;
38                         break;
39                 case 1:
40                         color = graphics.yellow;
41                         break;
42                 case 2:
43                         color = graphics.green;
44                         break;
45                 case 3:
46                         color = graphics.cyan;
47                         break;
48                 case 4:
49                         color = graphics.white;
50                         break;
51         }
52         
53         for (int i = 0 ; i < 20 ; i++)
54         {
55                 dy = Math::rrand(-150, -50);
56                 dy /= 100;
57                 map.addParticle(self->x + (Math::prand() % self->width), self->y  + (Math::prand() % self->height), dx, dy, Math::rrand(1, 60), color, NULL, PAR_WEIGHTLESS);
58         }
59         
60         self->setThinkTime(2);
61         self->setActionFinished(10);
62         self->think = &droidBossChangeParticles;
63         self->custom--;
64         
65         if (self->custom == 0)
66         {
67                 self->setThinkTime(2);
68                 self->setActionFinished(10);
69                 self->think = &droidBossAttack;
70         }
71 }
72
73 void droidBossChasePlayer()
74 {
75         (self->x < player.x) ? self->face = 0 : self->face = 1;
76         
77         float dx, dy;
78         
79         Math::calculateSlope(player.x, player.y, self->x, self->y, &dx, &dy);
80         
81         self->dx = (dx * 2);
82         self->dy = (dy * 2);
83         
84         self->setThinkTime(10);
85         self->setActionFinished(10);
86         self->think = &droidBossAttack;
87 }
88
89 void droidBossChangeFrequency()
90 {
91         (self->x < player.x) ? self->face = 0 : self->face = 1;
92         
93         self->shieldFrequency = Math::rrand(WP_PISTOL, WP_SPREAD);
94         
95         self->think = &droidBossChangeParticles;
96         self->setThinkTime(2);
97         self->setActionFinished(2);
98         self->custom = 5;
99         
100         Math::removeBit(&self->flags, ENT_AIMS);
101         Math::removeBit(&self->flags, ENT_RAPIDFIRE);
102         
103         switch (self->shieldFrequency)
104         {
105                 case WP_PISTOL:
106                         self->currentWeapon = getWeaponByName("Aimed Pistol");
107                         Math::addBit(&self->flags, ENT_AIMS);
108                         self->setSprites(graphics.getSprite("JetpackBlobRight1", true), graphics.getSprite("JetpackBlobLeft1", true), graphics.getSprite("JetpackBlobLeft1", true));
109                         break;
110                 case WP_MACHINEGUN:
111                         self->currentWeapon = getWeaponByName("Machine Gun");
112                         Math::addBit(&self->flags, ENT_RAPIDFIRE);
113                         self->setSprites(graphics.getSprite("JetpackBlobRight2", true), graphics.getSprite("JetpackBlobLeft2", true), graphics.getSprite("JetpackBlobLeft2", true));
114                         break;
115                 case WP_LASER:
116                         self->currentWeapon = getWeaponByName("Alien Laser Cannon");
117                         self->setSprites(graphics.getSprite("JetpackBlobRight3", true), graphics.getSprite("JetpackBlobLeft3", true), graphics.getSprite("JetpackBlobLeft3", true));
118                         break;
119                 case WP_GRENADES:
120                         self->currentWeapon = getWeaponByName("Aimed Pistol");
121                         self->shieldFrequency = WP_PISTOL;
122                         Math::addBit(&self->flags, ENT_AIMS);
123                         self->setSprites(graphics.getSprite("JetpackBlobRight1", true), graphics.getSprite("JetpackBlobLeft1", true), graphics.getSprite("JetpackBlobLeft1", true));
124                         break;
125                 case WP_SPREAD:
126                         self->currentWeapon = &weapon[WP_ALIENSPREAD];
127                         Math::addBit(&self->flags, ENT_AIMS);
128                         self->setSprites(graphics.getSprite("JetpackBlobRight4", true), graphics.getSprite("JetpackBlobLeft4", true), graphics.getSprite("JetpackBlobLeft4", true));
129                         break;
130         }
131         
132         audio.playSound(SND_BOSSCUSTOM1, CH_AMBIANCE);
133 }
134
135 void droidBossDie()
136 {
137         self->health -= Math::rrand(1, 2);
138         self->setActionFinished(30);
139         self->setThinkTime(2);
140         
141         self->dx = Math::rrand(-3, 3);
142         self->dy = Math::rrand(-3, 3);
143         
144         addExplosion(self->x + Math::prand() % self->width, self->y + Math::prand() % self->height, 50, &player);
145         addSmokeAndFire(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 2);
146         
147         if (self->health <= -100)
148         {
149                 checkObjectives(self->name, false);
150                 
151                 map.mainBossPart = NULL;
152         }
153 }
154
155 void droidGoCrazy()
156 {
157         self->dx = Math::rrand(-8, 8);
158         self->dy = Math::rrand(-8, 8);
159         
160         (self->dx > 0) ? self->face = 0 : self->face = 1;
161         
162         if (self->y >= 4800)
163                 self->dy = -2;
164         
165         self->setThinkTime(2);
166         self->setActionFinished(5);
167         self->think = &droidGoCrazy;
168         
169         self->custom--;
170         
171         if (self->custom == 0)
172         {
173                 Math::removeBit(&self->flags, ENT_IMMUNE);
174                 self->think = &droidBossChangeFrequency;
175                 self->setActionFinished(2);
176                 self->setThinkTime(2);
177         }
178 }
179
180 void droidBossReact()
181 {
182         if ((Math::prand() % 10) == 0)
183         {
184                 Math::addBit(&self->flags, ENT_IMMUNE);
185                 audio.playSound(SND_BOSSCUSTOM2, CH_SPAWN);
186                 self->custom = 5;
187                 self->think = &droidGoCrazy;
188                 self->setActionFinished(2);
189                 self->setThinkTime(2);
190         }
191 }
192
193 void droidBossFire()
194 {       
195         (self->x < player.x) ? self->face = 0 : self->face = 1;
196         
197         if (hasClearShot((Entity*)self))
198         {
199                 self->flags & ENT_AIMS ? addBullet((Entity*)self, 0, 0) : addBullet((Entity*)self, self->currentWeapon->getSpeed(self->face), 0);
200                 
201                 if (self->currentWeapon == &weapon[WP_ALIENSPREAD])
202                 {
203                         addBullet(self, self->currentWeapon->getSpeed(self->face), 2);
204                         addBullet(self, self->currentWeapon->getSpeed(self->face), -2);
205                 }
206         }
207                                         
208         self->setThinkTime(2);
209         self->setActionFinished(self->currentWeapon->reload);
210         
211         self->custom--;
212         if (self->custom == 0)
213                 self->think = &droidBossAttack;
214 }
215
216 void orbWait()
217 {
218         self->setThinkTime(60);
219         self->setActionFinished(60);
220 }
221
222 void orbExplode()
223 {
224         addExplosion(self->x, self->y, 50, self);
225         self->setThinkTime(2);
226         self->setActionFinished(2);
227         self->active = false;
228         self->face = 1;
229         self->think = &orbWait;
230         self->x = 9999;
231         self->y = 9999;
232 }
233
234 void doOrb()
235 {
236         (self->x < player.x) ? self->face = 0 : self->face = 1;
237         
238         float dx, dy;
239         
240         Math::calculateSlope(player.x, player.y, self->x, self->y, &dx, &dy);
241         
242         self->dx = (dx * (1 + game.skill));
243         self->dy = (dy * (1 + game.skill));
244         
245         self->setThinkTime(2);
246         self->setActionFinished(Math::rrand(10, 90));
247         self->think = &doOrb;
248         
249         if (game.skill >= 2)
250         {
251                 int distX = (int)fabs(player.x - self->x);
252                 int distY = (int)fabs(player.y - self->y);
253         
254                 distX *= distX;
255                 distY *= distY;
256         
257                 int distance = (int)sqrt(distX + distY);
258                 
259                 if (distance <= 25)
260                         self->health = -1;
261         }
262         
263         if ((Math::prand() % 10) == 0)
264                 self->health = -1;
265 }
266
267 void fireOrb(int i)
268 {
269         debug(("fireOrb()\n"));
270         
271         map.boss[i]->active = true;
272         map.boss[i]->maxHealth = map.boss[i]->health = 1 * game.skill;
273         map.boss[i]->x = self->x;
274         map.boss[i]->y = self->y + 20;
275         
276         map.boss[i]->think = &doOrb;
277         map.boss[i]->die = &orbExplode;
278         map.boss[i]->setActionFinished(2);
279         map.boss[i]->setThinkTime(2);
280 }
281
282 void droidBossOrbAttack()
283 {
284         debug(("droidBossClawAttack\n"));
285         
286         for (int i = 1 ; i < 6 ; i++)
287         {
288                 if (!map.boss[i]->active)
289                 {
290                         fireOrb(i);
291                         self->setThinkTime(2);
292                         self->setActionFinished(90);
293                         self->think = &droidBossAttack;
294                         return;
295                 }
296         }
297         
298         // nothing to do(!)
299         self->think = &droidBossAttack;
300 }
301
302 void droidBossMoveRandomly()
303 {
304         self->dx = Math::rrand(-200, 200);
305         self->dy = Math::rrand(-200, 200);
306         
307         self->dx *= 0.01;
308         self->dy *= 0.01;
309         
310         self->setThinkTime(2);
311         self->setActionFinished(90);
312         self->think = &droidBossAttack;
313 }
314
315 void droidBossAttack()
316 {
317         if (player.health < 1)
318         {
319                 self->dx = self->dy = 0;
320                 return;
321         }
322         
323         (self->x < player.x) ? self->face = 0 : self->face = 1;
324         
325         int r = Math::prand() % 110;
326         
327         if (r < 30)
328         {
329                 self->think = &droidBossChasePlayer;
330                 self->setThinkTime(2);
331                 self->setActionFinished(2);
332                 self->custom = 10;
333         }
334         else if (r < 70)
335         {
336                 self->think = &droidBossFire;
337                 self->setThinkTime(2);
338                 self->setActionFinished(2);
339                 self->custom = Math::rrand(1, 3);
340         }
341         else if (r < 95)
342         {
343                 self->think = &droidBossMoveRandomly;
344                 self->setThinkTime(2);
345                 self->setActionFinished(2);
346                 self->custom = 10;
347         }
348         else if (r < 108)
349         {
350                 self->think = &droidBossOrbAttack;
351                 self->setThinkTime(2);
352                 self->setActionFinished(2);
353                 self->custom = Math::rrand(1, 3);
354         }
355         else
356         {
357                 self->think = &droidBossChangeFrequency;
358                 self->setThinkTime(2);
359                 self->setActionFinished(2);
360         }
361 }
362
363 void droidBossInit()
364 {
365         debug(("droidBossInit\n"));
366         
367         map.boss[0] = new Boss();
368         strlcpy(map.boss[0]->name, "BioMech Jetpack Blob", sizeof map.boss[0]->name);
369         map.boss[0]->health = 30 * game.skill;
370         map.boss[0]->maxHealth = 30 * game.skill;
371         map.boss[0]->setSprites(graphics.getSprite("JetpackBlobRight1", true), graphics.getSprite("JetpackBlobLeft1", true), graphics.getSprite("JetpackBlobLeft1", true));
372         map.boss[0]->currentWeapon = getWeaponByName("Aimed Pistol");
373         map.boss[0]->face = 1;
374         map.boss[0]->active = true;
375         map.boss[0]->x = 3172;
376         map.boss[0]->y = 4646;
377         map.boss[0]->immune = 0;
378         map.boss[0]->setThinkTime(2);
379         map.boss[0]->setActionFinished(2);
380         map.boss[0]->think = &droidBossChangeFrequency;
381         map.boss[0]->react = &droidBossReact;
382         map.boss[0]->die = &droidBossDie;
383         Math::addBit(&map.boss[0]->flags, ENT_FLIES);
384         
385         map.setMainBossPart(map.boss[0]);
386         
387         for (int i = 1 ; i < 6 ; i++)
388         {
389                 map.boss[i] = new Boss();
390                 strlcpy(map.boss[i]->name, "Orb Bomb", sizeof map.boss[i]->name);
391                 map.boss[i]->setSprites(graphics.getSprite("DroidOrb", true), graphics.getSprite("DroidOrb", true), graphics.getSprite("DroidOrb", true));
392                 map.boss[i]->active = false;
393                 map.boss[i]->face = 1;
394                 map.boss[i]->think = &orbWait;
395                 map.boss[i]->x = 9999;
396                 map.boss[i]->y = 9999;
397                 Math::addBit(&map.boss[i]->flags, ENT_FLIES);
398         }
399         
400         audio.loadSound(SND_BOSSCUSTOM1, "sound/droidChangeFreq");
401         audio.loadSound(SND_BOSSCUSTOM2, "sound/droidFreakOut");
402         
403         debug(("droidBossInit: Done\n"));
404 }