aboutsummaryrefslogtreecommitdiff
path: root/src/enemies/batboss.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/enemies/batboss.c')
-rw-r--r--src/enemies/batboss.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/enemies/batboss.c b/src/enemies/batboss.c
new file mode 100644
index 0000000..8ea408d
--- /dev/null
+++ b/src/enemies/batboss.c
@@ -0,0 +1,319 @@
+#include "batboss.h"
+#include "../game.h"
+#include "../PHL.h"
+#include "../hero.h"
+#include "heads.h"
+#include <stdlib.h>
+#include <math.h>
+
+int boss2flag = 5;
+
+//void updateBatMask(Batboss* b);
+void batbossStep(Batboss* b);
+void batbossDraw(Batboss* b);
+
+void createBatboss(int x, int y)
+{
+ if (flags[boss2flag] == 0) { //have not beaten boss 2
+ PHL_FreeSurface(images[imgBoss]);
+ images[imgBoss] = PHL_LoadQDA("boss03.bmp");
+
+ int i;
+ for (i = 0; i < MAX_ENEMIES; i++) {
+ if (enemies[i] == NULL) {
+ setBossRoom();
+
+ Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
+ Batboss* b = /*(Batboss*)*/malloc(sizeof *b);
+ b->id = i;
+
+ b->x = x;
+ b->y = y;
+
+ b->vsp = 0;
+ b->hsp = 0;
+ b->grav = 0.1;
+
+ b->imageIndex = 0;
+
+ b->ypos = y;
+ b->rot = 0;
+
+ b->hp = 35;
+
+ b->invincible = 0;
+ b->state = 0;
+ b->timer = 0;
+ b->mode = 0; //0 for flame, 1 for tornado stomp
+
+ /*
+ b->mask.unused = b->mask.circle = 0;
+ b->mask.w = 100;
+ b->mask.h = 68;
+ updateBatMask(b);
+ */
+ //Setup phase
+ b->state = 0;
+ b->hsp = 2;
+ b->ypos = b->y - 24;
+ b->timer = 60;
+
+ e->data = b;
+ e->enemyStep = batbossStep;
+ e->enemyDraw = batbossDraw;
+ e->type = 41;
+
+ enemies[i] = e;
+ i = MAX_ENEMIES;
+ }
+ }
+ }
+}
+
+void batbossStep(Batboss* b)
+{
+ char dead = 0;
+
+ //Animate
+ {
+ //Wing flap
+ if (b->state == 0 || b->state == 1 || b->state == 2 || b->state == 5 || b->state == 6) {
+ b->imageIndex += 0.1;
+ if (b->imageIndex >= 2) {
+ b->imageIndex -= 2;
+ }
+ }
+ //Twister
+ if (b->state == 3 || b->state == 4) {
+ b->imageIndex += 0.2;
+ if (b->imageIndex >= 5) {
+ b->imageIndex -= 3;
+ }
+ }
+ }
+
+ //Counters
+ {
+ if (b->timer > 0) {
+ b->timer -= 1;
+ }
+
+ if (b->invincible > 0) {
+ b->invincible -= 1;
+ }
+ }
+
+ //Large vertical movement
+ {
+ if (b->state == 0 || b->state == 1) {
+ b->rot += 2;
+ if (b->rot >= 360) { b->rot -= 360; }
+
+ b->y = b->ypos - (40 * sin(b->rot * 3.14159 / 180));
+ }
+ }
+
+ //Small vertical movement
+ {
+ if (b->state == 2) {
+ b->rot += 2;
+ if (b->rot >= 360) { b->rot -= 360; }
+
+ b->y = b->ypos - (20 * sin(b->rot * 3.14159 / 180));
+ }
+ }
+
+ //Horizontal movement
+ if (b->state == 0) {
+ b->x += b->hsp;
+
+ if (b->x >= 520 || b->x <= 120) { //Hit walls
+ b->hsp *= -1;
+ }
+
+ if (b->timer <= 0) {
+ b->state = 1;
+ }
+ }
+ //Slow to halt
+ else if (b->state == 1) {
+ b->x += b->hsp;
+
+ if (b->x >= 520 || b->x <= 120) { //Hit walls
+ b->hsp *= -1;
+ }
+
+ double rate = 0.03;
+ if (b->hsp > 0) {
+ b->hsp -= rate;
+ if (b->hsp <= 0) { b->hsp = 0; }
+ }
+ else if (b->hsp < 0) {
+ b->hsp += rate;
+ if (b->hsp >= 0) { b->hsp = 0; }
+ }
+
+ if (b->hsp == 0 && b->rot <= 2) {
+ b->state = 2;
+ b->timer = 60;
+ }
+ }
+ else if (b->state == 2) {
+ if (b->timer == 1) {
+ //Shoot flame
+ int fx = b->x;
+ int fy = b->y + 24;
+ int fangle = (atan2(heroy - fy, fx - (herox - 20)) * 180 / 3.14159) + 270;
+ createFireball(fx, fy, fangle, b->id);
+ createFireball(fx, fy, fangle - 15, b->id);
+ createFireball(fx, fy, fangle + 15, b->id);
+ PHL_PlaySound(sounds[sndShot03], CHN_ENEMIES);
+ }
+
+ if (b->timer <= 0 && b->rot <= 2) {
+ if (b->mode == 0) {
+ b->state = 0;
+ b->timer = 60;
+ b->hsp = 2;
+ b->mode = 1;
+ }
+ else{
+ b->mode = 0;
+ b->state = 3;
+ b->imageIndex = 2;
+ b->vsp = -4;
+ PHL_PlaySound(sounds[sndShot06], CHN_ENEMIES);
+ }
+
+ if (herox < b->x) {
+ b->hsp *= -1;
+ }
+ }
+ }
+ //Stomp
+ else if (b->state == 3) {
+ b->y += b->vsp;
+ b->vsp += b->grav;
+ if (b->vsp >= 6) { b->vsp = 6; }
+
+ //Hit floor
+ if (b->y >= 480 - 176) {
+ b->y = 480 - 176;
+ b->state = 4;
+ b->timer = 120;
+ quakeTimer = 30;
+ PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
+ b->hsp = 1;
+ if (b->x > herox) {
+ b->hsp *= -1;
+ }
+ }
+ }
+ //Chase
+ else if (b->state == 4) {
+ b->x += b->hsp;
+
+ if (b->timer <= 0 || b->x >= 520 || b->x <= 120) {
+ b->state = 5;
+ b->timer = 80 + (rand() % 61);
+ }
+ }
+ //Rise
+ else if (b->state == 5) {
+ b->y -= 1;
+
+ if (b->timer <= 0) {
+ b->state = 0;
+ b->ypos = b->y;
+ b->rot = 0;
+ b->timer = 60;
+
+ b->hsp = 2;
+ if (b->x > herox) {
+ b->hsp *= -1;
+ }
+ }
+ }
+ //Death
+ else if (b->state == 6) {
+ b->y += 0.2;
+
+ if (b->timer % 12 == 0) {
+ createEffect(2, b->x - 64 + (rand() % 100), b->y + (rand() % 80));
+ }
+
+ if (b->timer <= 0) {
+ dead = 1;
+ }
+ }
+
+ if (b->state != 6) {
+ //Setup Mask
+ Mask mask;
+ {
+ mask.unused = mask.circle = 0;
+ if (b->state == 3 || b->state == 4) {
+ mask.w = 64;
+ mask.h = 96;
+ mask.y = b->y;
+ }else{
+ mask.w = 100;
+ mask.h = 68;
+ mask.y = b->y + 18;
+ }
+ mask.x = b->x - (mask.w / 2);
+ }
+
+ //Hit Player
+ {
+ if (checkCollision(mask, getHeroMask())) {
+ heroHit(30, b->x);
+ }
+ }
+
+ //Weapon collision
+ {
+ int i;
+ for (i = 0; i < MAX_WEAPONS; i++) {
+ if (weapons[i] != NULL) {
+ if (weapons[i]->cooldown == 0) {
+ if (checkCollision(mask, weapons[i]->weaponMask)) {
+ weaponHit(weapons[i]);
+ //Hit
+ b->invincible = 15;
+ b->hp -= 1;
+
+ i = MAX_WEAPONS;
+ }
+ }
+ }
+ }
+ }
+
+ if (b->hp <= 0) {
+ b->state = 6;
+ b->timer = 180;
+ b->invincible = 200;
+ }
+ }
+
+ //Destroy object
+ {
+ if (dead == 1) {
+ enemyDestroy(b->id);
+ bossDefeatedFlag = 1;
+ roomSecret = 1;
+
+ flags[boss2flag] = 1;
+ PHL_StopMusic();
+ }
+ }
+
+}
+
+void batbossDraw(Batboss* b)
+{
+ if (b->invincible % 2 == 0) {
+ PHL_DrawSurfacePart(b->x - 64, b->y, (int)b->imageIndex * 128, 0, 128, 96, images[imgBoss]);
+ }
+} \ No newline at end of file