2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
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 // **************** Machine Gun Boss ***********************
26 void tankBossMGFight();
27 void tankBossGLFight();
28 void activateGLBoss();
31 * Adds a load of particles within an area of the specified location
32 * @param x The x location
33 * @param y The y location
35 void plasmaBurstTraceParticles(int x, int y)
39 for (int i = 0 ; i < 7 ; i++)
41 color[i] = SDL_MapRGB(graphics.screen->format, 0, 100 + (i * 20), 0);
46 for (int i = 0 ; i < 25 ; i++)
48 dx = Math::rrand(0, 5);
55 map.addParticle(x + Math::rrand(-6, 6), y + Math::rrand(-2, 2), dx, 0, Math::rrand(1, 90), color[Math::rrand(0, 6)], NULL, PAR_WEIGHTLESS);
60 * Adds particles to the front of the MG Tank Boss's gun
62 void plasmaChargeParticles()
65 int y = (int)self->y + 10;
69 x += self->getFaceImage()->w;
74 for (int i = 0 ; i < 2 ; i++)
76 dx = Math::rrand(-30, 30); dx /= 90;
77 dy = Math::rrand(-30, 30); dy /= 90;
78 map.addParticle(x, y, dx, dy, Math::rrand(30, 60), graphics.green, NULL, PAR_WEIGHTLESS);
83 * Traces a line from the MG Tank Boss to 800 pixel in the
84 * direction it is facing. Anything in the path is killed immediately.
86 void traceTankBossMGFireLine()
96 int y = (int)self->y + 10;
100 for (int i = 0 ; i < 800 ; i++)
106 x += self->getFaceImage()->w;
111 plasmaBurstTraceParticles(x, y);
113 if (Collision::collision(player.x, player.y, 20, 20, x - 1, y - 1, 2, 2))
115 throwAndDamageEntity(&player, 100, dx * 10, dx * 10, 0);
117 for (int i = 0 ; i < 10 ; i++)
119 addExplosion(player.x + Math::rrand(-25, 25), player.y + Math::rrand(-25, 25), 10, self);
123 enemy = (Entity*)map.enemyList.getHead();
125 while (enemy->next != NULL)
127 enemy = (Entity*)enemy->next;
129 if (Collision::collision(enemy->x, enemy->y, enemy->getFaceImage()->w, enemy->getFaceImage()->h, x - 1, y - 1, 2, 2))
131 throwAndDamageEntity(enemy, 100, dx * 10, dx * 10, 0);
135 for (int i = 0 ; i < 10 ; i++)
137 addExplosion(enemy->x + Math::rrand(-25, 25), enemy->y + Math::rrand(-25, 25), 10, self);
143 self->setThinkTime(2);
144 self->setActionFinished(90);
145 Math::removeBit(&self->flags, ENT_IMMUNE);
146 self->think = &tankBossMGFight;
150 * Tells the Machine Gun Tank to fire it's beam laser
152 void tankBossMGCannonFire()
154 self->setThinkTime(2);
155 self->setActionFinished(2);
156 self->think = &tankBossMGCannonFire;
158 traceTankBossMGFireLine();
162 * Tells the Machine Gun boss to begin charging it's
163 * cannon and play the appropriate sound
165 void tankBossMGCannonChargeFire()
167 plasmaChargeParticles();
169 self->setActionFinished(2);
173 if (self->custom == 0)
175 self->think = tankBossMGCannonFire;
176 audio.playSound(SND_BOSSCUSTOM2, CH_AMBIANCE, self->x);
180 void tankBossMGRapidFire()
182 (self->x < player.x) ? self->face = 0 : self->face = 1;
184 addBullet((Entity*)self, 0, 0);
186 self->think = &tankBossMGRapidFire;
187 self->setActionFinished(4);
190 if (self->custom <= 0)
192 self->think = &tankBossMGFight;
193 self->setThinkTime(2);
194 self->setActionFinished(90);
198 void tankBossMGFire()
200 (self->x < player.x) ? self->face = 0 : self->face = 1;
202 addBullet((Entity*)self, 0, 0);
204 self->think = &tankBossMGFire;
205 self->setActionFinished(15);
208 if (self->custom <= 0)
210 self->think = &tankBossMGFight;
211 self->setThinkTime(2);
212 self->setActionFinished(60);
216 void tankBossMGJump()
220 (player.x < self->x) ? self->dx = -6 : self->dx = 6;
222 self->think = &tankBossMGFight;
223 self->setActionFinished(45);
228 self->setThinkTime(60);
229 self->setActionFinished(60);
230 self->health -= Math::rrand(1, 2);
232 // don't hurt the player(!)
233 addExplosion(self->x, self->y, 50, &player);
234 addSmokeAndFire(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 2);
235 addBlood(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 3);
237 if ((Math::prand() % 5) == 0)
239 self->dx = Math::rrand(-15, 15);
240 self->dy = Math::rrand(-8, 0);
243 if (self->health <= -100)
245 checkObjectives(self->name, false);
251 void tankBossMGAttack()
253 (player.x > self->x) ? self->face = 0 : self->face = 1;
255 int r = Math::prand() % 12;
259 self->custom = Math::rrand(1, 6);
260 self->think = &tankBossMGFire;
261 self->setThinkTime(0);
262 self->setActionFinished(2);
266 self->custom = Math::rrand(35, 80);
267 self->think = &tankBossMGCannonChargeFire;
268 self->setThinkTime(0);
269 self->setActionFinished(2);
270 audio.playSound(SND_BOSSCUSTOM1, CH_AMBIANCE, self->x);
271 Math::addBit(&self->flags, ENT_IMMUNE);
276 self->think = &tankBossMGRapidFire;
277 self->setThinkTime(0);
278 self->setActionFinished(2);
282 void tankBossMGFight()
284 if (player.health < 1)
290 int r = Math::prand() % 10;
294 if (player.x - 320 < self->x)
296 else if (player.x + 320 > self->x)
299 self->dx = Math::rrand(-2, 2);
301 (self->x < player.x) ? self->face = 0 : self->face = 1;
302 self->setActionFinished(60);
303 self->setThinkTime(1);
307 self->think = &tankBossMGJump;
308 self->setActionFinished(2);
309 self->setThinkTime(2);
314 self->setThinkTime(2);
315 self->think = &tankBossMGAttack;
319 void activateGLBoss()
321 if (map.boss[1] == NULL)
323 map.mainBossPart = NULL;
327 map.boss[1]->active = true;
328 map.boss[1]->dx = Math::rrand(416, 928);
329 map.boss[1]->dy = 8576;
330 map.boss[1]->setThinkTime(2);
331 map.boss[1]->setActionFinished(2);
332 map.boss[1]->think = &tankBossGLFight;
333 Math::addBit(&map.boss[1]->flags, ENT_TELEPORTING);
335 map.setMainBossPart(map.boss[1]);
338 void tankBossMGSwap()
340 // Machine Gun Boss wait state
341 self->active = false;
344 // Grenade launcher boss active state
348 void tankBossMGReact()
350 if (map.boss[1] == NULL)
355 if (self->flags & ENT_IMMUNE)
360 if ((Math::prand() % 25) > 0)
367 self->think = &tankBossMGSwap;
368 self->setThinkTime(2);
369 self->setActionFinished(2);
370 Math::addBit(&self->flags, ENT_TELEPORTING);
373 void tankBossMGStart()
375 self->dx = Math::rrand(416, 928);
377 Math::addBit(&self->flags, ENT_TELEPORTING);
378 self->think = &tankBossMGFight;
381 void tankBossMGInit()
383 debug(("tankBossMGInit\n"));
385 map.boss[0] = new Boss();
386 strlcpy(map.boss[0]->name, "BioMech Tank V1.1", sizeof map.boss[0]->name);
387 map.boss[0]->health = 65 * game.skill;
388 map.boss[0]->maxHealth = 65 * game.skill;
389 map.boss[0]->setSprites(graphics.getSprite("BlobTankCannonRight", true), graphics.getSprite("BlobTankCannonLeft", true), graphics.getSprite("BlobTankCannonLeft", true));
390 map.boss[0]->currentWeapon = &weapon[WP_PLASMARIFLE];
391 map.boss[0]->face = 0;
392 map.boss[0]->active = false;
393 map.boss[0]->x = 900;
394 map.boss[0]->y = 8256;
395 map.boss[0]->immune = 0;
396 map.boss[0]->setThinkTime(1);
397 map.boss[0]->setActionFinished(1);
398 map.boss[0]->think = &tankBossMGStart;
399 map.boss[0]->react = &tankBossMGReact;
400 map.boss[0]->die = &tankBossMGDie;
401 Math::addBit(&map.boss[0]->flags, ENT_AIMS);
403 audio.loadSound(SND_BOSSCUSTOM1, "sound/tankBeam");
404 audio.loadSound(SND_BOSSCUSTOM2, "sound/tankBeamFire");
406 map.setMainBossPart(map.boss[0]);
408 debug(("tankBossMGInit: Done\n"));
411 // **************** Grenade Launcher Boss ***********************
413 void tankBossGLJump()
417 (player.x < self->x) ? self->dx = -6 : self->dx = 6;
419 self->think = &tankBossGLFight;
420 self->setActionFinished(45);
423 void tankBossGLRapidFire()
425 (self->x < player.x) ? self->face = 0 : self->face = 1;
427 addBullet((Entity*)self, 0, 0);
429 self->think = &tankBossGLRapidFire;
430 self->setActionFinished(4);
433 if (self->custom <= 0)
435 self->think = &tankBossGLFight;
436 self->setThinkTime(2);
437 self->setActionFinished(90);
441 void tankBossGLMortor()
443 (self->x < player.x) ? self->face = 0 : self->face = 1;
445 int speed = Math::rrand(3, 5);
449 addBullet((Entity*)self, speed, 0);
451 self->think = &tankBossGLMortor;
452 self->setActionFinished(20);
455 if (self->custom <= 0)
457 self->think = &tankBossGLFight;
458 self->setThinkTime(2);
459 self->setActionFinished(60);
463 void tankBossGLAttack()
465 (player.x > self->x) ? self->face = 0 : self->face = 1;
467 int r = Math::prand() % 10;
471 Math::removeBit(&self->flags, ENT_AIMS);
472 self->currentWeapon = getWeaponByName("Mortor Shells");
473 self->think = &tankBossGLMortor;
474 self->setThinkTime(0);
475 self->setActionFinished(2);
476 self->custom = Math::rrand(2, 5);
480 Math::addBit(&self->flags, ENT_AIMS);
481 self->currentWeapon = getWeaponByName("Aimed Pistol");
483 self->think = &tankBossGLRapidFire;
484 self->setThinkTime(0);
485 self->setActionFinished(2);
489 self->custom = Math::rrand(45, 60);
490 //self->think = &tankBossGLCannonChargeFire;
491 self->setThinkTime(0);
492 self->setActionFinished(2);
496 void tankBossGLFight()
498 if (player.health < 1)
504 int r = Math::prand() % 10;
508 if (player.x - 320 < self->x)
510 else if (player.x + 320 > self->x)
513 self->dx = Math::rrand(-2, 2);
515 (self->x < player.x) ? self->face = 0 : self->face = 1;
516 self->setActionFinished(60);
517 self->setThinkTime(1);
521 self->think = &tankBossGLJump;
522 self->setActionFinished(2);
523 self->setThinkTime(2);
528 self->setThinkTime(2);
529 self->think = &tankBossGLAttack;
533 void activateMGBoss()
535 if (map.boss[0] == NULL)
537 map.mainBossPart = NULL;
541 map.boss[0]->active = true;
542 map.boss[0]->dx = Math::rrand(416, 928);
543 map.boss[0]->dy = 8576;
544 map.boss[0]->setThinkTime(2);
545 map.boss[0]->setActionFinished(2);
546 map.boss[0]->think = &tankBossMGFight;
547 Math::addBit(&map.boss[0]->flags, ENT_TELEPORTING);
549 map.setMainBossPart(map.boss[0]);
552 void tankBossGLSwap()
554 // Grenade launcher Boss wait state
555 self->active = false;
558 // Machine Gun boss active state
562 void tankBossGLReact()
564 if (map.boss[0] == NULL)
567 if ((Math::prand() % 25) > 0)
572 self->think = &tankBossGLSwap;
573 self->setThinkTime(2);
574 self->setActionFinished(2);
575 Math::addBit(&self->flags, ENT_TELEPORTING);
580 self->setThinkTime(60);
581 self->setActionFinished(60);
582 self->health -= Math::rrand(1, 2);
584 // don't hurt the player(!)
585 addExplosion(self->x, self->y, 50, &player);
586 addSmokeAndFire(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 2);
587 addBlood(self, Math::rrand(-5, 5), Math::rrand(-5, 5), 3);
589 if ((Math::prand() % 5) == 0)
591 self->dx = Math::rrand(-15, 15);
592 self->dy = Math::rrand(-8, 0);
595 if (self->health <= -100)
597 checkObjectives(self->name, false);
603 void tankBossGLInit()
605 debug(("tankBossGLInit\n"));
607 map.boss[1] = new Boss();
608 strlcpy(map.boss[1]->name, "BioMech Tank V2.6", sizeof map.boss[1]->name);
609 map.boss[1]->health = 65 * game.skill;
610 map.boss[1]->maxHealth = 65 * game.skill;
611 map.boss[1]->setSprites(graphics.getSprite("BlobTankGrenadeRight", true), graphics.getSprite("BlobTankGrenadeLeft", true), graphics.getSprite("BlobTankGrenadeLeft", true));
612 map.boss[1]->currentWeapon = getWeaponByName("Mortor Shells");
613 map.boss[1]->face = 1;
614 map.boss[1]->active = false;
615 map.boss[1]->x = 420;
616 map.boss[1]->y = 8256;
617 map.boss[1]->immune = 0;
618 map.boss[1]->setThinkTime(1);
619 map.boss[1]->setActionFinished(1);
620 map.boss[1]->think = &tankBossGLFight;
621 map.boss[1]->react = &tankBossGLReact;
622 map.boss[1]->die = &tankBossGLDie;
624 debug(("tankBossMGInit: Done\n"));