#include "devil.h"
#include "../game.h"
#include "../PHL.h"
#include "../hero.h"
#include <stdlib.h>
#include <math.h>
int boss6flag = 31;
void devilStep(Devil* d);
void devilDraw(Devil* d);
void orbStep(Orb* o);
void orbDraw(Orb* o);
void createDevil(int x, int y)
{
if (flags[boss6flag] == 0) { //have not beaten boss 6
PHL_FreeSurface(images[imgBoss]);
images[imgBoss] = PHL_LoadQDA("boss04.bmp");
int i;
for (i = 0; i < MAX_ENEMIES; i++) {
if (enemies[i] == NULL) {
setBossRoom();
Enemy
* e
= /*(Enemy*)*/malloc(sizeof *e
);
Devil
* d
= /*(Devil*)*/malloc(sizeof *d
);
d->id = i;
d->x = x;
d->y = y;
d->ystart = d->y;
d->newystart = d->ystart;
d->hsp = -2.5;
d->hp = 100;
//d->hp = 1;
d->state = 0;
d->timer = 0;
d->blink = 0;
d->boblen = 32;
d->bobspd = 3;
d->tailangle = 90;
d->rotcounter = 0;
d->bobcounter = 0;
d->bobspd = 3;
d->rotspd = 1;
d->imageIndex = 0;
e->data = d;
e->enemyStep = devilStep;
e->enemyDraw = devilDraw;
e->type = 45;
enemies[i] = e;
i = MAX_ENEMIES;
}
}
}
}
void devilStep(Devil* d)
{
char dead = 0;
//Animate
{
d->imageIndex += 0.1;
if (d->imageIndex >= 2) {
d->imageIndex -= 2;
}
if (d->blink > 0) {
d->blink -= 1;
}
}
//Bob
{
if (d->state != 4) {
d->bobcounter += d->bobspd;
if (d->bobcounter >= 360) {
d->bobcounter -= 360;
}
d
->y
= d
->ystart
+ (d
->boblen
* cos(d
->bobcounter
* 3.14159 / 180));
}
}
//Swing tail
{
d->rotcounter += d->rotspd;
if (d->rotcounter >= 360) {
d->rotcounter -= 360;
}
d
->tailangle
= 90 + (55 * cos(d
->rotcounter
* 3.14159 / 180));
}
//Patterns
{
//movement
if (d->state == 0 || d->state == 2)
{
d->rotspd = 1;
d->boblen = 32;
d->bobspd = 3;
//Re-align ystart
if (d->ystart > d->newystart) {
d->ystart -= 1;
}
if (d->ystart < d->newystart) {
d->ystart += 1;
}
d->x += d->hsp;
//Slow Down
double rate = 0.016;
if (d->hsp < 0) {
d->hsp += rate;
if (d->hsp >= 0) {
d->hsp = 0;
}
}
if (d->hsp > 0) {
d->hsp -= rate;
if (d->hsp <= 0) {
d->hsp = 0;
}
}
if (d->hsp == 0) {
d->timer = 0;
if (d->state == 0) {
d->state = 1;
}
if (d->state == 2) {
if ((d->rotcounter >= 90 && d->rotcounter <= 90 + d->rotspd) || (d->rotcounter >= 270 && d->rotcounter <= 270 + d->rotspd)) {
d->state = 3;
}
}
}
}
//mid room pause
else if (d->state == 1)
{
d->timer += 1;
if (d->timer >= 60) {
if (d->state == 1) {
d->hsp = 2.5;
if (herox < d->x) {
d->hsp *= -1;
}
}
d->state = 2;
}
}
//Shoot
else if (d->state == 3)
{
d->rotspd = 3;
d->boblen = 10;
d->bobspd = 10;
d->timer += 1;
//Shoot orbs
if (d->timer == 120 || d->timer == 240 || d->timer == 360) {
int aim
= (atan2((heroy
+ 20) - d
->y
, d
->x
- herox
) * 180 / 3.14159) + 270;
int spawnY = d->y + 20;
createOrb(d->x, spawnY, aim + 22);
createOrb(d->x, spawnY, aim + 11);
createOrb(d->x, spawnY, aim);
createOrb(d->x, spawnY, aim - 11);
createOrb(d->x, spawnY, aim - 22);
PHL_PlaySound(sounds[sndShot03], CHN_ENEMIES);
}
if (d->timer == 360) {
d->state = 0;
d->hsp = 2.5;
if (d->x > 320) {
d->hsp *= -1;
}
int chaseY = heroy - d->ystart;
if (chaseY > 52) { chaseY = 52; }
if (chaseY < -52) { chaseY = -52; }
d->newystart = d->ystart + chaseY;
}
}
//Death
if (d->state == 4) {
d->rotspd = 3;
d->y += 0.2;
d->timer -= 1;
if (d->timer % 12 == 0) {
createEffect
(2, d
->x
- 64 + (rand() % 100), d
->y
- 64 + (rand() % 80));
}
if (d->timer <= 0) {
dead = 1;
}
}
}
//Collisions
if (d->state != 4) {
//Setup masks
Mask masks[6];
//Head mask
masks[0].unused = masks[0].circle = 0;
masks[0].w = 100;
masks[0].h = 104;
masks[0].x = d->x - (masks[0].w / 2);
masks[0].y = d->y - (masks[0].h / 2);
//Link masks
for (int i = 1; i < 5; i++) {
int taildis[4] = {54, 80, 108, 134};
int taillag[4] = {10, 15, 10, 5};
double newtailangle
= 90 + (55 * cos((d
->rotcounter
- taillag
[i
-1]) * 3.14159 / 180));
masks[i].unused = 0;
masks[i].circle = 1;
masks[i].w = 16;
masks[i].h = 16;
masks
[i
].
x = d
->x
+ (taildis
[i
-1] * cos(newtailangle
* 3.14159 / 180));
masks
[i
].
y = d
->y
+ (taildis
[i
-1] * sin(newtailangle
* 3.14159 / 180));
}
//Barb mask
masks[5].unused = masks[5].circle = 0;
masks[5].w = 40;
masks[5].h = 40;
masks
[5].
x = (d
->x
+ (160 * cos(d
->tailangle
* 3.14159 / 180))) - (masks
[5].
w / 2);
masks
[5].
y = (d
->y
+ (160 * sin(d
->tailangle
* 3.14159 / 180))) - (masks
[5].
h / 2);
//Collisions
int hitHead = 0;
for (int a = 0; a < 6; a++)
{
if (a == 0 || a == 5) {
//Hit Player
if (checkCollision(masks[a], getHeroMask())) {
int damage = 25;
if (a == 0) {
damage = 50;
}
if (heroHit(damage, masks[a].x + (masks[a].w / 2)) == 1) {
if (a == 5) { //Barb
heroStun();
}
}
}
}
//Weapon collision
if (hitHead == 0) {
for (int i = 0; i < MAX_WEAPONS; i++) {
if (weapons[i] != NULL) {
if (weapons[i]->cooldown == 0) {
if (checkCollision(masks[a], weapons[i]->weaponMask)) {
weaponHit(weapons[i]);
//Head
if (a == 0) {
d->hp -= 1;
d->blink = 15;
hitHead = 1;
if (d->hp <= 0) {
d->state = 4;
d->timer = 180;
d->blink = 200;
}
}else{
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
}
i = MAX_WEAPONS;
}
}
}
}
}
}
}
//Destroy
if (dead == 1) {
enemyDestroy(d->id);
bossDefeatedFlag = 1;
roomSecret = 1;
flags[boss6flag] = 1;
PHL_StopMusic();
}
}
void devilDraw(Devil* d)
{
if (d->blink % 2 == 0)
{
int dx, dy;
//Draw tail
int taildis[4] = {54, 80, 108, 134};
int taillag[4] = {10, 15, 10, 5};
for (int i = 0; i < 4; i++) {
double newtailangle
= 90 + (55 * cos((d
->rotcounter
- taillag
[i
]) * 3.14159 / 180));
dx
= d
->x
+ (taildis
[i
] * cos(newtailangle
* 3.14159 / 180)) - 32;
dy
= d
->y
+ (taildis
[i
] * sin(newtailangle
* 3.14159 / 180)) - 32;
PHL_DrawSurfacePart(dx, dy, 0, 128, 64, 64, images[imgBoss]);
}
//Draw Head
dx = d->x - 64;
dy = d->y - 64;
PHL_DrawSurfacePart(dx, dy, (int)d->imageIndex * 128, 0, 128, 128, images[imgBoss]);
//Draw Tail Tip
dx
= d
->x
+ (160 * cos(d
->tailangle
* 3.14159 / 180)) - 32;
dy
= d
->y
+ (160 * sin(d
->tailangle
* 3.14159 / 180)) - 32;
PHL_DrawSurfacePart(dx, dy, 64, 128, 64, 64, images[imgBoss]);
}
}
//Stone Orbs
void createOrb(int x, int y, double dir)
{
int i;
for (i = 0; i < MAX_ENEMIES; i++) {
if (enemies[i] == NULL) {
Enemy
* e
= /*(Enemy*)*/malloc(sizeof *e
);
Orb
* o
= /*(Orb*)*/malloc(sizeof *o
);
o->id = i;
o->x = x;
o->y = y;
o->dir = dir;
o->imageIndex = 0;
e->data = o;
e->enemyStep = orbStep;
e->enemyDraw = orbDraw;
e->type = -1;
enemies[i] = e;
i = MAX_ENEMIES;
}
}
}
void orbStep(Orb* o)
{
char dead = 0;
//Animate
{
o->imageIndex += 0.33;
if (o->imageIndex >= 4) {
o->imageIndex -= 4;
}
}
//Movement
{
int spd = 4;
o
->x
+= spd
* sin(o
->dir
* 3.14159 / 180);
o
->y
+= spd
* cos(o
->dir
* 3.14159 / 180);
}
//Collision
{
Mask mask;
mask.unused = 0;
mask.circle = 1;
mask.w = 6;
mask.x = o->x;
mask.y = o->y;
//Collide with shield
/*if (checkCollision(mask, shieldMask)) {
createEffect(1, o->x - 20, o->y - 20);
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
dead = 1;
}else{*/
//Hit player
if (checkCollision(getHeroMask(), mask)) {
heroStone();
heroHit(25, mask.x);
}
//}
//Collide with weapon
int i;
for (i = 0; i < MAX_WEAPONS; i++) {
if (weapons[i] != NULL) {
if (checkCollision(mask, weapons[i]->weaponMask)) {
weaponHit(weapons[i]);
createEffect(2, o->x - 32, o->y - 32);
dead = 1;
i = MAX_WEAPONS;
}
}
}
}
//Destroy if outside of room
{
if (o->x < -20 || o->x > 660 || o->y < -20 || o->y > 500) {
dead = 1;
}
}
//Finally erase object
{
if (dead == 1) {
enemyDestroy(o->id);
}
}
}
void orbDraw(Orb* o)
{
int animation[4] = {0, 1, 0, 2};
PHL_DrawSurfacePart(o->x - 20, o->y - 20, 440 + (animation[(int)o->imageIndex] * 40), 480, 40, 40, images[imgMisc20]);
}