2 Copyright (C) 2004 Parallel Realities
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.
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.
13 See the GNU General Public License for more details.
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.
25 if (player.health < 1)
28 if (map.bossNextThink > 0)
36 switch (Math::prand() % 4)
45 r = ITEM_DOUBLECHERRY;
48 r = ITEM_TRIPLECHERRY;
55 switch (Math::prand() % 4)
71 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
73 Entity *enemy = (Entity*)map.enemyList.getHead();
80 if ((Math::prand() % 3) == 0)
82 addEnemy("Red Blob", Math::rrand(525, 800), 8100, 0);
87 addEnemy("Red Blob", Math::rrand(525, 800), 8100, 0);
91 while (enemy->next != NULL)
93 enemy = (Entity*)enemy->next;
95 if (strcmp(enemy->name, "Red Blob 1") == 0)
98 if (strcmp(enemy->name, "Red Blob 2") == 0)
104 addEnemy("Red Blob 1", 1100, 8352, 0);
105 debug(("Added Red Blob #1\n"));
110 addEnemy("Red Blob 2", 120, 8352, 0);
111 debug(("Added Red Blob #2\n"));
114 map.bossNextThink = Math::rrand(10, 15) * 60;
119 if (player.health < 1)
122 if (map.bossNextThink > 0)
128 switch (Math::prand() % 4)
131 addEnemy("Aqua Blob", 1600, 530, 0);
134 addEnemy("Aqua Blob", 1600, 690, 0);
137 addEnemy("Aqua Blob", 1600, 820, 0);
140 addEnemy("Aqua Blob", 1600, 940, 0);
144 map.bossNextThink = Math::rrand(5, 10) * 60;
146 map.bossNextThink = Math::rrand(2, 6) * 60;
149 void droidBossLevel()
151 if (player.health < 1)
154 if (map.bossNextThink > 0)
160 Entity *item = (Entity*)map.itemList.getHead();
162 bool addPistol, addMachineGun, addLaser, addSpread;
163 addPistol = addMachineGun = addLaser = addSpread = true;
165 while (item->next != NULL)
167 item = (Entity*)item->next;
169 if (item->flags & ENT_DYING)
177 case ITEM_MACHINEGUN:
178 addMachineGun = false;
190 addItem(defItem[ITEM_PISTOL].id, defItem[ITEM_PISTOL].name, 2432, 4576, defItem[ITEM_PISTOL].sprite[0]->name, 240, defItem[ITEM_PISTOL].value, 0, false);
193 addItem(defItem[ITEM_MACHINEGUN].id, defItem[ITEM_MACHINEGUN].name, 2432, 4224, defItem[ITEM_MACHINEGUN].sprite[0]->name, 240, defItem[ITEM_MACHINEGUN].value, 0, false);
196 addItem(defItem[ITEM_LASER].id, defItem[ITEM_LASER].name, 3552, 4384, defItem[ITEM_LASER].sprite[0]->name, 240, defItem[ITEM_LASER].value, 0, false);
199 addItem(defItem[ITEM_SPREAD].id, defItem[ITEM_SPREAD].name, 3552, 4800, defItem[ITEM_SPREAD].sprite[0]->name, 240, defItem[ITEM_SPREAD].value, 0, false);
201 int r = Math::prand() % 6;
203 r = Math::prand() % 4;
210 addEnemy("Eye Droid V4.0", 3648, 4704, 0);
213 addEnemy("Eye Droid V4.0", 3648, 4224, 0);
216 addEnemy("Eye Droid V4.0", 2336, 4128, 0);
219 addEnemy("Eye Droid V4.0", 2336, 4736, 0);
225 for (int i = 0 ; i < 2 ; i++)
227 r = Math::rrand(ITEM_CHERRY, ITEM_DOUBLECHERRY);
228 x = (int)player.x >> BRICKSHIFT;
229 y = (int)player.y >> BRICKSHIFT;
230 x += Math::rrand(-10, 10);
231 y += Math::rrand(-10, 10);
232 if (map.data[x][y] == MAP_AIR)
236 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
240 map.bossNextThink = Math::rrand(10, 15) * 60;
247 void galdovFinalLevel()
249 if (player.health < 1)
252 if (map.bossNextThink > 0)
258 map.bossNextThink = Math::rrand(10, 15) * 60;
260 if ((map.boss[0]->health > 30 * game.skill) || (map.boss[0]->health <= 15 * game.skill))
267 for (int i = 6 ; i < 10 ; i++)
269 if (map.boss[i] == NULL)
272 if (map.boss[i]->health <= -60)
282 int x = Math::rrand(23, 62);
283 int y = Math::rrand(42, 61);
285 if (map.data[x][y] == MAP_AIR)
289 map.boss[bossIndex]->active = true;
290 map.boss[bossIndex]->place(x, y);
291 map.boss[bossIndex]->dx = 0;
292 map.boss[bossIndex]->dy = 0;
293 map.boss[bossIndex]->health = 3 * game.skill;
294 map.boss[bossIndex]->maxHealth = 3 * game.skill;
295 Math::addBit(&map.boss[bossIndex]->flags, ENT_FLIES);
296 addTeleportParticles(map.boss[bossIndex]->x + (map.boss[bossIndex]->width / 2), map.boss[bossIndex]->y + (map.boss[bossIndex]->height / 2), 50, SND_TELEPORT2);
300 void createBoss(const char *stageName)
302 map.mainBossPart = NULL;
304 if (!map.isBossMission)
309 debug(("createBoss()\n"));
311 if (strcmp(stageName, "BioMech Supply Depot") == 0)
315 map.bossNextThink = 0;
316 map.doBossLevelAction = &tankBossLevel;
318 else if (strcmp(stageName, "BioMech Communications") == 0)
321 map.bossNextThink = 0;
322 map.doBossLevelAction = &aquaBossLevel;
324 else if (strcmp(stageName, "BioMech Assimilator") == 0)
327 map.bossNextThink = 0;
328 map.doBossLevelAction = &droidBossLevel;
330 else if (strcmp(stageName, "BioMech HQ") == 0)
333 map.bossNextThink = 0;
334 map.doBossLevelAction = &galdovLevel;
336 else if (strcmp(stageName, "Final Battle") == 0)
339 map.bossNextThink = 0;
340 map.doBossLevelAction = &galdovFinalLevel;
343 debug(("createBoss(): Done\n"));
348 int x, y, absX, absY;
352 for (int i = 0 ; i < 10 ; i++)
354 if (map.boss[i] == NULL)
361 moveEntity((Entity*)self);
363 if (self->flags & ENT_TELEPORTING)
366 x = (int)(self->x - engine.playerPosX);
367 y = (int)(self->y - engine.playerPosY);
372 if ((absX < 700) && (absY < 500))
374 if (self->flags & ENT_FIRETRAIL)
376 addFireTrailParticle(self->x + (self->face * 16) + Math::rrand(-1, 1), self->y + Math::rrand(-1, 1));
378 graphics.blit(self->getFaceImage(), x, y, graphics.screen, false);
387 if (self->health <= 0)
389 if (self->health > -100)
395 checkObjectives(self->name, false);
397 if (!self->referenced)
399 debug(("Deleting unreferenced Boss...\n"));
405 self->referenced = false;
408 else if (self->actionFinished())
410 if (self->readyForThink())
417 map.doBossLevelAction();
420 bool isCorrectShieldFrequency(Entity *bullet)
422 if (bullet->id != self->shieldFrequency)
424 bullet->owner = self;
425 bullet->dx = -bullet->dx;
429 bullet->x += bullet->dx;
430 bullet->y += bullet->dy;
432 bullet->health += 60;
434 bullet->owner = self;
436 Math::removeBit(&bullet->flags, ENT_WEIGHTLESS);
437 Math::removeBit(&bullet->flags, ENT_BOUNCES);
439 audio.playSound(SND_RICO1, CH_ANY);
447 void checkBossBulletCollisions(Entity *bullet)
449 if ((bullet->health < 1) || (player.health <= -60))
454 if (game.missionOver > 0)
461 if (bullet->owner == &player)
463 for (int i = 0 ; i < 10 ; i++)
465 if (map.boss[i] == NULL)
472 if (Collision::collision((Entity*)self, bullet))
475 if (map.boss[i]->shieldFrequency != 999)
477 if (!isCorrectShieldFrequency(bullet))
483 if (!(self->flags & ENT_IMMUNE))
485 self->health -= bullet->damage;
486 audio.playSound(SND_CLANG, CH_ANY);
487 addColorParticles(bullet->x, bullet->y, Math::rrand(25, 75), -1);
488 Math::removeBit(&bullet->flags, ENT_SPARKS);
489 Math::removeBit(&bullet->flags, ENT_PUFFS);
492 if (self->react != NULL && self->health > 0)
497 if (bullet->id != WP_LASER)
506 void doGaldovAI(Entity *galdov)
508 map.fightingGaldov = true;
510 if (SDL_GetTicks() < map.bossNextThink)
513 map.bossNextThink = SDL_GetTicks() + Math::rrand(250, 1500);
515 switch (Math::prand() % 4)
518 if ((Math::prand() % 5) == 0)
520 if (galdov->flags & ENT_FLIES)
522 Math::removeBit(&galdov->flags, ENT_FLIES);
523 Math::removeBit(&galdov->flags, ENT_FIRETRAIL);
527 Math::addBit(&galdov->flags, ENT_FLIES);
528 Math::addBit(&galdov->flags, ENT_FIRETRAIL);
533 if (galdov->flags & ENT_JUMPS)
535 Math::removeBit(&galdov->flags, ENT_JUMPS);
539 Math::addBit(&galdov->flags, ENT_JUMPS);
543 galdov->currentWeapon = getRandomGaldovWeapon();
546 if (galdov->flags & ENT_RAPIDFIRE)
548 Math::removeBit(&galdov->flags, ENT_RAPIDFIRE);
552 Math::addBit(&galdov->flags, ENT_RAPIDFIRE);
557 if ((Math::prand() % 25) == 0)
559 switch (Math::prand() % 5)
562 engine.setInfoMessage("Galdov: Stupid creature!! Give up and join us!", 0, INFO_HINT);
565 engine.setInfoMessage("Galdov: Why do you persist in fighting us?!", 0, INFO_HINT);
568 engine.setInfoMessage("Galdov: And this is the best the Blob Army can offer?", 0, INFO_HINT);
571 engine.setInfoMessage("Galdov: We WILL have the crystals! NOTHING will stop us!!", 0, INFO_HINT);
574 engine.setInfoMessage("Galdov: You're mine now!!!", 0, INFO_HINT);