/*
 * File: z_en_vm.c
 * Overlay: ovl_En_Vm
 * Description: Beamos
 */

#include "z_en_vm.h"
#include "objects/object_vm/object_vm.h"
#include "overlays/actors/ovl_En_Bom/z_en_bom.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ResourceManagerHelpers.h"

#define FLAGS (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_UPDATE_CULLING_DISABLED)

void EnVm_Init(Actor* thisx, PlayState* play);
void EnVm_Destroy(Actor* thisx, PlayState* play);
void EnVm_Update(Actor* thisx, PlayState* play);
void EnVm_Draw(Actor* thisx, PlayState* play);

void EnVm_SetupWait(EnVm* this);
void EnVm_Wait(EnVm* this, PlayState* play);
void EnVm_SetupAttack(EnVm* this);
void EnVm_Attack(EnVm* this, PlayState* play);
void EnVm_Stun(EnVm* this, PlayState* play);
void EnVm_Die(EnVm* this, PlayState* play);

const ActorInit En_Vm_InitVars = {
    ACTOR_EN_VM,
    ACTORCAT_ENEMY,
    FLAGS,
    OBJECT_VM,
    sizeof(EnVm),
    (ActorFunc)EnVm_Init,
    (ActorFunc)EnVm_Destroy,
    (ActorFunc)EnVm_Update,
    (ActorFunc)EnVm_Draw,
    NULL,
};

static ColliderCylinderInit sCylinderInit = {
    {
        COLTYPE_METAL,
        AT_NONE,
        AC_ON | AC_HARD | AC_TYPE_PLAYER,
        OC1_ON | OC1_TYPE_ALL,
        OC2_TYPE_1,
        COLSHAPE_CYLINDER,
    },
    {
        ELEMTYPE_UNK0,
        { 0x00000000, 0x00, 0x00 },
        { 0xFFCFFFFF, 0x00, 0x00 },
        TOUCH_NONE,
        BUMP_ON,
        OCELEM_ON,
    },
    { 25, 70, 0, { 0, 0, 0 } },
};

static ColliderQuadInit sQuadInit1 = {
    {
        COLTYPE_METAL,
        AT_ON | AT_TYPE_ENEMY,
        AC_NONE,
        OC1_NONE,
        OC2_NONE,
        COLSHAPE_QUAD,
    },
    {
        ELEMTYPE_UNK0,
        { 0xFFCFFFFF, 0x00, 0x10 },
        { 0x00000000, 0x00, 0x00 },
        TOUCH_ON | TOUCH_SFX_NORMAL | TOUCH_UNK7,
        BUMP_NONE,
        OCELEM_NONE,
    },
    { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
};

static ColliderQuadInit sQuadInit2 = {
    {
        COLTYPE_METAL,
        AT_NONE,
        AC_ON | AC_TYPE_PLAYER,
        OC1_NONE,
        OC2_NONE,
        COLSHAPE_QUAD,
    },
    {
        ELEMTYPE_UNK0,
        { 0x00000000, 0x00, 0x00 },
        { 0xFFCFFFFF, 0x00, 0x00 },
        TOUCH_NONE,
        BUMP_ON,
        OCELEM_NONE,
    },
    { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
};

static Vec3f D_80B2EAEC = { 0.0f, 0.0f, 0.0f };

static Vec3f D_80B2EAF8 = { 0.0f, 0.0f, 0.0f };

static Vec3f D_80B2EB04 = { 500.0f, 0.0f, 0.0f };

static Vec3f D_80B2EB10 = { -500.0f, 0.0f, 0.0f };

static Vec3f D_80B2EB1C = { 0.0f, 0.0f, 0.0f };

static Vec3f D_80B2EB28 = { 0.0f, 0.0f, 1600.0f };

static Vec3f D_80B2EB34 = { 1000.0f, 700.0f, 2000.0f };

static Vec3f D_80B2EB40 = { 1000.0f, -700.0f, 2000.0f };

static Vec3f D_80B2EB4C = { -1000.0f, 700.0f, 1500.0f };

static Vec3f D_80B2EB58 = { -1000.0f, -700.0f, 1500.0f };

static Vec3f D_80B2EB64 = { 500.0f, 0.0f, 0.0f };

static Vec3f D_80B2EB70 = { -500.0f, 0.0f, 0.0f };

static Vec3f D_80B2EB7C = { 0.4f, 0.4f, 0.4f };

static void* D_80B2EB88[] = {
    gEffEnemyDeathFlame1Tex, gEffEnemyDeathFlame2Tex,  gEffEnemyDeathFlame3Tex, gEffEnemyDeathFlame4Tex,
    gEffEnemyDeathFlame5Tex, gEffEnemyDeathFlame6Tex,  gEffEnemyDeathFlame7Tex, gEffEnemyDeathFlame8Tex,
    gEffEnemyDeathFlame9Tex, gEffEnemyDeathFlame10Tex,
};

void EnVm_SetupAction(EnVm* this, EnVmActionFunc actionFunc) {
    this->actionFunc = actionFunc;
}

void EnVm_Init(Actor* thisx, PlayState* play) {
    EnVm* this = (EnVm*)thisx;

    SkelAnime_Init(play, &this->skelAnime, &gBeamosSkel, &gBeamosAnim, this->jointTable, this->morphTable, 11);
    ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f);
    Collider_InitCylinder(play, &this->colliderCylinder);
    Collider_SetCylinder(play, &this->colliderCylinder, thisx, &sCylinderInit);
    Collider_InitQuad(play, &this->colliderQuad1);
    Collider_SetQuad(play, &this->colliderQuad1, thisx, &sQuadInit1);
    Collider_InitQuad(play, &this->colliderQuad2);
    Collider_SetQuad(play, &this->colliderQuad2, thisx, &sQuadInit2);
    this->beamSightRange = (thisx->params >> 8) * 40.0f;
    thisx->params &= 0xFF;
    thisx->naviEnemyId = 0x39;

    if (thisx->params == BEAMOS_LARGE) {
        thisx->colChkInfo.health = 2;
        Actor_SetScale(thisx, 0.014f);
    } else {
        thisx->colChkInfo.health = 1;
        Actor_SetScale(thisx, 0.01f);
    }

    EnVm_SetupWait(this);
}

void EnVm_Destroy(Actor* thisx, PlayState* play) {
    EnVm* this = (EnVm*)thisx;

    Collider_DestroyCylinder(play, &this->colliderCylinder);

    ResourceMgr_UnregisterSkeleton(&this->skelAnime);
}

void EnVm_SetupWait(EnVm* this) {
    f32 frameCount = Animation_GetLastFrame(&gBeamosAnim);

    Animation_Change(&this->skelAnime, &gBeamosAnim, 1.0f, frameCount, frameCount, ANIMMODE_ONCE, 0.0f);
    this->unk_25E = this->unk_260 = 0;
    this->unk_21C = 0;
    this->timer = 10;
    EnVm_SetupAction(this, EnVm_Wait);
}

void EnVm_Wait(EnVm* this, PlayState* play) {
    Player* player = GET_PLAYER(play);
    f32 dist;
    s16 headRot;
    s16 pad;
    s16 pitch;

    switch (this->unk_25E) {
        case 0:
            Math_SmoothStepToS(&this->beamRot.x, 0, 10, 1500, 0);
            headRot = this->actor.yawTowardsPlayer - this->headRotY - this->actor.shape.rot.y;
            pitch = Math_Vec3f_Pitch(&this->beamPos1, &player->actor.world.pos);

            if (pitch > 0x1B91) {
                pitch = 0x1B91;
            }

            dist = this->beamSightRange - this->actor.xzDistToPlayer;

            if (this->actor.xzDistToPlayer <= this->beamSightRange && ABS(headRot) <= 0x2710 && pitch >= 0xE38 &&
                this->actor.yDistToPlayer <= 80.0f && this->actor.yDistToPlayer >= -160.0f) {
                Math_SmoothStepToS(&this->beamRot.x, pitch, 10, 0xFA0, 0);
                if (Math_SmoothStepToS(&this->headRotY, this->actor.yawTowardsPlayer - this->actor.shape.rot.y, 1,
                                       (ABS((s16)(dist * 180.0f)) / 3) + 0xFA0, 0) <= 5460) {
                    this->timer--;
                    if (this->timer == 0) {
                        this->unk_25E++;
                        this->skelAnime.curFrame = 0.0f;
                        this->skelAnime.startFrame = 0.0f;
                        this->skelAnime.playSpeed = 2.0f;
                        Audio_PlayActorSound2(&this->actor, NA_SE_EN_BIMOS_AIM);
                    }
                }
            } else {
                this->headRotY -= 0x1F4;
            }

            SkelAnime_Update(&this->skelAnime);
            return;
        case 1:
            break;
        default:
            return;
    }

    Math_SmoothStepToS(&this->headRotY, this->actor.yawTowardsPlayer - this->actor.shape.rot.y, 1, 0x1F40, 0);

    if (SkelAnime_Update(&this->skelAnime)) {
        this->unk_260++;
        this->skelAnime.curFrame = 0.0f;
    }

    if (this->unk_260 == 2) {
        this->beamRot.y = this->actor.yawTowardsPlayer;
        this->beamRot.x = Math_Vec3f_Pitch(&this->beamPos1, &player->actor.world.pos);

        if (this->beamRot.x > 0x1B91) {
            this->beamRot.x = 0x1B91;
        }

        if (this->beamRot.x < 0xAAA) {
            this->skelAnime.startFrame = this->skelAnime.curFrame = this->skelAnime.endFrame;
            this->unk_25E = this->unk_260 = 0;
            this->timer = 10;
            this->skelAnime.playSpeed = 1.0f;
        } else {
            this->skelAnime.curFrame = 6.0f;
            EffectSsDeadDd_Spawn(play, &this->beamPos2, &D_80B2EAEC, &D_80B2EAEC, 150, -25, 0, 0, 255, 0, 255, 255,
                                 255, 16, 20);
            EnVm_SetupAttack(this);
        }
    }
}

void EnVm_SetupAttack(EnVm* this) {
    Animation_Change(&this->skelAnime, &gBeamosAnim, 3.0f, 3.0f, 7.0f, ANIMMODE_ONCE, 0.0f);
    this->timer = 305;
    this->beamScale.x = 0.6f;
    this->beamSpeed = 40.0f;
    this->unk_21C = 1;
    this->colliderQuad1.base.atFlags &= ~AT_HIT;
    EnVm_SetupAction(this, EnVm_Attack);
}

void EnVm_Attack(EnVm* this, PlayState* play) {
    Player* player = GET_PLAYER(play);
    s16 pitch = Math_Vec3f_Pitch(&this->beamPos1, &player->actor.world.pos);
    f32 dist;
    Vec3f playerPos;

    if (pitch > 0x1B91) {
        pitch = 0x1B91;
    }

    if (this->colliderQuad1.base.atFlags & AT_HIT) {
        this->colliderQuad1.base.atFlags &= ~AT_HIT;
        this->timer = 0;

        if (this->beamScale.x > 0.1f) {
            this->beamScale.x = 0.1f;
        }
    }

    if (this->beamRot.x < 0xAAA || this->timer == 0) {
        Math_SmoothStepToF(&this->beamScale.x, 0.0f, 1.0f, 0.03f, 0.0f);
        this->unk_260 = 0;

        if (this->beamScale.x == 0.0f) {
            this->beamScale.y = this->beamScale.z = 0.0f;
            EnVm_SetupWait(this);
        }
    } else {
        if (--this->timer > 300) {
            return;
        }

        Math_SmoothStepToS(&this->headRotY, -this->actor.shape.rot.y + this->actor.yawTowardsPlayer, 10, 0xDAC, 0);
        Math_SmoothStepToS(&this->beamRot.y, this->actor.yawTowardsPlayer, 10, 0xDAC, 0);
        Math_SmoothStepToS(&this->beamRot.x, pitch, 10, 0xDAC, 0);
        playerPos = player->actor.world.pos;

        if (player->actor.floorHeight > BGCHECK_Y_MIN) {
            playerPos.y = player->actor.floorHeight;
        }

        dist = Math_Vec3f_DistXYZ(&this->beamPos1, &playerPos);
        Math_SmoothStepToF(&this->beamScale.z, dist, 1.0f, this->beamSpeed, 0.0f);
        Math_SmoothStepToF(&this->beamScale.x, 0.1f, 1.0f, 0.12f, 0.0f);
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_BIMOS_LAZER - SFX_FLAG);

        if (this->unk_260 > 2) {
            CollisionCheck_SetAT(play, &play->colChkCtx, &this->colliderQuad1.base);
        }

        this->unk_260 = 3;
    }

    if (SkelAnime_Update(&this->skelAnime)) {
        this->skelAnime.curFrame = this->skelAnime.startFrame;
    }
}

void EnVm_SetupStun(EnVm* this) {
    Animation_Change(&this->skelAnime, &gBeamosAnim, -1.0f, Animation_GetLastFrame(&gBeamosAnim), 0.0f, ANIMMODE_ONCE,
                     0.0f);
    this->unk_260 = 0;
    this->timer = 180;
    this->unk_25E = this->unk_260;
    this->unk_21C = 2;
    this->beamScale.z = 0.0f;
    this->beamScale.y = 0.0f;
    Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
    EnVm_SetupAction(this, EnVm_Stun);
}

void EnVm_Stun(EnVm* this, PlayState* play) {
    if (this->timer == 0) {
        if (SkelAnime_Update(&this->skelAnime)) {
            this->unk_25E++;
            if (this->unk_25E == 3) {
                EnVm_SetupWait(this);
            } else if (this->unk_25E == 1) {
                Animation_Change(&this->skelAnime, &gBeamosAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gBeamosAnim),
                                 ANIMMODE_ONCE, 0.0f);
            } else {
                this->timer = 10;
                this->skelAnime.curFrame = 0.0f;
                this->skelAnime.playSpeed = 2.0f;
            }
        }
    } else {
        Math_SmoothStepToS(&this->beamRot.x, 0, 10, 0x5DC, 0);
        this->timer--;
        SkelAnime_Update(&this->skelAnime);
    }
}

void EnVm_SetupDie(EnVm* this) {
    Animation_Change(&this->skelAnime, &gBeamosAnim, -1.0f, Animation_GetLastFrame(&gBeamosAnim), 0.0f, ANIMMODE_ONCE,
                     0.0f);
    this->timer = 33;
    this->unk_25E = this->unk_260 = 0;
    this->unk_21C = 3;
    this->beamScale.z = 0.0f;
    this->beamScale.y = 0.0f;
    this->actor.shape.yOffset = -5000.0f;
    this->actor.world.pos.y += 5000.0f * this->actor.scale.y;
    this->actor.velocity.y = 8.0f;
    this->actor.gravity = -0.5f;
    this->actor.speedXZ = Rand_ZeroOne() + 1.0f;
    this->actor.world.rot.y = Rand_CenteredFloat(65535.0f);
    EnVm_SetupAction(this, EnVm_Die);
    GameInteractor_ExecuteOnEnemyDefeat(&this->actor);
}

void EnVm_Die(EnVm* this, PlayState* play) {
    EnBom* bomb;

    this->beamRot.x += 0x5DC;
    this->headRotY += 0x9C4;
    Actor_MoveXZGravity(&this->actor);

    if (--this->timer == 0) {
        bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
                                   this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x6FF, BOMB_BODY, true);

        if (bomb != NULL) {
            bomb->timer = 0;
        }

        Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xA0);
        Actor_Kill(&this->actor);
    }
}

void EnVm_CheckHealth(EnVm* this, PlayState* play) {
    EnBom* bomb;

    if (Actor_GetCollidedExplosive(play, &this->colliderCylinder.base) != NULL) {
        this->actor.colChkInfo.health--;
        osSyncPrintf("hp down %d\n", this->actor.colChkInfo.health);
    } else {
        if (!(this->colliderQuad2.base.acFlags & AC_HIT) || this->unk_21C == 2) {
            return;
        }
        this->colliderQuad2.base.acFlags &= ~AC_HIT;
    }

    if (this->actor.colChkInfo.health != 0) {
        Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 8);
        EnVm_SetupStun(this);
    } else {
        bomb = (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x,
                                   this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0x601, BOMB_BODY, true);

        if (bomb != NULL) {
            bomb->timer = 0;
        }

        EnVm_SetupDie(this);
    }
}

void EnVm_Update(Actor* thisx, PlayState* play) {
    EnVm* this = (EnVm*)thisx;
    CollisionCheckContext* colChkCtx = &play->colChkCtx;

    if (this->actor.colChkInfo.health != 0) {
        EnVm_CheckHealth(this, play);
    }

    if (this->unk_260 == 4) {
        EffectSsDeadDs_SpawnStationary(play, &this->beamPos3, 20, -1, 255, 20);
        func_80033480(play, &this->beamPos3, 6.0f, 1, 120, 20, 1);
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_BIMOS_LAZER_GND - SFX_FLAG);
    }

    this->actionFunc(this, play);
    this->beamTexScroll += 0xC;

    if (this->actor.colChkInfo.health != 0 && this->unk_21C != 2) {
        Audio_PlayActorSound2(&this->actor, NA_SE_EN_BIMOS_ROLL_HEAD - SFX_FLAG);
    }

    Collider_UpdateCylinder(&this->actor, &this->colliderCylinder);
    CollisionCheck_SetOC(play, colChkCtx, &this->colliderCylinder.base);

    if (this->actor.colorFilterTimer == 0 && this->actor.colChkInfo.health != 0) {
        CollisionCheck_SetAC(play, colChkCtx, &this->colliderCylinder.base);
    }

    CollisionCheck_SetAC(play, colChkCtx, &this->colliderQuad2.base);
    this->actor.focus.pos = this->actor.world.pos;
    this->actor.focus.pos.y += (6500.0f + this->actor.shape.yOffset) * this->actor.scale.y;
}

s32 EnVm_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
    EnVm* this = (EnVm*)thisx;

    if (limbIndex == 2) {
        rot->x += this->beamRot.x;
        rot->y += this->headRotY;
    } else if (limbIndex == 10) {
        if (this->unk_21C == 3) {
            *dList = NULL;
        }
    }

    return false;
}

void EnVm_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
    EnVm* this = (EnVm*)thisx;
    Vec3f sp80 = D_80B2EAF8;
    Vec3f sp74 = D_80B2EB04;
    Vec3f sp68 = D_80B2EB10;
    s32 pad;
    Vec3f posResult;
    CollisionPoly* poly;
    s32 bgId;
    f32 dist;

    if (limbIndex == 2) {
        Matrix_MultVec3f(&D_80B2EB1C, &this->beamPos1);
        Matrix_MultVec3f(&D_80B2EB28, &this->beamPos2);

        if (this->unk_260 >= 3) {
            poly = NULL;
            sp80.z = (this->beamScale.z + 500.0f) * (this->actor.scale.y * 10000.0f);
            Matrix_MultVec3f(&sp80, &this->beamPos3);

            if (BgCheck_EntityLineTest1(&play->colCtx, &this->beamPos1, &this->beamPos3, &posResult, &poly, true,
                                        true, false, true, &bgId) == true) {
                this->beamScale.z = Math_Vec3f_DistXYZ(&this->beamPos1, &posResult) - 5.0f;
                this->unk_260 = 4;
                this->beamPos3 = posResult;
            }
            if (this->beamScale.z != 0.0f) {
                dist = 100.0f;
                if (this->actor.scale.y > 0.01f) {
                    dist = 70.0f;
                }
                sp74.z = sp68.z = Math_Vec3f_DistXYZ(&this->beamPos1, &this->beamPos3) * dist;
                Matrix_MultVec3f(&D_80B2EB64, &this->colliderQuad1.dim.quad[3]);
                Matrix_MultVec3f(&D_80B2EB70, &this->colliderQuad1.dim.quad[2]);
                Matrix_MultVec3f(&sp74, &this->colliderQuad1.dim.quad[1]);
                Matrix_MultVec3f(&sp68, &this->colliderQuad1.dim.quad[0]);
                Collider_SetQuadVertices(&this->colliderQuad1, &this->colliderQuad1.dim.quad[0],
                                         &this->colliderQuad1.dim.quad[1], &this->colliderQuad1.dim.quad[2],
                                         &this->colliderQuad1.dim.quad[3]);
            }
        }
        Matrix_MultVec3f(&D_80B2EB34, &this->colliderQuad2.dim.quad[1]);
        Matrix_MultVec3f(&D_80B2EB40, &this->colliderQuad2.dim.quad[0]);
        Matrix_MultVec3f(&D_80B2EB4C, &this->colliderQuad2.dim.quad[3]);
        Matrix_MultVec3f(&D_80B2EB58, &this->colliderQuad2.dim.quad[2]);
        Collider_SetQuadVertices(&this->colliderQuad2, &this->colliderQuad2.dim.quad[0],
                                 &this->colliderQuad2.dim.quad[1], &this->colliderQuad2.dim.quad[2],
                                 &this->colliderQuad2.dim.quad[3]);
    }
}

void EnVm_Draw(Actor* thisx, PlayState* play2) {
    EnVm* this = (EnVm*)thisx;
    PlayState* play = play2;
    Vec3f actorPos;

    OPEN_DISPS(play->state.gfxCtx);

    Gfx_SetupDL_25Opa(play->state.gfxCtx);
    Gfx_SetupDL_25Xlu(play->state.gfxCtx);
    SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnVm_OverrideLimbDraw,
                      EnVm_PostLimbDraw, this);
    actorPos = this->actor.world.pos;
    func_80033C30(&actorPos, &D_80B2EB7C, 255, play);

    if (this->unk_260 >= 3) {
        Matrix_Translate(this->beamPos3.x, this->beamPos3.y + 10.0f, this->beamPos3.z, MTXMODE_NEW);
        Matrix_Scale(0.8f, 0.8f, 0.8f, MTXMODE_APPLY);
        gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
                  G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
        gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 168);
        Gfx_SetupDL_60NoCDXlu(play->state.gfxCtx);
        gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 255, 0);
        gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(D_80B2EB88[play->gameplayFrames % 8]));
        gSPDisplayList(POLY_XLU_DISP++, gEffEnemyDeathFlameDL);
        Matrix_RotateY(32767.0f, MTXMODE_APPLY);
        gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
                  G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
        gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(D_80B2EB88[(play->gameplayFrames + 4) % 8]));
        gSPDisplayList(POLY_XLU_DISP++, gEffEnemyDeathFlameDL);
    }
    gSPSegment(POLY_OPA_DISP++, 0x08, func_80094E78(play->state.gfxCtx, 0, this->beamTexScroll));
    Matrix_Translate(this->beamPos1.x, this->beamPos1.y, this->beamPos1.z, MTXMODE_NEW);
    Matrix_RotateZYX(this->beamRot.x, this->beamRot.y, this->beamRot.z, MTXMODE_APPLY);
    Matrix_Scale(this->beamScale.x * 0.1f, this->beamScale.x * 0.1f, this->beamScale.z * 0.0015f, MTXMODE_APPLY);
    gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
              G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
    gSPDisplayList(POLY_OPA_DISP++, gBeamosLaserDL);

    CLOSE_DISPS(play->state.gfxCtx);
}
