Removed that logo from this bramch aswell..
[dbw.git] / src / galdov.cpp
blobe3e7f205fab015f5f68756bd02fa90fa9dcf8269
1 /*
2 Copyright © 2004 Parallel Realities
3 Copyright © 2007-2008 Kővágó Zoltán <DirtY.iCE.hu@gmail.com>
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.
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.
14 See the GNU General Public License for more details.
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.
22 #include "CAudio.h"
23 #include "CGame.h"
24 #include "CGraphics.h"
25 #include "CMap.h"
26 #include "CMath.h"
27 #include "console/console.hpp"
28 #include "galdov.h"
30 void galdovAttack();
31 void galdovCheckSplit();
33 void splitParticles()
35 (self->x < player.x) ? self->face = 0 : self->face = 1;
37 int color = 0;
38 float dx, dy;
40 dx = 0;
42 switch (rand() % 5)
44 case 0:
45 color = graphics.red;
46 break;
47 case 1:
48 color = graphics.yellow;
49 break;
50 case 2:
51 color = graphics.green;
52 break;
53 case 3:
54 color = graphics.cyan;
55 break;
56 case 4:
57 color = graphics.white;
58 break;
61 for (int i = 0 ; i < 20 ; i++)
63 dy = Math::rrand(-150, -50);
64 dy /= 100;
65 map.addParticle(self->x + (rand() % self->width), self->y + (rand() % self->height), dx, dy, Math::rrand(1, 60), color, NULL, PAR_WEIGHTLESS);
68 self->setThinkTime(1);
69 self->setActionFinished(1);
70 self->think = &splitParticles;
71 self->custom--;
73 if (self->custom == 0)
75 self->setThinkTime(2);
76 self->setActionFinished(2);
77 self->think = &galdovAttack;
79 if (self == map.boss[0])
81 if ((rand() % self->health) == 0)
83 self->think = &galdovCheckSplit;
90 void galdovTeleport()
92 self->setThinkTime(2);
93 self->setActionFinished(2);
95 int x = (int)player.x >> BRICKSHIFT;
96 int y = (int)player.y >> BRICKSHIFT;
97 x += Math::rrand(-10, 10);
98 y += Math::rrand(-10, 10);
100 Math::limitInt(&x, 1, 28);
101 Math::limitInt(&y, 259, 283);
103 if (map.data[x][y] == MAP_AIR)
105 x = x << BRICKSHIFT;
106 y = y << BRICKSHIFT;
107 self->x = x;
108 self->y = y;
109 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
110 self->think = &galdovAttack;
114 void galdovReact()
116 if (self->health < 0)
117 return;
119 int r = rand() % 10;
121 if (r == 0)
123 self->setThinkTime(2);
124 self->setActionFinished(2);
125 self->think = &galdovTeleport;
127 r = rand() % 3;
129 if (r == 0)
131 self->setThinkTime(2);
132 self->setActionFinished(2);
133 self->think = &galdovCheckSplit;
138 void galdovSplit(int i)
140 audio.playSound(SND_BOSSCUSTOM1, CH_AMBIANCE);
142 map.boss[i]->active = true;
143 map.boss[i]->health = 4 * game.skill;
144 map.boss[i]->maxHealth = 4 * game.skill;
145 map.boss[i]->x = map.boss[0]->x;
146 map.boss[i]->y = map.boss[0]->y;
147 map.boss[i]->flags = map.boss[0]->flags;
148 map.boss[i]->think = &galdovAttack;
150 if ((rand() % 2) == 0)
152 map.boss[i]->currentWeapon = getRandomAimedWeapon();
153 Math::addBit(&map.boss[i]->flags, ENT_AIMS);
155 else
157 map.boss[i]->currentWeapon = getRandomStraightWeapon();
158 Math::removeBit(&map.boss[i]->flags, ENT_AIMS);
161 if ((rand() % 2) == 0)
163 map.boss[0]->dx = -.5;
164 map.boss[0]->dy = 0;
165 map.boss[i]->dx = .5;
166 map.boss[i]->dy = 0;
168 else
170 map.boss[0]->dx = .5;
171 map.boss[0]->dy = 0;
172 map.boss[i]->dx = -.5;
173 map.boss[i]->dy = 0;
176 map.boss[0]->think = &splitParticles;
177 map.boss[0]->setThinkTime(1);
178 map.boss[0]->setActionFinished(1);
179 map.boss[0]->custom = 60;
181 map.boss[i]->think = &splitParticles;
182 map.boss[i]->setThinkTime(1);
183 map.boss[i]->setActionFinished(1);
184 map.boss[i]->custom = 60;
187 void galdovCheckSplit()
189 for (int i = 1 ; i < 10 ; i++)
191 if (!map.boss[i]->active)
193 galdovSplit(i);
194 return;
199 void galdovFire()
201 (self->x < player.x) ? self->face = 0 : self->face = 1;
203 self->setActionFinished(9);
204 self->setThinkTime(2);
205 self->think = &galdovFire;
207 if (hasClearShot(self))
209 self->flags & ENT_AIMS ? addBullet((Entity*)self, 0, 0) : addBullet((Entity*)self, self->currentWeapon->getSpeed(self->face), 0);
211 if (self->currentWeapon == &weapon[WP_ALIENSPREAD])
213 addBullet(self, self->currentWeapon->getSpeed(self->face), 2);
214 addBullet(self, self->currentWeapon->getSpeed(self->face), -2);
218 self->custom--;
219 if (self->custom == 0)
221 self->think = &galdovAttack;
225 void galdovRocketAttack()
227 (self->x < player.x) ? self->face = 0 : self->face = 1;
229 if (!hasClearShot(self))
230 return;
232 self->setActionFinished(5);
233 self->setThinkTime(2);
234 self->think = &galdovRocketAttack;
236 addBullet((Entity*)self, 0, 0);
238 self->custom--;
240 if (self->custom == 0)
242 self->think = &galdovAttack;
243 self->currentWeapon = getRandomGaldovWeapon();
247 void galdovChasePlayer()
249 (self->x < player.x) ? self->face = 0 : self->face = 1;
251 float dx, dy;
253 Math::calculateSlope(player.x, player.y, self->x, self->y, &dx, &dy);
255 self->dx = (dx * 2);
256 self->dy = (dy * 2);
258 self->setThinkTime(10);
259 self->setActionFinished(10);
260 self->think = &galdovAttack;
263 void galdovMoveRandom()
265 self->think = &galdovAttack;
267 if (self->flags & ENT_FLIES)
269 self->dx = Math::rrand(-200, 200);
270 self->dy = Math::rrand(-200, 200);
272 self->dx *= 0.01;
273 self->dy *= 0.01;
275 self->setThinkTime(2);
276 self->setActionFinished(Math::rrand(60, 90));
278 else
280 self->dy = Math::rrand(-12, 0);
282 (player.x < self->x) ? self->dx = -3 : self->dx = 3;
284 self->think = &galdovAttack;
285 self->setActionFinished(45);
289 void galdovDoInvisible()
291 if ((rand() % 2) == 0)
293 map.boss[0]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovLeft", true));
295 else
297 map.boss[0]->setSprites(graphics.getSprite("GaldovInvsRight", true), graphics.getSprite("GaldovInvsLeft", true), graphics.getSprite("GaldovInvsLeft", true));
300 self->setThinkTime(2);
301 self->setActionFinished(2);
302 self->think = &galdovAttack;
305 void galdovAttack()
307 if (player.health < 1)
309 self->dx = self->dy = 0;
310 return;
313 (self->x < player.x) ? self->face = 0 : self->face = 1;
315 self->think = &galdovAttack;
316 self->setThinkTime(2);
317 self->setActionFinished(2);
319 int r = rand() % 100;
321 if (r < 10)
323 self->think = &galdovFire;
324 self->custom = Math::rrand(1, 8);
326 else if (r < 17)
328 // Make sure only the real Galdov does this!
329 if (self == map.boss[0])
331 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
332 self->x = -9999;
333 self->y = -9999;
334 self->setActionFinished(120);
335 self->setThinkTime(2);
336 self->think = &galdovTeleport;
339 else if (r < 40)
341 self->think = &galdovChasePlayer;
343 else if (r < 60)
345 self->think = &galdovMoveRandom;
347 else if (r < 80)
349 if ((self->flags & ENT_FLIES) && (rand() % 5) == 0)
351 Math::removeBit(&self->flags, ENT_FLIES);
352 Math::removeBit(&self->flags, ENT_FIRETRAIL);
354 else
356 Math::addBit(&self->flags, ENT_FLIES);
357 Math::addBit(&self->flags, ENT_FIRETRAIL);
360 else if (r < 85)
362 if (self == map.boss[0])
364 self->think = &galdovDoInvisible;
367 else if (r < 90)
369 map.boss[0]->currentWeapon = getRandomGaldovWeapon();
371 else if (r == 91)
373 // Make sure only the real Galdov does this!
374 if (self == map.boss[0])
376 self->custom = Math::rrand(4, 8);
377 self->currentWeapon = &weapon[WP_ROCKETS];
378 self->think = &galdovRocketAttack;
381 else
383 // Make sure only the real Galdov does this!
384 if (self == map.boss[0])
386 self->think = &galdovCheckSplit;
391 void galdovDie()
393 self->health--;
395 if (map.mainBossPart != NULL)
397 map.mainBossPart = NULL;
398 audio.playSound(SND_BOSSCUSTOM2, CH_AMBIANCE);
401 if ((self->health % 5) == 0)
403 self->setActionFinished(5);
404 self->setThinkTime(2);
406 self->dx = Math::rrand(-5, 5);
407 self->dy = Math::rrand(-5, 5);
409 addExplosion(self->x, self->y, 5, &player);
410 addSmokeAndFire(self, Math::rrand(-4, 4), Math::rrand(-4, 4), 2);
413 for (int i = 1 ; i < 10 ; i++)
415 if (map.boss[i]->health > -1)
417 map.boss[i]->health = -1;
421 if (self->health <= -100)
423 checkObjectives(self->name, false);
424 map.mainBossPart = NULL;
425 addTeleportParticles(self->x, self->y, 75, SND_TELEPORT3);
429 void dropItems(int x, int y)
431 int r;
433 for (int i = 0 ; i < 2 ; i++)
435 r = Math::rrand(ITEM_PISTOL, ITEM_DOUBLECHERRY);
437 // Grenades make this battle far too easy(!)
438 if (r == ITEM_GRENADES)
439 r = ITEM_LASER;
441 if ((rand() % 10) == 0)
442 r = ITEM_TRIPLECHERRY;
444 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
448 void fakeDie()
450 dropItems((int)self->x, (int)self->y);
452 addExplosion(self->x, self->y, 50, self);
453 self->setThinkTime(2);
454 self->setActionFinished(2);
455 self->active = false;
456 self->face = 1;
457 self->x = 9999;
458 self->y = 9999;
461 void galdovInit()
463 debug("boss", 2) << "galdovInit" << std::endl;
465 map.boss[0] = new Boss();
466 strcpy(map.boss[0]->name, "Galdov");
467 map.boss[0]->health = 45 * game.skill;
468 map.boss[0]->maxHealth = 45 * game.skill;
469 map.boss[0]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovLeft", true));
470 map.boss[0]->currentWeapon = &weapon[WP_AIMEDPISTOL];
471 map.boss[0]->face = 0;
472 map.boss[0]->active = true;
473 map.boss[0]->x = 448;
474 map.boss[0]->y = 9024;
475 map.boss[0]->immune = 0;
476 map.boss[0]->setThinkTime(2);
477 map.boss[0]->setActionFinished(2);
478 map.boss[0]->think = &galdovCheckSplit;
479 map.boss[0]->react = &galdovReact;
480 map.boss[0]->die = &galdovDie;
482 Math::addBit(&map.boss[0]->flags, ENT_AIMS);
484 SDL_SetAlpha(graphics.getSprite("GaldovInvsLeft", true)->image[0], SDL_SRCALPHA|SDL_RLEACCEL, 100);
485 SDL_SetAlpha(graphics.getSprite("GaldovInvsRight", true)->image[0], SDL_SRCALPHA|SDL_RLEACCEL, 100);
487 for (int i = 1 ; i < 10 ; i++)
489 map.boss[i] = new Boss();
490 strcpy(map.boss[i]->name, "Fake");
491 map.boss[i]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovLeft", true));
492 map.boss[i]->x = 9999;
493 map.boss[i]->y = 9999;
494 map.boss[i]->active = false;
495 map.boss[i]->think = &galdovAttack;
496 map.boss[i]->react = NULL;
497 map.boss[i]->die = &fakeDie;
500 map.setMainBossPart(map.boss[0]);
502 audio.loadSound(SND_BOSSCUSTOM1, "sound/galdovSplit.wav");
503 audio.loadSound(SND_BOSSCUSTOM2, "sound/galdovPain.wav");
505 debug("boss", 2) << "galdovInit: Done" << std::endl;