/*
 * File: z_en_sw.c
 * Overlay: ovl_En_Sw
 * Description: Skullwalltula
 */

#include "z_en_sw.h"

#define FLAGS 0x00000005

#define THIS ((EnSw*)thisx)

void EnSw_Init(Actor* thisx, GlobalContext* globalCtx);
void EnSw_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnSw_Update(Actor* thisx, GlobalContext* globalCtx);
void EnSw_Draw(Actor* thisx, GlobalContext* globalCtx);

void func_808DA350(EnSw* this, GlobalContext* globalCtx);
void func_808DA3F4(EnSw* this, GlobalContext* globalCtx);
void func_808DA578(EnSw* this, GlobalContext* globalCtx);
void func_808DA6FC(EnSw* this, GlobalContext* globalCtx);
void func_808DA89C(EnSw* this, GlobalContext* globalCtx);
void func_808DAA60(EnSw* this, GlobalContext* globalCtx);
void func_808DACF4(EnSw* this, GlobalContext* globalCtx);
void func_808DAEB4(EnSw* this, GlobalContext* globalCtx);
void func_808DB100(EnSw* this, GlobalContext* globalCtx);
void func_808DB25C(EnSw* this, GlobalContext* globalCtx);
void func_808DB2E0(EnSw* this, GlobalContext* globalCtx);

extern AnimationHeader D_06000304;
extern Gfx D_06003FB0[];
extern Gfx D_060043D8[];
extern Gfx D_060045C0[];
extern Gfx D_06004658[];
extern Gfx D_060046F0[];
extern Gfx D_06004788[];
extern Gfx D_06004820[];
extern Gfx D_060048B8[];
extern Gfx D_06004950[];
extern Gfx D_060049E8[];
extern SkeletonHeader D_06005298;
extern AnimationHeader D_060055A8;
extern AnimationHeader D_06005B98;

const ActorInit En_Sw_InitVars = {
    ACTOR_EN_SW,
    ACTORCAT_NPC,
    FLAGS,
    OBJECT_ST,
    sizeof(EnSw),
    (ActorFunc)EnSw_Init,
    (ActorFunc)EnSw_Destroy,
    (ActorFunc)EnSw_Update,
    (ActorFunc)EnSw_Draw,
};

static ColliderSphereInit sSphereInit = {
    {
        COLTYPE_NONE,
        AT_ON | AT_TYPE_ENEMY,
        AC_ON | AC_TYPE_PLAYER,
        OC1_ON | OC1_TYPE_ALL,
        OC2_TYPE_1,
        COLSHAPE_SPHERE,
    },
    {
        ELEMTYPE_UNK0,
        { 0xF7CFFFFF, 0x00, 0x00 },
        { 0xF7CFFFFF, 0x00, 0x00 },
        TOUCH_ON | TOUCH_SFX_NORMAL,
        BUMP_ON,
        OCELEM_ON,
    },
    { 0, { { 0, 0, 0 }, 16 }, 100 },
};

static CollisionCheckInfoInit2 sColChkInfoInit = { 1, 0, 0, 0, MASS_IMMOVABLE };

static DamageTable sDamageTable = {
    /* Deku Nut       */ DMG_ENTRY(1, 0x0),
    /* Deku Stick     */ DMG_ENTRY(1, 0x0),
    /* Horse trample  */ DMG_ENTRY(0, 0x0),
    /* Explosives     */ DMG_ENTRY(1, 0x0),
    /* Zora boomerang */ DMG_ENTRY(1, 0x0),
    /* Normal arrow   */ DMG_ENTRY(1, 0x0),
    /* UNK_DMG_0x06   */ DMG_ENTRY(0, 0x0),
    /* Hookshot       */ DMG_ENTRY(1, 0x0),
    /* Goron punch    */ DMG_ENTRY(1, 0x0),
    /* Sword          */ DMG_ENTRY(1, 0x0),
    /* Goron pound    */ DMG_ENTRY(2, 0x0),
    /* Fire arrow     */ DMG_ENTRY(2, 0x2),
    /* Ice arrow      */ DMG_ENTRY(2, 0x3),
    /* Light arrow    */ DMG_ENTRY(2, 0x4),
    /* Goron spikes   */ DMG_ENTRY(1, 0x0),
    /* Deku spin      */ DMG_ENTRY(1, 0x0),
    /* Deku bubble    */ DMG_ENTRY(1, 0x0),
    /* Deku launch    */ DMG_ENTRY(2, 0x0),
    /* UNK_DMG_0x12   */ DMG_ENTRY(1, 0x0),
    /* Zora barrier   */ DMG_ENTRY(1, 0x5),
    /* Normal shield  */ DMG_ENTRY(1, 0x0),
    /* Light ray      */ DMG_ENTRY(1, 0x0),
    /* Thrown object  */ DMG_ENTRY(1, 0x0),
    /* Zora punch     */ DMG_ENTRY(1, 0x0),
    /* Spin attack    */ DMG_ENTRY(1, 0x0),
    /* Sword beam     */ DMG_ENTRY(0, 0x0),
    /* Normal Roll    */ DMG_ENTRY(0, 0x0),
    /* UNK_DMG_0x1B   */ DMG_ENTRY(0, 0x0),
    /* UNK_DMG_0x1C   */ DMG_ENTRY(0, 0x0),
    /* Unblockable    */ DMG_ENTRY(0, 0x0),
    /* UNK_DMG_0x1E   */ DMG_ENTRY(0, 0x0),
    /* Powder Keg     */ DMG_ENTRY(1, 0x0),
};

static CollisionCheckInfoInit2 sColChkInfoInit2 = { 1, 0, 0, 0, MASS_IMMOVABLE };

static DamageTable sDamageTable2 = {
    /* Deku Nut       */ DMG_ENTRY(0, 0x1),
    /* Deku Stick     */ DMG_ENTRY(1, 0x0),
    /* Horse trample  */ DMG_ENTRY(0, 0x0),
    /* Explosives     */ DMG_ENTRY(1, 0x0),
    /* Zora boomerang */ DMG_ENTRY(1, 0x0),
    /* Normal arrow   */ DMG_ENTRY(1, 0x0),
    /* UNK_DMG_0x06   */ DMG_ENTRY(0, 0x0),
    /* Hookshot       */ DMG_ENTRY(1, 0x0),
    /* Goron punch    */ DMG_ENTRY(1, 0x0),
    /* Sword          */ DMG_ENTRY(1, 0x0),
    /* Goron pound    */ DMG_ENTRY(2, 0x0),
    /* Fire arrow     */ DMG_ENTRY(2, 0x2),
    /* Ice arrow      */ DMG_ENTRY(2, 0x3),
    /* Light arrow    */ DMG_ENTRY(2, 0x4),
    /* Goron spikes   */ DMG_ENTRY(1, 0x0),
    /* Deku spin      */ DMG_ENTRY(1, 0x0),
    /* Deku bubble    */ DMG_ENTRY(1, 0x0),
    /* Deku launch    */ DMG_ENTRY(2, 0x0),
    /* UNK_DMG_0x12   */ DMG_ENTRY(0, 0x1),
    /* Zora barrier   */ DMG_ENTRY(1, 0x5),
    /* Normal shield  */ DMG_ENTRY(1, 0x0),
    /* Light ray      */ DMG_ENTRY(1, 0x0),
    /* Thrown object  */ DMG_ENTRY(1, 0x0),
    /* Zora punch     */ DMG_ENTRY(1, 0x0),
    /* Spin attack    */ DMG_ENTRY(1, 0x0),
    /* Sword beam     */ DMG_ENTRY(0, 0x0),
    /* Normal Roll    */ DMG_ENTRY(0, 0x0),
    /* UNK_DMG_0x1B   */ DMG_ENTRY(0, 0x0),
    /* UNK_DMG_0x1C   */ DMG_ENTRY(0, 0x0),
    /* Unblockable    */ DMG_ENTRY(0, 0x0),
    /* UNK_DMG_0x1E   */ DMG_ENTRY(0, 0x0),
    /* Powder Keg     */ DMG_ENTRY(1, 0x0),
};

static ActorAnimationEntryS sAnimations[] = {
    { &D_06000304, 1.0f, 0, -1, 3, 0 },
    { &D_06000304, 1.0f, 0, -1, 3, -4 },
    { &D_060055A8, 1.0f, 0, -1, 1, -4 },
    { &D_06005B98, 1.0f, 0, -1, 1, -4 },
};

void func_808D8940(EnSw* this, GlobalContext* globalCtx) {
    static Color_RGBA8 D_808DBAA4 = { 170, 130, 90, 255 };
    static Color_RGBA8 D_808DBAA8 = { 100, 60, 20, 0 };
    s32 i;
    Vec3f spB8;
    Vec3f spAC;
    Vec3f spA0;
    Vec3f sp94;
    s32 temp_f4;
    s16 temp_s0;

    temp_s0 = (Rand_ZeroOne() - 0.5f) * 0x10000;
    spA0.y = this->actor.floorHeight;

    for (i = 0; i < 8; i++, temp_s0 += 0x1FFE) {
        temp_f4 = (Rand_ZeroOne() * 4.0f) + 8.0f;
        sp94.x = 0.0f;
        sp94.y = (Rand_ZeroOne() * 0.2f) + 0.1f;
        sp94.z = Rand_ZeroOne() + 1.0f;
        Lib_Vec3f_TranslateAndRotateY(&D_801D15B0, temp_s0, &sp94, &spAC);
        sp94.x = 0.0f;
        sp94.y = 0.7f;
        sp94.z = 2.0f;
        Lib_Vec3f_TranslateAndRotateY(&D_801D15B0, temp_s0, &sp94, &spB8);
        spA0.x = this->actor.world.pos.x + (2.0f * spB8.x);
        spA0.z = this->actor.world.pos.z + (2.0f * spB8.z);
        func_800B0EB0(globalCtx, &spA0, &spB8, &spAC, &D_808DBAA4, &D_808DBAA8, 60, 30, temp_f4);
    }
}

s32 func_808D8B58(EnSw* this) {
    s16 phi_s2 = (s16)((s16)(Rand_ZeroOne() * 1000.0f) % ARRAY_COUNT(this->unk_464)) * 0x1555;
    s32 i;

    for (i = 0; i < ARRAY_COUNT(this->unk_464); i++, phi_s2 += 0x1555) {
        if (this->unk_412 != 10) {
            this->unk_464[i] = (Rand_ZeroOne() * 16.0f) + 8.0f;
        } else {
            this->unk_464[i] = 80;
        }
        this->unk_47C[i] = this->unk_464[i];
        this->unk_418[i] = 0.45000002f;
        if ((this->unk_412 == 0) || (this->unk_412 == 1) || (this->unk_412 == 10)) {
            this->unk_380[i].y = (Rand_ZeroOne() - 0.5f) * 20.0f;
        } else {
            this->unk_380[i].y = ((Rand_ZeroOne() - 0.5f) * 20.0f) + 10.0f;
        }
        this->unk_380[i].x = Math_SinS(phi_s2) * 10.0f;
        this->unk_380[i].z = Math_CosS(phi_s2) * 10.0f;
    }
    this->unk_462 = 1;
    return 0;
}

s32 func_808D8D60(EnSw* this, GlobalContext* globalCtx, s32 arg2) {
    s32 ret = false;
    u8 sp53;
    Vec3f sp44;
    f32 sp40;

    if (arg2 < this->unk_462) {
        if (this->unk_464[arg2] != 0) {
            sp40 = (f32)this->unk_464[arg2] / this->unk_47C[arg2];
            sp53 = this->unk_412;
            Math_ApproachF(&this->unk_418[arg2], 0.3f, 0.3f, 0.5f);
            Math_Vec3f_Copy(&sp44, &this->actor.world.pos);
            sp44.x += this->unk_380[arg2].x;
            sp44.y += this->unk_380[arg2].y;
            sp44.z += this->unk_380[arg2].z;
            if (sp53 == 10) {
                if ((this->unk_47C[arg2] - this->unk_464[arg2]) < 20) {
                    sp53 = 11;
                }
                sp40 = 1.0f;
            }
            func_800BE680(globalCtx, &this->actor, &sp44, 1, 0.3f, this->unk_418[arg2], sp40, sp53);
            ret = true;
        }
    }
    return ret;
}

void func_808D8ED0(EnSw* this, GlobalContext* globalCtx) {
    Vec3f sp54;
    s32 i;

    for (i = 0; i < ARRAY_COUNT(this->unk_380); i++) {
        Math_Vec3f_Copy(&sp54, &this->actor.world.pos);
        sp54.x += this->unk_380[i].x;
        sp54.y += this->unk_380[i].y;
        sp54.z += this->unk_380[i].z;
        Math_Vec3f_Copy(&this->unk_380[i], &sp54);
    }
    func_800BF7CC(globalCtx, &this->actor, this->unk_380, ARRAY_COUNT(this->unk_380), 3, 0.1f, 0.3f);
}

void func_808D8FC4(EnSw* this, GlobalContext* globalCtx) {
    Math_Vec3f_ToVec3s(&this->collider.dim.worldSphere.center, &this->actor.world.pos);
    this->collider.dim.worldSphere.radius = this->collider.dim.modelSphere.radius * this->collider.dim.scale;
    if (!(this->unk_410 & 0x10) && (this->actor.colChkInfo.health != 0) && (DECR(this->unk_458) <= 10)) {
        CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
    }

    if (!(this->unk_410 & 0x10) && (this->actor.colChkInfo.health != 0)) {
        CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
    }

    if (this->unk_410 & 4) {
        CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
    }
}

s32 func_808D90C4(EnSw* this) {
    if (this->actor.colChkInfo.damage < this->actor.colChkInfo.health) {
        this->actor.colChkInfo.health -= this->actor.colChkInfo.damage;
    } else {
        this->actor.colChkInfo.health = 0;
    }
    return this->actor.colChkInfo.health;
}

void func_808D90F0(EnSw* this, s32 arg1, s16 arg2) {
    Vec3f sp2C;
    s16 sp2A;
    s16 temp;

    if (arg1 == 1) {
        sp2A = this->unk_494;
        Math_ApproachS(&this->unk_494, this->unk_496, 4, 0xE38);
        temp = this->unk_494 - sp2A;
    } else {
        temp = arg2;
    }

    Matrix_InsertRotationAroundUnitVector_f(BINANG_TO_RAD(temp), &this->unk_368, 0);
    Matrix_MultiplyVector3fByState(&this->unk_350, &sp2C);
    Math_Vec3f_Copy(&this->unk_350, &sp2C);
    Math3D_CrossProduct(&this->unk_368, &this->unk_350, &this->unk_35C);
}

s32 func_808D91C4(EnSw* this, CollisionPoly* arg1) {
    f32 sp4C;
    f32 temp_f12;
    f32 temp_f0;
    Vec3f sp38;
    Vec3f sp2C;

    this->actor.floorPoly = arg1;
    if (arg1 != 0) {
        sp38.x = COLPOLY_GET_NORMAL(arg1->normal.x);
        sp38.y = COLPOLY_GET_NORMAL(arg1->normal.y);
        sp38.z = COLPOLY_GET_NORMAL(arg1->normal.z);
    } else {
        return false;
    }

    temp_f12 = DOTXYZ(sp38, this->unk_368);
    if (fabsf(temp_f12) >= 0.999f) {
        return false;
    }

    sp4C = func_80086C48(temp_f12);
    if (sp4C < 0.001f) {
        return false;
    }

    Math3D_CrossProduct(&this->unk_368, &sp38, &sp2C);
    temp_f0 = Math3D_Vec3fMagnitude(&sp2C);
    if (temp_f0 < 0.001f) {
        return false;
    }

    Math_Vec3f_Scale(&sp2C, 1.0f / temp_f0);
    Matrix_InsertRotationAroundUnitVector_f(sp4C, &sp2C, MTXMODE_NEW);
    Matrix_MultiplyVector3fByState(&this->unk_35C, &sp2C);
    Math_Vec3f_Copy(&this->unk_35C, &sp2C);
    Math3D_CrossProduct(&this->unk_35C, &sp38, &this->unk_350);

    temp_f0 = Math3D_Vec3fMagnitude(&this->unk_350);
    if (temp_f0 < 0.001f) {
        return false;
    }

    Math_Vec3f_Scale(&this->unk_350, 1.0f / temp_f0);
    Math_Vec3f_Copy(&this->unk_368, &sp38);

    return true;
}

void func_808D93BC(EnSw* this) {
    MtxF sp18;

    sp18.xx = this->unk_35C.x;
    sp18.xy = this->unk_35C.y;
    sp18.xz = this->unk_35C.z;
    sp18.yx = this->unk_368.x;
    sp18.yy = this->unk_368.y;
    sp18.yz = this->unk_368.z;
    sp18.zx = this->unk_350.x;
    sp18.zy = this->unk_350.y;
    sp18.zz = this->unk_350.z;
    func_8018219C(&sp18, &this->actor.world.rot, 0);
    this->actor.world.rot.x = -this->actor.world.rot.x;
}

s32 func_808D9440(GlobalContext* globalCtx, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, CollisionPoly** arg4, u32* arg5) {
    s32 ret = false;

    if (func_800C55C4(&globalCtx->colCtx, arg1, arg2, arg3, arg4, 1, 1, 1, 1, arg5) &&
        !(func_800C9A4C(&globalCtx->colCtx, *arg4, *arg5) & 0x30)) {
        ret = true;
    }
    return ret;
}

#ifdef NON_MATCHING
void func_808D94D0(EnSw* this, GlobalContext* globalCtx, s32 arg2, s32 arg3, s16 arg4) {
    CollisionPoly* spA4;
    CollisionPoly* spA0;
    s32 pad;
    Vec3f sp90;
    Vec3f sp84;
    Vec3f sp78;
    Vec3f sp6C;
    u32 sp68;
    u32 sp64;
    Actor* thisx = &this->actor;
    f32 temp_f20;
    s32 i;

    spA4 = NULL;
    spA0 = NULL;
    sp68 = 50;
    sp64 = 50;
    func_808D90F0(this, arg3, arg4);
    this->actor.speedXZ = this->unk_44C;
    temp_f20 = thisx->speedXZ * 2.0f;

    sp90.x = this->actor.world.pos.x + (this->unk_368.x * 2.0f);
    sp90.y = this->actor.world.pos.y + (this->unk_368.y * 2.0f);
    sp90.z = this->actor.world.pos.z + (this->unk_368.z * 2.0f);

    sp84.x = this->actor.world.pos.x - (this->unk_368.x * 4.0f);
    sp84.y = this->actor.world.pos.y - (this->unk_368.y * 4.0f);
    sp84.z = this->actor.world.pos.z - (this->unk_368.z * 4.0f);

    if (func_808D9440(globalCtx, &sp90, &sp84, &sp6C, &spA0, &sp68)) {
        sp84.x = (this->unk_350.x * temp_f20) + sp90.x;
        sp84.y = (this->unk_350.y * temp_f20) + sp90.y;
        sp84.z = (this->unk_350.z * temp_f20) + sp90.z;
        if (func_808D9440(globalCtx, &sp90, &sp84, &sp78, &spA4, &sp64)) {
            func_808D91C4(this, spA4);
            Math_Vec3f_Copy(&this->actor.world.pos, &sp78);
            this->actor.floorBgId = sp64;
            this->actor.speedXZ = 0.0f;
        } else {
            if (spA0 != this->actor.floorPoly) {
                func_808D91C4(this, spA0);
            }
            Math_Vec3f_Copy(&this->actor.world.pos, &sp6C);
            this->actor.floorBgId = sp68;
        }
    } else {
        this->actor.speedXZ = 0.0f;
        temp_f20 *= 3.0f;
        Math_Vec3f_Copy(&sp90, &sp84);

        for (i = 0; i < 3; i++) {
            if (i == 0) {
                if (this && this && this) {}
                sp84.x = sp90.x - (this->unk_350.x * temp_f20);
                sp84.y = sp90.y - (this->unk_350.y * temp_f20);
                sp84.z = sp90.z - (this->unk_350.z * temp_f20);
            } else if (i == 1) {
                sp84.x = sp90.x + (this->unk_35C.x * temp_f20);
                sp84.y = sp90.y + (this->unk_35C.y * temp_f20);
                sp84.z = sp90.z + (this->unk_35C.z * temp_f20);
            } else {
                sp84.x = sp90.x - (this->unk_35C.x * temp_f20);
                sp84.y = sp90.y - (this->unk_35C.y * temp_f20);
                sp84.z = sp90.z - (this->unk_35C.z * temp_f20);
            }

            if (func_808D9440(globalCtx, &sp90, &sp84, &sp78, &spA4, &sp64)) {
                func_808D91C4(this, spA4);
                Math_Vec3f_Copy(&this->actor.world.pos, &sp78);
                this->actor.floorBgId = sp64;
                break;
            }
        }
    }

    func_808D93BC(this);
    this->actor.shape.rot.x = -this->actor.world.rot.x;
    this->actor.shape.rot.y = this->actor.world.rot.y;
    this->actor.shape.rot.z = this->actor.world.rot.z;

    if (this->actor.speedXZ != 0.0f) {
        this->unk_44C = this->actor.speedXZ;
    }

    if (arg2 == 1) {
        Actor_SetVelocityAndMoveXYRotation(&this->actor);
    }
}
#else
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Sw/func_808D94D0.s")
#endif

void func_808D9894(EnSw* this, Vec3f* vec) {
    Vec3f sp5C;
    MtxF sp1C;

    sp1C.xx = this->unk_35C.x;
    sp1C.yx = this->unk_35C.y;
    sp1C.zx = this->unk_35C.z;
    sp1C.wx = 0.0f;

    sp1C.xy = this->unk_368.x;
    sp1C.yy = this->unk_368.y;
    sp1C.zy = this->unk_368.z;
    sp1C.wy = 0.0f;

    sp1C.xz = this->unk_350.x;
    sp1C.yz = this->unk_350.y;
    sp1C.zz = this->unk_350.z;
    sp1C.wz = 0.0f;

    sp1C.xw = 0.0f;
    sp1C.yw = 0.0f;
    sp1C.zw = 0.0f;
    sp1C.ww = 0.0f;

    Matrix_SetCurrentState(&sp1C);
    sp5C.x = vec->x - this->actor.world.pos.x;
    sp5C.y = vec->y - this->actor.world.pos.y;
    sp5C.z = vec->z - this->actor.world.pos.z;
    Matrix_MultiplyVector3fByState(&sp5C, vec);
}

s32 func_808D9968(EnSw* this, GlobalContext* globalCtx) {
    s32 ret = false;
    u8 param = ENSW_GET_3FC(&this->actor);

    if (ENSW_GET_3(&this->actor)) {
        if ((param != 0x3F) && Actor_GetChestFlag(globalCtx, param)) {
            ret = true;
        }
    }

    return ret;
}

s32 func_808D99C8(EnSw* this, GlobalContext* globalCtx) {
    s32 phi_v1 = 0;

    if (ENSW_GET_3(&this->actor) || (this->unk_458 > 10) || (this->actor.colChkInfo.health == 0)) {
        return false;
    }

    if ((this->actor.xyzDistToPlayerSq < ((sREG(16) * 10) + 60000)) && (globalCtx->actorCtx.unk1F5 != 0) &&
        (globalCtx->actorCtx.unk1F4 == 0)) {
        this->actor.colChkInfo.damage = 4;
        phi_v1 = true;
    }

    return phi_v1;
}

s32 func_808D9A70(EnSw* this, GlobalContext* globalCtx) {
    s16 sp2E = 0;
    f32 frame;

    if (DECR(this->unk_454) == 0) {
        if (!Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
            frame = this->skelAnime.endFrame - this->skelAnime.curFrame;
            sp2E = (80.0f * frame) * this->unk_450;
        } else {
            if (this->unk_456 != 0) {
                if (!ENSW_GET_3(&this->actor)) {
                    Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_ROLL);
                } else {
                    Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALGOLD_ROLL);
                }
                this->unk_456--;
                this->skelAnime.curFrame = 0.0f;
            } else {
                this->unk_454 = Rand_S16Offset(20, 20);
                this->unk_456 = (Rand_ZeroOne() * 10.0f) + 3.0f;
            }

            if (this->unk_456 % 2) {
                if (Rand_ZeroOne() < 0.5f) {
                    this->unk_450 = -1.0f;
                } else {
                    this->unk_450 = 1.0f;
                }
            }
        }
        func_808D94D0(this, globalCtx, 0, 0, sp2E);
    }

    return false;
}

s32 func_808D9C18(EnSw* this) {
    Vec3f sp3C;
    Vec3f sp30;
    f32 new_var;

    if ((this->unk_498 == 0xF9) || (this->unk_498 == 0x82) || (this->unk_498 == 0xE4) || (this->unk_498 == 0xE5)) {
        this->actor.velocity.x = this->actor.speedXZ;
        this->actor.velocity.z = this->actor.speedXZ;
        this->actor.velocity.x *= Math_SinS(this->actor.world.rot.y);
        this->actor.velocity.z *= Math_CosS(this->actor.world.rot.y);
    } else {
        new_var = this->actor.speedXZ * this->unk_350.x;
        this->actor.velocity.x = new_var + (this->actor.speedXZ * this->unk_368.x);
        new_var = this->actor.speedXZ * this->unk_350.z;
        this->actor.velocity.z = new_var + this->actor.speedXZ * this->unk_368.z;
        this->actor.velocity.y = 14.0f;
        Math_Vec3f_Copy(&sp3C, &this->actor.world.pos);
        Math_Vec3f_Copy(&sp30, &this->actor.world.pos);
        sp30.x += this->actor.velocity.x;
        sp30.y += this->actor.velocity.y;
        sp30.z += this->actor.velocity.z;
        this->actor.world.rot.x = 0;
        this->actor.world.rot.z = 0;
        this->actor.world.rot.y = Math_Vec3f_Yaw(&sp3C, &sp30);
    }

    Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTURA_APPEAR);

    if (ENSW_GET_3(&this->actor) == 1) {
        Actor_SetScale(&this->actor, 0.0f);
        this->actor.world.rot.x = 0;
        this->actor.world.rot.z = 0;
        Math_Vec3s_Copy(&this->actor.shape.rot, &this->actor.world.rot);
        this->unk_410 |= 4;
    }

    this->actor.gravity = -1.4f;
    this->actor.parent = NULL;
    return false;
}

void func_808D9DA0(EnSw* this) {
    static Vec3f D_808DBAAC = { 0.0f, 1.0f, 0.0f };
    s32 pad;
    MtxF sp24;

    SkinMatrix_SetRotateYRP(&sp24, this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z);
    SkinMatrix_Vec3fMtxFMultXYZ(&sp24, &D_808DBAAC, &this->unk_368);
    this->unk_350.x = Math_SinS(this->actor.shape.rot.y);
    this->unk_350.y = 0.0f;
    this->unk_350.z = Math_CosS(this->actor.shape.rot.y);
    this->unk_35C.x = Math_SinS(BINANG_ADD(this->actor.shape.rot.y, 0x4000));
    this->unk_35C.y = 0.0f;
    this->unk_35C.z = Math_CosS(BINANG_ADD(this->actor.shape.rot.y, 0x4000));
}

void func_808D9E44(EnSw* this) {
    Vec3f sp1C;

    this->actor.shape.rot.z = -0x8000;
    this->actor.shape.rot.x = 0;
    this->actor.shape.rot.y = 0;
    Math_Vec3s_Copy(&this->actor.world.rot, &this->actor.shape.rot);
    this->actor.gravity = -1.4f;
    this->actor.velocity.y = 0.0f;
    this->unk_456 = 2;
    Math_Vec3f_Copy(&sp1C, &this->actor.world.pos);
    sp1C.x += this->unk_368.x * 16.0f;
    sp1C.y += this->unk_368.y * 16.0f;
    sp1C.z += this->unk_368.z * 16.0f;
    Math_Vec3f_Copy(&this->actor.world.pos, &sp1C);
}

void func_808D9F08(EnSw* this) {
    this->unk_454 = Rand_S16Offset(20, 20);
    this->unk_456 = (Rand_ZeroOne() * 10.0f) + 3.0f;
    this->unk_414 = 0.0f;
    this->unk_45E = this->unk_460;
}

void func_808D9F78(EnSw* this, GlobalContext* globalCtx, s32 arg2) {
    if (arg2 != 0) {
        func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, 5);
    }
    Actor_SetScale(&this->actor, 0.02f);
    func_808D9DA0(this);
    this->actor.speedXZ = 10.0f;
    this->unk_44C = 10.0f;
    func_808D94D0(this, globalCtx, 0, 0, 0);
    this->actor.speedXZ = 0.0f;
    this->unk_44C = 0.0f;
    this->unk_450 = 1.0f;
    Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos);
    this->unk_410 |= 4;
}

void func_808DA024(EnSw* this, GlobalContext* globalCtx) {
    func_808D9DA0(this);
    this->actor.speedXZ = 10.0f;
    this->unk_44C = 10.0f;
    func_808D94D0(this, globalCtx, 0, 0, 0);
    this->actor.speedXZ = 0.0f;
    this->unk_44C = 0.0f;
    this->unk_450 = 1.0f;
}

s32 func_808DA08C(EnSw* this, GlobalContext* globalCtx) {
    s32 ret = 0;
    s32 i;

    if (func_808D99C8(this, globalCtx) || (this->collider.base.acFlags & AC_HIT)) {
        this->collider.base.acFlags &= ~AC_HIT;

        if (this->actor.colChkInfo.damageEffect == 4) {
            Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x,
                        this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS);
        }

        if (this->unk_412 == 10) {
            // clang-format off
            for (i = 0; i < ARRAY_COUNT(this->unk_464); i++) { this->unk_464[i] = 0; }
            // clang-format on

            this->unk_45C = 0;
        } else if (!func_808D90C4(this)) {
            Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EN_STALTU_DEAD);
            Enemy_StartFinishingBlow(globalCtx, &this->actor);
            this->actor.flags &= ~1;
            if (!ENSW_GET_3(&this->actor)) {
                func_8013BC6C(&this->skelAnime, sAnimations, 3);
            }

            switch (this->actor.colChkInfo.damageEffect) {
                case 4:
                    this->unk_412 = 20;
                    this->unk_45C = 20;
                    func_808D8B58(this);
                    break;

                case 3:
                    this->unk_412 = 10;
                    this->unk_45C = 0;
                    func_808D8B58(this);
                    break;

                case 2:
                    this->unk_412 = 0;
                    this->unk_45C = 20;
                    func_808D8B58(this);
                    break;

                case 5:
                    this->unk_412 = 30;
                    this->unk_45C = 20;
                    func_808D8B58(this);
                    break;

                default:
                    this->unk_412 = 1;
                    this->unk_45C = 0;
                    break;
            }

            if (!ENSW_GET_3(&this->actor) && (this->unk_412 != 10)) {
                func_808D9E44(this);
            }
            this->unk_458 = 20;
            this->unk_45A = 0;
            func_800BCB70(&this->actor, 0x4000, 200, 0, this->unk_458);
            ret = true;
        } else if (this->actor.colChkInfo.damageEffect == 1) {
            if (this->unk_45A == 0) {
                Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE);
                this->unk_45A = 40;
                func_800BCB70(&this->actor, 0, 200, 0, this->unk_45A);
            }
        } else {
            Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_DAMAGE);
            this->unk_458 = 20;
            this->unk_45A = 0;
            func_800BCB70(&this->actor, 0x4000, 200, 0, this->unk_458);
        }
    }
    return ret;
}

void func_808DA350(EnSw* this, GlobalContext* globalCtx) {
    Player* player = GET_PLAYER(globalCtx);

    if ((player->stateFlags1 & 0x200000) && (this->actor.xyzDistToPlayerSq < 8000.0f)) {
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_LAUGH);
        Math_Vec3f_Copy(&this->unk_374, &player->actor.world.pos);
        this->unk_410 &= ~0x20;
        this->unk_414 = 0.0f;
        this->actionFunc = func_808DA3F4;
    } else {
        func_808D9A70(this, globalCtx);
    }
}

void func_808DA3F4(EnSw* this, GlobalContext* globalCtx) {
    s16 temp_v0;
    s16 temp_s1 = 0;
    Vec3f sp38;
    f32 temp_f16;

    if (!Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
        temp_f16 = this->skelAnime.endFrame - this->skelAnime.curFrame;
        temp_s1 = (s16)(80.0f * temp_f16);
        Math_Vec3f_Copy(&sp38, &this->unk_374);
        func_808D9894(this, &sp38);

        temp_v0 = Math_FAtan2F(sp38.z, sp38.x);
        if (ABS_ALT(temp_v0) < temp_s1) {
            this->skelAnime.curFrame = 0.0f;
            Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DASH);
            this->unk_414 = 0.0f;
            if (this->unk_410 & 0x20) {
                this->actionFunc = func_808DA6FC;
            } else {
                this->actionFunc = func_808DA578;
            }
            temp_s1 = ABS_ALT(temp_v0);
        }
        temp_s1 *= (temp_v0 < 0) ? -1 : 1;
    } else {
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_ROLL);
        this->skelAnime.curFrame = 0.0f;
    }
    func_808D94D0(this, globalCtx, 0, 0, temp_s1);
}

#ifdef NON_MATCHING
void func_808DA578(EnSw* this, GlobalContext* globalCtx) {
    f32 temp_f0;
    s32 test;
    s32 test2;
    Vec3f sp30;

    if (!Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
        temp_f0 = this->skelAnime.endFrame - this->skelAnime.curFrame;
        this->unk_44C = 0.3f * temp_f0;
        func_808D94D0(this, globalCtx, 1, 0, 0);
        if ((this->actor.speedXZ == 0.0f) && (this->unk_44C != 0.0f)) {
            Math_Vec3f_Copy(&sp30, &this->unk_374);
            func_808D9894(this, &sp30);
            func_808D94D0(this, globalCtx, 0, 0, Math_FAtan2F(sp30.z, sp30.x));
        }
    } else if (this->unk_410 & 0x20) {
        Math_Vec3f_Copy(&this->unk_374, &this->actor.home.pos);
        this->actionFunc = func_808DA3F4;
    } else {
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DASH);
        this->skelAnime.curFrame = 0.0f;
    }

    temp_f0 = Math_Vec3f_DistXYZ(&this->actor.world.pos, &this->unk_374);
    if (!(this->unk_410 & 0x20)) {
        test = this->unk_414;
        test2 = temp_f0;
        if ((test != 0) && (test < test2)) {
            this->unk_410 |= 0x20;
        }
    }
    this->unk_414 = temp_f0;
}
#else
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Sw/func_808DA578.s")
#endif

#ifdef NON_MATCHING
void func_808DA6FC(EnSw* this, GlobalContext* globalCtx) {
    f32 sp4C;
    s32 temp;
    s32 temp2;
    Vec3f sp38;
    f32 temp_f0;

    if (!Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
        temp_f0 = this->skelAnime.endFrame - this->skelAnime.curFrame;
        this->unk_44C = 0.14f * temp_f0;
        func_808D94D0(this, globalCtx, 1, 0, 0);
        if ((this->actor.speedXZ == 0.0f) && (this->unk_44C != 0.0f)) {
            Math_Vec3f_Copy(&sp38, &this->unk_374);
            func_808D9894(this, &sp38);
            func_808D94D0(this, globalCtx, 0, 0, Math_FAtan2F(sp38.z, sp38.x));
        }
    } else {
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DASH);
        this->skelAnime.curFrame = 0.0f;
    }

    sp4C = Math_Vec3f_DistXYZ(&this->actor.world.pos, &this->unk_374);
    temp = this->unk_414;
    temp2 = sp4C;
    if ((temp != 0) && (temp < temp2)) {
        Math_Vec3f_Copy(&this->actor.world.pos, &this->unk_374);
        this->unk_454 = Rand_S16Offset(20, 20);
        this->unk_456 = (Rand_ZeroOne() * 10.0f) + 3.0f;
        this->actionFunc = func_808DA350;
        this->skelAnime.curFrame = 0.0f;
    }
    this->unk_414 = sp4C;
}
#else
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Sw/func_808DA6FC.s")
#endif

void func_808DA89C(EnSw* this, GlobalContext* globalCtx) {
    if (this->unk_412 == 10) {
        s32 i;
        s32 count;
        s16 phi_a0;

        for (i = 0, count = 0; i < ARRAY_COUNT(this->unk_464); i++) {
            if (this->unk_464[i] == 0) {
                phi_a0 = 0;
            } else {
                this->unk_464[i]--;
                phi_a0 = this->unk_464[i];
            }
            if (phi_a0 == 0) {
                count++;
            }
        }

        if (count == ARRAY_COUNT(this->unk_464)) {
            if (!ENSW_GET_3(&this->actor)) {
                func_808D9E44(this);
            }
            this->unk_412 = 1;
            func_808D8ED0(this, globalCtx);
        }
        return;
        if (1) {}
    }

    if (ENSW_GET_3(&this->actor)) {
        this->actionFunc = func_808DAEB4;
        return;
    }

    if (this->actor.bgCheckFlags & 1) {
        f32 temp_f2;

        this->actor.shape.yOffset = 400.0f;
        temp_f2 = fabsf(this->actor.velocity.y) * 0.6f;
        this->actor.velocity.y = temp_f2;
        this->unk_448 = temp_f2;
        this->actor.speedXZ = 0.0f;
        if ((s32)temp_f2 != 0) {
            Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTURA_BOUND);
        } else {
            this->actionFunc = func_808DAEB4;
            this->actor.velocity.y = 0.0f;
        }
        if ((s32)this->actor.velocity.y >= 2) {
            func_808D8940(this, globalCtx);
        }
    } else {
        Math_ApproachF(&this->actor.shape.yOffset, 400.0f, 0.3f, 1000.0f);
    }

    Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
    Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 12.0f, 0.0f, 4);
}

void func_808DAA60(EnSw* this, GlobalContext* globalCtx) {
    Vec3s* sp44;
    s16 temp_v0;
    s16 sp40;
    Vec3f sp34;
    f32 temp_f16;

    sp44 = (Vec3s*)Lib_SegmentedToVirtual(this->unk_1E4->points);
    sp40 = 0;

    if (DECR(this->unk_454) == 0) {
        if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) == 0) {
            temp_f16 = this->skelAnime.endFrame - this->skelAnime.curFrame;
            sp40 = 80.0f * temp_f16;
            if (this->unk_45E == 0) {
                Math_Vec3s_ToVec3f(&sp34, &sp44[this->unk_4A0]);
                func_808D9894(this, &sp34);
                temp_v0 = Math_FAtan2F(sp34.z, sp34.x);
                if (ABS_ALT(temp_v0) < sp40) {
                    this->skelAnime.curFrame = 0.0f;
                    Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DASH);
                    Math_Vec3s_ToVec3f(&this->unk_374, &sp44[this->unk_4A0]);
                    this->actionFunc = func_808DACF4;
                    this->unk_414 = 0.0f;
                    sp40 = ABS_ALT(temp_v0);
                }
                sp40 *= (temp_v0 < 0) ? -1 : 1;
            }
        } else {
            if (this->unk_456 != 0) {
                Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALGOLD_ROLL);
                this->unk_456--;
                this->skelAnime.curFrame = 0.0f;
            } else {
                this->unk_454 = Rand_S16Offset(20, 20);
                this->unk_456 = (Rand_ZeroOne() * 10.0f) + 3.0f;
                if (this->unk_45E != 0) {
                    this->unk_45E--;
                }
            }

            if (this->unk_456 % 2) {
                if (Rand_ZeroOne() < 0.5f) {
                    this->unk_450 = -1.0f;
                } else {
                    this->unk_450 = 1.0f;
                }
            }
        }
    }
    func_808D94D0(this, globalCtx, 0, 0, sp40);
}

#ifdef NON_MATCHING
void func_808DACF4(EnSw* this, GlobalContext* globalCtx) {
    f32 sp4C;
    f32 temp_f0;
    s32 temp_f6;

    if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) == 0) {
        Vec3f sp38;
        f32 temp;

        temp = this->skelAnime.endFrame - this->skelAnime.curFrame;
        this->unk_44C = 0.1f * temp;
        func_808D94D0(this, globalCtx, 1, 0, 0);
        if ((this->actor.speedXZ == 0.0f) && (this->unk_44C != 0.0f)) {

            Math_Vec3f_Copy(&sp38, &this->unk_374);
            func_808D9894(this, &sp38);
            func_808D94D0(this, globalCtx, 0, 0, Math_FAtan2F(sp38.z, sp38.x));
        }
    } else {
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DASH);
        this->skelAnime.curFrame = 0.0f;
    }

    sp4C = Math_Vec3f_DistXYZ(&this->actor.world.pos, &this->unk_374);
    temp_f6 = this->unk_414;
    if ((temp_f6 != 0) && (temp_f6 < (s32)sp4C)) {
        Math_Vec3f_Copy(&this->actor.world.pos, &this->unk_374);
        this->unk_4A0 += this->unk_49C;
        if ((this->unk_4A0 >= this->unk_1E4->count) || (this->unk_4A0 < 0)) {
            this->unk_49C = -this->unk_49C;
            this->unk_4A0 += this->unk_49C * 2;
        }

        if (this->unk_410 & 8) {
            func_808D9F08(this);
            this->actionFunc = func_808DAA60;
        } else {
            this->actionFunc = func_808DB100;
        }
    }
    this->unk_414 = sp4C;
}
#else
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Sw/func_808DACF4.s")
#endif

void func_808DAEB4(EnSw* this, GlobalContext* globalCtx) {
    Vec3f sp5C;
    s32 i;
    s32 count;
    s16 phi_a0;

    if (this->unk_410 & 2) {
        if (!ENSW_GET_3(&this->actor)) {
            if (this->unk_410 & 4) {
                phi_a0 = DECR(this->unk_45C);
                if (phi_a0 == 0) {
                    this->unk_410 &= ~4;
                }
            }

            for (i = 0, count = 0; i < ARRAY_COUNT(this->unk_464); i++) {
                if (this->unk_464[i] == 0) {
                    phi_a0 = 0;
                } else {
                    this->unk_464[i]--;
                    phi_a0 = this->unk_464[i];
                }
                if (phi_a0 == 0) {
                    count++;
                }
            }

            if (count == ARRAY_COUNT(this->unk_464)) {
                Actor_MarkForDeath(&this->actor);
            }
        } else {
            Math_ApproachF(&this->actor.scale.x, 0.0f, 0.08f, 1.0f);
            Actor_SetScale(&this->actor, this->actor.scale.x);
            if ((s32)(this->actor.scale.x * 100.0f) == 0) {

                Math_Vec3f_Copy(&sp5C, &this->actor.world.pos);
                sp5C.x += this->unk_368.x * 10.0f;
                sp5C.y += this->unk_368.y * 10.0f;
                sp5C.z += this->unk_368.z * 10.0f;
                if (Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_SI, sp5C.x, sp5C.y,
                                       sp5C.z, 0, 0, 0, this->actor.params) != NULL) {
                    play_sound(NA_SE_SY_KINSTA_MARK_APPEAR);
                }
                Actor_MarkForDeath(&this->actor);
            }
            func_808D94D0(this, globalCtx, 0, 0, 0x1554);
        }
    } else {
        phi_a0 = DECR(this->unk_45C);
        if (phi_a0 == 0) {
            this->unk_410 |= 2;
            if (!ENSW_GET_3(&this->actor) && (this->unk_412 == 1)) {
                func_808D8B58(this);
                this->unk_45C = 10;
            } else {
                this->unk_45C = 20;
            }
        }
    }
}

void func_808DB100(EnSw* this, GlobalContext* globalCtx) {
    if (this->actor.parent != NULL) {
        this->unk_498 = this->actor.parent->id;
        this->unk_456 = 0;
        this->unk_454 = 0;
        this->skelAnime.curFrame = 0.0f;
        func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, 4);
        this->actionFunc = func_808DB25C;
        return;
    }

    if (!(this->unk_410 & 1)) {
        func_808D9A70(this, globalCtx);
        return;
    }

    if ((DECR(this->unk_454) == 0) && Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
        if (this->unk_456 != 0) {
            if (!ENSW_GET_3(&this->actor)) {
                Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_ROLL);
            } else {
                Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALGOLD_ROLL);
            }
            this->unk_456--;
            this->skelAnime.curFrame = 0.0f;
        } else {
            this->unk_454 = Rand_S16Offset(20, 20);
            this->unk_456 = (Rand_ZeroOne() * 10.0f) + 3.0f;
        }
    }
}

void func_808DB25C(EnSw* this, GlobalContext* globalCtx) {
    if (ActorCutscene_GetCurrentIndex() == 0x7C) {
        ActorCutscene_Stop(0x7C);
    } else if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
        ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor);
        func_808D9C18(this);
        this->actionFunc = func_808DB2E0;
    } else {
        ActorCutscene_SetIntentToPlay(this->actor.cutscene);
    }
}

void func_808DB2E0(EnSw* this, GlobalContext* globalCtx) {
    f32 temp_f2;

    if (this->actor.bgCheckFlags & 1) {
        func_808D9F78(this, globalCtx, 0);
        temp_f2 = fabsf(this->actor.velocity.y) * 0.6f;
        this->actor.velocity.x *= 0.5f;
        this->actor.velocity.y = temp_f2;
        this->unk_448 = temp_f2;
        this->actor.velocity.z *= 0.5f;

        if ((s32)temp_f2 != 0) {
            Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTURA_BOUND);
        } else {
            func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, 5);
            Math_Vec3f_Copy(&this->actor.velocity, &D_801D15B0);
            this->unk_410 &= ~(0x10 | 0x1);
            this->actionFunc = func_808DB100;
        }

        if ((s32)this->actor.velocity.y >= 2) {
            func_808D8940(this, globalCtx);
        }
    }

    Math_ApproachF(&this->actor.scale.x, 0.02f, 0.4f, 1.0f);
    Actor_SetScale(&this->actor, this->actor.scale.x);
    this->actor.velocity.y += this->actor.gravity;
    Actor_ApplyMovement(&this->actor);
    Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 12.0f, 0.0f, 4);
}

void EnSw_Init(Actor* thisx, GlobalContext* globalCtx) {
    EnSw* this = THIS;
    s32 pad;

    if (!func_808D9968(this, globalCtx)) {
        ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
        SkelAnime_Init(globalCtx, &this->skelAnime, &D_06005298, NULL, this->jointTable, this->morphTable, 30);
        func_8013BC6C(&this->skelAnime, sAnimations, 0);
        this->skelAnime.playSpeed = 4.0f;

        Collider_InitAndSetSphere(globalCtx, &this->collider, &this->actor, &sSphereInit);
        if (!ENSW_GET_3(&this->actor)) {
            this->actor.hintId = 0x1F;
            CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
            this->collider.info.toucher.damage = 8;
        } else {
            this->actor.hintId = 0x20;
            CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable2, &sColChkInfoInit2);
            this->collider.info.toucher.damage = 16;
        }

        this->unk_1E4 = func_8013BEDC(globalCtx, ENSW_GET_FF00(&this->actor), 255, &this->unk_4A0);
        if (this->unk_1E4 != NULL) {
            this->unk_4A0 = 1;
        }

        switch (ENSW_GET_3(&this->actor)) {
            case 0:
                func_808D9F78(this, globalCtx, 1);
                this->actionFunc = func_808DA350;
                break;

            case 1:
                this->actor.flags &= ~1;
                this->actor.flags |= 0x10;

                if (this->actor.world.rot.z < 0) {
                    this->unk_460 = -thisx->world.rot.z;
                } else {
                    this->unk_460 = thisx->world.rot.z;
                }

                if (this->actor.world.rot.z >= 0) {
                    this->unk_410 |= 8;
                }

                func_808DA024(this, globalCtx);
                this->unk_410 |= (0x10 | 0x1);
                this->unk_410 &= ~4;
                this->actionFunc = func_808DB100;
                break;

            case 2:
            case 3:
                this->actor.flags &= ~1;
                this->actor.flags |= 0x10;

                if (this->actor.world.rot.z < 0) {
                    this->unk_460 = -thisx->world.rot.z;
                } else {
                    this->unk_460 = thisx->world.rot.z;
                }

                if (this->actor.world.rot.z >= 0) {
                    this->unk_410 |= 8;
                }

                func_808D9F78(this, globalCtx, 1);
                if (this->unk_1E4 != NULL) {
                    this->unk_49C = 1;
                    func_808D9F08(this);
                    this->actionFunc = func_808DAA60;
                } else {
                    this->actionFunc = func_808DB100;
                }
                break;
        }
    } else {
        Actor_MarkForDeath(&this->actor);
    }
}

void EnSw_Destroy(Actor* thisx, GlobalContext* globalCtx) {
    EnSw* this = THIS;

    Collider_DestroySphere(globalCtx, &this->collider);
}

void EnSw_Update(Actor* thisx, GlobalContext* globalCtx) {
    EnSw* this = THIS;

    if (func_808DA08C(this, globalCtx)) {
        this->actionFunc = func_808DA89C;
    } else if (DECR(this->unk_45A) == 0) {
        this->actionFunc(this, globalCtx);
    }

    if ((this->unk_412 != 10) || (this->unk_45A != 0)) {
        SkelAnime_Update(&this->skelAnime);
    }

    Actor_SetHeight(&this->actor, 0.0f);
    func_808D8FC4(this, globalCtx);
}

s32 EnSw_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
    EnSw* this = THIS;

    if (ENSW_GET_3(&this->actor)) {
        switch (limbIndex) {
            case 23:
                *dList = D_06004788;
                break;

            case 8:
                *dList = D_060046F0;
                break;

            case 14:
                *dList = D_06004658;
                break;

            case 11:
                *dList = D_060045C0;
                break;

            case 26:
                *dList = D_06004820;
                break;

            case 20:
                *dList = D_060048B8;
                break;

            case 17:
                *dList = D_06004950;
                break;

            case 29:
                *dList = D_060049E8;
                break;

            case 5:
                *dList = D_06003FB0;
                break;

            case 4:
                *dList = D_060043D8;
                break;
        }
    }
    return false;
}

void EnSw_Draw(Actor* thisx, GlobalContext* globalCtx) {
    EnSw* this = THIS;
    s32 i;
    s32 count;

    if (this->unk_410 & 4) {
        if (ENSW_GET_3(&this->actor)) {
            func_800B8050(&this->actor, globalCtx, MTXMODE_NEW);
        }
        func_8012C28C(globalCtx->state.gfxCtx);
        Matrix_InsertXRotation_s(-0x3C72, MTXMODE_APPLY);
        SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnSw_OverrideLimbDraw, NULL,
                          &this->actor);
    }

    for (i = 0, count = 0; i < ARRAY_COUNT(this->unk_464); i++) {
        count += func_808D8D60(this, globalCtx, i);
    }

    if (count != 0) {
        this->unk_462 += 3;
    }
}
