Some Window$ specific edits.
[dbw.git] / src / galdov.cpp
blob1714600fa6199ed3a589306099383d51596b3ce9
1 /*
2 Copyright (C) 2004 Parallel Realities
3 Copyright (C) 2007 Kővágó Zoltán
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 "galdov.h"
23 #include "console/console.hpp"
25 void galdovAttack();
26 void galdovCheckSplit();
28 void splitParticles()
30 (self->x < player.x) ? self->face = 0 : self->face = 1;
32 int color = 0;
33 float dx, dy;
35 dx = 0;
37 switch (rand() % 5)
39 case 0:
40 color = graphics.red;
41 break;
42 case 1:
43 color = graphics.yellow;
44 break;
45 case 2:
46 color = graphics.green;
47 break;
48 case 3:
49 color = graphics.cyan;
50 break;
51 case 4:
52 color = graphics.white;
53 break;
56 for (int i = 0 ; i < 20 ; i++)
58 dy = Math::rrand(-150, -50);
59 dy /= 100;
60 map.addParticle(self->x + (rand() % self->width), self->y + (rand() % self->height), dx, dy, Math::rrand(1, 60), color, NULL, PAR_WEIGHTLESS);
63 self->setThinkTime(1);
64 self->setActionFinished(1);
65 self->think = &splitParticles;
66 self->custom--;
68 if (self->custom == 0)
70 self->setThinkTime(2);
71 self->setActionFinished(2);
72 self->think = &galdovAttack;
74 if (self == map.boss[0])
76 if ((rand() % self->health) == 0)
78 self->think = &galdovCheckSplit;
85 void galdovTeleport()
87 self->setThinkTime(2);
88 self->setActionFinished(2);
90 int x = (int)player.x >> BRICKSHIFT;
91 int y = (int)player.y >> BRICKSHIFT;
92 x += Math::rrand(-10, 10);
93 y += Math::rrand(-10, 10);
95 Math::limitInt(&x, 1, 28);
96 Math::limitInt(&y, 259, 283);
98 if (map.data[x][y] == MAP_AIR)
100 x = x << BRICKSHIFT;
101 y = y << BRICKSHIFT;
102 self->x = x;
103 self->y = y;
104 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
105 self->think = &galdovAttack;
109 void galdovReact()
111 if (self->health < 0)
112 return;
114 int r = rand() % 10;
116 if (r == 0)
118 self->setThinkTime(2);
119 self->setActionFinished(2);
120 self->think = &galdovTeleport;
122 r = rand() % 3;
124 if (r == 0)
126 self->setThinkTime(2);
127 self->setActionFinished(2);
128 self->think = &galdovCheckSplit;
133 void galdovSplit(int i)
135 audio.playSound(SND_BOSSCUSTOM1, CH_AMBIANCE);
137 map.boss[i]->active = true;
138 map.boss[i]->health = 4 * game.skill;
139 map.boss[i]->maxHealth = 4 * game.skill;
140 map.boss[i]->x = map.boss[0]->x;
141 map.boss[i]->y = map.boss[0]->y;
142 map.boss[i]->flags = map.boss[0]->flags;
143 map.boss[i]->think = &galdovAttack;
145 if ((rand() % 2) == 0)
147 map.boss[i]->currentWeapon = getRandomAimedWeapon();
148 Math::addBit(&map.boss[i]->flags, ENT_AIMS);
150 else
152 map.boss[i]->currentWeapon = getRandomStraightWeapon();
153 Math::removeBit(&map.boss[i]->flags, ENT_AIMS);
156 if ((rand() % 2) == 0)
158 map.boss[0]->dx = -.5;
159 map.boss[0]->dy = 0;
160 map.boss[i]->dx = .5;
161 map.boss[i]->dy = 0;
163 else
165 map.boss[0]->dx = .5;
166 map.boss[0]->dy = 0;
167 map.boss[i]->dx = -.5;
168 map.boss[i]->dy = 0;
171 map.boss[0]->think = &splitParticles;
172 map.boss[0]->setThinkTime(1);
173 map.boss[0]->setActionFinished(1);
174 map.boss[0]->custom = 60;
176 map.boss[i]->think = &splitParticles;
177 map.boss[i]->setThinkTime(1);
178 map.boss[i]->setActionFinished(1);
179 map.boss[i]->custom = 60;
182 void galdovCheckSplit()
184 for (int i = 1 ; i < 10 ; i++)
186 if (!map.boss[i]->active)
188 galdovSplit(i);
189 return;
194 void galdovFire()
196 (self->x < player.x) ? self->face = 0 : self->face = 1;
198 self->setActionFinished(9);
199 self->setThinkTime(2);
200 self->think = &galdovFire;
202 if (hasClearShot(self))
204 self->flags & ENT_AIMS ? addBullet((Entity*)self, 0, 0) : addBullet((Entity*)self, self->currentWeapon->getSpeed(self->face), 0);
206 if (self->currentWeapon == &weapon[WP_ALIENSPREAD])
208 addBullet(self, self->currentWeapon->getSpeed(self->face), 2);
209 addBullet(self, self->currentWeapon->getSpeed(self->face), -2);
213 self->custom--;
214 if (self->custom == 0)
216 self->think = &galdovAttack;
220 void galdovRocketAttack()
222 (self->x < player.x) ? self->face = 0 : self->face = 1;
224 if (!hasClearShot(self))
225 return;
227 self->setActionFinished(5);
228 self->setThinkTime(2);
229 self->think = &galdovRocketAttack;
231 addBullet((Entity*)self, 0, 0);
233 self->custom--;
235 if (self->custom == 0)
237 self->think = &galdovAttack;
238 self->currentWeapon = getRandomGaldovWeapon();
242 void galdovChasePlayer()
244 (self->x < player.x) ? self->face = 0 : self->face = 1;
246 float dx, dy;
248 Math::calculateSlope(player.x, player.y, self->x, self->y, &dx, &dy);
250 self->dx = (dx * 2);
251 self->dy = (dy * 2);
253 self->setThinkTime(10);
254 self->setActionFinished(10);
255 self->think = &galdovAttack;
258 void galdovMoveRandom()
260 self->think = &galdovAttack;
262 if (self->flags & ENT_FLIES)
264 self->dx = Math::rrand(-200, 200);
265 self->dy = Math::rrand(-200, 200);
267 self->dx *= 0.01;
268 self->dy *= 0.01;
270 self->setThinkTime(2);
271 self->setActionFinished(Math::rrand(60, 90));
273 else
275 self->dy = Math::rrand(-12, 0);
277 (player.x < self->x) ? self->dx = -3 : self->dx = 3;
279 self->think = &galdovAttack;
280 self->setActionFinished(45);
284 void galdovDoInvisible()
286 if ((rand() % 2) == 0)
288 map.boss[0]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovLeft", true));
290 else
292 map.boss[0]->setSprites(graphics.getSprite("GaldovInvsRight", true), graphics.getSprite("GaldovInvsLeft", true), graphics.getSprite("GaldovInvsLeft", true));
295 self->setThinkTime(2);
296 self->setActionFinished(2);
297 self->think = &galdovAttack;
300 void galdovAttack()
302 if (player.health < 1)
304 self->dx = self->dy = 0;
305 return;
308 (self->x < player.x) ? self->face = 0 : self->face = 1;
310 self->think = &galdovAttack;
311 self->setThinkTime(2);
312 self->setActionFinished(2);
314 int r = rand() % 100;
316 if (r < 10)
318 self->think = &galdovFire;
319 self->custom = Math::rrand(1, 8);
321 else if (r < 17)
323 // Make sure only the real Galdov does this!
324 if (self == map.boss[0])
326 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
327 self->x = -9999;
328 self->y = -9999;
329 self->setActionFinished(120);
330 self->setThinkTime(2);
331 self->think = &galdovTeleport;
334 else if (r < 40)
336 self->think = &galdovChasePlayer;
338 else if (r < 60)
340 self->think = &galdovMoveRandom;
342 else if (r < 80)
344 if ((self->flags & ENT_FLIES) && (rand() % 5) == 0)
346 Math::removeBit(&self->flags, ENT_FLIES);
347 Math::removeBit(&self->flags, ENT_FIRETRAIL);
349 else
351 Math::addBit(&self->flags, ENT_FLIES);
352 Math::addBit(&self->flags, ENT_FIRETRAIL);
355 else if (r < 85)
357 if (self == map.boss[0])
359 self->think = &galdovDoInvisible;
362 else if (r < 90)
364 map.boss[0]->currentWeapon = getRandomGaldovWeapon();
366 else if (r == 91)
368 // Make sure only the real Galdov does this!
369 if (self == map.boss[0])
371 self->custom = Math::rrand(4, 8);
372 self->currentWeapon = &weapon[WP_ROCKETS];
373 self->think = &galdovRocketAttack;
376 else
378 // Make sure only the real Galdov does this!
379 if (self == map.boss[0])
381 self->think = &galdovCheckSplit;
386 void galdovDie()
388 self->health--;
390 if (map.mainBossPart != NULL)
392 map.mainBossPart = NULL;
393 audio.playSound(SND_BOSSCUSTOM2, CH_AMBIANCE);
396 if ((self->health % 5) == 0)
398 self->setActionFinished(5);
399 self->setThinkTime(2);
401 self->dx = Math::rrand(-5, 5);
402 self->dy = Math::rrand(-5, 5);
404 addExplosion(self->x, self->y, 5, &player);
405 addSmokeAndFire(self, Math::rrand(-4, 4), Math::rrand(-4, 4), 2);
408 for (int i = 1 ; i < 10 ; i++)
410 if (map.boss[i]->health > -1)
412 map.boss[i]->health = -1;
416 if (self->health <= -100)
418 checkObjectives(self->name, false);
419 map.mainBossPart = NULL;
420 addTeleportParticles(self->x, self->y, 75, SND_TELEPORT3);
424 void dropItems(int x, int y)
426 int r;
428 for (int i = 0 ; i < 2 ; i++)
430 r = Math::rrand(ITEM_PISTOL, ITEM_DOUBLECHERRY);
432 // Grenades make this battle far too easy(!)
433 if (r == ITEM_GRENADES)
434 r = ITEM_LASER;
436 if ((rand() % 10) == 0)
437 r = ITEM_TRIPLECHERRY;
439 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
443 void fakeDie()
445 dropItems((int)self->x, (int)self->y);
447 addExplosion(self->x, self->y, 50, self);
448 self->setThinkTime(2);
449 self->setActionFinished(2);
450 self->active = false;
451 self->face = 1;
452 self->x = 9999;
453 self->y = 9999;
456 void galdovInit()
458 debug << "galdovInit" << std::endl;
460 map.boss[0] = new Boss();
461 strcpy(map.boss[0]->name, "Galdov");
462 map.boss[0]->health = 45 * game.skill;
463 map.boss[0]->maxHealth = 45 * game.skill;
464 map.boss[0]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovLeft", true));
465 map.boss[0]->currentWeapon = &weapon[WP_AIMEDPISTOL];
466 map.boss[0]->face = 0;
467 map.boss[0]->active = true;
468 map.boss[0]->x = 448;
469 map.boss[0]->y = 9024;
470 map.boss[0]->immune = 0;
471 map.boss[0]->setThinkTime(2);
472 map.boss[0]->setActionFinished(2);
473 map.boss[0]->think = &galdovCheckSplit;
474 map.boss[0]->react = &galdovReact;
475 map.boss[0]->die = &galdovDie;
477 Math::addBit(&map.boss[0]->flags, ENT_AIMS);
479 SDL_SetAlpha(graphics.getSprite("GaldovInvsLeft", true)->image[0], SDL_SRCALPHA|SDL_RLEACCEL, 100);
480 SDL_SetAlpha(graphics.getSprite("GaldovInvsRight", true)->image[0], SDL_SRCALPHA|SDL_RLEACCEL, 100);
482 for (int i = 1 ; i < 10 ; i++)
484 map.boss[i] = new Boss();
485 strcpy(map.boss[i]->name, "Fake");
486 map.boss[i]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovLeft", true));
487 map.boss[i]->x = 9999;
488 map.boss[i]->y = 9999;
489 map.boss[i]->active = false;
490 map.boss[i]->think = &galdovAttack;
491 map.boss[i]->react = NULL;
492 map.boss[i]->die = &fakeDie;
495 map.setMainBossPart(map.boss[0]);
497 audio.loadSound(SND_BOSSCUSTOM1, "sound/galdovSplit.wav");
498 audio.loadSound(SND_BOSSCUSTOM2, "sound/galdovPain.wav");
500 debug << "galdovInit: Done" << std::endl;