mirror of
https://github.com/zeldaret/oot.git
synced 2025-07-03 06:24:30 +00:00
Decompile and label EnEiyer (#852)
* En_Eiyer OK * Label EnEiyer * Style fixes * Rename colCyl -> collider * Use CLAMP_MIN * Format * Review changes
This commit is contained in:
parent
23dc339882
commit
877544491b
38 changed files with 661 additions and 1980 deletions
|
@ -9,14 +9,40 @@ void EnEiyer_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|||
void EnEiyer_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnEiyer_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
extern UNK_TYPE D_06000288;
|
||||
extern UNK_TYPE D_060004C4;
|
||||
extern UNK_TYPE D_06000704;
|
||||
extern UNK_TYPE D_06000FC0;
|
||||
extern UNK_TYPE D_060012AC;
|
||||
extern UNK_TYPE D_06003410;
|
||||
void EnEiyer_SetupAppearFromGround(EnEiyer* this);
|
||||
void EnEiyer_SetupUnderground(EnEiyer* this);
|
||||
void EnEiyer_SetupInactive(EnEiyer* this);
|
||||
void EnEiyer_SetupAmbush(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_SetupGlide(EnEiyer* this);
|
||||
void EnEiyer_SetupStartAttack(EnEiyer* this);
|
||||
void EnEiyer_SetupDiveAttack(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_SetupLand(EnEiyer* this);
|
||||
void EnEiyer_SetupHurt(EnEiyer* this);
|
||||
void EnEiyer_SetupDie(EnEiyer* this);
|
||||
void EnEiyer_SetupDead(EnEiyer* this);
|
||||
void EnEiyer_SetupStunned(EnEiyer* this);
|
||||
|
||||
void EnEiyer_AppearFromGround(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_WanderUnderground(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_CircleUnderground(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Inactive(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Ambush(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Glide(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_StartAttack(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_DiveAttack(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Land(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Hurt(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Die(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Dead(EnEiyer* this, GlobalContext* globalCtx);
|
||||
void EnEiyer_Stunned(EnEiyer* this, GlobalContext* globalCtx);
|
||||
|
||||
extern AnimationHeader D_06000288;
|
||||
extern AnimationHeader D_060004C4;
|
||||
extern AnimationHeader D_06000704;
|
||||
extern AnimationHeader D_06000FC0;
|
||||
extern AnimationHeader D_060012AC;
|
||||
extern SkeletonHeader D_06003410;
|
||||
|
||||
/*
|
||||
const ActorInit En_Eiyer_InitVars = {
|
||||
ACTOR_EN_EIYER,
|
||||
ACTORCAT_ENEMY,
|
||||
|
@ -29,7 +55,7 @@ const ActorInit En_Eiyer_InitVars = {
|
|||
(ActorFunc)EnEiyer_Draw,
|
||||
};
|
||||
|
||||
static ColliderCylinderInit D_80A01970 = {
|
||||
static ColliderCylinderInit sColCylInit = {
|
||||
{
|
||||
COLTYPE_HIT0,
|
||||
AT_ON | AT_TYPE_ENEMY,
|
||||
|
@ -48,69 +74,651 @@ static ColliderCylinderInit D_80A01970 = {
|
|||
},
|
||||
{ 27, 17, -10, { 0, 0, 0 } },
|
||||
};
|
||||
*/
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/EnEiyer_Init.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/EnEiyer_Destroy.s")
|
||||
static CollisionCheckInfoInit sColChkInfoInit = { 2, 45, 15, 100 };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A001A4.s")
|
||||
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(2, 0x0),
|
||||
/* Kokiri sword */ DMG_ENTRY(1, 0x0),
|
||||
/* Master sword */ DMG_ENTRY(2, 0x0),
|
||||
/* Giant's Knife */ DMG_ENTRY(4, 0x0),
|
||||
/* Fire arrow */ DMG_ENTRY(2, 0x0),
|
||||
/* Ice arrow */ DMG_ENTRY(2, 0x0),
|
||||
/* Light arrow */ DMG_ENTRY(2, 0x0),
|
||||
/* Unk arrow 1 */ DMG_ENTRY(2, 0x0),
|
||||
/* Unk arrow 2 */ DMG_ENTRY(2, 0x0),
|
||||
/* Unk arrow 3 */ DMG_ENTRY(2, 0x0),
|
||||
/* Fire magic */ DMG_ENTRY(0, 0x0),
|
||||
/* Ice magic */ DMG_ENTRY(4, 0x0),
|
||||
/* Light magic */ DMG_ENTRY(4, 0x0),
|
||||
/* 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),
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00218.s")
|
||||
static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_S8(naviEnemyId, 25, ICHAIN_CONTINUE),
|
||||
ICHAIN_VEC3F_DIV1000(scale, 5, ICHAIN_CONTINUE),
|
||||
ICHAIN_F32(targetArrowOffset, 2500, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00358.s")
|
||||
/**
|
||||
* params 0: Spawn 3 clones and circle around spawn point
|
||||
* params 1-3: Clone, spawn another clone for the main Eiyer if params < 3
|
||||
* params 10: Normal Eiyer, wander around spawn point
|
||||
*/
|
||||
void EnEiyer_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnEiyer* this = THIS;
|
||||
s32 pad;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A003B4.s")
|
||||
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||
ActorShape_Init(&this->actor.shape, 600.0f, ActorShadow_DrawCircle, 65.0f);
|
||||
SkelAnime_Init(globalCtx, &this->skelanime, &D_06003410, &D_060012AC, this->jointTable, this->morphTable, 19);
|
||||
Collider_InitCylinder(globalCtx, &this->collider);
|
||||
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sColCylInit);
|
||||
CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A003DC.s")
|
||||
if (this->actor.params < 3) {
|
||||
// Each clone spawns another clone
|
||||
if (Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_EIYER, this->actor.home.pos.x,
|
||||
this->actor.home.pos.y, this->actor.home.pos.z, 0, this->actor.shape.rot.y + 0x4000, 0,
|
||||
this->actor.params + 1) == NULL) {
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A004BC.s")
|
||||
if (this->actor.params == 0) {
|
||||
Actor* child = this->actor.child;
|
||||
s32 clonesSpawned;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00534.s")
|
||||
for (clonesSpawned = 0; clonesSpawned != 3; clonesSpawned++) {
|
||||
if (child == NULL) {
|
||||
break;
|
||||
}
|
||||
child = child->child;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00544.s")
|
||||
if (clonesSpawned != 3) {
|
||||
for (child = &this->actor; child != NULL; child = child->child) {
|
||||
Actor_Kill(child);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
this->actor.child->parent = &this->actor;
|
||||
this->actor.child->child->parent = &this->actor;
|
||||
this->actor.child->child->child->parent = &this->actor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00588.s")
|
||||
if (this->actor.params == 0 || this->actor.params == 10) {
|
||||
EnEiyer_SetupAppearFromGround(this);
|
||||
} else {
|
||||
EnEiyer_SetupInactive(this);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00600.s")
|
||||
void EnEiyer_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnEiyer* this = THIS;
|
||||
Collider_DestroyCylinder(globalCtx, &this->collider);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A006B0.s")
|
||||
void EnEiyer_RotateAroundHome(EnEiyer* this) {
|
||||
this->actor.world.pos.x = Math_SinS(this->actor.world.rot.y) * 80.0f + this->actor.home.pos.x;
|
||||
this->actor.world.pos.z = Math_CosS(this->actor.world.rot.y) * 80.0f + this->actor.home.pos.z;
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y + 0x4000;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A0076C.s")
|
||||
void EnEiyer_SetupAppearFromGround(EnEiyer* this) {
|
||||
this->collider.info.bumper.dmgFlags = 0x19;
|
||||
Animation_PlayLoop(&this->skelanime, &D_060012AC);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00794.s")
|
||||
this->actor.world.pos.x = this->actor.home.pos.x;
|
||||
this->actor.world.pos.y = this->actor.home.pos.y - 40.0f;
|
||||
this->actor.world.pos.z = this->actor.home.pos.z;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00858.s")
|
||||
if (this->actor.params != 0xA) {
|
||||
if (this->actor.params == 0) {
|
||||
this->actor.world.rot.y = Rand_ZeroOne() * 0x10000;
|
||||
} else {
|
||||
this->actor.world.rot.y = this->actor.parent->world.rot.y + this->actor.params * 0x4000;
|
||||
}
|
||||
EnEiyer_RotateAroundHome(this);
|
||||
} else {
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y = Rand_ZeroOne() * 0x10000;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A008A4.s")
|
||||
this->collider.base.atFlags &= ~AT_ON;
|
||||
this->collider.base.acFlags &= ~AC_ON;
|
||||
this->actor.flags &= ~0x1001;
|
||||
this->actor.shape.shadowScale = 0.0f;
|
||||
this->actor.shape.yOffset = 0.0f;
|
||||
this->actionFunc = EnEiyer_AppearFromGround;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A008D4.s")
|
||||
void EnEiyer_SetupUnderground(EnEiyer* this) {
|
||||
if (this->actor.params == 0xA) {
|
||||
this->actor.speedXZ = -0.5f;
|
||||
this->actionFunc = EnEiyer_WanderUnderground;
|
||||
} else {
|
||||
this->actionFunc = EnEiyer_CircleUnderground;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00950.s")
|
||||
this->collider.base.acFlags |= AC_ON;
|
||||
this->actor.flags &= ~0x10;
|
||||
this->actor.flags |= 1;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00A84.s")
|
||||
void EnEiyer_SetupInactive(EnEiyer* this) {
|
||||
this->actor.flags &= ~1;
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||
this->actionFunc = EnEiyer_Inactive;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00B18.s")
|
||||
void EnEiyer_SetupAmbush(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
this->actor.speedXZ = 0.0f;
|
||||
Animation_PlayOnce(&this->skelanime, &D_06000704);
|
||||
this->collider.info.bumper.dmgFlags = ~0x00300000;
|
||||
this->basePos = this->actor.world.pos;
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||
this->actor.flags |= 0x1000;
|
||||
this->collider.base.acFlags &= ~AC_ON;
|
||||
this->actor.shape.shadowScale = 65.0f;
|
||||
this->actor.shape.yOffset = 600.0f;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_OCTAROCK_JUMP);
|
||||
EffectSsGSplash_Spawn(globalCtx, &this->actor.world.pos, NULL, NULL, 1, 700);
|
||||
this->actionFunc = EnEiyer_Ambush;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00C70.s")
|
||||
void EnEiyer_SetupGlide(EnEiyer* this) {
|
||||
this->targetYaw = this->actor.shape.rot.y;
|
||||
this->basePos.y = (cosf(-M_PI / 8) * 5.0f) + this->actor.world.pos.y;
|
||||
Animation_MorphToLoop(&this->skelanime, &D_06000FC0, -5.0f);
|
||||
this->timer = 60;
|
||||
this->actionFunc = EnEiyer_Glide;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00E8C.s")
|
||||
void EnEiyer_SetupStartAttack(EnEiyer* this) {
|
||||
this->actionFunc = EnEiyer_StartAttack;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A00F84.s")
|
||||
void EnEiyer_SetupDiveAttack(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A01010.s")
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->basePos.y = player->actor.world.pos.y + 15.0f;
|
||||
this->collider.base.atFlags |= AT_ON;
|
||||
this->collider.base.atFlags &= ~AT_HIT;
|
||||
this->actionFunc = EnEiyer_DiveAttack;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A01104.s")
|
||||
void EnEiyer_SetupLand(EnEiyer* this) {
|
||||
Animation_MorphToPlayOnce(&this->skelanime, &D_060004C4, -3.0f);
|
||||
this->collider.base.atFlags &= ~AT_ON;
|
||||
this->actor.flags |= 0x10;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A01240.s")
|
||||
// Update BgCheck info, play sound, and spawn effect on the first frame of the land action
|
||||
this->timer = -1;
|
||||
this->actor.gravity = 0.0f;
|
||||
this->collider.dim.height = sColCylInit.dim.height;
|
||||
this->actionFunc = EnEiyer_Land;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A012F4.s")
|
||||
void EnEiyer_SetupHurt(EnEiyer* this) {
|
||||
this->basePos.y = this->actor.world.pos.y;
|
||||
Animation_Change(&this->skelanime, &D_06000FC0, 2.0f, 0.0f, 0.0f, 0, -3.0f);
|
||||
this->timer = 40;
|
||||
this->actor.gravity = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.speedXZ = 5.0f;
|
||||
Actor_SetColorFilter(&this->actor, 0x4000, 200, 0, 40);
|
||||
this->collider.base.acFlags &= ~AC_ON;
|
||||
this->actionFunc = EnEiyer_Hurt;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A01374.s")
|
||||
void EnEiyer_SetupDie(EnEiyer* this) {
|
||||
this->timer = 20;
|
||||
Actor_SetColorFilter(&this->actor, 0x4000, 200, 0, 40);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A0142C.s")
|
||||
if (this->collider.info.bumper.dmgFlags != 0x19) {
|
||||
this->actor.speedXZ = 6.0f;
|
||||
Animation_MorphToLoop(&this->skelanime, &D_06000FC0, -3.0f);
|
||||
} else {
|
||||
this->actor.speedXZ -= 6.0f;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/EnEiyer_Update.s")
|
||||
this->collider.info.bumper.dmgFlags = ~0x00300000;
|
||||
this->collider.base.atFlags &= ~AT_ON;
|
||||
this->collider.base.acFlags &= ~AC_ON;
|
||||
this->actionFunc = EnEiyer_Die;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/func_80A0178C.s")
|
||||
void EnEiyer_SetupDead(EnEiyer* this) {
|
||||
this->actor.colorFilterParams |= 0x2000;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actionFunc = EnEiyer_Dead;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Eiyer/EnEiyer_Draw.s")
|
||||
void EnEiyer_SetupStunned(EnEiyer* this) {
|
||||
Animation_Change(&this->skelanime, &D_06000288, 2.0f, 0.0f, 0.0f, 0, -8.0f);
|
||||
this->timer = 80;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.gravity = -1.0f;
|
||||
this->collider.dim.height = sColCylInit.dim.height + 8;
|
||||
Actor_SetColorFilter(&this->actor, 0, 200, 0, 80);
|
||||
this->collider.base.atFlags &= ~AT_ON;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
|
||||
this->actionFunc = EnEiyer_Stunned;
|
||||
}
|
||||
|
||||
void EnEiyer_AppearFromGround(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 0.75f)) {
|
||||
EnEiyer_SetupUnderground(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_CheckPlayerCollision(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) {
|
||||
this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER;
|
||||
EnEiyer_SetupAmbush(this, globalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_CircleUnderground(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
this->actor.world.rot.y += -0x60;
|
||||
EnEiyer_RotateAroundHome(this);
|
||||
EnEiyer_CheckPlayerCollision(this, globalCtx);
|
||||
|
||||
// Clones disappear when the main Eiyer leaves the ground
|
||||
if (this->actor.params != 0 && ((EnEiyer*)this->actor.parent)->actionFunc != EnEiyer_CircleUnderground) {
|
||||
EnEiyer_SetupInactive(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_WanderUnderground(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (Actor_WorldDistXZToPoint(&this->actor, &this->actor.home.pos) > 100.0f) {
|
||||
this->targetYaw = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos) + 0x8000;
|
||||
} else if (this->targetYaw == this->actor.world.rot.y && Rand_ZeroOne() > 0.99f) {
|
||||
this->targetYaw = this->actor.world.rot.y +
|
||||
(Rand_ZeroOne() < 0.5f ? -1 : 1) * (Rand_ZeroOne() * 0x2000 + 0x2000);
|
||||
}
|
||||
|
||||
Math_ScaledStepToS(&this->actor.world.rot.y, this->targetYaw, 0xB6);
|
||||
EnEiyer_CheckPlayerCollision(this, globalCtx);
|
||||
}
|
||||
|
||||
void EnEiyer_Inactive(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
EnEiyer* parent;
|
||||
|
||||
if (this->actor.home.pos.y - 50.0f < this->actor.world.pos.y) {
|
||||
this->actor.world.pos.y -= 0.5f;
|
||||
}
|
||||
|
||||
parent = (EnEiyer*)this->actor.parent;
|
||||
if (parent->actionFunc == EnEiyer_Dead) {
|
||||
Actor_Kill(&this->actor);
|
||||
} else if (parent->actionFunc == EnEiyer_AppearFromGround) {
|
||||
EnEiyer_SetupAppearFromGround(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_Ambush(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
s32 animFinished;
|
||||
f32 curFrame;
|
||||
f32 xzOffset;
|
||||
s32 bgId;
|
||||
|
||||
animFinished = SkelAnime_Update(&this->skelanime);
|
||||
curFrame = this->skelanime.curFrame;
|
||||
|
||||
if (this->skelanime.curFrame < 12.0f) {
|
||||
this->actor.world.pos.y = ((1.0f - cosf((0.996f * M_PI / 12.0f) * curFrame)) * 40.0f) + this->actor.home.pos.y;
|
||||
xzOffset = sinf((0.996f * M_PI / 12.0f) * curFrame) * -40.0f;
|
||||
this->actor.world.pos.x = (Math_SinS(this->actor.shape.rot.y) * xzOffset) + this->basePos.x;
|
||||
this->actor.world.pos.z = (Math_CosS(this->actor.shape.rot.y) * xzOffset) + this->basePos.z;
|
||||
} else {
|
||||
Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y + 80.0f, 0.5f);
|
||||
this->actor.speedXZ = 0.8f;
|
||||
}
|
||||
|
||||
if (animFinished) {
|
||||
this->collider.base.acFlags |= AC_ON;
|
||||
EnEiyer_SetupGlide(this);
|
||||
} else {
|
||||
this->actor.floorHeight = BgCheck_EntityRaycastFloor4(&globalCtx->colCtx, &this->actor.floorPoly, &bgId,
|
||||
&this->actor, &this->actor.world.pos);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_Glide(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
f32 curFrame;
|
||||
s32 pad;
|
||||
s16 yawChange;
|
||||
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
curFrame = this->skelanime.curFrame;
|
||||
Math_ApproachF(&this->basePos.y, this->actor.floorHeight + 80.0f + 5.0f, 0.3f, this->actor.speedXZ);
|
||||
this->actor.world.pos.y = this->basePos.y - cosf((curFrame - 5.0f) * (M_PI / 40)) * 5.0f;
|
||||
|
||||
if (curFrame <= 45.0f) {
|
||||
Math_StepToF(&this->actor.speedXZ, 1.0f, 0.03f);
|
||||
} else {
|
||||
Math_StepToF(&this->actor.speedXZ, 1.5f, 0.03f);
|
||||
}
|
||||
|
||||
if (this->actor.bgCheckFlags & 8) {
|
||||
this->targetYaw = this->actor.wallYaw;
|
||||
}
|
||||
|
||||
if (Math_ScaledStepToS(&this->actor.world.rot.y, this->targetYaw, 0xB6)) {
|
||||
if (this->timer != 0 || Rand_ZeroOne() > 0.05f) {
|
||||
this->actor.world.rot.y += 0x100;
|
||||
} else {
|
||||
yawChange = Rand_S16Offset(0x2000, 0x2000);
|
||||
this->targetYaw = (Rand_ZeroOne() < 0.5f ? -1 : 1) * yawChange + this->actor.world.rot.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->timer == 0 && this->actor.yDistToPlayer < 0.0f && this->actor.xzDistToPlayer < 120.0f) {
|
||||
EnEiyer_SetupStartAttack(this);
|
||||
}
|
||||
|
||||
func_8002F974(&this->actor, NA_SE_EN_EIER_FLY - SFX_FLAG);
|
||||
}
|
||||
|
||||
void EnEiyer_StartAttack(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
Vec3f focus;
|
||||
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (this->actor.shape.rot.x > 0 && this->actor.shape.rot.x < 0x8000) {
|
||||
focus.x = player->actor.world.pos.x;
|
||||
focus.y = player->actor.world.pos.y + 20.0f;
|
||||
focus.z = player->actor.world.pos.z;
|
||||
|
||||
if (Math_ScaledStepToS(&this->actor.shape.rot.x, Actor_WorldPitchTowardPoint(&this->actor, &focus), 0x1000)) {
|
||||
EnEiyer_SetupDiveAttack(this, globalCtx);
|
||||
}
|
||||
} else {
|
||||
this->actor.shape.rot.x -= 0x1000;
|
||||
}
|
||||
|
||||
this->actor.world.rot.x = -this->actor.shape.rot.x;
|
||||
Math_StepToF(&this->actor.speedXZ, 5.0f, 0.3f);
|
||||
Math_ApproachS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 2, 0x71C);
|
||||
func_8002F974(&this->actor, NA_SE_EN_EIER_FLY - SFX_FLAG);
|
||||
}
|
||||
|
||||
void EnEiyer_DiveAttack(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
this->actor.speedXZ *= 1.1f;
|
||||
|
||||
if (this->actor.bgCheckFlags & 8 || this->actor.bgCheckFlags & 1) {
|
||||
EnEiyer_SetupLand(this);
|
||||
}
|
||||
|
||||
if (this->collider.base.atFlags & AT_HIT) {
|
||||
this->collider.base.atFlags &= ~(AT_ON | AT_HIT);
|
||||
}
|
||||
|
||||
func_8002F974(&this->actor, NA_SE_EN_EIER_FLY - SFX_FLAG);
|
||||
}
|
||||
|
||||
void EnEiyer_Land(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
Math_ScaledStepToS(&this->actor.world.rot.x, -0x4000, 0x450);
|
||||
Math_StepToF(&this->actor.speedXZ, 7.0f, 1.0f);
|
||||
|
||||
if (this->timer == -1) {
|
||||
if (this->actor.bgCheckFlags & 8 || this->actor.bgCheckFlags & 1) {
|
||||
this->timer = 10;
|
||||
Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 30, NA_SE_EN_OCTAROCK_SINK);
|
||||
|
||||
if (this->actor.bgCheckFlags & 1) {
|
||||
EffectSsGSplash_Spawn(globalCtx, &this->actor.world.pos, NULL, NULL, 1, 700);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
if (this->timer == 0) {
|
||||
this->actor.shape.rot.x = 0;
|
||||
this->actor.world.rot.x = 0;
|
||||
EnEiyer_SetupAppearFromGround(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_Hurt(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
Math_ApproachF(&this->basePos.y, this->actor.floorHeight + 80.0f + 5.0f, 0.5f, this->actor.speedXZ);
|
||||
this->actor.world.pos.y = this->basePos.y - 5.0f;
|
||||
|
||||
if (this->actor.bgCheckFlags & 8) {
|
||||
this->targetYaw = this->actor.wallYaw;
|
||||
} else {
|
||||
this->targetYaw = this->actor.yawTowardsPlayer + 0x8000;
|
||||
}
|
||||
|
||||
Math_ScaledStepToS(&this->actor.world.rot.y, this->targetYaw, 0x38E);
|
||||
Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x200);
|
||||
this->actor.shape.rot.z = sinf(this->timer * (M_PI / 5)) * 5120.0f;
|
||||
|
||||
if (this->timer == 0) {
|
||||
this->actor.shape.rot.x = 0;
|
||||
this->actor.shape.rot.z = 0;
|
||||
this->collider.base.acFlags |= AC_ON;
|
||||
EnEiyer_SetupGlide(this);
|
||||
}
|
||||
this->actor.world.rot.x = -this->actor.shape.rot.x;
|
||||
}
|
||||
|
||||
void EnEiyer_Die(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (this->actor.speedXZ > 0.0f) {
|
||||
Math_ScaledStepToS(&this->actor.shape.rot.x, -0x4000, 0x400);
|
||||
} else {
|
||||
Math_ScaledStepToS(&this->actor.shape.rot.x, 0x4000, 0x400);
|
||||
}
|
||||
|
||||
this->actor.shape.rot.z += 0x1000;
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
this->actor.world.rot.x = -this->actor.shape.rot.x;
|
||||
|
||||
if (this->timer == 0 || this->actor.bgCheckFlags & 0x10) {
|
||||
EnEiyer_SetupDead(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_Dead(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
this->actor.shape.shadowAlpha = CLAMP_MIN((s16)(this->actor.shape.shadowAlpha - 5), 0);
|
||||
this->actor.world.pos.y -= 2.0f;
|
||||
|
||||
if (this->actor.shape.shadowAlpha == 0) {
|
||||
Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 80);
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_Stunned(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x200);
|
||||
SkelAnime_Update(&this->skelanime);
|
||||
|
||||
if (Animation_OnFrame(&this->skelanime, 0.0f)) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EIER_FLUTTER);
|
||||
}
|
||||
|
||||
if (this->actor.bgCheckFlags & 2) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DODO_M_GND);
|
||||
}
|
||||
|
||||
if (this->timer == 0) {
|
||||
this->actor.gravity = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->collider.dim.height = sColCylInit.dim.height;
|
||||
EnEiyer_SetupGlide(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_UpdateDamage(EnEiyer* this, GlobalContext* globalCtx) {
|
||||
if (this->collider.base.acFlags & AC_HIT) {
|
||||
this->collider.base.acFlags &= ~AC_HIT;
|
||||
func_80035650(&this->actor, &this->collider.info, 1);
|
||||
|
||||
if (this->actor.colChkInfo.damageEffect != 0 || this->actor.colChkInfo.damage != 0) {
|
||||
if (Actor_ApplyDamage(&this->actor) == 0) {
|
||||
func_80032C7C(globalCtx, &this->actor);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EIER_DEAD);
|
||||
this->actor.flags &= ~1;
|
||||
}
|
||||
|
||||
// If underground, one hit kill
|
||||
if (this->collider.info.bumper.dmgFlags == 0x19) {
|
||||
if (this->actor.colChkInfo.damage == 0) {
|
||||
EnEiyer_SetupAmbush(this, globalCtx);
|
||||
} else {
|
||||
EnEiyer_SetupDie(this);
|
||||
}
|
||||
} else if (this->actor.colChkInfo.damageEffect == 1) {
|
||||
if (this->actionFunc != EnEiyer_Stunned) {
|
||||
EnEiyer_SetupStunned(this);
|
||||
}
|
||||
} else if (this->actor.colChkInfo.health != 0) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EIER_DAMAGE);
|
||||
EnEiyer_SetupHurt(this);
|
||||
} else {
|
||||
this->collider.dim.height = sColCylInit.dim.height;
|
||||
EnEiyer_SetupDie(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnEiyer_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnEiyer* this = THIS;
|
||||
s32 pad;
|
||||
|
||||
EnEiyer_UpdateDamage(this, globalCtx);
|
||||
this->actionFunc(this, globalCtx);
|
||||
|
||||
if (this->actor.world.rot.x == 0 || this->actionFunc == EnEiyer_Stunned) {
|
||||
Actor_MoveForward(&this->actor);
|
||||
} else {
|
||||
func_8002D97C(&this->actor);
|
||||
}
|
||||
|
||||
if (this->actionFunc == EnEiyer_Glide || this->actionFunc == EnEiyer_DiveAttack ||
|
||||
this->actionFunc == EnEiyer_Stunned || this->actionFunc == EnEiyer_Die || this->actionFunc == EnEiyer_Hurt ||
|
||||
(this->actionFunc == EnEiyer_Land && this->timer == -1)) {
|
||||
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 5.0f, 27.0f, 30.0f, 7);
|
||||
}
|
||||
|
||||
if (this->actor.params == 0xA ||
|
||||
(this->actionFunc != EnEiyer_AppearFromGround && this->actionFunc != EnEiyer_CircleUnderground)) {
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
}
|
||||
|
||||
// only the main Eiyer can ambush the player
|
||||
if (this->actor.params == 0 || this->actor.params == 0xA) {
|
||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||||
if (this->collider.base.atFlags & AT_ON) {
|
||||
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
if (this->collider.base.acFlags & AC_ON) {
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
if (this->actionFunc != EnEiyer_Ambush) {
|
||||
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->actor.flags & 1) {
|
||||
this->actor.focus.pos.x = this->actor.world.pos.x + Math_SinS(this->actor.shape.rot.y) * 12.5f;
|
||||
this->actor.focus.pos.z = this->actor.world.pos.z + Math_CosS(this->actor.shape.rot.y) * 12.5f;
|
||||
this->actor.focus.pos.y = this->actor.world.pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
s32 EnEiyer_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx,
|
||||
Gfx** gfx) {
|
||||
EnEiyer* this = THIS;
|
||||
|
||||
if (limbIndex == 1) {
|
||||
pos->z += 2500.0f;
|
||||
}
|
||||
|
||||
if (this->collider.info.bumper.dmgFlags == 0x19 && limbIndex != 9 && limbIndex != 10) {
|
||||
*dList = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EnEiyer_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnEiyer* this = THIS;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_eiyer.c", 1494);
|
||||
if (this->actionFunc != EnEiyer_Dead) {
|
||||
func_80093D18(globalCtx->state.gfxCtx);
|
||||
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]);
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
|
||||
|
||||
POLY_OPA_DISP = SkelAnime_Draw(globalCtx, this->skelanime.skeleton, this->skelanime.jointTable,
|
||||
EnEiyer_OverrideLimbDraw, NULL, this, POLY_OPA_DISP);
|
||||
} else {
|
||||
func_80093D84(globalCtx->state.gfxCtx);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha);
|
||||
|
||||
POLY_XLU_DISP = SkelAnime_Draw(globalCtx, this->skelanime.skeleton, this->skelanime.jointTable,
|
||||
EnEiyer_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||
}
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_eiyer.c", 1541);
|
||||
}
|
||||
|
|
|
@ -6,9 +6,18 @@
|
|||
|
||||
struct EnEiyer;
|
||||
|
||||
typedef void (*EnEiyerActionFunc)(struct EnEiyer*, GlobalContext*);
|
||||
|
||||
typedef struct EnEiyer {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ char unk_14C[0x188];
|
||||
/* 0x014C */ SkelAnime skelanime;
|
||||
/* 0x0190 */ EnEiyerActionFunc actionFunc;
|
||||
/* 0x0194 */ s16 timer;
|
||||
/* 0x0196 */ s16 targetYaw;
|
||||
/* 0x0198 */ Vec3s jointTable[19];
|
||||
/* 0x020A */ Vec3s morphTable[19];
|
||||
/* 0x027C */ Vec3f basePos;
|
||||
/* 0x0288 */ ColliderCylinder collider;
|
||||
} EnEiyer; // size = 0x02D4
|
||||
|
||||
extern const ActorInit En_Eiyer_InitVars;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue