#define NENT_DEPRECATED #include "entity.h" #include "enemy.h" #include "functions.h" typedef struct { Entity base; u8 filler[0x10]; u16 unk_78; u8 unk_7a; u8 unk_7b; u8 unk_7c; u8 unk_7d; u8 unk_7e; u8 unk_7f; } BallChainSoldierEntity; extern Entity* gUnk_020000B0; void (*const gUnk_080D06E0[])(BallChainSoldierEntity*); void (*const gUnk_080D06F8[])(BallChainSoldierEntity*); const u8 gUnk_080D0724[]; const u16 gUnk_080D0728[]; const u16 gUnk_080D0730[]; extern u32 sub_0804A044(Entity*, Entity*, u32); extern void sub_0803E86C(BallChainSoldierEntity*); extern void sub_0803E9A4(BallChainSoldierEntity*); extern bool32 sub_0803E9D4(BallChainSoldierEntity*); extern void sub_0803E8CC(BallChainSoldierEntity*); extern void sub_0803E92C(BallChainSoldierEntity*); extern bool32 sub_0803EA64(BallChainSoldierEntity*); extern void sub_0803E94C(BallChainSoldierEntity*, u32); extern bool32 sub_0803EAD0(BallChainSoldierEntity*, u32); void BallChainSoldier(Entity* this) { EnemyFunctionHandler(this, (EntityActionArray)gUnk_080D06E0); } void sub_0803E538(BallChainSoldierEntity* this) { gUnk_080D06F8[super->action](this); } void sub_0803E550(BallChainSoldierEntity* this) { sub_0804AA30(super, gUnk_080D06E0); } void sub_0803E560(BallChainSoldierEntity* this) { sub_08001324(super); sub_0803E538(this); } void BallChainSoldier_CreateDeathFx(BallChainSoldierEntity* this) { CreateDeathFx(super, 0xff, 0x57); } void nullsub_20(BallChainSoldierEntity* this) { } void BallChainSoldier_Init(BallChainSoldierEntity* this) { Entity* ent; sub_0804A720(super); ent = CreateProjectileWithParent(super, BALL_AND_CHAIN, 0); if (ent == NULL) return; ent->parent = super; super->child = ent; COLLISION_ON(super); super->spriteSettings.draw = 1; super->animationState = Random() & 3; this->unk_7b = 0; this->unk_7c = 0; this->unk_7e = 0x20; this->unk_7f = 0xfe; InitAnimationForceUpdate(super, super->animationState << 2); sub_0803E86C(this); } void sub_0803E5E8(BallChainSoldierEntity* this) { this->unk_7c -= 0xa; sub_0803E9A4(this); if (sub_0803E9D4(this) == 0) { if (--this->unk_78 == 0) { sub_0803E8CC(this); } } } void sub_0803E61C(BallChainSoldierEntity* this) { this->unk_7c -= 0xa; sub_0803E9A4(this); if (sub_0803E9D4(this) == 0) { if (super->knockbackDuration == 0) { if (ProcessMovement(super) == 0) { sub_0803E86C(this); return; } } if (--this->unk_78 == 0) { sub_0803E92C(this); } } } void sub_0803E66C(BallChainSoldierEntity* this) { this->unk_7c -= 0x10; sub_0803E9A4(this); if (this->unk_7e <= 0x21) { this->unk_7e++; } if (!sub_08049FDC(super, 1) || sub_0803EA64(this) == 0) { super->action = 4; this->unk_7b = 0; } } void sub_0803E6B4(BallChainSoldierEntity* this) { this->unk_7c -= 0xa; sub_0803E9A4(this); if (this->unk_7e > 0x20) { this->unk_7e--; } else { sub_0803E86C(this); } } void sub_0803E6E0(BallChainSoldierEntity* this) { this->unk_7c -= 0xc; sub_0803E9A4(this); this->unk_7e -= 4; if ((s8)this->unk_7e <= 0) { this->unk_7e = 0; super->action = 6; super->actionDelay = 0x1e; InitAnimationForceUpdate(super, super->animationState + 0x20); } } void sub_0803E71C(BallChainSoldierEntity* this) { if (--super->actionDelay == 0) { super->action = 7; super->actionDelay = 1; this->unk_7c = gUnk_080D0724[super->animationState]; this->unk_7b = 0; this->unk_7f = 0xf6; EnqueueSFX(SFX_15B); } } void sub_0803E75C(BallChainSoldierEntity* this) { if ((super->frame & 0x80) == 0) { UpdateAnimationSingleFrame(super); } else { if (--super->actionDelay == 0) { super->actionDelay = 2; this->unk_7f++; } if (this->unk_7f) { this->unk_7e += 5; } else { super->action = 8; super->actionDelay = 0x1e; InitScreenShake(8, 0); } } } void sub_0803E7B4(BallChainSoldierEntity* this) { if (--super->actionDelay == 0) { super->action = 9; } } void sub_0803E7CC(BallChainSoldierEntity* this) { this->unk_7e -= 2; if (this->unk_7e <= 0xa) { super->action = 0xa; super->actionDelay = 0x5a; super->direction = DirectionFromAnimationState(super->animationState); this->unk_7c = 0; this->unk_7f = 0xfe; sub_0803E94C(this, 0x10); } else if (this->unk_7e <= 0x12) { COLLISION_OFF(super->child); } } void sub_0803E818(BallChainSoldierEntity* this) { if (super->actionDelay) { if (--super->actionDelay == 0) { COLLISION_ON(super->child); sub_0803E94C(this, 0); } } else { this->unk_7c -= 0xa; sub_0803E9A4(this); if (++this->unk_7e > 0x1f) { sub_0803E86C(this); } } } void sub_0803E86C(BallChainSoldierEntity* this) { if (sub_08049FDC(super, 1) && sub_0803EAD0(this, 0x50)) { super->direction = DirectionRoundUp(GetFacingDirection(super, gUnk_020000B0)); } super->action = 1; this->unk_78 = gUnk_080D0728[Random() & 3]; this->unk_7a = 4; sub_0803E94C(this, 0); } void sub_0803E8CC(BallChainSoldierEntity* this) { u32 rand = Random(); u32 temp; u32 dir; if (sub_08049FA0(super) == 0 && (rand & 3)) { dir = sub_08049EE4(super) + 4; temp = 0x18; } else { temp = 0x18; dir = rand; } super->direction = dir & temp; super->action = 2; this->unk_78 = gUnk_080D0730[(rand >> 0x10) & 3]; this->unk_7a = 4; sub_0803E94C(this, 0x10); } void sub_0803E92C(BallChainSoldierEntity* this) { if (Random() & 1) { sub_0803E86C(this); } else { sub_0803E8CC(this); } } void sub_0803E94C(BallChainSoldierEntity* this, u32 arg2) { s32 animationState = DirectionToAnimationState(super->direction); if ((super->animIndex & 0x10) == arg2) { u32 dir = super->direction & 7; s32 currentAnimationState = super->animationState; if (dir == 4) { if (((currentAnimationState - (super->direction >> 3)) & 3) <= 1) return; } if (animationState == currentAnimationState) return; } super->animationState = animationState; animationState = arg2 + (super->animIndex & 3) + animationState * 4; InitAnimationForceUpdate(super, animationState); } void sub_0803E9A4(BallChainSoldierEntity* this) { s32 val = ((this->unk_7c + 0x20) & 0xff) >> 6; if ((super->animIndex & 3) == val) return; InitAnimationForceUpdate(super, val + (super->animIndex & -4)); } bool32 sub_0803E9D4(BallChainSoldierEntity* this) { u32 dir; if (sub_08049FDC(super, 1)) { if (sub_0803EAD0(this, 0x38)) { super->action = 3; super->direction = DirectionRoundUp(GetFacingDirection(super, gUnk_020000B0)); this->unk_7b = 1; sub_0803E94C(this, 0); return 1; } else if (sub_0803EAD0(this, 0x4e)) { dir = sub_0804A044(super, gUnk_020000B0, 0x12); if (dir != 0xff) { if (--this->unk_7a != 0) return 0; super->action = 5; super->direction = dir; this->unk_7a = 4; sub_0803E94C(this, 0); return 1; } } } this->unk_7a = 4; return 0; } bool32 sub_0803EA64(BallChainSoldierEntity* this) { u32 dir; if (sub_08049FDC(super, 1)) { if (sub_0803EAD0(this, 0x4e)) { dir = sub_0804A044(super, gUnk_020000B0, 0x12); if (dir != 0xff) { if (--this->unk_7a != 0) return 1; super->action = 5; super->direction = dir; sub_0803E94C(this, 0); return 1; } } if (sub_0803EAD0(this, 0x38)) return 1; } this->unk_7a = 4; return 0; } bool32 sub_0803EAD0(BallChainSoldierEntity* this, u32 distance) { return EntityWithinDistance(super, gUnk_020000B0->x.HALF.HI, gUnk_020000B0->y.HALF.HI - 4, distance); } void (*const gUnk_080D06E0[])(BallChainSoldierEntity*) = { sub_0803E538, sub_0803E550, sub_0803E560, BallChainSoldier_CreateDeathFx, (void (*const)(BallChainSoldierEntity*))sub_08001242, nullsub_20, }; void (*const gUnk_080D06F8[])(BallChainSoldierEntity*) = { BallChainSoldier_Init, sub_0803E5E8, sub_0803E61C, sub_0803E66C, sub_0803E6B4, sub_0803E6E0, sub_0803E71C, sub_0803E75C, sub_0803E7B4, sub_0803E7CC, sub_0803E818, }; const u8 gUnk_080D0724[] = { 0, 0x44, 0x80, 0xBC }; const u16 gUnk_080D0728[] = { 0x1E, 0x32, 0x46, 0x5A }; const u16 gUnk_080D0730[] = { 0x3C, 0x5A, 0x78, 0x96 };