/*
 * File: z_en_ru2.c
 * Overlay: En_Ru2
 * Description: Adult Ruto
 */

#include "z_en_ru2.h"
#include <vt.h>

#define FLAGS 0x00000010

#define THIS ((EnRu2*)thisx)

void EnRu2_Init(Actor* thisx, GlobalContext* globalCtx);
void EnRu2_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnRu2_Update(Actor* thisx, GlobalContext* globalCtx);
void EnRu2_Draw(Actor* thisx, GlobalContext* globalCtx);

void func_80AF2CB4(EnRu2* this, GlobalContext* globalCtx);
void func_80AF2CD4(EnRu2* this, GlobalContext* globalCtx);
void func_80AF2CF4(EnRu2* this, GlobalContext* globalCtx);
void func_80AF2D2C(EnRu2* this, GlobalContext* globalCtx);
void func_80AF2D6C(EnRu2* this, GlobalContext* globalCtx);
void func_80AF2DAC(EnRu2* this, GlobalContext* globalCtx);
void func_80AF2DEC(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3144(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3174(EnRu2* this, GlobalContext* globalCtx);
void func_80AF31C8(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3604(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3624(EnRu2* this, GlobalContext* globalCtx);
void func_80AF366C(EnRu2* this, GlobalContext* globalCtx);
void func_80AF36AC(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3BC8(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3C04(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3C64(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3CB8(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3D0C(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3D60(EnRu2* this, GlobalContext* globalCtx);

void func_80AF3F14(EnRu2* this, GlobalContext* globalCtx);
void func_80AF3F20(EnRu2* this, GlobalContext* globalCtx);
void func_80AF321C(EnRu2* this, GlobalContext* globalCtx);

void func_80AF2AB4(EnRu2* this, GlobalContext* globalCtx);

static ColliderCylinderInit_Set3 sCylinderInit = {
    { COLTYPE_UNK10, 0x00, 0x09, 0x00, COLSHAPE_CYLINDER },
    { 0x00, { 0x00000000, 0x00, 0x00 }, { 0x00000080, 0x00, 0x00 }, 0x00, 0x01, 0x00 },
    { 30, 100, 0, { 0 } },
};

static UNK_PTR D_80AF410C[] = {
    0x06000F20,
    0x060022E0,
    0x06002AE0,
};

static UNK_TYPE D_80AF4118 = 0;

#include "z_en_ru2_cutscene_data.c" EARLY

static EnRu2ActionFunc sActionFuncs[] = {
    func_80AF2CB4, func_80AF2CD4, func_80AF2CF4, func_80AF2D2C, func_80AF2D6C, func_80AF2DAC, func_80AF2DEC,
    func_80AF3144, func_80AF3174, func_80AF31C8, func_80AF3604, func_80AF3624, func_80AF366C, func_80AF36AC,
    func_80AF3BC8, func_80AF3C04, func_80AF3C64, func_80AF3CB8, func_80AF3D0C, func_80AF3D60,
};

static EnRu2DrawFunc sDrawFuncs[] = {
    func_80AF3F14,
    func_80AF3F20,
    func_80AF321C,
};

const ActorInit En_Ru2_InitVars = {
    ACTOR_EN_RU2,
    ACTORTYPE_NPC,
    FLAGS,
    OBJECT_RU2,
    sizeof(EnRu2),
    (ActorFunc)EnRu2_Init,
    (ActorFunc)EnRu2_Destroy,
    (ActorFunc)EnRu2_Update,
    (ActorFunc)EnRu2_Draw,
};

extern AnimationHeader D_060004CC;
extern SkeletonHeader D_0600C700;
extern AnimationHeader D_0600D3DC;
extern AnimationHeader D_0600DCAC;
extern AnimationHeader D_06000DE8;
extern AnimationHeader D_0600E630;
extern AnimationHeader D_0600F03C;
extern AnimationHeader D_0600F8B8;

void func_80AF2550(Actor* thisx, GlobalContext* globalCtx) {
    EnRu2* this = THIS;

    Collider_InitCylinder(globalCtx, &this->collider);
    Collider_SetCylinder_Set3(globalCtx, &this->collider, &this->actor, &sCylinderInit);
}

void func_80AF259C(EnRu2* this, GlobalContext* globalCtx) {
    s32 pad;
    ColliderCylinder* collider = &this->collider;
    Actor* thisx = &this->actor;
    s32 pad2[2];

    Collider_CylinderUpdate(thisx, collider);
    CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, collider);
}

void EnRu2_Destroy(Actor* thisx, GlobalContext* globalCtx) {
    EnRu2* this = THIS;

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

void func_80AF2608(EnRu2* this) {
    s32 pad[3];
    s16* unk_2A6 = &this->unk_2A6;
    s16* unk_2A4 = &this->unk_2A4;

    if (!DECR(*unk_2A6)) {
        *unk_2A6 = Math_Rand_S16Offset(0x3C, 0x3C);
    }

    *unk_2A4 = *unk_2A6;
    if (*unk_2A4 >= 3) {
        *unk_2A4 = 0;
    }
}

s32 func_80AF2690(EnRu2* this) {
    s32 params_shift = this->actor.params >> 8;

    return params_shift & 0xFF;
}

s32 func_80AF26A0(EnRu2* this) {
    s16 params = this->actor.params;

    return params & 0xFF;
}

void func_80AF26AC(EnRu2* this) {
    this->action = 7;
    this->drawConfig = 0;
    this->unk_2B4 = 0;
    this->unk_2B8 = 0;
    this->actor.shape.unk_14 = 0;
    this->unk_2B0 = 0.0f;
}

void func_80AF26D0(EnRu2* this, GlobalContext* globalCtx) {
    s32 one; // Needed to match

    if (globalCtx->csCtx.state == 0) {
        if (D_80AF4118 != 0) {
            if (this->actor.params == 2) {
                func_80AF26AC(this);
            }
            D_80AF4118 = 0;
            return;
        }
    } else {
        one = 1;
        if (D_80AF4118 == 0) {
            D_80AF4118 = one;
        }
    }
}

void func_80AF2744(EnRu2* this, GlobalContext* globalCtx) {
    func_8002E4B4(globalCtx, &this->actor, 75.0f, 30.0f, 30.0f, 4);
}

s32 EnRu2_FrameUpdateMatrix(EnRu2* this) {
    return SkelAnime_FrameUpdateMatrix(&this->skelAnime);
}

CsCmdActorAction* func_80AF27AC(GlobalContext* globalCtx, s32 npcActionIdx) {
    if (globalCtx->csCtx.state != 0) {
        return globalCtx->csCtx.npcActions[npcActionIdx];
    }
    return NULL;
}

s32 func_80AF27D0(EnRu2* this, GlobalContext* globalCtx, u16 arg2, s32 npcActionIdx) {
    CsCmdActorAction* csCmdActorAction = func_80AF27AC(globalCtx, npcActionIdx);

    if (csCmdActorAction != NULL && csCmdActorAction->action == arg2) {
        return 1;
    }
    return 0;
}

s32 func_80AF281C(EnRu2* this, GlobalContext* globalCtx, u16 arg2, s32 npcActionIdx) {
    CsCmdActorAction* csCmdNPCAction = func_80AF27AC(globalCtx, npcActionIdx);

    if (csCmdNPCAction != NULL && csCmdNPCAction->action != arg2) {
        return 1;
    }
    return 0;
}

void func_80AF2868(EnRu2* this, GlobalContext* globalCtx, u32 npcActionIdx) {
    CsCmdActorAction* csCmdNPCAction = func_80AF27AC(globalCtx, npcActionIdx);
    s16 newRotY;
    Actor* thisx = &this->actor;

    if (csCmdNPCAction != NULL) {
        thisx->posRot.pos.x = csCmdNPCAction->startPos.x;
        thisx->posRot.pos.y = csCmdNPCAction->startPos.y;
        thisx->posRot.pos.z = csCmdNPCAction->startPos.z;
        newRotY = csCmdNPCAction->rot.y;
        thisx->shape.rot.y = newRotY;
        thisx->posRot.rot.y = newRotY;
    }
}

void func_80AF28E8(EnRu2* this, AnimationHeader* animation, u8 arg2, f32 transitionRate, s32 arg4) {
    f32 frameCount = SkelAnime_GetFrameCount(&animation->genericHeader);
    f32 playbackSpeed;
    f32 unk0;
    f32 fc;

    if (arg4 == 0) {
        unk0 = 0.0f;
        fc = frameCount;
        playbackSpeed = 1.0f;
    } else {
        unk0 = frameCount;
        fc = 0.0f;
        playbackSpeed = -1.0f;
    }

    SkelAnime_ChangeAnim(&this->skelAnime, animation, playbackSpeed, unk0, fc, arg2, transitionRate);
}

void func_80AF2978(EnRu2* this, GlobalContext* globalCtx) {
    this->actor.shape.unk_08 += 83.333336f;
}

void func_80AF2994(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF28E8(this, &D_06000DE8, 0, 0.0f, 0);
    this->actor.shape.unk_08 = -10000.0f;
}

void func_80AF29DC(EnRu2* this, GlobalContext* globalCtx) {
    Actor* thisx = &this->actor;
    f32 posX = thisx->posRot.pos.x;
    f32 posY = thisx->posRot.pos.y;
    f32 posZ = thisx->posRot.pos.z;

    Actor_SpawnAttached(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DOOR_WARP1, posX, posY, posZ, 0, 0, 0, 2);
}

void func_80AF2A38(EnRu2* this, GlobalContext* globalCtx) {
    Player* player = PLAYER;
    f32 posX = player->actor.posRot.pos.x;
    f32 posY = player->actor.posRot.pos.y + 50.0f;
    f32 posZ = player->actor.posRot.pos.z;

    Actor_SpawnAttached(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
                        10);
    Item_Give(globalCtx, ITEM_MEDALLION_WATER);
}

void func_80AF2AB4(EnRu2* this, GlobalContext* globalCtx) {
    s32 pad[2];
    Player* player;
    s16 temp;

    if (gSaveContext.chamberCutsceneNum == 2 && gSaveContext.sceneSetupIndex < 4) {
        player = PLAYER;
        this->action = 1;
        globalCtx->csCtx.segment = &D_80AF411C;
        gSaveContext.cutsceneTrigger = 2;
        Item_Give(globalCtx, ITEM_MEDALLION_WATER);
        temp = this->actor.posRot.rot.y + 0x8000;
        player->actor.shape.rot.y = temp;
        player->actor.posRot.rot.y = temp;
    }
}

void func_80AF2B44(EnRu2* this, GlobalContext* globalCtx) {
    CutsceneContext* csCtx = &globalCtx->csCtx;
    CsCmdActorAction* csCmdNPCAction;

    if (csCtx->state != 0) {
        csCmdNPCAction = csCtx->npcActions[3];
        if (csCmdNPCAction != NULL && csCmdNPCAction->action == 2) {
            this->action = 2;
            this->drawConfig = 1;
            func_80AF29DC(this, globalCtx);
        }
    }
}

void func_80AF2B94(EnRu2* this) {
    if (this->actor.shape.unk_08 >= 0.0f) {
        this->action = 3;
        this->actor.shape.unk_08 = 0.0f;
    }
}

void func_80AF2BC0(EnRu2* this, GlobalContext* globalCtx) {
    AnimationHeader* animation = &D_0600D3DC;
    CsCmdActorAction* csCmdNPCAction;

    if (globalCtx->csCtx.state != 0) {
        csCmdNPCAction = globalCtx->csCtx.npcActions[3];
        if (csCmdNPCAction != NULL && csCmdNPCAction->action == 3) {
            SkelAnime_ChangeAnim(&this->skelAnime, animation, 1.0f, 0.0f,
                                 SkelAnime_GetFrameCount(&animation->genericHeader), 2, 0.0f);
            this->action = 4;
        }
    }
}

void func_80AF2C54(EnRu2* this, UNK_TYPE arg1) {
    if (arg1 != 0) {
        this->action = 5;
    }
}

void func_80AF2C68(EnRu2* this, GlobalContext* globalCtx) {
    CsCmdActorAction* csCmdNPCAction;

    if (globalCtx->csCtx.state != 0) {
        csCmdNPCAction = globalCtx->csCtx.npcActions[6];
        if (csCmdNPCAction != NULL && csCmdNPCAction->action == 2) {
            this->action = 6;
            func_80AF2A38(this, globalCtx);
        }
    }
}

void func_80AF2CB4(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2AB4(this, globalCtx);
}

void func_80AF2CD4(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2B44(this, globalCtx);
}

void func_80AF2CF4(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2978(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF2B94(this);
}

void func_80AF2D2C(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF2BC0(this, globalCtx);
}

void func_80AF2D6C(EnRu2* this, GlobalContext* globalCtx) {
    UNK_TYPE something;

    func_80AF2744(this, globalCtx);
    something = EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF2C54(this, something);
}

void func_80AF2DAC(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF2C68(this, globalCtx);
}

void func_80AF2DEC(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
}

void func_80AF2E1C(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF28E8(this, &D_060004CC, 2, 0.0f, 0);
    this->action = 7;
    this->actor.shape.unk_14 = 0;
}

void func_80AF2E64() {
    func_800788CC(NA_SE_SY_WHITE_OUT_T);
}

void func_80AF2E84(EnRu2* this, GlobalContext* globalCtx) {
    Actor_SpawnAttached(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DEMO_6K, this->actor.posRot.pos.x,
                        kREG(19) + 24.0f + this->actor.posRot.pos.y, this->actor.posRot.pos.z, 0, 0, 0, 8);
}

void func_80AF2F04(EnRu2* this, GlobalContext* globalCtx) {
    if (func_80AF27D0(this, globalCtx, 4, 3)) {
        this->action = 8;
        this->drawConfig = 2;
        this->unk_2B4 = 0;
        this->actor.shape.unk_14 = 0;
        this->unk_2B0 = 0.0f;
        func_80AF2E64();
    }
}

void func_80AF2F58(EnRu2* this, GlobalContext* globalCtx) {
    f32* unk_2B0 = &this->unk_2B0;
    s32 something;

    if (func_80AF27D0(this, globalCtx, 4, 3)) {
        *unk_2B0 += 1.0f;
        if (*unk_2B0 >= kREG(5) + 10.0f) {
            this->action = 9;
            this->drawConfig = 1;
            *unk_2B0 = kREG(5) + 10.0f;
            this->unk_2B4 = 0xFF;
            this->actor.shape.unk_14 = 0xFF;
            return;
        }
    } else {
        *unk_2B0 -= 1.0f;
        if (*unk_2B0 <= 0.0f) {
            this->action = 7;
            this->drawConfig = 0;
            *unk_2B0 = 0.0f;
            this->unk_2B4 = 0;
            this->actor.shape.unk_14 = 0;
            return;
        }
    }
    something = (*unk_2B0 / (kREG(5) + 10.0f)) * 255.0f;
    this->unk_2B4 = something;
    this->actor.shape.unk_14 = something;
}

void func_80AF30AC(EnRu2* this, GlobalContext* globalCtx) {
    if (func_80AF281C(this, globalCtx, 4, 3)) {
        this->action = 8;
        this->drawConfig = 2;
        this->unk_2B0 = kREG(5) + 10.0f;
        this->unk_2B4 = 0xFF;
        if (this->unk_2B8 == 0) {
            func_80AF2E84(this, globalCtx);
            this->unk_2B8 = 1;
        }
        this->actor.shape.unk_14 = 0xFF;
    }
}

void func_80AF3144(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2F04(this, globalCtx);
    func_80AF26D0(this, globalCtx);
}

void func_80AF3174(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF2F58(this, globalCtx);
    func_80AF26D0(this, globalCtx);
}

void func_80AF31C8(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF30AC(this, globalCtx);
    func_80AF26D0(this, globalCtx);
}

void func_80AF321C(EnRu2* this, GlobalContext* globalCtx) {
    s32 pad[2];
    s16 temp = this->unk_2A4;
    UNK_PTR addr = D_80AF410C[temp];
    SkelAnime* skelAnime = &this->skelAnime;
    GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
    Gfx* dispRefs[4];

    Graph_OpenDisps(dispRefs, globalCtx->state.gfxCtx, "../z_en_ru2_inKenjyanomaDemo02.c", 264);
    func_80093D84(globalCtx->state.gfxCtx);

    gSPSegment(gfxCtx->polyXlu.p++, 0x08, SEGMENTED_TO_VIRTUAL(addr));
    gSPSegment(gfxCtx->polyXlu.p++, 0x09, SEGMENTED_TO_VIRTUAL(addr));
    gDPSetEnvColor(gfxCtx->polyXlu.p++, 0x00, 0x00, 0x00, this->unk_2B4);
    gSPSegment(gfxCtx->polyXlu.p++, 0x0C, &D_80116280[0]);

    gfxCtx->polyXlu.p = SkelAnime_DrawSV2(globalCtx, skelAnime->skeleton, skelAnime->limbDrawTbl, skelAnime->dListCount,
                                          NULL, NULL, NULL, gfxCtx->polyXlu.p);

    Graph_CloseDisps(dispRefs, globalCtx->state.gfxCtx, "../z_en_ru2_inKenjyanomaDemo02.c", 291);
}

void func_80AF3394(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF28E8(this, &D_0600E630, 0, 0.0f, 0);
    this->action = 10;
    this->drawConfig = 0;
    this->actor.shape.unk_14 = 0;
}

void func_80AF33E0(EnRu2* this) {
    f32* unk_2B0 = &this->unk_2B0;
    f32 temp_f0;
    s32 temp_f18;

    *unk_2B0 += 1.0f;

    temp_f0 = kREG(17) + 10.0f;
    if (temp_f0 <= *unk_2B0) {
        this->unk_2B4 = 0xFF;
        this->actor.shape.unk_14 = 0xFF;
    } else {
        temp_f18 = (*unk_2B0 / temp_f0) * 255.0f;
        this->unk_2B4 = temp_f18;
        this->actor.shape.unk_14 = temp_f18;
    }
}

void func_80AF346C(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2868(this, globalCtx, 3);
    this->action = 11;
    this->drawConfig = 2;
}

void func_80AF34A4(EnRu2* this) {
    if (this->unk_2B0 >= kREG(17) + 10.0f) {
        this->action = 12;
        this->drawConfig = 1;
    }
}

void func_80AF34F0(EnRu2* this) {
    func_80AF28E8(this, &D_0600DCAC, 2, 0.0f, 0);
    this->action = 13;
}

void func_80AF3530(EnRu2* this, UNK_TYPE arg1) {
    if (arg1 != 0) {
        func_80AF28E8(this, &D_0600F03C, 0, 0.0f, 0);
    }
}

void func_80AF3564(EnRu2* this, GlobalContext* globalCtx) {
    CsCmdActorAction* csCmdNPCAction = func_80AF27AC(globalCtx, 3);
    s32 action;
    s32 unk_2BC;

    if (csCmdNPCAction != NULL) {
        action = csCmdNPCAction->action;
        unk_2BC = this->unk_2BC;
        if (action != unk_2BC) {
            switch (action) {
                case 7:
                    func_80AF346C(this, globalCtx);
                    break;
                case 8:
                    func_80AF34F0(this);
                    break;
                default:
                    osSyncPrintf("En_Ru2_inEnding_Check_DemoMode:そんな動作は無い!!!!!!!!\n");
                    break;
            }
            this->unk_2BC = action;
        }
    }
}

void func_80AF3604(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF3564(this, globalCtx);
}

void func_80AF3624(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF33E0(this);
    func_80AF34A4(this);
}

void func_80AF366C(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF3564(this, globalCtx);
}

void func_80AF36AC(EnRu2* this, GlobalContext* globalCtx) {
    UNK_TYPE something;

    func_80AF2744(this, globalCtx);
    something = EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    func_80AF3530(this, something);
}

void func_80AF36EC(EnRu2* this, GlobalContext* globalCtx) {
    Flags_SetSwitch(globalCtx, func_80AF2690(this));
}

s32 func_80AF3718(EnRu2* this, GlobalContext* globalCtx) {
    return Flags_GetSwitch(globalCtx, func_80AF2690(this));
}

void func_80AF3744(EnRu2* this, GlobalContext* globalCtx) {
    if (func_80AF3718(this, globalCtx)) {
        Actor_Kill(&this->actor);
    } else {
        func_80AF28E8(this, &D_06000DE8, 0, 0.0f, 0);
        this->action = 14;
        this->drawConfig = 1;
    }
}

void func_80AF37AC() {
    func_800F5C64(0x51);
}

void func_80AF37CC(EnRu2* this) {
    f32 funcFloat;

    this->unk_2C0 += 1;
    funcFloat = func_8006F9BC((kREG(2) + 0x96) & 0xFFFF, 0, this->unk_2C0, 8, 0);
    this->actor.posRot.pos.y = this->actor.initPosRot.pos.y + (300.0f * funcFloat);
}

s32 func_80AF383C(EnRu2* this, GlobalContext* globalCtx) {
    Player* player = PLAYER;
    f32 thisPosX = this->actor.posRot.pos.x;
    f32 playerPosX = player->actor.posRot.pos.x;

    if (playerPosX - thisPosX >= -202.0f) {
        return 1;
    }
    return 0;
}

void func_80AF3878(EnRu2* this, GlobalContext* globalCtx) {
    if (func_80AF383C(this, globalCtx) && !Gameplay_InCsMode(globalCtx)) {
        this->action = 16;
        func_800800F8(globalCtx, 0xC3A, -0x63, &this->actor, 0);
    }
}

void func_80AF38D0(EnRu2* this, GlobalContext* globalCtx) {
    this->action = 16;
    func_800800F8(globalCtx, 0xC3A, -0x63, &this->actor, 0);
}

void func_80AF390C(EnRu2* this, GlobalContext* globalCtx) {
    f32* unk_2C4 = &this->unk_2C4;

    *unk_2C4 += 1.0f;
    if (*unk_2C4 == kREG(6) + 40.0f) {
        func_80AF37AC();
    } else if (*unk_2C4 > kREG(4) + 50.0f) {
        this->actor.textId = 0x403E;
        func_8010B680(globalCtx, this->actor.textId, 0);
        this->action = 17;
    }
}

void func_80AF39DC(EnRu2* this, GlobalContext* globalCtx) {
    s32 pad;
    MessageContext* msgCtx;
    s32 pad2;
    u8 dialogState;
    Player* player;
    s32 pad3;

    msgCtx = &globalCtx->msgCtx;
    dialogState = func_8010BDBC(msgCtx);

    if (dialogState == 3) {
        if (this->unk_2C3 != 3) {
            osSyncPrintf("おれが小松だ！ \n");
            this->unk_2C2++;
            if (this->unk_2C2 % 6 == 3) {
                player = PLAYER;
                osSyncPrintf("うおりゃー！ \n");
                func_8005B1A4(ACTIVE_CAM);
                player->actor.posRot.pos.x = 820.0f;
                player->actor.posRot.pos.y = 0.0f;
                player->actor.posRot.pos.z = 180.0f;
            }
        }
    }

    this->unk_2C3 = dialogState;
    if (func_8010BDBC(msgCtx) == 2) {
        this->action = 18;
        func_8005B1A4(ACTIVE_CAM);
    }
}

void func_80AF3ADC(EnRu2* this, GlobalContext* globalCtx) {
    this->unk_2C4 += 1.0f;
    if (this->unk_2C4 > kREG(5) + 100.0f) {
        func_80AF28E8(this, &D_0600F8B8, 0, -12.0f, 0);
        this->action = 0x13;
        func_80AF36EC(this, globalCtx);
    }
}

void func_80AF3B74(EnRu2* this, GlobalContext* globalCtx) {
    if (this->unk_2C0 > (((u16)(kREG(3) + 0x28)) + ((u16)(kREG(2) + 0x96)) & 0xFFFF)) {
        Actor_Kill(&this->actor);
    }
}

void func_80AF3BC8(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF3878(this, globalCtx);
    Actor_SetHeight(&this->actor, 50.0f);
    func_80AF259C(this, globalCtx);
}

void func_80AF3C04(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    func_80AF259C(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    Actor_SetHeight(&this->actor, 50.0f);
    func_80AF38D0(this, globalCtx);
}

void func_80AF3C64(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    Actor_SetHeight(&this->actor, 50.0f);
    func_80AF390C(this, globalCtx);
}

void func_80AF3CB8(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    Actor_SetHeight(&this->actor, 50.0f);
    func_80AF39DC(this, globalCtx);
}

void func_80AF3D0C(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    Actor_SetHeight(&this->actor, 50.0f);
    func_80AF3ADC(this, globalCtx);
}

void func_80AF3D60(EnRu2* this, GlobalContext* globalCtx) {
    func_80AF37CC(this);
    func_80AF2744(this, globalCtx);
    EnRu2_FrameUpdateMatrix(this);
    func_80AF2608(this);
    Actor_SetHeight(&this->actor, 50.0f);
    func_80AF3B74(this, globalCtx);
}

void EnRu2_Update(Actor* thisx, GlobalContext* globalCtx) {
    EnRu2* this = THIS;

    if (this->action < 0 || this->action >= 20 || sActionFuncs[this->action] == 0) {
        osSyncPrintf(VT_FGCOL(RED) "メインモードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST);
        return;
    }
    sActionFuncs[this->action](this, globalCtx);
}

void EnRu2_Init(Actor* thisx, GlobalContext* globalCtx) {
    EnRu2* this = THIS;

    ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawFunc_Circle, 30.0f);
    func_80AF2550(thisx, globalCtx);
    SkelAnime_InitSV(globalCtx, &this->skelAnime, &D_0600C700, NULL, &this->limbDrawTable, &this->transitionDrawTable,
                     23);

    switch (func_80AF26A0(this)) {
        case 2:
            func_80AF2E1C(this, globalCtx);
            break;
        case 3:
            func_80AF3394(this, globalCtx);
            break;
        case 4:
            func_80AF3744(this, globalCtx);
            break;
        default:
            func_80AF2994(this, globalCtx);
            break;
    }

    this->unk_2C2 = 0;
    this->unk_2C3 = 3;
}

void func_80AF3F14(EnRu2* this, GlobalContext* globalCtx) {
}

void func_80AF3F20(EnRu2* this, GlobalContext* globalCtx) {
    s32 pad[2];
    s16 temp = this->unk_2A4;
    UNK_PTR addr = D_80AF410C[temp];
    SkelAnime* skelAnime = &this->skelAnime;
    GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
    Gfx* dispRefs[4];

    Graph_OpenDisps(dispRefs, globalCtx->state.gfxCtx, "../z_en_ru2.c", 642);
    func_80093D18(globalCtx->state.gfxCtx);

    gSPSegment(gfxCtx->polyOpa.p++, 0x08, SEGMENTED_TO_VIRTUAL(addr));
    gSPSegment(gfxCtx->polyOpa.p++, 0x09, SEGMENTED_TO_VIRTUAL(addr));
    gDPSetEnvColor(gfxCtx->polyOpa.p++, 0x00, 0x00, 0x00, 0xFF);
    gSPSegment(gfxCtx->polyOpa.p++, 0x0C, &D_80116280[2]);

    SkelAnime_DrawSV(globalCtx, skelAnime->skeleton, skelAnime->limbDrawTbl, skelAnime->dListCount, NULL, NULL,
                     &this->actor);
    Graph_CloseDisps(dispRefs, globalCtx->state.gfxCtx, "../z_en_ru2.c", 663);
}

void EnRu2_Draw(Actor* thisx, GlobalContext* globalCtx) {
    EnRu2* this = THIS;

    if (this->drawConfig < 0 || this->drawConfig >= 3 || sDrawFuncs[this->drawConfig] == 0) {
        osSyncPrintf(VT_FGCOL(RED) "描画モードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST);
        return;
    }
    sDrawFuncs[this->drawConfig](this, globalCtx);
}
