tmc/src/enemy/eyegore.c

487 lines
16 KiB
C

/**
* @file eyegore.c
* @ingroup Enemies
*
* @brief Eyegore enemy
*/
#include "enemy.h"
#include "fade.h"
#include "functions.h"
#include "hitbox.h"
#include "object.h"
#include "tiles.h"
typedef struct {
/*0x00*/ Entity base;
/*0x68*/ u8 unk_68[0x5];
/*0x6d*/ u8 unk_6d;
/*0x6e*/ u8 unk_6e[0x6];
/*0x74*/ u16 unk_74;
/*0x76*/ u16 unk_76;
/*0x78*/ u8 unk_78;
/*0x79*/ u8 unk_79;
/*0x7a*/ u8 unk_7a;
/*0x7b*/ u8 unk_7b;
/*0x7c*/ u16 unk_7c;
/*0x7e*/ u8 unk_7e;
/*0x7f*/ u8 unk_7f;
/*0x80*/ u16 tileIndex1;
/*0x82*/ u16 tileIndex2;
/*0x84*/ u16 tileIndex3;
/*0x86*/ u16 tileIndex4;
} EyegoreEntity;
extern Entity* sub_08017A90(Entity*, Entity*);
extern Entity* gUnk_020000B0;
extern const u8 gMapMetaTileTypeToCollisionData[];
void sub_08031344(EyegoreEntity*);
void sub_08031344(EyegoreEntity*);
void sub_08031320(EyegoreEntity*);
void sub_08030F00(EyegoreEntity*);
void sub_08030E58(EyegoreEntity*);
void sub_08030FB4(EyegoreEntity*);
void sub_08031024(EyegoreEntity*);
void sub_08030E3C(EyegoreEntity*);
void sub_08031250(EyegoreEntity*);
void sub_08030E70(EyegoreEntity*);
void sub_08030E80(EyegoreEntity*);
void Eyegore_OnTick(EyegoreEntity*);
void Eyegore_OnCollision(EyegoreEntity*);
void Eyegore_OnDeath(EyegoreEntity*);
void Eyegore_OnGrabbed(EyegoreEntity*);
void Eyegore_Init(EyegoreEntity*);
void Eyegore_Action1(EyegoreEntity*);
void Eyegore_Action2(EyegoreEntity*);
void Eyegore_Action3(EyegoreEntity*);
void Eyegore_Action4(EyegoreEntity*);
void Eyegore_Action5(EyegoreEntity*);
void Eyegore_Action6(EyegoreEntity*);
void (*const Eyegore_Functions[])(EyegoreEntity*) = {
Eyegore_OnTick,
Eyegore_OnCollision,
(void (*)(EyegoreEntity*))GenericKnockback,
Eyegore_OnDeath,
(void (*)(EyegoreEntity*))GenericConfused,
Eyegore_OnGrabbed,
};
void Eyegore(EyegoreEntity* this) {
EnemyFunctionHandler(super, (EntityActionArray)&Eyegore_Functions);
}
void Eyegore_OnTick(EyegoreEntity* this) {
static void (*const Eyegore_Actions[])(EyegoreEntity*) = {
Eyegore_Init, Eyegore_Action1, Eyegore_Action2, Eyegore_Action3,
Eyegore_Action4, Eyegore_Action5, Eyegore_Action6,
};
Eyegore_Actions[super->action](this);
}
void Eyegore_OnCollision(EyegoreEntity* this) {
u32 tmp;
if ((super->contactFlags == (CONTACT_NOW | 0x15)) || (super->contactFlags == (CONTACT_NOW | 0xe))) {
Entity* entity = super->contactedEntity;
tmp = (((entity->direction + 4) & 0x18) ^ 0x10) >> 3;
if (tmp == super->animationState) {
if ((tmp & 1) != 0) {
if (0x10 < ((entity->y.HALF.HI + entity->z.HALF.HI) - (super->y.HALF.HI + super->z.HALF.HI)) + 0x14U) {
} else {
if (super->contactFlags == (CONTACT_NOW | 0xe)) {
super->health = 0;
} else {
super->health--;
}
super->iframes = 0x10;
EnqueueSFX(SFX_HIT);
sub_08031344(this);
}
} else {
if ((entity->x.HALF.HI - super->x.HALF.HI) + 8U <= 0x10) {
if (super->action == 1) {
sub_08031320(this);
EnqueueSFX(SFX_BUTTON_PRESS);
sub_08031344(this);
} else {
if (super->contactFlags == (CONTACT_NOW | 0xe)) {
super->health = 0;
} else {
super->health--;
}
super->iframes = 0x0f;
EnqueueSFX(SFX_HIT);
sub_08031344(this);
}
}
}
}
}
if (super->health == 0) {
super->flags &= ~ENT_COLLIDE;
super->iframes = 0x78;
}
EnemyFunctionHandlerAfterCollision(super, Eyegore_Functions);
}
void Eyegore_OnDeath(EyegoreEntity* this) {
if (this->unk_7e != 0) {
this->unk_7e--;
GravityUpdate(super, Q_8_8(28.0));
} else {
if ((super->gustJarState & 2) == 0) {
CreateFx(super, FX_GIANT_EXPLOSION4, 0);
}
GenericDeath(super);
}
}
void Eyegore_OnGrabbed(EyegoreEntity* this) {
}
void Eyegore_Init(EyegoreEntity* this) {
sub_0804A720(super);
super->action = 1;
super->animationState = IdleEast;
super->x.HALF.HI &= 0xfff0;
super->y.HALF.HI = (super->y.HALF.HI & 0xfff0) + 0xc;
this->unk_6d |= 8;
this->unk_74 = super->x.HALF.HI;
this->unk_76 = super->y.HALF.HI;
this->unk_7e = 0x3c;
sub_08030F00(this);
if (this->unk_7c != 0) {
super->flags &= ~ENT_COLLIDE;
InitializeAnimation(super, 10);
} else {
InitializeAnimation(super, 0xe);
}
}
void Eyegore_Action1(EyegoreEntity* this) {
if ((this->unk_7c != 0) && CheckFlags(this->unk_7c)) {
sub_08031320(this);
}
}
void Eyegore_Action2(EyegoreEntity* this) {
if (super->timer != 0) {
super->timer--;
} else {
if (sub_08049FDC(super, 1)) {
super->action = 3;
super->timer = 60;
super->direction = (CalculateDirectionTo(super->x.HALF.HI + super->hitbox->offset_x,
super->y.HALF.HI + super->hitbox->offset_y,
gUnk_020000B0->x.HALF.HI, gUnk_020000B0->y.HALF.HI) +
4) &
0x18;
InitializeAnimation(super, 10);
}
}
}
void Eyegore_Action3(EyegoreEntity* this) {
static const u8 gUnk_080CE2BC[] = {
0,
255,
0,
1,
};
if (super->timer != 0) {
super->spriteOffsetX = gUnk_080CE2BC[--super->timer & 3];
} else {
GetNextFrame(super);
if ((super->frame & ANIM_DONE) != 0) {
super->flags |= ENT_COLLIDE;
super->animationState = IdleEast;
sub_08030E58(this);
InitializeAnimation(super, 2);
sub_08030FB4(this);
}
}
}
void Eyegore_Action4(EyegoreEntity* this) {
GetNextFrame(super);
switch (super->frame & 7) {
case 1:
sub_08031024(this);
sub_08030E3C(this);
break;
case 2:
if ((super->frame & ANIM_DONE) != 0) {
super->animationState = this->unk_7f;
InitializeAnimation(super, super->animationState + 4);
}
if (this->unk_7a != 0) {
sub_08031250(this);
}
if (GravityUpdate(super, Q_8_8(28.0)) == 0) {
sub_08030E70(this);
}
break;
default:
if ((super->frame & ANIM_DONE) != 0) {
InitializeAnimation(super, super->animationState);
if ((this->unk_79 & 0x80) != 0) {
super->action = 5;
this->unk_7a = 0;
}
}
break;
}
}
void Eyegore_Action5(EyegoreEntity* this) {
GetNextFrame(super);
switch (super->frame & 7) {
case 1:
if (super->animationState != IdleEast) {
if (super->animationState >= 3) {
this->unk_7f = (super->animationState - 1) & 3;
} else {
this->unk_7f = (super->animationState + 1) & 3;
}
}
sub_08030E3C(this);
break;
case 2:
if ((super->frame & ANIM_DONE) != 0) {
super->animationState = this->unk_7f;
InitializeAnimation(super, super->animationState + 4);
}
if (GravityUpdate(super, Q_8_8(28.0)) == 0) {
sub_08030E70(this);
}
break;
default:
if ((super->frame & ANIM_DONE) != 0) {
InitializeAnimation(super, super->animationState);
if (sub_08049FDC(super, 1)) {
sub_08030E58(this);
} else {
if (super->animationState == IdleEast) {
super->action = 6;
super->flags &= ~ENT_COLLIDE;
InitializeAnimation(super, 0xe);
sub_08030F00(this);
}
}
break;
}
}
}
void Eyegore_Action6(EyegoreEntity* this) {
GetNextFrame(super);
if ((super->frame & ANIM_DONE) != 0) {
super->action = 2;
}
}
void sub_08030E3C(EyegoreEntity* this) {
super->frame = 0;
super->zVelocity = Q_16_16(1.0 + 3.0 / 32.0);
EnqueueSFX(SFX_157);
}
void sub_08030E58(EyegoreEntity* this) {
super->action = 4;
this->unk_7a = 0;
this->unk_79 = 0;
this->unk_78 = 0;
}
void sub_08030E70(EyegoreEntity* this) {
sub_08030E80(this);
EnqueueSFX(SFX_158);
}
const s8 gUnk_080CE2C0[] = {
// This has to be before gUnk_080CE2F4.
-8, -10, 8, -10, 16, -4, 16, 4, -8, 10, 8, 10, -16, -4, -16, 4, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0,
14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 0, 64,
};
void sub_08030E80(EyegoreEntity* this) {
static const s8 gUnk_080CE2F4[] = {
-11, 9, 11, 9, -9, -2, -8, 10, -11, -1, 11, -1, 9, -2, 8, 10,
};
u32 tmp = super->animationState << 2;
Entity* effect = CreateObject(SPECIAL_FX, FX_DEATH, 0);
if (effect != NULL) {
CopyPosition(super, effect);
effect->x.HALF.HI += gUnk_080CE2F4[tmp + 0];
effect->y.HALF.HI += gUnk_080CE2F4[tmp + 1];
}
effect = CreateObject(SPECIAL_FX, FX_DEATH, 0);
if (effect != NULL) {
CopyPosition(super, effect);
effect->x.HALF.HI += gUnk_080CE2F4[tmp + 2];
effect->y.HALF.HI += gUnk_080CE2F4[tmp + 3];
}
}
void sub_08030F00(EyegoreEntity* this) {
u32 metaTilePos = COORD_TO_TILE_OFFSET(super, 8, 20);
u16 tileIndex = GetMetaTileIndex(metaTilePos + TILE_POS(0, 0), super->collisionLayer);
this->tileIndex1 = tileIndex;
tileIndex = GetMetaTileIndex(metaTilePos + TILE_POS(1, 0), super->collisionLayer);
this->tileIndex2 = tileIndex;
tileIndex = GetMetaTileIndex(metaTilePos + TILE_POS(0, 1), super->collisionLayer);
this->tileIndex3 = tileIndex;
tileIndex = GetMetaTileIndex(metaTilePos + TILE_POS(1, 1), super->collisionLayer);
this->tileIndex4 = tileIndex;
SetMetaTile(SPECIAL_META_TILE_34, metaTilePos, super->collisionLayer);
SetMetaTile(SPECIAL_META_TILE_34, metaTilePos + 1, super->collisionLayer);
SetMetaTile(SPECIAL_META_TILE_34, metaTilePos + TILE_POS(0, 1), super->collisionLayer);
SetMetaTile(SPECIAL_META_TILE_34, metaTilePos + TILE_POS(1, 1), super->collisionLayer);
}
void sub_08030FB4(EyegoreEntity* this) {
u32 metaTilePos = COORD_TO_TILE_OFFSET(super, 8, 20);
SetMetaTile(this->tileIndex1, metaTilePos + TILE_POS(0, 0), super->collisionLayer);
SetMetaTile(this->tileIndex2, metaTilePos + TILE_POS(1, 0), super->collisionLayer);
SetMetaTile(this->tileIndex3, metaTilePos + TILE_POS(0, 1), super->collisionLayer);
SetMetaTile(this->tileIndex4, metaTilePos + TILE_POS(1, 1), super->collisionLayer);
}
void sub_08031024(EyegoreEntity* this) {
u32 uVar5;
bool32 boolresult;
u32 uVar8;
u32 tmp, tmp2;
if (sub_08049FDC(super, 1)) {
boolresult = 1;
} else {
boolresult = 0;
}
if (this->unk_79 == 0) {
if (boolresult != 0) {
super->direction = CalculateDirectionTo(super->x.HALF.HI + super->hitbox->offset_x,
super->y.HALF.HI + super->hitbox->offset_y,
gUnk_020000B0->x.HALF.HI, gUnk_020000B0->y.HALF.HI);
} else {
this->unk_79 = 1;
this->unk_78 = boolresult != 0;
super->direction = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->unk_74, this->unk_76);
}
} else {
if (boolresult != 0) {
this->unk_79 = 0;
} else {
if (this->unk_78 != 0) {
if (this->unk_78 == 1) {
this->unk_78 |= 0x80;
super->direction =
CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->unk_74, this->unk_76);
this->unk_7b = (super->direction + 4) & 0x18;
if (this->unk_7b < super->direction) {
super->direction = (this->unk_7b + 8) & 0x18;
} else {
super->direction = (this->unk_7b - 8) & 0x18;
}
} else if ((this->unk_78 & 2) != 0) {
super->direction ^= 0x10;
}
tmp = (this->unk_78 & 0x70) * 0x1000000;
if (tmp != 0) {
tmp >>= 0x19;
this->unk_78 = tmp | (this->unk_78 & 0x8f);
if (((this->unk_78) & 0x10) != 0) {
super->direction = this->unk_7b;
this->unk_78 = 0;
}
} else {
tmp2 = this->unk_7b >> 1;
uVar5 = GetMetaTileTypeByPos(super->x.HALF.HI + gUnk_080CE2C0[tmp2],
super->y.HALF.HI + gUnk_080CE2C0[tmp2 + 1], super->collisionLayer);
uVar8 = GetMetaTileTypeByPos(super->x.HALF.HI + gUnk_080CE2C0[tmp2 + 2],
super->y.HALF.HI + gUnk_080CE2C0[tmp2 + 3], super->collisionLayer);
if (!(((gMapMetaTileTypeToCollisionData[uVar5] == 0) &&
(gMapMetaTileTypeToCollisionData[uVar8] == 0)) ||
((this->unk_7b | 1) & 1) == 0)) {
if (super->direction >> 3 == super->animationState) {
this->unk_78 |= 0x20;
} else {
this->unk_78 |= 0x40;
}
} else {
super->direction = this->unk_7b;
this->unk_78 = 0;
}
}
} else {
super->direction = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->unk_74, this->unk_76);
}
}
}
if (((super->direction + 4) & 0x18) >> 3 == super->animationState) {
this->unk_7a = 1;
this->unk_7f = super->animationState;
} else {
this->unk_7a = 0;
if (((super->direction + super->animationState * -8) & 0x1f) >= 0x11U) {
this->unk_7f = (super->animationState - 1) & 3;
} else {
this->unk_7f = (super->animationState + 1) & 3;
}
}
super->direction = (super->direction + 4) & 0x18;
super->x.HALF.LO = 0;
super->y.HALF.LO = 0;
}
void sub_08031250(EyegoreEntity* this) {
u32 tmp2;
u32 tmp = (u32)super->animationState * 4;
DoTileInteraction(super, 9, super->x.HALF.HI + gUnk_080CE2C0[tmp], super->y.HALF.HI + gUnk_080CE2C0[tmp + 1]);
DoTileInteraction(super, 9, super->x.HALF.HI + gUnk_080CE2C0[tmp + 2], super->y.HALF.HI + gUnk_080CE2C0[tmp + 3]);
if (this->unk_79 != 0) {
tmp2 = 0;
if ((super->x.HALF.HI - (u32)this->unk_74) + 2 < 5) {
super->x.HALF.HI = this->unk_74;
tmp2 = 0x80;
}
if ((super->y.HALF.HI - (u32)this->unk_76) + 2 < 5) {
super->y.HALF.HI = this->unk_76;
this->unk_79 = tmp2 | this->unk_79;
}
if (((this->unk_79 & 0x80) == 0) && (ProcessMovement0(super) == 0)) {
if ((this->unk_78 & 0x80) != 0) {
this->unk_78 = 0x82;
} else {
this->unk_78 = 1;
}
}
} else {
ProcessMovement0(super);
}
}
void sub_08031320(EyegoreEntity* this) {
super->action = 2;
super->flags &= ~ENT_COLLIDE;
super->timer = 30;
super->hitbox = (Hitbox*)&gUnk_080FD308;
InitializeAnimation(super, 10);
}
void sub_08031344(EyegoreEntity* this) {
static const s8 gUnk_080CE304[] = {
0, -6, -14, -14, 0, -28, 14, -14,
};
Entity* entity = sub_08017A90(super->contactedEntity, super);
if (entity != NULL) {
const s8* ptr = &gUnk_080CE304[entity->animationState * 2];
entity->spriteOffsetX = ptr[0];
entity->spriteOffsetY = ptr[1];
}
}