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.
24 #include "CGraphics.h"
27 #include "console/console.hpp"
31 void galdovCheckSplit();
35 (self
->x
< player
.x
) ? self
->face
= 0 : self
->face
= 1;
48 color
= graphics
.yellow
;
51 color
= graphics
.green
;
54 color
= graphics
.cyan
;
57 color
= graphics
.white
;
61 for (int i
= 0 ; i
< 20 ; i
++)
63 dy
= Math::rrand(-150, -50);
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
;
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
;
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
)
109 addTeleportParticles(self
->x
+ 10, self
->y
+ 10, 50, SND_TELEPORT2
);
110 self
->think
= &galdovAttack
;
116 if (self
->health
< 0)
123 self
->setThinkTime(2);
124 self
->setActionFinished(2);
125 self
->think
= &galdovTeleport
;
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
);
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;
165 map
.boss
[i
]->dx
= .5;
170 map
.boss
[0]->dx
= .5;
172 map
.boss
[i
]->dx
= -.5;
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
)
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);
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
))
232 self
->setActionFinished(5);
233 self
->setThinkTime(2);
234 self
->think
= &galdovRocketAttack
;
236 addBullet((Entity
*)self
, 0, 0);
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;
253 Math::calculateSlope(player
.x
, player
.y
, self
->x
, self
->y
, &dx
, &dy
);
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);
275 self
->setThinkTime(2);
276 self
->setActionFinished(Math::rrand(60, 90));
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));
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
;
307 if (player
.health
< 1)
309 self
->dx
= self
->dy
= 0;
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;
323 self
->think
= &galdovFire
;
324 self
->custom
= Math::rrand(1, 8);
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
);
334 self
->setActionFinished(120);
335 self
->setThinkTime(2);
336 self
->think
= &galdovTeleport
;
341 self
->think
= &galdovChasePlayer
;
345 self
->think
= &galdovMoveRandom
;
349 if ((self
->flags
& ENT_FLIES
) && (rand() % 5) == 0)
351 Math::removeBit(&self
->flags
, ENT_FLIES
);
352 Math::removeBit(&self
->flags
, ENT_FIRETRAIL
);
356 Math::addBit(&self
->flags
, ENT_FLIES
);
357 Math::addBit(&self
->flags
, ENT_FIRETRAIL
);
362 if (self
== map
.boss
[0])
364 self
->think
= &galdovDoInvisible
;
369 map
.boss
[0]->currentWeapon
= getRandomGaldovWeapon();
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
;
383 // Make sure only the real Galdov does this!
384 if (self
== map
.boss
[0])
386 self
->think
= &galdovCheckSplit
;
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
)
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
)
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);
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;
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
;