]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/finalBattle.cpp
Update copyright statements.
[quix0rs-blobwars.git] / src / finalBattle.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 "finalBattle.h"
23
24 void galdovMiniAttack();
25 void galdovFinalFlee1();
26 void blackDroidAttack();
27
28 // ************************ Black Droids for Part 2 *************************************
29
30 void blackDroidFire()
31 {       
32         (self->x < player.x) ? self->face = 0 : self->face = 1;
33         
34         if (!hasClearShot(self))
35                 return;
36         
37         self->setActionFinished(9);
38         self->setThinkTime(2);
39         self->think = &blackDroidFire;
40         
41         addBullet((Entity*)self, 0, 0);
42         
43         self->custom--;
44         if (self->custom == 0)
45         {
46                 self->think = &blackDroidAttack;
47         }
48 }
49
50 void blackDroidDie()
51 {
52         self->health--;
53         Math::removeBit(&self->flags, ENT_FLIES);
54         
55         if (self->health < -10)
56         {
57                 if ((self->health % 3) == 0)
58                 {
59                         addExplosion(self->x, self->y, 35, self);
60                         addSmokeAndFire(self, Math::rrand(-15, 15), Math::rrand(-15, 15), 2);
61                 }
62         }
63         
64         if (self->health <= -60)
65         {
66                 if ((Math::prand() % 2) == 0)
67                 {
68                         dropItems((int)self->x, (int)self->y);
69                         dropItems((int)self->x, (int)self->y);
70                 }
71                 else
72                 {
73                         addItem(100, "Red Keycard", (int)self->x, (int)self->y, "RedKeyCard", 240, 1, ENT_DYING, true);
74                 }
75                 self->active = false;
76                 self->place(9999, 9999);
77         }
78 }
79
80 void blackDroidChasePlayer()
81 {
82         self->think = &blackDroidAttack;
83         
84         (self->x < player.x) ? self->face = 0 : self->face = 1;
85         
86         float dx, dy;
87         
88         Math::calculateSlope(player.x, player.y, self->x, self->y, &dx, &dy);
89         
90         self->dx = (dx * 2);
91         self->dy = (dy * 2);
92         
93         self->setThinkTime(10);
94         self->setActionFinished(10);
95 }
96
97 void blackDroidMoveRandom()
98 {
99         (self->x < player.x) ? self->face = 0 : self->face = 1;
100         
101         self->think = &blackDroidAttack;
102         
103         self->dx = Math::rrand(-200, 200);
104         self->dy = Math::rrand(-200, 200);
105
106         self->dx *= 0.01;
107         self->dy *= 0.01;
108
109         self->setThinkTime(2);
110         self->setActionFinished(Math::rrand(60, 90));
111 }
112
113 void blackDroidAttack()
114 {
115         self->think = blackDroidAttack;
116         self->setThinkTime(2);
117         self->setActionFinished(2);
118         
119         int r = Math::prand() % 15;
120         
121         if (r <= 2)
122         {
123                 self->think = &blackDroidFire;
124                 self->setThinkTime(2);
125                 self->setActionFinished(2);
126                 self->custom = Math::rrand(2, 4) * game.skill;
127         }
128         else if (r < 5)
129         {
130                 self->think = &blackDroidChasePlayer;
131                 self->setThinkTime(2);
132                 self->setActionFinished(2);
133         }
134         else
135         {
136                 self->think = &blackDroidMoveRandom;
137                 self->setThinkTime(2);
138                 self->setActionFinished(2);
139         }
140 }
141
142 void galdovInitBlackDroids()
143 {
144         for (int i = 6 ; i < 10 ; i++)
145         {
146                 if (map.boss[i] == NULL)
147                 {
148                         map.boss[i] = new Boss();
149                 }
150                 debug(("BlackDroid %d init\n", i));
151                 strlcpy(map.boss[i]->name, "BlackDrod", sizeof map.boss[i]->name);
152                 map.boss[i]->health = -90;
153                 map.boss[i]->maxHealth = -90;
154                 map.boss[i]->setSprites(graphics.getSprite("BlackDroidRight", true), graphics.getSprite("BlackDroidLeft", true), graphics.getSprite("BlackDroidDie", true));
155                 map.boss[i]->currentWeapon = &weapon[WP_PLASMARIFLE];
156                 map.boss[i]->face = 0;
157                 map.boss[i]->active = false;
158                 map.boss[i]->place(9999, 9999);
159                 map.boss[i]->immune = 0;
160                 map.boss[i]->setThinkTime(2);
161                 map.boss[i]->think = &blackDroidAttack;
162                 map.boss[i]->react = NULL;
163                 map.boss[i]->die = &blackDroidDie;
164                 map.boss[i]->setActionFinished(120);
165                 Math::addBit(&map.boss[i]->flags, ENT_FLIES);
166                 Math::addBit(&map.boss[i]->flags, ENT_AIMS);
167                 Math::removeBit(&map.boss[i]->flags, ENT_FIRETRAIL);
168         }
169 }
170
171 // ************************ First part of final battle **********************************
172
173 void galdovFinalKeepAlive1()
174 {
175         map.boss[0]->health = 30 * game.skill;
176 }
177
178 void galdovFinalPainThrow()
179 {
180         self->dx = -3;
181         self->dy = -12;
182         
183         self->think = &galdovFinalFlee1;
184         self->setThinkTime(2);
185         self->setActionFinished(140);
186 }
187
188 void galdovFinalDropCrystal()
189 {
190         self->setThinkTime(2);
191         self->setActionFinished(2);
192         
193         int x = (int)player.x >> BRICKSHIFT;
194         int y = (int)player.y >> BRICKSHIFT;
195         x += Math::rrand(-2, 2);
196         y += Math::rrand(-2, 2);
197         
198         Math::limitInt(&x, 2, 62);
199         Math::limitInt(&y, 2, 26);
200         
201         if (map.data[x][y] == MAP_AIR)
202         {
203                 x = x << BRICKSHIFT;
204                 y = y << BRICKSHIFT;
205                 self->x = x;
206                 self->y = y;
207                 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
208                 addItem(101, "Reality Crystal", (int)self->x, (int)self->y, "RealityCrystal", 100, 1, 0, true);
209                 self->think = &galdovFinalPainThrow;
210                 self->react = &galdovFinalKeepAlive1;
211                 Math::removeBit(&self->flags, ENT_FLIES);
212                 Math::removeBit(&self->flags, ENT_FIRETRAIL);
213                 map.setMainBossPart(NULL);
214                 map.boss[0]->health = 30 * game.skill;
215                 map.boss[0]->setSprites(graphics.getSprite("GaldovPain", true), graphics.getSprite("GaldovPain", true), graphics.getSprite("GaldovPain", true));
216                 engine.setInfoMessage("Galdov has dropped the crystal! Quick! Get it!!", 99, INFO_HINT);
217                 audio.playSound(SND_BOSSCUSTOM2, CH_AMBIANCE);
218         }
219 }
220
221 void galdovFinalDie()
222 {
223         if (game.missionOverReason == MIS_INPROGRESS)
224         {
225                 game.missionOverReason = MIS_GAMECOMPLETE;
226                 audio.stopMusic();
227                 audio.playSound(SND_BOSSCUSTOM3, CH_AMBIANCE);
228                 player.health = 10;
229                 self->dx = 5;
230                 self->dy = -6;
231                 self->react = NULL;
232                 Math::removeBit(&self->flags, ENT_FLIES);
233                 Math::removeBit(&self->flags, ENT_FIRETRAIL);
234                 presentPlayerMedal("Final_Battle");
235         }
236         
237         self->setActionFinished(1);
238         self->setThinkTime(1);
239         
240         self->health--;
241         
242         if (self->health > -35)
243                 return;
244         
245         if (self->health == -99)
246         {
247                 checkObjectives(self->name, false);
248         }
249         
250         Math::wrapInt(&self->health, -99, -41);
251         
252         if ((self->health % 3) == 0)
253         {
254                 self->setActionFinished(5);
255                 self->setThinkTime(2);
256                 
257                 self->dx = Math::rrand(-5, 5);
258                 self->dy = Math::rrand(-5, 5);
259                 
260                 addExplosion(self->x, self->y, 50, &player);
261                 addSmokeAndFire(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 2);
262         }
263 }
264
265 void galdovMiniFire()
266 {       
267         (self->x < player.x) ? self->face = 0 : self->face = 1;
268         
269         if (!hasClearShot(self))
270                 return;
271         
272         self->setActionFinished(9);
273         self->setThinkTime(2);
274         self->think = &galdovMiniFire;
275         
276         addBullet((Entity*)self, 0, 0);
277         
278         self->custom--;
279         if (self->custom == 0)
280         {
281                 self->think = &galdovMiniAttack;
282         }
283 }
284
285 void galdovFinalTeleport()
286 {
287         self->setThinkTime(2);
288         self->setActionFinished(2);
289         
290         int x = (int)player.x >> BRICKSHIFT;
291         int y = (int)player.y >> BRICKSHIFT;
292         x += Math::rrand(-10, 10);
293         y += Math::rrand(-10, 10);
294         
295         Math::limitInt(&x, 2, 62);
296         Math::limitInt(&y, 2, 26);
297         
298         if (self == map.boss[0])
299         {
300                 if (self->health < 45 * game.skill)
301                 {
302                         Math::limitInt(&x, 23, 62);
303                         Math::limitInt(&y, 42, 61);
304                         self->currentWeapon = getRandomGaldovWeapon();
305                 }
306         }
307         
308         if (map.data[x][y] == MAP_AIR)
309         {
310                 x = x << BRICKSHIFT;
311                 y = y << BRICKSHIFT;
312                 self->x = x;
313                 self->y = y;
314                 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
315                 self->think = &galdovMiniAttack;
316         }
317 }
318
319 void galdovMiniChasePlayer()
320 {
321         (self->x < player.x) ? self->face = 0 : self->face = 1;
322         
323         float dx, dy;
324         
325         Math::calculateSlope(player.x, player.y, self->x, self->y, &dx, &dy);
326         
327         self->dx = (dx * 2);
328         self->dy = (dy * 2);
329         
330         self->setThinkTime(10);
331         self->setActionFinished(10);
332         self->think = &galdovMiniAttack;
333 }
334
335 void galdovMiniMoveRandom()
336 {
337         self->think = &galdovMiniAttack;
338         
339         if (self->flags & ENT_FLIES)
340         {
341                 self->dx = Math::rrand(-200, 200);
342                 self->dy = Math::rrand(-200, 200);
343         
344                 self->dx *= 0.01;
345                 self->dy *= 0.01;
346         
347                 self->setThinkTime(2);
348                 self->setActionFinished(Math::rrand(60, 90));
349         }
350         else
351         {
352                 self->dy = Math::rrand(-12, 0);
353         
354                 (player.x < self->x) ? self->dx = -3 : self->dx = 3;
355                 
356                 self->think = &galdovMiniAttack;
357                 self->setActionFinished(45);
358         }
359 }
360
361 void galdovMiniAttack()
362 {
363         if (player.health < 1)
364         {
365                 self->dx = self->dy = 0;
366                 return;
367         }
368         
369         (self->x < player.x) ? self->face = 0 : self->face = 1;
370         
371         self->think = &galdovMiniAttack;
372         self->setThinkTime(2);
373         self->setActionFinished(2);
374         
375         int r = Math::prand() % 100;
376         
377         if (r < 10)
378         {
379                 self->think = &galdovMiniFire;
380                 self->custom = Math::rrand(1, 8);
381         }
382         else if (r < 15)
383         {
384                 addTeleportParticles(self->x + 10, self->y + 10, 50, SND_TELEPORT2);
385                 self->x = -9999;
386                 self->y = -9999;
387                 self->setActionFinished(120);
388                 self->setThinkTime(2);
389                 self->think = &galdovFinalTeleport;
390         }
391         else if (r < 80)
392         {
393                 self->think = &galdovMiniChasePlayer;
394         }
395         else if (r < 90)
396         {
397                 self->think = &galdovMiniMoveRandom;
398         }
399         else
400         {
401                 if ((self->flags & ENT_FLIES) && (Math::prand() % 5) == 0)
402                 {
403                         Math::removeBit(&self->flags, ENT_FLIES);
404                         Math::removeBit(&self->flags, ENT_FIRETRAIL);
405                 }
406                 else
407                 {
408                         Math::addBit(&self->flags, ENT_FLIES);
409                         Math::addBit(&self->flags, ENT_FIRETRAIL);
410                 }
411         }
412 }
413
414 void galdovMiniDie()
415 {
416         addExplosion(self->x, self->y, 5, self);
417         dropItems((int)self->x, (int)self->y);
418         self->setThinkTime(2);
419         self->setActionFinished(2);
420         self->active = false;
421         self->place(9999, 9999);
422         
423         // Don't kill it properly(!!)
424         self->health = -1;
425         
426         bool allDead = true;
427         
428         for (int i = 1 ; i < 10 ; i++)
429         {
430                 if (map.boss[i]->health > 0)
431                 {
432                         allDead = false;
433                 }
434         }
435         
436         if (allDead)
437         {
438                 map.boss[0]->think = &galdovFinalDropCrystal;
439                 map.boss[0]->setThinkTime(2);
440                 map.boss[0]->setActionFinished(2);
441         }
442 }
443
444 void galdovRejoin()
445 {
446         debug(("galdovRejoin\n"));
447         
448         for (int i = 1 ; i < 10 ; i++)
449         {
450                 if (map.boss[i] != NULL)
451                 {
452                         addTeleportParticles(map.boss[i]->x + 4, map.boss[i]->y + 4, 75, -1);
453                         
454                         if ((Math::prand() % (2 + (game.skill))) == 0)
455                         {
456                                 dropItems((int)map.boss[i]->x, (int)map.boss[i]->y);
457                         }
458                         
459                         map.boss[i]->place(9999, 9999);
460                         map.boss[i]->active = false;
461                 }
462         }
463         
464         self->setThinkTime(2);
465         self->setActionFinished(120);
466         self->think = &galdovFinalTeleport;
467         self->currentWeapon = getRandomGaldovWeapon();
468         
469         audio.playSound(SND_BOSSCUSTOM1, CH_AMBIANCE);
470         
471         map.setMainBossPart(map.boss[0]);
472         
473         debug(("galdovRejoin: Done\n"));
474 }
475
476 void galdovFinalMiniReact()
477 {
478         if (self->health > 0)
479         {
480                 map.setMainBossPart(self);
481         }
482         else
483         {
484                 map.setMainBossPart(NULL);
485         }
486 }
487
488 void galdovFinalSplit()
489 {
490         debug(("galdovFinalSplit\n"));
491         
492         for (int i = 1 ; i < 10 ; i++)
493         {
494                 if (map.boss[i] == NULL)
495                 {
496                         map.boss[i] = new Boss();
497                         strlcpy(map.boss[i]->name, "MiniGaldov", sizeof map.boss[i]->name);
498                         map.boss[i]->health = 10 * game.skill;
499                         map.boss[i]->maxHealth = 10 * game.skill;
500                 }
501                 map.boss[i]->setSprites(graphics.getSprite("GaldovMiniRight", true), graphics.getSprite("GaldovMiniLeft", true), graphics.getSprite("GaldovMiniLeft", true));
502                 map.boss[i]->currentWeapon = getRandomAimedWeapon();
503                 map.boss[i]->face = 0;
504                 map.boss[i]->active = true;
505                 
506                 if (map.boss[i]->health > 0)
507                 {
508                         map.boss[i]->dx = Math::rrand(-2, 2);
509                         map.boss[i]->dy = Math::rrand(-2, 2);
510                         map.boss[i]->x = map.boss[0]->x;
511                         map.boss[i]->y = map.boss[0]->y;
512                 }
513                 else
514                 {
515                         map.boss[i]->active = false;
516                 }
517                 
518                 map.boss[i]->immune = 0;
519                 map.boss[i]->setThinkTime(2);
520                 map.boss[i]->setActionFinished(120);
521                 map.boss[i]->think = &galdovMiniAttack;
522                 map.boss[i]->react = &galdovFinalMiniReact;
523                 map.boss[i]->die = &galdovMiniDie;
524                 Math::addBit(&map.boss[i]->flags, ENT_AIMS);
525                 Math::addBit(&map.boss[i]->flags, ENT_FLIES);
526                 Math::addBit(&map.boss[i]->flags, ENT_FIRETRAIL);
527                 
528                 addTeleportParticles(map.boss[i]->x + 10 + map.boss[i]->dx, map.boss[i]->y + 10 + map.boss[i]->dy, 75, -1);
529         }
530         
531         map.boss[0]->place(9999, 9999);
532         map.boss[0]->setThinkTime(2);
533         map.boss[0]->setActionFinished(Math::rrand(10, 15) * 60);
534         map.boss[0]->think = &galdovRejoin;
535         map.boss[0]->active = true;
536         
537         audio.playSound(SND_BOSSCUSTOM1, CH_AMBIANCE);
538         map.setMainBossPart(NULL);
539         
540         debug(("galdovFinalSplit: Done\n"));
541 }
542
543 void galdovFinalReact()
544 {
545         map.boss[0]->health = 45 * game.skill;
546         
547         if ((Math::prand() % 5) == 0)
548         {
549                 map.boss[0]->setThinkTime(2);
550                 map.boss[0]->setActionFinished(2);
551                 map.boss[0]->think = &galdovFinalSplit;
552         }
553 }
554
555 void galdovFinalInit()
556 {
557         debug(("galdovFinalInit\n"));
558         
559         map.boss[0] = new Boss();
560         strlcpy(map.boss[0]->name, "Galdov", sizeof map.boss[0]->name);
561         map.boss[0]->health = 45 * game.skill;
562         map.boss[0]->maxHealth = 45 * game.skill;
563         map.boss[0]->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovDie", true));
564         map.boss[0]->currentWeapon = &weapon[WP_AIMEDPISTOL];
565         map.boss[0]->face = 0;
566         map.boss[0]->active = true;
567         map.boss[0]->x = 480;
568         map.boss[0]->y = 576;
569         map.boss[0]->immune = 0;
570         map.boss[0]->setThinkTime(2);
571         map.boss[0]->setActionFinished(2);
572         map.boss[0]->think = &galdovMiniAttack;
573         //map.boss[0]->think = &galdovFinalDropCrystal;
574         map.boss[0]->react = &galdovFinalReact;
575         map.boss[0]->die = &galdovFinalDie;
576         Math::addBit(&map.boss[0]->flags, ENT_AIMS);
577         
578         audio.loadSound(SND_BOSSCUSTOM1, "sound/galdovSplit");
579         audio.loadSound(SND_BOSSCUSTOM2, "sound/galdovPain");
580         audio.loadSound(SND_BOSSCUSTOM3, "sound/galdovDie");
581         
582         map.setMainBossPart(map.boss[0]);
583         
584         debug(("galdovFinalInit: Done\n"));
585 }
586
587 // ******************** Second part of Final Battle *********************************
588
589 void galdovFinalReact2()
590 {
591         if (self->health < 1)
592                 return;
593         
594         if ((Math::prand() % 12) == 0)
595         {
596                 addTeleportParticles(self->x + (self->width / 2), self->y + (self->height / 2), 50, SND_TELEPORT3);
597                 map.boss[0]->setThinkTime(2);
598                 map.boss[0]->setActionFinished(2);
599                 map.boss[0]->think = &galdovFinalTeleport;
600         }
601 }
602
603 void galdovFinalStandUp()
604 {
605         map.boss[0]->setSprites(graphics.getSprite("GaldovShieldRight", true), graphics.getSprite("GaldovShieldLeft", true), graphics.getSprite("GaldovShieldLeft", true));
606         self->setThinkTime(2);
607         self->setActionFinished(2);
608         addTeleportParticles(self->x + (self->width / 2), self->y + (self->height / 2), 50, SND_TELEPORT3);
609         self->think = &galdovFinalTeleport;
610         
611         if (map.boss[0]->health <= 15 * game.skill)
612         {
613                 self->setSprites(graphics.getSprite("GaldovRight", true), graphics.getSprite("GaldovLeft", true), graphics.getSprite("GaldovDie", true));
614                 Math::removeBit(&map.boss[0]->flags, ENT_IMMUNE);
615                 map.boss[0]->react = &galdovFinalReact2;
616         }
617 }
618
619 void galdovFinalPainThrow2()
620 {
621         self->dx = -3;
622         self->dy = -12;
623         
624         self->think = &galdovFinalStandUp;
625         self->setThinkTime(2);
626         self->setActionFinished(90);
627 }
628
629 void orbSeekGaldov()
630 {
631         (self->x < player.x) ? self->face = 0 : self->face = 1;
632         
633         float dx, dy;
634         
635         Math::calculateSlope(map.boss[0]->x, map.boss[0]->y, self->x, self->y, &dx, &dy);
636         
637         self->dx = (dx * (1 + game.skill));
638         self->dy = (dy * (1 + game.skill));
639         
640         self->setThinkTime(2);
641         self->setActionFinished(5);
642         self->think = &orbSeekGaldov;
643         
644         int distX = (int)fabs(map.boss[0]->x - self->x);
645         int distY = (int)fabs(map.boss[0]->y - self->y);
646
647         distX *= distX;
648         distY *= distY;
649
650         int distance = (int)sqrt(distX + distY);
651         
652         if (distance <= 10)
653         {
654                 self->active = false;
655                 self->setActionFinished(60);
656                 self->setThinkTime(60);
657                 addExplosion(self->x, self->y, 75, &player);
658                 self->place(9999, 9999);
659                 map.boss[0]->setSprites(graphics.getSprite("GaldovPain", true), graphics.getSprite("GaldovPain", true), graphics.getSprite("GaldovPain", true));
660                 map.boss[0]->think = &galdovFinalPainThrow2;
661                 map.boss[0]->health -= (3 * game.skill);
662                 Math::removeBit(&map.boss[0]->flags, ENT_FLIES);
663                 Math::removeBit(&map.boss[0]->flags, ENT_FIRETRAIL);
664                 audio.playSound(SND_BOSSCUSTOM2, CH_AMBIANCE);
665         }
666 }
667
668 void galdovFinalShieldInit()
669 {
670         self->setActionFinished(60);
671         self->setThinkTime(60);
672         self->think = &galdovMiniAttack;
673         self->react = NULL;
674         
675         Math::addBit(&map.boss[0]->flags, ENT_IMMUNE);
676         
677         for (int i = 1 ; i < 6 ; i++)
678         {
679                 if (map.boss[i] != NULL)
680                 {
681                         delete map.boss[i];
682                 }
683                 map.boss[i] = new Boss();
684                 strlcpy(map.boss[i]->name, "OrbBomb", sizeof map.boss[i]->name);
685                 map.boss[i]->setSprites(graphics.getSprite("DroidOrb", true), graphics.getSprite("DroidOrb", true), graphics.getSprite("DroidOrb", true));
686                 map.boss[i]->health = 999999;
687                 map.boss[i]->maxHealth = 99999;
688                 map.boss[i]->immune = 0;
689                 Math::addBit(&map.boss[0]->flags, ENT_IMMUNE);
690                 map.boss[i]->active = false;
691                 map.boss[i]->setActionFinished(2);
692                 map.boss[i]->setThinkTime(2);
693                 map.boss[i]->think = &orbSeekGaldov;
694                 map.boss[i]->react = NULL;
695                 Math::addBit(&map.boss[i]->flags, ENT_FLIES);
696         }
697         
698         map.boss[1]->place(864, 1536);
699         map.boss[2]->place(864, 1792);
700         map.boss[3]->place(1856, 1792);
701         map.boss[4]->place(1888, 1440);
702         map.boss[5]->place(1408, 1472);
703         
704         galdovInitBlackDroids();
705 }
706
707 void galdovFinalWaitForObjective()
708 {
709         self->setActionFinished(120);
710         self->setThinkTime(2);
711         
712         Objective *objective = (Objective*)map.objectiveList.getHead();
713
714         while (objective->next != NULL)
715         {
716                 objective = (Objective*)objective->next;
717
718                 if (strstr(objective->target, "Reality"))
719                 {
720                         if (objective->completed)
721                         {
722                                 player.dx = 1000;
723                                 player.dy = 1408;
724                                 Math::addBit(&player.flags, ENT_TELEPORTING);
725                                 self->think = &galdovFinalShieldInit;
726                                 map.boss[0]->setSprites(graphics.getSprite("GaldovShieldRight", true), graphics.getSprite("GaldovShieldLeft", true), graphics.getSprite("GaldovShieldLeft", true));
727                                 self->setActionFinished(2);
728                                 self->setThinkTime(2);
729                                 map.setMainBossPart(map.boss[0]);
730                         }
731                 }
732         }
733 }
734
735 void galdovFinalFlee1()
736 {
737         self->dx = 800;
738         self->dy = 1408;
739         addTeleportParticles(self->x + (self->width / 2), self->y + (self->height / 2), 50, SND_TELEPORT3);
740         Math::addBit(&self->flags, ENT_TELEPORTING);
741         Math::addBit(&self->flags, ENT_FLIES);
742         Math::addBit(&self->flags, ENT_FIRETRAIL);
743         self->think = &galdovFinalWaitForObjective;
744         self->setActionFinished(2);
745         self->setThinkTime(2);
746 }