Shipwright/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c

1147 lines
42 KiB
C

/*
* File: z_en_floormas
* Overlay: En_Floormas
* Description: Floormaster
*/
#include "z_en_floormas.h"
#include "objects/object_wallmaster/object_wallmaster.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2 | ACTOR_FLAG_10)
#define SPAWN_INVISIBLE 0x8000
#define SPAWN_SMALL 0x10
#define MERGE_MASTER 0x40
#define MERGE_SLAVE 0x20
void EnFloormas_Init(Actor* thisx, GlobalContext* globalCtx);
void EnFloormas_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnFloormas_Update(Actor* thisx, GlobalContext* globalCtx);
void EnFloormas_Draw(Actor* thisx, GlobalContext* globalCtx);
void EnFloormas_GrabLink(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Split(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Recover(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_DrawHighlighted(Actor* this, GlobalContext* globalCtx);
void EnFloormas_SmWait(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_SetupBigDecideAction(EnFloormas* this);
void EnFloormas_Freeze(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_TakeDamage(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Merge(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_JumpAtLink(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_SmSlaveJumpAtMaster(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_SmShrink(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_SmDecideAction(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_SmWalk(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Land(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Hover(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Turn(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Run(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_BigStopWalk(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_BigWalk(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Stand(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_BigDecideAction(EnFloormas* this, GlobalContext* globalCtx);
void EnFloormas_Charge(EnFloormas* this, GlobalContext* globalCtx);
const ActorInit En_Floormas_InitVars = {
ACTOR_EN_FLOORMAS,
ACTORCAT_ENEMY,
FLAGS,
OBJECT_WALLMASTER,
sizeof(EnFloormas),
(ActorFunc)EnFloormas_Init,
(ActorFunc)EnFloormas_Destroy,
(ActorFunc)EnFloormas_Update,
(ActorFunc)EnFloormas_Draw,
NULL,
};
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_HIT0,
AT_ON | AT_TYPE_ENEMY,
AC_ON | AC_TYPE_PLAYER,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_1,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0xFFCFFFFF, 0x04, 0x10 },
{ 0xFFCFFFFF, 0x00, 0x00 },
TOUCH_ON | TOUCH_SFX_HARD,
BUMP_ON | BUMP_HOOKABLE,
OCELEM_ON,
},
{ 25, 40, 0, { 0, 0, 0 } },
};
static CollisionCheckInfoInit sColChkInfoInit = { 4, 30, 40, 150 };
static DamageTable sDamageTable = {
/* Deku nut */ DMG_ENTRY(0, 0x1),
/* Deku stick */ DMG_ENTRY(2, 0x0),
/* Slingshot */ DMG_ENTRY(1, 0x0),
/* Explosive */ DMG_ENTRY(2, 0x0),
/* Boomerang */ DMG_ENTRY(0, 0x1),
/* Normal arrow */ DMG_ENTRY(2, 0x0),
/* Hammer swing */ DMG_ENTRY(2, 0x0),
/* Hookshot */ DMG_ENTRY(0, 0x1),
/* Kokiri sword */ DMG_ENTRY(1, 0x0),
/* Master sword */ DMG_ENTRY(2, 0x0),
/* Giant's Knife */ DMG_ENTRY(4, 0x0),
/* Fire arrow */ DMG_ENTRY(4, 0x2),
/* Ice arrow */ DMG_ENTRY(2, 0x0),
/* Light arrow */ DMG_ENTRY(4, 0x4),
/* Unk arrow 1 */ DMG_ENTRY(4, 0x0),
/* Unk arrow 2 */ DMG_ENTRY(2, 0x0),
/* Unk arrow 3 */ DMG_ENTRY(2, 0x0),
/* Fire magic */ DMG_ENTRY(4, 0x2),
/* Ice magic */ DMG_ENTRY(0, 0x0),
/* Light magic */ DMG_ENTRY(4, 0x4),
/* Shield */ DMG_ENTRY(0, 0x0),
/* Mirror Ray */ DMG_ENTRY(0, 0x0),
/* Kokiri spin */ DMG_ENTRY(1, 0x0),
/* Giant spin */ DMG_ENTRY(4, 0x0),
/* Master spin */ DMG_ENTRY(2, 0x0),
/* Kokiri jump */ DMG_ENTRY(2, 0x0),
/* Giant jump */ DMG_ENTRY(8, 0x0),
/* Master jump */ DMG_ENTRY(4, 0x0),
/* Unknown 1 */ DMG_ENTRY(0, 0x0),
/* Unblockable */ DMG_ENTRY(0, 0x0),
/* Hammer jump */ DMG_ENTRY(4, 0x0),
/* Unknown 2 */ DMG_ENTRY(0, 0x0),
};
static InitChainEntry sInitChain[] = {
ICHAIN_S8(naviEnemyId, 0x31, ICHAIN_CONTINUE),
ICHAIN_F32(targetArrowOffset, 5500, ICHAIN_CONTINUE),
ICHAIN_F32_DIV1000(gravity, -1000, ICHAIN_STOP),
};
void EnFloormas_Init(Actor* thisx, GlobalContext* globalCtx2) {
EnFloormas* this = (EnFloormas*)thisx;
GlobalContext* globalCtx = globalCtx2;
s32 invisble;
s32 pad;
Actor_ProcessInitChain(&this->actor, sInitChain);
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 50.0f);
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gWallmasterSkel, &gWallmasterWaitAnim, this->jointTable,
this->morphTable, 25);
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
this->zOffset = -1600;
invisble = this->actor.params & SPAWN_INVISIBLE;
// s16 cast needed
this->actor.params &= (s16) ~(SPAWN_INVISIBLE);
if (invisble) {
this->actor.flags |= ACTOR_FLAG_7;
this->actor.draw = EnFloormas_DrawHighlighted;
}
if (this->actor.params == SPAWN_SMALL) {
this->actor.draw = NULL;
this->actor.flags &= ~ACTOR_FLAG_0;
this->actionFunc = EnFloormas_SmWait;
} else {
// spawn first small floormaster
this->actor.parent =
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_FLOORMAS, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL);
if (this->actor.parent == NULL) {
Actor_Kill(&this->actor);
return;
}
// spawn 2nd small floormaster
this->actor.child =
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_FLOORMAS, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, invisble + SPAWN_SMALL);
if (this->actor.child == NULL) {
Actor_Kill(this->actor.parent);
Actor_Kill(&this->actor);
return;
}
// link floormasters together
this->actor.parent->child = &this->actor;
this->actor.parent->parent = this->actor.child;
this->actor.child->parent = &this->actor;
this->actor.child->child = this->actor.parent;
EnFloormas_SetupBigDecideAction(this);
}
}
void EnFloormas_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnFloormas* this = (EnFloormas*)thisx;
ColliderCylinder* col = &this->collider;
Collider_DestroyCylinder(globalCtx, col);
}
void EnFloormas_MakeInvulnerable(EnFloormas* this) {
this->collider.base.colType = COLTYPE_HARD;
this->collider.base.acFlags |= AC_HARD;
this->actionTarget = 0x28;
}
void EnFloormas_MakeVulnerable(EnFloormas* this) {
this->collider.base.colType = COLTYPE_HIT0;
this->actionTarget = 0;
this->collider.base.acFlags &= ~AC_HARD;
}
void EnFloormas_SetupBigDecideAction(EnFloormas* this) {
Animation_PlayOnce(&this->skelAnime, &gWallmasterWaitAnim);
this->actionFunc = EnFloormas_BigDecideAction;
this->actor.speedXZ = 0.0f;
}
void EnFloormas_SetupStand(EnFloormas* this) {
Animation_MorphToPlayOnce(&this->skelAnime, &gWallmasterStandUpAnim, -3.0f);
this->actionFunc = EnFloormas_Stand;
}
void EnFloormas_SetupBigWalk(EnFloormas* this) {
if (this->actionFunc != EnFloormas_Run) {
Animation_PlayLoopSetSpeed(&this->skelAnime, &gWallmasterWalkAnim, 1.5f);
} else {
this->skelAnime.playSpeed = 1.5f;
}
this->actionTimer = Rand_S16Offset(2, 4);
this->actionFunc = EnFloormas_BigWalk;
this->actor.speedXZ = 1.5f;
}
void EnFloormas_SetupBigStopWalk(EnFloormas* this) {
Animation_PlayOnce(&this->skelAnime, &gWallmasterStopWalkAnim);
this->actionFunc = EnFloormas_BigStopWalk;
this->actor.speedXZ = 0.0f;
}
void EnFloormas_SetupRun(EnFloormas* this) {
this->actionTimer = 0;
this->actionFunc = EnFloormas_Run;
this->actor.speedXZ = 5.0f;
this->skelAnime.playSpeed = 3.0f;
}
void EnFloormas_SetupTurn(EnFloormas* this) {
s16 rotDelta = this->actionTarget - this->actor.shape.rot.y;
this->actor.speedXZ = 0.0f;
if (rotDelta > 0) {
Animation_MorphToPlayOnce(&this->skelAnime, &gFloormasterTurnAnim, -3.0f);
} else {
Animation_Change(&this->skelAnime, &gFloormasterTurnAnim, -1.0f, Animation_GetLastFrame(&gFloormasterTurnAnim),
0.0f, ANIMMODE_ONCE, -3.0f);
}
if (this->actor.scale.x > 0.004f) {
this->actionTarget = (rotDelta * (2.0f / 30.0f));
} else {
this->skelAnime.playSpeed = this->skelAnime.playSpeed + this->skelAnime.playSpeed;
this->actionTarget = rotDelta * (2.0f / 15.0f);
}
this->actionFunc = EnFloormas_Turn;
}
void EnFloormas_SetupHover(EnFloormas* this, GlobalContext* globalCtx) {
Animation_Change(&this->skelAnime, &gWallmasterHoverAnim, 3.0f, 0, Animation_GetLastFrame(&gWallmasterHoverAnim),
ANIMMODE_ONCE, -3.0f);
this->actor.speedXZ = 0.0f;
this->actor.gravity = 0.0f;
EnFloormas_MakeInvulnerable(this);
Actor_SpawnFloorDustRing(globalCtx, &this->actor, &this->actor.world.pos, 15.0f, 6, 20.0f, 300, 100, true);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_ATTACK);
this->actionFunc = EnFloormas_Hover;
}
void EnFloormas_SetupCharge(EnFloormas* this) {
this->actionTimer = 25;
this->actor.gravity = -0.15f;
this->actionFunc = EnFloormas_Charge;
this->actor.speedXZ = 0.5f;
}
void EnFloormas_SetupLand(EnFloormas* this) {
Animation_Change(&this->skelAnime, &gWallmasterJumpAnim, 1.0f, 41.0f, 42.0f, ANIMMODE_ONCE, 5.0f);
if ((this->actor.speedXZ < 0.0f) || (this->actionFunc != EnFloormas_Charge)) {
this->actionTimer = 30;
} else {
this->actionTimer = 45;
}
this->actor.gravity = -1.0f;
this->actionFunc = EnFloormas_Land;
}
void EnFloormas_SetupSplit(EnFloormas* this) {
Actor_SetScale(&this->actor, 0.004f);
this->actor.flags |= ACTOR_FLAG_4;
if (CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_7)) {
this->actor.draw = EnFloormas_DrawHighlighted;
} else {
this->actor.draw = EnFloormas_Draw;
}
this->actor.shape.rot.y = this->actor.parent->shape.rot.y + 0x5555;
this->actor.world.pos = this->actor.parent->world.pos;
this->actor.params = 0x10;
Animation_Change(&this->skelAnime, &gWallmasterJumpAnim, 1.0f, 41.0f, Animation_GetLastFrame(&gWallmasterJumpAnim),
ANIMMODE_ONCE, 0.0f);
this->collider.dim.radius = sCylinderInit.dim.radius * 0.6f;
this->collider.dim.height = sCylinderInit.dim.height * 0.6f;
this->collider.info.bumperFlags &= ~BUMP_HOOKABLE;
this->actor.speedXZ = 4.0f;
this->actor.velocity.y = 7.0f;
// using div creates a signed check.
this->actor.colChkInfo.health = sColChkInfoInit.health >> 1;
this->actionFunc = EnFloormas_Split;
}
void EnFloormas_SetupSmWalk(EnFloormas* this) {
Animation_PlayLoopSetSpeed(&this->skelAnime, &gWallmasterWalkAnim, 4.5f);
this->actionFunc = EnFloormas_SmWalk;
this->actor.speedXZ = 5.0f;
}
void EnFloormas_SetupSmDecideAction(EnFloormas* this) {
if (this->actionFunc != EnFloormas_SmWalk) {
Animation_PlayLoopSetSpeed(&this->skelAnime, &gWallmasterWalkAnim, 4.5f);
}
this->actionFunc = EnFloormas_SmDecideAction;
this->actor.speedXZ = 5.0f;
}
void EnFloormas_SetupSmShrink(EnFloormas* this, GlobalContext* globalCtx) {
static Vec3f velocity = { 0.0f, 0.0f, 0.0f };
static Vec3f accel = { 0.0f, 0.0f, 0.0f };
Vec3f pos;
this->actor.speedXZ = 0.0f;
this->actor.velocity.y = 0.0f;
pos.x = this->actor.world.pos.x;
pos.y = this->actor.world.pos.y + 15.0f;
pos.z = this->actor.world.pos.z;
EffectSsDeadDb_Spawn(globalCtx, &pos, &velocity, &accel, 150, -10, 255, 255, 255, 255, 0, 0, 255, 1, 9, true);
this->actionFunc = EnFloormas_SmShrink;
}
void EnFloormas_SetupSlaveJumpAtMaster(EnFloormas* this) {
Animation_Change(&this->skelAnime, &gWallmasterJumpAnim, 2.0f, 0.0f, 41.0f, ANIMMODE_ONCE, 0.0f);
this->actionFunc = EnFloormas_SmSlaveJumpAtMaster;
this->actor.speedXZ = 0.0f;
}
void EnFloormas_SetupJumpAtLink(EnFloormas* this) {
Animation_Change(&this->skelAnime, &gWallmasterJumpAnim, 2.0f, 0.0f, 41.0f, ANIMMODE_ONCE, 0.0f);
this->actionFunc = EnFloormas_JumpAtLink;
this->actor.speedXZ = 0.0f;
}
void EnFloormas_SetupGrabLink(EnFloormas* this, Player* player) {
f32 yDelta;
f32 xzDelta;
Animation_Change(&this->skelAnime, &gWallmasterJumpAnim, 1.0f, 36.0f, 45.0f, ANIMMODE_ONCE, -3.0f);
this->actor.flags &= ~ACTOR_FLAG_0;
this->actor.speedXZ = 0.0f;
this->actor.velocity.y = 0.0f;
EnFloormas_MakeInvulnerable(this);
if (!LINK_IS_ADULT) {
yDelta = CLAMP(-this->actor.yDistToPlayer, 20.0f, 30.0f);
xzDelta = -10.0f;
} else {
yDelta = CLAMP(-this->actor.yDistToPlayer, 25.0f, 45.0f);
xzDelta = -70.0f;
}
this->actor.world.pos.y = player->actor.world.pos.y + yDelta;
this->actor.world.pos.x = Math_SinS(this->actor.shape.rot.y) * (xzDelta * 0.1f) + player->actor.world.pos.x;
this->actor.world.pos.z = Math_CosS(this->actor.shape.rot.y) * (xzDelta * 0.1f) + player->actor.world.pos.z;
this->actor.shape.rot.x = -0x4CE0;
this->actionFunc = EnFloormas_GrabLink;
}
void EnFloormas_SetupMerge(EnFloormas* this) {
Animation_PlayOnce(&this->skelAnime, &gWallmasterWaitAnim);
this->actionTimer = 0;
this->smActionTimer += 1500;
EnFloormas_MakeInvulnerable(this);
this->actionFunc = EnFloormas_Merge;
}
void EnFloormas_SetupSmWait(EnFloormas* this) {
EnFloormas* parent = (EnFloormas*)this->actor.parent;
EnFloormas* child = (EnFloormas*)this->actor.child;
// if this is the last remaining small floor master, kill all.
if ((parent->actionFunc == EnFloormas_SmWait) && (child->actionFunc == EnFloormas_SmWait)) {
Actor_Kill(&parent->actor);
Actor_Kill(&child->actor);
Actor_Kill(&this->actor);
return;
}
this->actor.draw = NULL;
this->actionFunc = EnFloormas_SmWait;
this->actor.flags &= ~(ACTOR_FLAG_0 | ACTOR_FLAG_4);
}
void EnFloormas_SetupTakeDamage(EnFloormas* this) {
Animation_MorphToPlayOnce(&this->skelAnime, &gWallmasterDamageAnim, -3.0f);
if (this->collider.info.acHitInfo->toucher.dmgFlags & 0x1F824) {
this->actor.world.rot.y = this->collider.base.ac->world.rot.y;
} else {
this->actor.world.rot.y = Actor_WorldYawTowardActor(&this->actor, this->collider.base.ac) + 0x8000;
}
Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 0x14);
this->actionFunc = EnFloormas_TakeDamage;
this->actor.speedXZ = 5.0f;
this->actor.velocity.y = 5.5f;
}
void EnFloormas_SetupRecover(EnFloormas* this) {
Animation_PlayOnce(&this->skelAnime, &gWallmasterRecoverFromDamageAnim);
this->actor.velocity.y = this->actor.speedXZ = 0.0f;
this->actor.world.rot.y = this->actor.shape.rot.y;
this->actionFunc = EnFloormas_Recover;
}
void EnFloormas_SetupFreeze(EnFloormas* this) {
Animation_Change(&this->skelAnime, &gWallmasterJumpAnim, 1.5f, 0, 20.0f, ANIMMODE_ONCE, -3.0f);
this->actor.speedXZ = 0.0f;
if (this->actor.colChkInfo.damageEffect == 4) {
Actor_SetColorFilter(&this->actor, -0x8000, 0xFF, 0, 0x50);
} else {
Actor_SetColorFilter(&this->actor, 0, 0xFF, 0, 0x50);
if (this->actor.scale.x > 0.004f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
} else {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
}
}
this->actionTimer = 80;
this->actionFunc = EnFloormas_Freeze;
}
void EnFloormas_Die(EnFloormas* this, GlobalContext* globalCtx) {
//Originally was doing > 0.004f, better fix thanks Gary :D
if (this->actor.scale.x > (f32)0.004f) {
// split
this->actor.shape.rot.y = this->actor.yawTowardsPlayer + 0x8000;
EnFloormas_SetupSplit((EnFloormas*)this->actor.child);
EnFloormas_SetupSplit((EnFloormas*)this->actor.parent);
EnFloormas_SetupSplit(this);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SPLIT);
} else {
// Die
Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x90);
EnFloormas_SetupSmShrink(this, globalCtx);
}
}
void EnFloormas_BigDecideAction(EnFloormas* this, GlobalContext* globalCtx) {
if (SkelAnime_Update(&this->skelAnime)) {
// within 400 units of link and within 90 degrees rotation of him
if (this->actor.xzDistToPlayer < 400.0f && !Actor_IsFacingPlayer(&this->actor, 0x4000)) {
this->actionTarget = this->actor.yawTowardsPlayer;
EnFloormas_SetupTurn(this);
// within 280 units of link and within 45 degrees rotation of him
} else if (this->actor.xzDistToPlayer < 280.0f && Actor_IsFacingPlayer(&this->actor, 0x2000)) {
EnFloormas_SetupHover(this, globalCtx);
} else {
EnFloormas_SetupStand(this);
}
}
}
void EnFloormas_Stand(EnFloormas* this, GlobalContext* globalCtx) {
if (SkelAnime_Update(&this->skelAnime)) {
if (this->actor.scale.x > 0.004f) {
EnFloormas_SetupBigWalk(this);
} else if (this->actor.params == MERGE_SLAVE) {
EnFloormas_SetupSmDecideAction(this);
} else {
EnFloormas_SetupSmWalk(this);
}
}
}
void EnFloormas_BigWalk(EnFloormas* this, GlobalContext* globalCtx) {
s32 animPastFrame;
SkelAnime_Update(&this->skelAnime);
animPastFrame = Animation_OnFrame(&this->skelAnime, 0.0f);
if (animPastFrame) {
if (this->actionTimer != 0) {
this->actionTimer--;
}
}
if (((animPastFrame || (Animation_OnFrame(&this->skelAnime, 12.0f))) ||
(Animation_OnFrame(&this->skelAnime, 24.0f) != 0)) ||
(Animation_OnFrame(&this->skelAnime, 36.0f) != 0)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FALL_WALK);
}
if ((this->actor.xzDistToPlayer < 320.0f) && (Actor_IsFacingPlayer(&this->actor, 0x4000))) {
EnFloormas_SetupRun(this);
} else if (this->actor.bgCheckFlags & 8) {
// set target rotation to the colliding wall's rotation
this->actionTarget = this->actor.wallYaw;
EnFloormas_SetupTurn(this);
} else if ((this->actor.xzDistToPlayer < 400.0f) && !Actor_IsFacingPlayer(&this->actor, 0x4000)) {
// set target rotation to link.
this->actionTarget = this->actor.yawTowardsPlayer;
EnFloormas_SetupTurn(this);
} else if (this->actionTimer == 0) {
EnFloormas_SetupBigStopWalk(this);
}
}
void EnFloormas_BigStopWalk(EnFloormas* this, GlobalContext* globalCtx) {
if (SkelAnime_Update(&this->skelAnime)) {
EnFloormas_SetupBigDecideAction(this);
}
}
void EnFloormas_Run(EnFloormas* this, GlobalContext* globalCtx) {
SkelAnime_Update(&this->skelAnime);
if (Animation_OnFrame(&this->skelAnime, 0.0f) || Animation_OnFrame(&this->skelAnime, 12.0f) ||
Animation_OnFrame(&this->skelAnime, 24.0f) || Animation_OnFrame(&this->skelAnime, 36.0f)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FALL_WALK);
}
Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 0x71C);
if ((this->actor.xzDistToPlayer < 280.0f) && Actor_IsFacingPlayer(&this->actor, 0x2000) &&
!(this->actor.bgCheckFlags & 8)) {
EnFloormas_SetupHover(this, globalCtx);
} else if (this->actor.xzDistToPlayer > 400.0f) {
EnFloormas_SetupBigWalk(this);
}
}
void EnFloormas_Turn(EnFloormas* this, GlobalContext* globalCtx) {
char pad[4];
f32 sp30;
f32 sp2C;
if (SkelAnime_Update(&this->skelAnime)) {
EnFloormas_SetupStand(this);
}
if (((this->skelAnime.playSpeed > 0.0f) && Animation_OnFrame(&this->skelAnime, 21.0f)) ||
((this->skelAnime.playSpeed < 0.0f) && Animation_OnFrame(&this->skelAnime, 6.0f))) {
if (this->actor.scale.x > 0.004f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FALL_WALK);
} else {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_WALK);
}
}
// Needed to match
if (!this->skelAnime.curFrame) {}
if (this->skelAnime.curFrame >= 7.0f && this->skelAnime.curFrame < 22.0f) {
sp30 = Math_SinS(this->actor.shape.rot.y + 0x4268);
sp2C = Math_CosS(this->actor.shape.rot.y + 0x4268);
this->actor.shape.rot.y += this->actionTarget;
this->actor.world.pos.x -=
(this->actor.scale.x * 2700.0f) * (Math_SinS(this->actor.shape.rot.y + 0x4268) - sp30);
this->actor.world.pos.z -=
(this->actor.scale.x * 2700.0f) * (Math_CosS(this->actor.shape.rot.y + 0x4268) - sp2C);
}
}
void EnFloormas_Hover(EnFloormas* this, GlobalContext* globalCtx) {
if (SkelAnime_Update(&this->skelAnime)) {
EnFloormas_SetupCharge(this);
}
this->actor.shape.rot.x += 0x140;
this->actor.world.pos.y += 10.0f;
Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 2730);
Math_StepToS(&this->zOffset, 1200, 100);
}
void EnFloormas_Slide(EnFloormas* this, GlobalContext* globalCtx) {
static Vec3f accel = { 0.0f, 0.0f, 0.0f };
Vec3f pos;
Vec3f velocity;
pos.x = this->actor.world.pos.x;
pos.z = this->actor.world.pos.z;
pos.y = this->actor.floorHeight;
velocity.y = 2.0f;
velocity.x = Math_SinS(this->actor.shape.rot.y + 0x6000) * 7.0f;
velocity.z = Math_CosS(this->actor.shape.rot.y + 0x6000) * 7.0f;
func_800286CC(globalCtx, &pos, &velocity, &accel, 450, 100);
velocity.x = Math_SinS(this->actor.shape.rot.y - 0x6000) * 7.0f;
velocity.z = Math_CosS(this->actor.shape.rot.y - 0x6000) * 7.0f;
func_800286CC(globalCtx, &pos, &velocity, &accel, 450, 100);
func_8002F974(&this->actor, NA_SE_EN_FLOORMASTER_SLIDING);
}
void EnFloormas_Charge(EnFloormas* this, GlobalContext* globalCtx) {
f32 distFromGround;
if (this->actionTimer != 0) {
this->actionTimer--;
}
Math_StepToF(&this->actor.speedXZ, 15.0f, SQ(this->actor.speedXZ) * (1.0f / 3.0f));
Math_ScaledStepToS(&this->actor.shape.rot.x, -0x1680, 0x140);
distFromGround = this->actor.world.pos.y - this->actor.floorHeight;
if (distFromGround < 10.0f) {
this->actor.world.pos.y = this->actor.floorHeight + 10.0f;
this->actor.gravity = 0.0f;
this->actor.velocity.y = 0.0f;
}
if (distFromGround < 12.0f) {
EnFloormas_Slide(this, globalCtx);
}
if ((this->actor.bgCheckFlags & 8) || (this->actionTimer == 0)) {
EnFloormas_SetupLand(this);
}
}
void EnFloormas_Land(EnFloormas* this, GlobalContext* globalCtx) {
s32 isOnGround;
isOnGround = this->actor.bgCheckFlags & 1;
if (this->actor.bgCheckFlags & 2) {
if (this->actor.params != MERGE_MASTER) {
EnFloormas_MakeVulnerable(this);
}
if (this->actor.velocity.y < -4.0f) {
if (this->actor.scale.x > 0.004f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FALL_LAND);
} else {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_LAND);
}
}
}
if (this->actor.bgCheckFlags & 8) {
this->actor.speedXZ = 0.0f;
}
if (isOnGround) {
Math_StepToF(&this->actor.speedXZ, 0.0f, 2.0f);
}
if ((this->actor.speedXZ > 0.0f) && ((this->actor.world.pos.y - this->actor.floorHeight) < 12.0f)) {
EnFloormas_Slide(this, globalCtx);
}
if (SkelAnime_Update(&this->skelAnime)) {
if (this->actionTimer != 0) {
this->actionTimer--;
}
if (this->actionTimer == 0 && isOnGround) {
if (this->skelAnime.endFrame < 45.0f) {
this->skelAnime.endFrame = Animation_GetLastFrame(&gWallmasterJumpAnim);
} else if (this->actor.params == MERGE_MASTER) {
EnFloormas_SetupMerge(this);
} else {
EnFloormas_SetupStand(this);
this->smActionTimer = 50;
}
}
}
Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x140);
Math_StepToS(&this->zOffset, -1600, 100);
}
void EnFloormas_Split(EnFloormas* this, GlobalContext* globalCtx) {
if (this->actor.bgCheckFlags & 1) {
if (SkelAnime_Update(&this->skelAnime)) {
this->actor.flags |= ACTOR_FLAG_0;
this->smActionTimer = 50;
EnFloormas_SetupStand(this);
}
Math_StepToF(&this->actor.speedXZ, 0.0f, 1.0f);
}
if (this->actor.bgCheckFlags & 2) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_LAND);
}
}
void EnFloormas_SmWalk(EnFloormas* this, GlobalContext* globalCtx) {
SkelAnime_Update(&this->skelAnime);
DECR(this->smActionTimer);
if (Animation_OnFrame(&this->skelAnime, 0.0f) || Animation_OnFrame(&this->skelAnime, 18.0f)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_WALK);
}
if (this->smActionTimer == 0) {
EnFloormas_SetupSmDecideAction(this);
} else if (this->actor.bgCheckFlags & 8) {
this->actionTarget = this->actor.wallYaw;
EnFloormas_SetupTurn(this);
} else if (this->actor.xzDistToPlayer < 120.0f) {
Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer + 0x8000, 0x38E);
}
}
void EnFloormas_SmDecideAction(EnFloormas* this, GlobalContext* globalCtx) {
Actor* primaryFloormas;
s32 isAgainstWall;
SkelAnime_Update(&this->skelAnime);
if (Animation_OnFrame(&this->skelAnime, 0.0f) || Animation_OnFrame(&this->skelAnime, 18.0f)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_WALK);
}
isAgainstWall = this->actor.bgCheckFlags & 8;
if (isAgainstWall) {
this->actionTarget = this->actor.wallYaw;
EnFloormas_SetupTurn(this);
return;
}
if (this->actor.params == MERGE_SLAVE) {
if (this->actor.parent->params == MERGE_MASTER) {
primaryFloormas = this->actor.parent;
} else if (this->actor.child->params == MERGE_MASTER) {
primaryFloormas = this->actor.child;
} else {
this->actor.params = 0x10;
return;
}
Math_ScaledStepToS(&this->actor.shape.rot.y, Actor_WorldYawTowardActor(&this->actor, primaryFloormas), 0x38E);
if (Actor_WorldDistXZToActor(&this->actor, primaryFloormas) < 80.0f) {
EnFloormas_SetupSlaveJumpAtMaster(this);
}
} else {
Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 0x71C);
if (this->actor.xzDistToPlayer < 80.0f) {
EnFloormas_SetupJumpAtLink(this);
}
}
}
void EnFloormas_SmShrink(EnFloormas* this, GlobalContext* globalCtx) {
if (Math_StepToF(&this->actor.scale.x, 0.0f, 0.0015f)) {
EnFloormas_SetupSmWait(this);
}
this->actor.scale.z = this->actor.scale.x;
this->actor.scale.y = this->actor.scale.x;
}
void EnFloormas_JumpAtLink(EnFloormas* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
SkelAnime_Update(&this->skelAnime);
if (this->skelAnime.curFrame < 20.0f) {
Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38);
} else if (Animation_OnFrame(&this->skelAnime, 20.0f)) {
this->actor.speedXZ = 5.0f;
this->actor.velocity.y = 7.0f;
} else if (this->actor.bgCheckFlags & 2) {
this->actionTimer = 0x32;
this->actor.speedXZ = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_LAND);
EnFloormas_SetupLand(this);
} else if ((this->actor.yDistToPlayer < -10.0f) && (this->collider.base.ocFlags1 & OC1_HIT) &&
(&player->actor == this->collider.base.oc)) {
globalCtx->grabPlayer(globalCtx, player);
EnFloormas_SetupGrabLink(this, player);
}
}
void EnFloormas_GrabLink(EnFloormas* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
EnFloormas* parent;
EnFloormas* child;
f32 yDelta;
f32 xzDelta;
if (SkelAnime_Update(&this->skelAnime)) {
if (this->skelAnime.playSpeed > 0.0f) {
this->skelAnime.playSpeed = -1.0f;
this->skelAnime.endFrame = 36.0f;
this->skelAnime.startFrame = 45.0f;
} else {
this->skelAnime.playSpeed = 1.0f;
this->skelAnime.endFrame = 45.0f;
this->skelAnime.startFrame = 36.0f;
}
}
if (!LINK_IS_ADULT) {
yDelta = CLAMP(-this->actor.yDistToPlayer, 20.0f, 30.0f);
xzDelta = -10.0f;
} else {
yDelta = CLAMP(-this->actor.yDistToPlayer, 25.0f, 45.0f);
xzDelta = -30.0f;
}
this->actor.world.pos.y = player->actor.world.pos.y + yDelta;
this->actor.world.pos.x = Math_SinS(this->actor.shape.rot.y) * (xzDelta * 0.1f) + player->actor.world.pos.x;
this->actor.world.pos.z = Math_CosS(this->actor.shape.rot.y) * (xzDelta * 0.1f) + player->actor.world.pos.z;
// let go
if (!(player->stateFlags2 & 0x80) || (player->invincibilityTimer < 0)) {
parent = (EnFloormas*)this->actor.parent;
child = (EnFloormas*)this->actor.child;
if (((parent->actionFunc == EnFloormas_GrabLink) || parent->actionFunc == EnFloormas_SmWait) &&
(child->actionFunc == EnFloormas_GrabLink || child->actionFunc == EnFloormas_SmWait)) {
parent->actor.params = MERGE_SLAVE;
child->actor.params = MERGE_SLAVE;
this->actor.params = MERGE_MASTER;
}
this->actor.shape.rot.x = 0;
this->actor.velocity.y = 6.0f;
this->actor.flags |= ACTOR_FLAG_0;
this->actor.speedXZ = -3.0f;
EnFloormas_SetupLand(this);
} else {
// Damage link every 20 frames
if ((this->actionTarget % 20) == 0) {
if (!LINK_IS_ADULT) {
func_8002F7DC(&player->actor, NA_SE_VO_LI_DAMAGE_S_KID);
} else {
func_8002F7DC(&player->actor, NA_SE_VO_LI_DAMAGE_S);
}
globalCtx->damagePlayer(globalCtx, -8);
}
}
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_STICK);
}
void EnFloormas_SmSlaveJumpAtMaster(EnFloormas* this, GlobalContext* globalCtx) {
Actor* primFloormas;
SkelAnime_Update(&this->skelAnime);
if (this->actor.parent->params == MERGE_MASTER) {
primFloormas = this->actor.parent;
} else if (this->actor.child->params == MERGE_MASTER) {
primFloormas = this->actor.child;
} else {
if (this->actor.bgCheckFlags & 2) {
this->actor.params = 0x10;
EnFloormas_SetupLand(this);
}
return;
}
if (Animation_OnFrame(&this->skelAnime, 20.0f)) {
this->actor.speedXZ = 5.0f;
this->actor.velocity.y = 7.0f;
} else if (this->skelAnime.curFrame < 20.0f) {
Math_ApproachS(&this->actor.shape.rot.y, Actor_WorldYawTowardActor(&this->actor, primFloormas), 2, 0xE38);
} else if ((((primFloormas->world.pos.y - this->actor.world.pos.y) < -10.0f) &&
(fabsf(this->actor.world.pos.x - primFloormas->world.pos.x) < 10.0f)) &&
(fabsf(this->actor.world.pos.z - primFloormas->world.pos.z) < 10.0f)) {
EnFloormas_SetupSmWait(this);
this->collider.base.ocFlags1 |= OC1_ON;
} else if (this->actor.bgCheckFlags & 2) {
this->actor.speedXZ = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_LAND);
EnFloormas_SetupLand(this);
}
if (fabsf(this->actor.world.pos.x - primFloormas->world.pos.x) < 5.0f &&
fabsf(this->actor.world.pos.z - primFloormas->world.pos.z) < 5.0f) {
Math_StepToF(&this->actor.speedXZ, 0, 2.0f);
}
}
void EnFloormas_Merge(EnFloormas* this, GlobalContext* globalCtx) {
EnFloormas* parent;
EnFloormas* child;
s32 mergeCnt;
f32 prevScale;
f32 curScale;
mergeCnt = 0;
DECR(this->smActionTimer);
parent = (EnFloormas*)this->actor.parent;
child = (EnFloormas*)this->actor.child;
if (this->smActionTimer == 0) {
if (parent->actionFunc != EnFloormas_SmWait) {
EnFloormas_SetupSmShrink(parent, globalCtx);
}
if (child->actionFunc != EnFloormas_SmWait) {
EnFloormas_SetupSmShrink(child, globalCtx);
}
} else {
if ((parent->actionFunc != EnFloormas_SmWait) && (parent->actionFunc != EnFloormas_SmShrink)) {
mergeCnt++;
}
if ((child->actionFunc != EnFloormas_SmWait) && (child->actionFunc != EnFloormas_SmShrink)) {
mergeCnt++;
}
}
prevScale = this->actor.scale.x;
if (mergeCnt == 1) {
Math_StepToF(&this->actor.scale.x, 0.007f, 0.0005f);
} else if (mergeCnt == 0) {
Math_StepToF(&this->actor.scale.x, 0.01f, 0.0005f);
}
curScale = this->actor.scale.x;
this->actor.scale.y = this->actor.scale.z = curScale;
if (((prevScale == 0.007f) || (prevScale == 0.004f)) && (prevScale != this->actor.scale.x)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_EXPAND);
}
this->collider.dim.radius = (sCylinderInit.dim.radius * 100.0f) * this->actor.scale.x;
this->collider.dim.height = (sCylinderInit.dim.height * 100.0f) * this->actor.scale.x;
if (SkelAnime_Update(&this->skelAnime) != 0) {
if (this->actor.scale.x >= 0.01f) {
this->actor.flags &= ~ACTOR_FLAG_4;
EnFloormas_MakeVulnerable(this);
this->actor.params = 0;
this->collider.info.bumperFlags |= BUMP_HOOKABLE;
this->actor.colChkInfo.health = sColChkInfoInit.health;
EnFloormas_SetupStand(this);
} else {
if (this->actionTimer == 0) {
Animation_PlayOnce(&this->skelAnime, &gFloormasterTapFingerAnim);
this->actionTimer = 1;
} else {
Animation_PlayOnce(&this->skelAnime, &gWallmasterWaitAnim);
this->actionTimer = 0;
}
}
}
func_8002F974(&this->actor, NA_SE_EN_FLOORMASTER_RESTORE - SFX_FLAG);
}
void EnFloormas_SmWait(EnFloormas* this, GlobalContext* globalCtx) {
}
void EnFloormas_TakeDamage(EnFloormas* this, GlobalContext* globalCtx) {
if (SkelAnime_Update(&this->skelAnime) != 0) {
if (this->actor.colChkInfo.health == 0) {
EnFloormas_Die(this, globalCtx);
} else {
EnFloormas_SetupRecover(this);
}
}
if (Animation_OnFrame(&this->skelAnime, 13.0f)) {
if (this->actor.scale.x > 0.004f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DODO_M_GND);
} else {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DODO_M_GND);
}
}
Math_StepToF(&this->actor.speedXZ, 0.0f, 0.2f);
}
void EnFloormas_Recover(EnFloormas* this, GlobalContext* globalCtx) {
if (SkelAnime_Update(&this->skelAnime) != 0) {
EnFloormas_SetupStand(this);
}
}
void EnFloormas_Freeze(EnFloormas* this, GlobalContext* globalCtx) {
SkelAnime_Update(&this->skelAnime);
if (this->actionTimer != 0) {
this->actionTimer--;
}
if (this->actionTimer == 0) {
if (this->actor.colChkInfo.health == 0) {
EnFloormas_Die(this, globalCtx);
return;
}
EnFloormas_SetupStand(this);
}
}
void EnFloormas_ColliderCheck(EnFloormas* this, GlobalContext* globalCtx) {
s32 pad;
s32 isSmall;
if ((this->collider.base.acFlags & AC_HIT) != 0) {
this->collider.base.acFlags &= ~AC_HIT;
Actor_SetDropFlag(&this->actor, &this->collider.info, 1);
if ((this->actor.colChkInfo.damageEffect != 0) || (this->actor.colChkInfo.damage != 0)) {
if (this->collider.base.colType != COLTYPE_HARD) {
isSmall = 0;
if (this->actor.scale.x < 0.01f) {
isSmall = 1;
}
if (isSmall && this->collider.info.acHitInfo->toucher.dmgFlags & 0x80) {
this->actor.colChkInfo.damage = 2;
this->actor.colChkInfo.damageEffect = 0;
}
if (Actor_ApplyDamage(&this->actor) == 0) {
if (isSmall) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FLOORMASTER_SM_DEAD);
} else {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FALL_DEAD);
}
Enemy_StartFinishingBlow(globalCtx, &this->actor);
this->actor.flags &= ~ACTOR_FLAG_0;
} else if (this->actor.colChkInfo.damage != 0) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FALL_DAMAGE);
}
if ((this->actor.colChkInfo.damageEffect == 4) || (this->actor.colChkInfo.damageEffect == 1)) {
if (this->actionFunc != EnFloormas_Freeze) {
EnFloormas_SetupFreeze(this);
}
} else {
if (this->actor.colChkInfo.damageEffect == 2) {
EffectSsFCircle_Spawn(globalCtx, &this->actor, &this->actor.world.pos,
this->actor.scale.x * 4000.0f, this->actor.scale.x * 4000.0f);
}
EnFloormas_SetupTakeDamage(this);
}
}
}
}
}
void EnFloormas_Update(Actor* thisx, GlobalContext* globalCtx) {
EnFloormas* this = (EnFloormas*)thisx;
s32 pad;
if (this->actionFunc != EnFloormas_SmWait) {
if (this->collider.base.atFlags & AT_HIT) {
this->collider.base.atFlags &= ~AT_HIT;
this->actor.speedXZ *= -0.5f;
if (-5.0f < this->actor.speedXZ) {
this->actor.speedXZ = -5.0f;
} else {
this->actor.speedXZ = this->actor.speedXZ;
}
this->actor.velocity.y = 5.0f;
EnFloormas_SetupLand(this);
}
EnFloormas_ColliderCheck(this, globalCtx);
this->actionFunc(this, globalCtx);
if (this->actionFunc != EnFloormas_TakeDamage) {
this->actor.world.rot.y = this->actor.shape.rot.y;
}
if (this->actionFunc != EnFloormas_GrabLink) {
Actor_MoveForward(&this->actor);
}
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, this->actor.scale.x * 3000.0f, 0.0f, 0x1D);
Collider_UpdateCylinder(&this->actor, &this->collider);
if (this->actionFunc == EnFloormas_Charge) {
this->actor.flags |= ACTOR_FLAG_24;
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
if (this->actionFunc != EnFloormas_GrabLink) {
if (this->actionFunc != EnFloormas_Split && this->actionFunc != EnFloormas_TakeDamage &&
this->actor.freezeTimer == 0) {
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
if ((this->actionFunc != EnFloormas_SmSlaveJumpAtMaster) || (this->skelAnime.curFrame < 20.0f)) {
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
Actor_SetFocus(&this->actor, this->actor.scale.x * 2500.0f);
if (this->collider.base.colType == COLTYPE_HARD) {
if (this->actionTarget != 0) {
this->actionTarget--;
}
if (this->actionTarget == 0) {
this->actionTarget = 0x28;
}
}
}
}
s32 EnFloormas_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
void* thisx, Gfx** gfx) {
EnFloormas* this = (EnFloormas*)thisx;
if (limbIndex == 1) {
pos->z += this->zOffset;
}
return false;
}
void EnFloormas_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx, Gfx** gfx) {
if (limbIndex == 2) {
Matrix_Push();
Matrix_Translate(1600.0f, -700.0f, -1700.0f, MTXMODE_APPLY);
Matrix_RotateY(DEGTORAD(60.0f), MTXMODE_APPLY);
Matrix_RotateZ(DEGTORAD(15.0f), MTXMODE_APPLY);
Matrix_Scale(2.0f, 2.0f, 2.0f, MTXMODE_APPLY);
gSPMatrix((*gfx)++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_LOAD);
gSPDisplayList((*gfx)++, gWallmasterFingerDL);
Matrix_Pop();
}
}
static Color_RGBA8 sMergeColor = { 0, 255, 0, 0 };
void EnFloormas_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnFloormas* this = (EnFloormas*)thisx;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
if (this->collider.base.colType == COLTYPE_HARD) {
func_80026230(globalCtx, &sMergeColor, this->actionTarget % 0x28, 0x28);
}
POLY_OPA_DISP =
SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
EnFloormas_OverrideLimbDraw, EnFloormas_PostLimbDraw, this, POLY_OPA_DISP);
if (this->collider.base.colType == COLTYPE_HARD) {
func_80026608(globalCtx);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
void EnFloormas_DrawHighlighted(Actor* thisx, GlobalContext* globalCtx) {
EnFloormas* this = (EnFloormas*)thisx;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D84(globalCtx->state.gfxCtx);
if (this->collider.base.colType == COLTYPE_HARD) {
func_80026690(globalCtx, &sMergeColor, this->actionTarget % 0x28, 0x28);
}
POLY_XLU_DISP =
SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
EnFloormas_OverrideLimbDraw, EnFloormas_PostLimbDraw, this, POLY_XLU_DISP);
if (this->collider.base.colType == COLTYPE_HARD) {
func_80026A6C(globalCtx);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}