mirror of
https://github.com/zeldaret/tmc
synced 2026-06-15 06:31:12 -04:00
333 lines
9.1 KiB
C
333 lines
9.1 KiB
C
/**
|
|
* @file enemy4D.c
|
|
* @ingroup Enemies
|
|
*
|
|
* @brief Enemy4D enemy
|
|
*/
|
|
#include "enemy.h"
|
|
#include "entity.h"
|
|
#include "functions.h"
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unk_68[0x5];
|
|
/*0x6d*/ u8 unk_6d;
|
|
/*0x6e*/ u8 unk_6e;
|
|
/*0x6f*/ u8 unk_6f;
|
|
/*0x70*/ u16 unk_70;
|
|
/*0x72*/ u16 unk_72;
|
|
/*0x74*/ u8 unk_74[0x4];
|
|
/*0x78*/ u16 unk_78;
|
|
/*0x7a*/ u8 unk_7a;
|
|
/*0x7b*/ u8 unk_7b;
|
|
/*0x7c*/ u8 unk_7c;
|
|
/*0x7d*/ u8 unk_7d;
|
|
/*0x7e*/ u8 unk_7e;
|
|
/*0x7f*/ u8 unk_7f;
|
|
/*0x80*/ u16 unk_80;
|
|
/*0x82*/ u16 unk_82;
|
|
/*0x84*/ u16 unk_84;
|
|
/*0x86*/ u16 unk_86;
|
|
} Enemy4DEntity;
|
|
|
|
extern void sub_0803E9A4(Entity*); // ballChainSoldier
|
|
extern void sub_0803E94C(Entity*, u32); // ballChainSoldier
|
|
|
|
void sub_0803EE8C(Enemy4DEntity*);
|
|
bool32 sub_0803EF20(Enemy4DEntity*);
|
|
bool32 sub_0803EEA4(Enemy4DEntity*);
|
|
bool32 sub_0803EF04(Enemy4DEntity*, u32);
|
|
void Enemy4D_OnTick(Enemy4DEntity*);
|
|
void Enemy4D_OnCollision(Enemy4DEntity*);
|
|
void Enemy4D_OnKnockback(Enemy4DEntity*);
|
|
void Enemy4D_OnDeath(Enemy4DEntity*);
|
|
void Enemy4D_OnGrabbed(Enemy4DEntity*);
|
|
void Enemy4D_Init(Enemy4DEntity*);
|
|
void Enemy4D_Action1(Enemy4DEntity*);
|
|
void Enemy4D_Action2(Enemy4DEntity*);
|
|
void Enemy4D_Action3(Enemy4DEntity*);
|
|
void Enemy4D_Action4(Enemy4DEntity*);
|
|
void Enemy4D_Action5(Enemy4DEntity*);
|
|
void Enemy4D_Action6(Enemy4DEntity*);
|
|
void Enemy4D_Action7(Enemy4DEntity*);
|
|
void Enemy4D_Action8(Enemy4DEntity*);
|
|
void Enemy4D_Action9(Enemy4DEntity*);
|
|
void Enemy4D_Action10(Enemy4DEntity*);
|
|
bool32 sub_0803EF70(Entity*, Entity*);
|
|
bool32 sub_0803EF74(Entity*, Entity*);
|
|
bool32 sub_0803EFAC(Entity*, Entity*);
|
|
|
|
void (*const Enemy4D_Functions[])(Enemy4DEntity*) = {
|
|
Enemy4D_OnTick,
|
|
Enemy4D_OnCollision,
|
|
Enemy4D_OnKnockback,
|
|
Enemy4D_OnDeath,
|
|
(void (*)(Enemy4DEntity*))GenericConfused,
|
|
Enemy4D_OnGrabbed,
|
|
};
|
|
|
|
void Enemy4D(Enemy4DEntity* this) {
|
|
EnemyFunctionHandler(super, (EntityActionArray)Enemy4D_Functions);
|
|
}
|
|
|
|
void Enemy4D_OnTick(Enemy4DEntity* this) {
|
|
static void (*const Enemy4D_Actions[])(Enemy4DEntity*) = {
|
|
Enemy4D_Init, Enemy4D_Action1, Enemy4D_Action2, Enemy4D_Action3, Enemy4D_Action4, Enemy4D_Action5,
|
|
Enemy4D_Action6, Enemy4D_Action7, Enemy4D_Action8, Enemy4D_Action9, Enemy4D_Action10,
|
|
};
|
|
Enemy4D_Actions[super->action](this);
|
|
}
|
|
|
|
void Enemy4D_OnCollision(Enemy4DEntity* this) {
|
|
EnemyFunctionHandlerAfterCollision(super, Enemy4D_Functions);
|
|
}
|
|
|
|
void Enemy4D_OnKnockback(Enemy4DEntity* this) {
|
|
GenericKnockback(super);
|
|
Enemy4D_OnTick(this);
|
|
}
|
|
|
|
void Enemy4D_OnDeath(Enemy4DEntity* this) {
|
|
EnemyCreateDeathFX((Enemy*)super, 0xff, 0x57);
|
|
}
|
|
|
|
void Enemy4D_OnGrabbed(Enemy4DEntity* this) {
|
|
}
|
|
|
|
void Enemy4D_Init(Enemy4DEntity* this) {
|
|
Entity* projectile;
|
|
|
|
sub_0804A720(super);
|
|
projectile = EnemyCreateProjectile(super, BALL_AND_CHAIN, 0);
|
|
if (projectile != NULL) {
|
|
projectile->parent = super;
|
|
super->child = projectile;
|
|
COLLISION_ON(super);
|
|
super->spriteSettings.draw = TRUE;
|
|
super->animationState = IdleEast;
|
|
this->unk_7b = 0;
|
|
this->unk_7c = 0;
|
|
this->unk_7e = 0x28;
|
|
this->unk_7f = 0xfe;
|
|
this->unk_80 = super->x.HALF.HI;
|
|
this->unk_82 = super->y.HALF.HI;
|
|
InitAnimationForceUpdate(super, super->animationState << 2);
|
|
sub_0803EE8C(this);
|
|
}
|
|
}
|
|
void Enemy4D_Action1(Enemy4DEntity* this) {
|
|
this->unk_7c -= 0xa;
|
|
if (sub_08049DF4(1)) {
|
|
super->direction = DirectionRoundUp(GetFacingDirection(super, gEnemyTarget));
|
|
sub_0803E94C(super, 0);
|
|
}
|
|
sub_0803E9A4(super);
|
|
if (EntityWithinDistance(super, this->unk_80, this->unk_82, 2) == FALSE) {
|
|
super->action = 4;
|
|
sub_0803E94C(super, 0x10);
|
|
} else {
|
|
if (sub_0803EF20(this) == FALSE) {
|
|
sub_0803EEA4(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action2(Enemy4DEntity* this) {
|
|
this->unk_7c -= 0x10;
|
|
sub_0803E9A4(super);
|
|
if (this->unk_7e > 0x1c) {
|
|
this->unk_7e--;
|
|
}
|
|
if (--this->unk_78 == 0) {
|
|
super->action = 3;
|
|
this->unk_7b = 0;
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action3(Enemy4DEntity* this) {
|
|
this->unk_7c -= 0xa;
|
|
sub_0803E9A4(super);
|
|
if (this->unk_7e < 0x28) {
|
|
this->unk_7e++;
|
|
} else {
|
|
sub_0803EE8C(this);
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action4(Enemy4DEntity* this) {
|
|
this->unk_7c -= 0xa;
|
|
sub_0803E9A4(super);
|
|
if (EntityWithinDistance(super, this->unk_80, this->unk_82, 1)) {
|
|
super->x.HALF.HI = this->unk_80;
|
|
super->y.HALF.HI = this->unk_82;
|
|
sub_0803EE8C(this);
|
|
sub_0803E94C(super, 0);
|
|
} else {
|
|
if (super->knockbackDuration == 0) {
|
|
super->direction = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->unk_80, this->unk_82);
|
|
sub_0803E94C(super, 0x10);
|
|
ProcessMovement0(super);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action5(Enemy4DEntity* this) {
|
|
s32 tmp;
|
|
this->unk_7c -= 0xc;
|
|
sub_0803E9A4(super);
|
|
tmp = this->unk_7e - 4;
|
|
this->unk_7e = tmp;
|
|
if ((tmp * 0x1000000) < 1) {
|
|
this->unk_7e = 0;
|
|
super->action = 6;
|
|
super->timer = 15;
|
|
InitAnimationForceUpdate(super, super->animationState + 0x20);
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action6(Enemy4DEntity* this) {
|
|
|
|
static const u8 gUnk_080D08C4[] = {
|
|
0,
|
|
68,
|
|
128,
|
|
188,
|
|
};
|
|
if (--super->timer == 0) {
|
|
super->action = 7;
|
|
super->timer = 1;
|
|
this->unk_7c = gUnk_080D08C4[super->animationState];
|
|
this->unk_7f = 0xf6;
|
|
EnqueueSFX(SFX_15B);
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action7(Enemy4DEntity* this) {
|
|
if ((super->frame & ANIM_DONE) == 0) {
|
|
UpdateAnimationSingleFrame(super);
|
|
} else {
|
|
if (--super->timer == 0) {
|
|
super->timer = 2;
|
|
this->unk_7f++;
|
|
}
|
|
if (this->unk_7f != 0) {
|
|
this->unk_7e += 5;
|
|
} else {
|
|
super->action = 8;
|
|
super->timer = 30;
|
|
InitScreenShake(8, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action8(Enemy4DEntity* this) {
|
|
if (--super->timer == 0) {
|
|
super->action = 9;
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action9(Enemy4DEntity* this) {
|
|
u8 tmp;
|
|
tmp = this->unk_7e = this->unk_7e - 2;
|
|
if (tmp < 0xb) {
|
|
super->action = 0xa;
|
|
super->timer = 60;
|
|
super->direction = super->animationState << 3;
|
|
this->unk_7c = 0;
|
|
this->unk_7f = 0xfe;
|
|
sub_0803E94C(super, 0x10);
|
|
} else if (tmp < 0x13) {
|
|
super->child->flags &= ~ENT_COLLIDE;
|
|
}
|
|
}
|
|
|
|
void Enemy4D_Action10(Enemy4DEntity* this) {
|
|
if (super->timer != 0) {
|
|
if (--super->timer == 0) {
|
|
super->child->flags |= ENT_COLLIDE;
|
|
sub_0803E94C(super, 0);
|
|
}
|
|
} else {
|
|
this->unk_7c -= 0xa;
|
|
sub_0803E9A4(super);
|
|
if (++this->unk_7e > 0x27) {
|
|
sub_0803EE8C(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0803EE8C(Enemy4DEntity* this) {
|
|
super->action = 1;
|
|
this->unk_7a = 0x1e;
|
|
sub_0803E94C(super, 0);
|
|
}
|
|
|
|
bool32 sub_0803EEA4(Enemy4DEntity* this) {
|
|
s32 tmp;
|
|
if (sub_08049FDC(super, 1)) {
|
|
if (sub_0803EF04(this, 0x4e) != 0) {
|
|
tmp = sub_0804A044(super, gEnemyTarget, 0x12);
|
|
if (tmp != 0xff) {
|
|
if (--this->unk_7a == 0) {
|
|
super->action = 5;
|
|
super->direction = tmp;
|
|
sub_0803E94C(super, 0);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
this->unk_7a = 0x1e;
|
|
return FALSE;
|
|
}
|
|
|
|
bool32 sub_0803EF04(Enemy4DEntity* this, u32 distance) {
|
|
return EntityWithinDistance(super, gEnemyTarget->x.HALF.HI, gEnemyTarget->y.HALF.HI - 4, distance);
|
|
}
|
|
|
|
bool32 sub_0803EF20(Enemy4DEntity* this) {
|
|
static bool32 (*const gUnk_080D08C8[])(Entity*, Entity*) = {
|
|
sub_0803EF70, sub_0803EF70, sub_0803EF70, sub_0803EF74, sub_0803EFAC, sub_0803EF70, sub_0803EF70, sub_0803EF70,
|
|
sub_0803EF70, sub_0803EF70, sub_0803EF70, sub_0803EF70, sub_0803EF70, sub_0803EF70, sub_0803EF70, sub_0803EFAC,
|
|
sub_0803EF70, sub_0803EFAC, sub_0803EFAC, sub_0803EFAC, sub_0803EF70, sub_0803EF70, sub_0803EFAC,
|
|
};
|
|
Entity* it;
|
|
LinkedList* list = &gEntityLists[2];
|
|
|
|
for (it = list->first; it != (Entity*)list; it = it->next) {
|
|
if ((it->kind == 8) && gUnk_080D08C8[it->id](super, it)) {
|
|
super->action = 2;
|
|
this->unk_78 = 0xb4;
|
|
this->unk_7b = 1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
bool32 sub_0803EF70(Entity* param_1, Entity* param_2) {
|
|
return FALSE;
|
|
}
|
|
|
|
bool32 sub_0803EF74(Entity* param_1, Entity* param_2) {
|
|
if (EntityWithinDistance(param_1, param_2->x.HALF.HI, param_2->y.HALF.HI, 0x50)) {
|
|
if (4 >= (((param_2->direction - GetFacingDirection(param_2, param_1)) + 2) & 0x1f)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
bool32 sub_0803EFAC(Entity* param_1, Entity* param_2) {
|
|
if (EntityInRectRadius(param_1, param_2, 0x50, 0x50)) {
|
|
u32 tmp = sub_0804A044(param_2, param_1, 0x1c);
|
|
if (tmp != 0xff) {
|
|
if (tmp == param_2->direction) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|