mirror of https://github.com/zeldaret/mm.git
En_Baguo (Nejiron) OK and mostly documented (#351)
* Migrate data to C * EnBaguo_Init OK * EnBaguo_Destroy OK * func_80A3B220 OK * func_80A3B2CC OK * func_80A3B2CC OK * func_80A3B794 OK * func_80A3B5E0 OK * func_80A3B7B8 OK * EnBaguo_Update OK * func_80A3B8F8 * func_80A3BE24 OK, some other not-OK junk * func_80A3BE60 OK (wow this is bad!) * Document the blink system * func_80A3C17C OK * Document timer and fix warnings * func_80A3C008 OK * Rename x/y/z so it's clear they are positions * func_80A3BE60 OK in a not-crazy way * func_80A3B958 OK * func_80A3BF0C OK * Make the rotation a Vec3s * Update the spec to use the built reloc * Use ARRAY_COUNT instead of hardcoded length * Document the state stuff * Document NejironParticle * Document the rolling rotation stuff * unk_1BC -> maxDistanceFromHome * unk_1B8 -> zRollDirection * Name the two draw functions * Name the static variables properly * Name all other functions * Clean up forward declares * Last bit of documentation and cleanup * Add an enum for the rolling direction * Add explanatory comment * state -> action and move action descriptions inline * Use enum for Stone Mask * Use "Setup" for the setup function * Document the damage effect * Add some space around the for-loop * ./format.sh * Use % 8 everywhere * Use -= instead of += a negative number * Switch order of max check * Use CLEAR_TAG_POP enum value * eyeIndexTemp -> eyeIndex * visible -> isVisible * Move enums above structs * Merge animation system changes * yDist fix * Respond to review feedback
This commit is contained in:
parent
693c701025
commit
c706b2be70
3
spec
3
spec
|
@ -2863,8 +2863,7 @@ beginseg
|
||||||
name "ovl_En_Baguo"
|
name "ovl_En_Baguo"
|
||||||
compress
|
compress
|
||||||
include "build/src/overlays/actors/ovl_En_Baguo/z_en_baguo.o"
|
include "build/src/overlays/actors/ovl_En_Baguo/z_en_baguo.o"
|
||||||
include "build/data/ovl_En_Baguo/ovl_En_Baguo.data.o"
|
include "build/src/overlays/actors/ovl_En_Baguo/ovl_En_Baguo_reloc.o"
|
||||||
include "build/data/ovl_En_Baguo/ovl_En_Baguo.reloc.o"
|
|
||||||
endseg
|
endseg
|
||||||
|
|
||||||
beginseg
|
beginseg
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* File z_en_baguo.c
|
* File: z_en_baguo.c
|
||||||
* Overlay: ovl_En_Baguo
|
* Overlay: ovl_En_Baguo
|
||||||
* Description: Nejiron
|
* Description: Nejiron
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +14,18 @@ void EnBaguo_Init(Actor* thisx, GlobalContext* globalCtx);
|
||||||
void EnBaguo_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
void EnBaguo_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||||
void EnBaguo_Update(Actor* thisx, GlobalContext* globalCtx);
|
void EnBaguo_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||||
|
|
||||||
#if 0
|
void EnBaguo_UndergroundIdle(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_EmergeFromUnderground(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_Idle(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_Roll(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_SetupRetreatUnderground(EnBaguo* this);
|
||||||
|
void EnBaguo_RetreatUnderground(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_DrawBody(Actor* thisx, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_InitializeParticle(EnBaguo* this, Vec3f* position, Vec3f* velocity, Vec3f* acceleration, f32 scale,
|
||||||
|
s16 timer);
|
||||||
|
void EnBaguo_UpdateParticles(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
void EnBaguo_DrawRockParticles(EnBaguo* this, GlobalContext* globalCtx);
|
||||||
|
|
||||||
const ActorInit En_Baguo_InitVars = {
|
const ActorInit En_Baguo_InitVars = {
|
||||||
ACTOR_EN_BAGUO,
|
ACTOR_EN_BAGUO,
|
||||||
ACTORCAT_ENEMY,
|
ACTORCAT_ENEMY,
|
||||||
|
@ -27,92 +38,453 @@ const ActorInit En_Baguo_InitVars = {
|
||||||
(ActorFunc)NULL,
|
(ActorFunc)NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
// static ColliderJntSphElementInit sJntSphElementsInit[1] = {
|
static ColliderJntSphElementInit sJntSphElementsInit[1] = {
|
||||||
static ColliderJntSphElementInit D_80A3C2F0[1] = {
|
|
||||||
{
|
{
|
||||||
{ ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
|
{
|
||||||
|
ELEMTYPE_UNK0,
|
||||||
|
{ 0xF7CFFFFF, 0x04, 0x04 },
|
||||||
|
{ 0xF7CFFFFF, 0x00, 0x00 },
|
||||||
|
TOUCH_ON | TOUCH_SFX_NORMAL,
|
||||||
|
BUMP_ON,
|
||||||
|
OCELEM_ON,
|
||||||
|
},
|
||||||
{ 1, { { 0, 0, 0 }, 0 }, 1 },
|
{ 1, { { 0, 0, 0 }, 0 }, 1 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// static ColliderJntSphInit sJntSphInit = {
|
static ColliderJntSphInit sJntSphInit = {
|
||||||
static ColliderJntSphInit D_80A3C314 = {
|
{
|
||||||
{ COLTYPE_HARD, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, },
|
COLTYPE_HARD,
|
||||||
1, D_80A3C2F0, // sJntSphElementsInit,
|
AT_ON | AT_TYPE_ENEMY,
|
||||||
|
AC_ON | AC_TYPE_PLAYER,
|
||||||
|
OC1_ON | OC1_TYPE_ALL,
|
||||||
|
OC2_TYPE_1,
|
||||||
|
COLSHAPE_JNTSPH,
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
sJntSphElementsInit,
|
||||||
};
|
};
|
||||||
|
|
||||||
// static DamageTable sDamageTable = {
|
typedef enum {
|
||||||
static DamageTable D_80A3C324 = {
|
/* 0x0 */ NEJIRON_DMGEFF_NONE, // Does not interact with the Nejiron at all
|
||||||
/* Deku Nut */ DMG_ENTRY(0, 0xF),
|
/* 0xE */ NEJIRON_DMGEFF_KILL = 14, // Kills and detonates the Nejiron
|
||||||
/* Deku Stick */ DMG_ENTRY(0, 0xF),
|
/* 0xF */ NEJIRON_DMGEFF_RECOIL // Deals no damage, but displays the appropriate hit mark and recoil animation
|
||||||
/* Horse trample */ DMG_ENTRY(0, 0x0),
|
} NejironDamageEffect;
|
||||||
/* Explosives */ DMG_ENTRY(1, 0xE),
|
|
||||||
/* Zora boomerang */ DMG_ENTRY(3, 0xE),
|
static DamageTable sDamageTable = {
|
||||||
/* Normal arrow */ DMG_ENTRY(0, 0xF),
|
/* Deku Nut */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0),
|
/* Deku Stick */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* Hookshot */ DMG_ENTRY(3, 0xE),
|
/* Horse trample */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* Goron punch */ DMG_ENTRY(2, 0xE),
|
/* Explosives */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* Sword */ DMG_ENTRY(1, 0xE),
|
/* Zora boomerang */ DMG_ENTRY(3, NEJIRON_DMGEFF_KILL),
|
||||||
/* Goron pound */ DMG_ENTRY(1, 0xE),
|
/* Normal arrow */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* Fire arrow */ DMG_ENTRY(0, 0xF),
|
/* UNK_DMG_0x06 */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* Ice arrow */ DMG_ENTRY(0, 0xF),
|
/* Hookshot */ DMG_ENTRY(3, NEJIRON_DMGEFF_KILL),
|
||||||
/* Light arrow */ DMG_ENTRY(1, 0xE),
|
/* Goron punch */ DMG_ENTRY(2, NEJIRON_DMGEFF_KILL),
|
||||||
/* Goron spikes */ DMG_ENTRY(2, 0xE),
|
/* Sword */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* Deku spin */ DMG_ENTRY(0, 0xF),
|
/* Goron pound */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* Deku bubble */ DMG_ENTRY(0, 0xF),
|
/* Fire arrow */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* Deku launch */ DMG_ENTRY(1, 0xE),
|
/* Ice arrow */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* UNK_DMG_0x12 */ DMG_ENTRY(0, 0xF),
|
/* Light arrow */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* Zora barrier */ DMG_ENTRY(0, 0x0),
|
/* Goron spikes */ DMG_ENTRY(2, NEJIRON_DMGEFF_KILL),
|
||||||
/* Normal shield */ DMG_ENTRY(0, 0x0),
|
/* Deku spin */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* Light ray */ DMG_ENTRY(0, 0x0),
|
/* Deku bubble */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* Thrown object */ DMG_ENTRY(0, 0x0),
|
/* Deku launch */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* Zora punch */ DMG_ENTRY(1, 0xE),
|
/* UNK_DMG_0x12 */ DMG_ENTRY(0, NEJIRON_DMGEFF_RECOIL),
|
||||||
/* Spin attack */ DMG_ENTRY(1, 0xE),
|
/* Zora barrier */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* Sword beam */ DMG_ENTRY(0, 0x0),
|
/* Normal shield */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* Normal Roll */ DMG_ENTRY(0, 0x0),
|
/* Light ray */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0),
|
/* Thrown object */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0),
|
/* Zora punch */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* Unblockable */ DMG_ENTRY(0, 0x0),
|
/* Spin attack */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
/* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0),
|
/* Sword beam */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
/* Powder Keg */ DMG_ENTRY(1, 0xE),
|
/* Normal Roll */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
|
/* UNK_DMG_0x1B */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
|
/* UNK_DMG_0x1C */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
|
/* Unblockable */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
|
/* UNK_DMG_0x1E */ DMG_ENTRY(0, NEJIRON_DMGEFF_NONE),
|
||||||
|
/* Powder Keg */ DMG_ENTRY(1, NEJIRON_DMGEFF_KILL),
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
extern Gfx D_060014C8;
|
||||||
|
extern Gfx D_060018C8;
|
||||||
|
extern Gfx D_06001CC8;
|
||||||
|
extern SkeletonHeader D_060020E8;
|
||||||
|
|
||||||
extern ColliderJntSphElementInit D_80A3C2F0[1];
|
void EnBaguo_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
extern ColliderJntSphInit D_80A3C314;
|
EnBaguo* this = THIS;
|
||||||
extern DamageTable D_80A3C324;
|
|
||||||
|
|
||||||
extern UNK_TYPE D_060020E8;
|
ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 0.0f);
|
||||||
|
SkelAnime_Init(globalCtx, &this->skelAnime, &D_060020E8, NULL, this->jointTable, this->morphTable, 3);
|
||||||
|
this->actor.hintId = 0xB;
|
||||||
|
this->maxDistanceFromHome = 240.0f;
|
||||||
|
this->maxDistanceFromHome += this->actor.world.rot.z * 40.0f;
|
||||||
|
this->actor.world.rot.z = 0;
|
||||||
|
Actor_SetScale(&this->actor, 0.01f);
|
||||||
|
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
||||||
|
this->actor.targetMode = 2;
|
||||||
|
Collider_InitAndSetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderElements);
|
||||||
|
this->collider.elements[0].dim.modelSphere.radius = 30;
|
||||||
|
this->collider.elements[0].dim.scale = 1.0f;
|
||||||
|
this->collider.elements[0].dim.modelSphere.center.x = 80;
|
||||||
|
this->collider.elements[0].dim.modelSphere.center.y = 80;
|
||||||
|
this->collider.elements[0].dim.modelSphere.center.z = 0;
|
||||||
|
this->actor.shape.yOffset = -3000.0f;
|
||||||
|
this->actor.gravity = -3.0f;
|
||||||
|
this->actor.colChkInfo.damageTable = &sDamageTable;
|
||||||
|
this->actor.flags |= 0x8000000;
|
||||||
|
this->actor.flags &= ~1;
|
||||||
|
this->collider.base.acFlags |= AC_HARD;
|
||||||
|
this->actionFunc = EnBaguo_UndergroundIdle;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/EnBaguo_Init.s")
|
void EnBaguo_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
EnBaguo* this = THIS;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/EnBaguo_Destroy.s")
|
Collider_DestroyJntSph(globalCtx, &this->collider);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B220.s")
|
void EnBaguo_UndergroundIdle(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
this->action = NEJIRON_ACTION_INACTIVE;
|
||||||
|
if (this->actor.xzDistToPlayer < 200.0f && Player_GetMask(globalCtx) != PLAYER_MASK_STONE_MASK) {
|
||||||
|
this->actor.draw = EnBaguo_DrawBody;
|
||||||
|
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BAKUO_APPEAR);
|
||||||
|
this->actor.world.rot.z = 0;
|
||||||
|
this->actor.world.rot.x = this->actor.world.rot.z;
|
||||||
|
this->actor.flags &= ~0x8000000;
|
||||||
|
this->actor.flags |= 1;
|
||||||
|
this->actionFunc = EnBaguo_EmergeFromUnderground;
|
||||||
|
}
|
||||||
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B2CC.s")
|
void EnBaguo_EmergeFromUnderground(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
this->actor.world.rot.y += 0x1518;
|
||||||
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||||
|
if ((globalCtx->gameplayFrames % 8) == 0) {
|
||||||
|
func_800BBDAC(globalCtx, &this->actor, &this->actor.world.pos, this->actor.shape.shadowScale - 20.0f, 10, 8.0f,
|
||||||
|
500, 10, 1);
|
||||||
|
}
|
||||||
|
Math_ApproachF(&this->actor.shape.shadowScale, 50.0f, 0.3f, 5.0f);
|
||||||
|
Math_ApproachF(&this->actor.shape.yOffset, 2700.0f, 100.0f, 500.0f);
|
||||||
|
if (this->actor.shape.yOffset > 2650.0f) {
|
||||||
|
this->action = NEJIRON_ACTION_ACTIVE;
|
||||||
|
this->actor.shape.yOffset = 2700.0f;
|
||||||
|
this->timer = 60;
|
||||||
|
this->actionFunc = EnBaguo_Idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B3E0.s")
|
void EnBaguo_Idle(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
s16 absoluteYaw;
|
||||||
|
s16 yaw;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B5E0.s")
|
if (this->timer != 0) {
|
||||||
|
// Depending on how the last roll ended, this actor may be "sitting" on
|
||||||
|
// something other than its legs. This slowly corrects that.
|
||||||
|
Math_SmoothStepToS(&this->actor.world.rot.x, 0, 10, 100, 1000);
|
||||||
|
Math_SmoothStepToS(&this->actor.world.rot.z, 0, 10, 100, 1000);
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B794.s")
|
// If this actor isn't mostly facing the player, do a discrete turn towards
|
||||||
|
// them. It takes 8 frames to turn, and we must wait 8 frames to do another.
|
||||||
|
if ((this->timer & 8) != 0) {
|
||||||
|
if (fabsf(this->actor.world.rot.y - this->actor.yawTowardsPlayer) > 200.0f) {
|
||||||
|
Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 30, 300, 1000);
|
||||||
|
if ((globalCtx->gameplayFrames % 8) == 0) {
|
||||||
|
func_800BBDAC(globalCtx, &this->actor, &this->actor.world.pos,
|
||||||
|
this->actor.shape.shadowScale - 20.0f, 10, 8.0f, 500, 10, 1);
|
||||||
|
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BAKUO_VOICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B7B8.s")
|
yaw = this->actor.yawTowardsPlayer - this->actor.world.rot.y;
|
||||||
|
absoluteYaw = ABS_ALT(yaw);
|
||||||
|
Math_Vec3f_Copy(&this->targetRotation, &D_801D15B0);
|
||||||
|
Math_Vec3f_Copy(&this->currentRotation, &D_801D15B0);
|
||||||
|
if (absoluteYaw < 0x2000) {
|
||||||
|
this->targetRotation.x = 2000.0f;
|
||||||
|
} else {
|
||||||
|
this->zRollDirection = NEJIRON_DIRECTION_RIGHT;
|
||||||
|
this->targetRotation.z = 2000.0f;
|
||||||
|
if ((s16)(this->actor.yawTowardsPlayer - this->actor.world.rot.y) > 0) {
|
||||||
|
this->zRollDirection = NEJIRON_DIRECTION_LEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->timer = 38;
|
||||||
|
this->actor.world.rot.y = this->actor.yawTowardsPlayer;
|
||||||
|
this->hardHitFlag = 0;
|
||||||
|
this->actionFunc = EnBaguo_Roll;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B8F8.s")
|
void EnBaguo_Roll(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
f32 xDistanceFromHome = this->actor.home.pos.x - this->actor.world.pos.x;
|
||||||
|
f32 zDistanceFromHome = this->actor.home.pos.z - this->actor.world.pos.z;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3B958.s")
|
if ((sqrtf(SQ(xDistanceFromHome) + SQ(zDistanceFromHome)) > this->maxDistanceFromHome) ||
|
||||||
|
(Player_GetMask(globalCtx) == PLAYER_MASK_STONE_MASK)) {
|
||||||
|
EnBaguo_SetupRetreatUnderground(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/EnBaguo_Update.s")
|
if (this->timer == 0) {
|
||||||
|
this->timer = 100;
|
||||||
|
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||||
|
this->actionFunc = EnBaguo_Idle;
|
||||||
|
this->actor.speedXZ = 0.0f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3BE24.s")
|
if (!this->hardHitFlag && this->collider.base.atFlags & AC_HARD) {
|
||||||
|
this->zRollDirection ^= 1;
|
||||||
|
this->hardHitFlag = 1;
|
||||||
|
this->actor.speedXZ = -7.0f;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3BE60.s")
|
Math_ApproachF(&this->currentRotation.x, this->targetRotation.x, 0.2f, 1000.0f);
|
||||||
|
Math_ApproachF(&this->currentRotation.z, this->targetRotation.z, 0.2f, 1000.0f);
|
||||||
|
Math_ApproachF(&this->actor.speedXZ, 5.0f, 0.3f, 0.5f);
|
||||||
|
this->actor.world.rot.x += (s16)this->currentRotation.x;
|
||||||
|
if (this->currentRotation.z != 0.0f) {
|
||||||
|
if (this->zRollDirection == NEJIRON_DIRECTION_RIGHT) {
|
||||||
|
this->actor.world.rot.z += (s16)this->currentRotation.z;
|
||||||
|
} else {
|
||||||
|
this->actor.world.rot.z -= (s16)this->currentRotation.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BAKUO_ROLL - SFX_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3BF0C.s")
|
void EnBaguo_SetupRetreatUnderground(EnBaguo* this) {
|
||||||
|
this->action = NEJIRON_ACTION_RETREATING;
|
||||||
|
this->actionFunc = EnBaguo_RetreatUnderground;
|
||||||
|
this->actor.speedXZ = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3C008.s")
|
void EnBaguo_RetreatUnderground(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
this->actor.world.rot.y -= 0x1518;
|
||||||
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||||
|
if ((globalCtx->gameplayFrames % 8) == 0) {
|
||||||
|
func_800BBDAC(globalCtx, &this->actor, &this->actor.world.pos, this->actor.shape.shadowScale - 20.0f, 10, 8.0f,
|
||||||
|
500, 10, 1);
|
||||||
|
}
|
||||||
|
Math_ApproachF(&this->actor.shape.yOffset, -3000.0f, 100.0f, 500.0f);
|
||||||
|
Math_ApproachZeroF(&this->actor.shape.shadowScale, 0.3f, 5.0f);
|
||||||
|
if (this->actor.shape.yOffset < -2970.0f) {
|
||||||
|
this->actor.shape.yOffset = -3000.0f;
|
||||||
|
this->actor.draw = EnBaguo_DrawBody;
|
||||||
|
Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.home.pos);
|
||||||
|
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BAKUO_APPEAR);
|
||||||
|
this->actor.flags |= 0x8000000;
|
||||||
|
this->actor.flags &= ~1;
|
||||||
|
this->actionFunc = EnBaguo_UndergroundIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Baguo/func_80A3C17C.s")
|
void EnBaguo_PostDetonation(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
if (this->timer == 0) {
|
||||||
|
Actor_MarkForDeath(&this->actor);
|
||||||
|
}
|
||||||
|
if (this->timer >= 26) {
|
||||||
|
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_CheckForDetonation(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
||||||
|
Vec3f acceleration = { 0.0f, 0.0f, 0.0f };
|
||||||
|
s32 i;
|
||||||
|
|
||||||
|
// In order to match, this variable must act as both a boolean to check if
|
||||||
|
// the Nejiron should forcibly explode and as a loop index.
|
||||||
|
i = false;
|
||||||
|
if (this->action != NEJIRON_ACTION_EXPLODING && this->action != NEJIRON_ACTION_RETREATING) {
|
||||||
|
if (!(this->actor.bgCheckFlags & 1) && this->actor.world.pos.y < (this->actor.home.pos.y - 100.0f)) {
|
||||||
|
// Force a detonation if we're off the ground and have fallen
|
||||||
|
// below our home position (e.g., we rolled off a ledge).
|
||||||
|
i = true;
|
||||||
|
}
|
||||||
|
if (this->actor.bgCheckFlags & 0x60 && this->actor.depthInWater >= 40.0f) {
|
||||||
|
// Force a detonation if we're too far below the water's surface.
|
||||||
|
i = true;
|
||||||
|
}
|
||||||
|
if ((this->collider.base.acFlags & AC_HIT || i)) {
|
||||||
|
this->collider.base.acFlags &= ~AC_HIT;
|
||||||
|
if (i || this->actor.colChkInfo.damageEffect == NEJIRON_DMGEFF_KILL) {
|
||||||
|
func_800BCB70(&this->actor, 0x4000, 0xFF, 0, 8);
|
||||||
|
this->action = NEJIRON_ACTION_EXPLODING;
|
||||||
|
this->actor.speedXZ = 0.0f;
|
||||||
|
this->actor.shape.shadowScale = 0.0f;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_COUNT(this->particles); i++) {
|
||||||
|
acceleration.x = (Rand_ZeroOne() - 0.5f) * 8.0f;
|
||||||
|
acceleration.y = -1.0f;
|
||||||
|
acceleration.z = (Rand_ZeroOne() - 0.5f) * 8.0f;
|
||||||
|
velocity.x = (Rand_ZeroOne() - 0.5f) * 14.0f;
|
||||||
|
velocity.y = Rand_ZeroOne() * 30.0f;
|
||||||
|
velocity.z = (Rand_ZeroOne() - 0.5f) * 14.0f;
|
||||||
|
EnBaguo_InitializeParticle(this, &this->actor.focus.pos, &velocity, &acceleration,
|
||||||
|
(Rand_ZeroFloat(1.0f) * 0.01f) + 0.003f, 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x,
|
||||||
|
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, CLEAR_TAG_POP);
|
||||||
|
Audio_PlayActorSound2(&this->actor, NA_SE_IT_BOMB_EXPLOSION);
|
||||||
|
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BAKUO_DEAD);
|
||||||
|
this->timer = 30;
|
||||||
|
this->actor.flags |= 0x8000000;
|
||||||
|
this->actor.flags &= ~1;
|
||||||
|
Actor_SetScale(&this->actor, 0.0f);
|
||||||
|
this->collider.elements->dim.scale = 3.0f;
|
||||||
|
this->collider.elements->info.toucher.damage = 8;
|
||||||
|
Item_DropCollectibleRandom(globalCtx, NULL, &this->actor.world.pos, 0xB0);
|
||||||
|
this->actionFunc = EnBaguo_PostDetonation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
EnBaguo* this = THIS;
|
||||||
|
|
||||||
|
Actor_SetHeight(&this->actor, 30.0f);
|
||||||
|
EnBaguo_UpdateParticles(this, globalCtx);
|
||||||
|
EnBaguo_CheckForDetonation(this, globalCtx);
|
||||||
|
this->actionFunc(this, globalCtx);
|
||||||
|
|
||||||
|
DECR(this->blinkTimer);
|
||||||
|
DECR(this->timer);
|
||||||
|
|
||||||
|
if (this->action != NEJIRON_ACTION_EXPLODING && this->action != NEJIRON_ACTION_INACTIVE) {
|
||||||
|
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->action != NEJIRON_ACTION_EXPLODING) {
|
||||||
|
this->actor.shape.rot.x = this->actor.world.rot.x;
|
||||||
|
this->actor.shape.rot.z = this->actor.world.rot.z;
|
||||||
|
if (this->blinkTimer == 0) {
|
||||||
|
this->eyeIndex++;
|
||||||
|
if (this->eyeIndex >= 3) {
|
||||||
|
this->eyeIndex = 0;
|
||||||
|
this->blinkTimer = Rand_ZeroFloat(60.0f) + 20.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
|
||||||
|
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 20.0f, 60.0f, 0x1D);
|
||||||
|
if (this->action != NEJIRON_ACTION_INACTIVE) {
|
||||||
|
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||||
|
}
|
||||||
|
if (this->action != NEJIRON_ACTION_EXPLODING) {
|
||||||
|
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
|
||||||
|
EnBaguo* this = THIS;
|
||||||
|
|
||||||
|
Collider_UpdateSpheres(limbIndex, &this->collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_DrawBody(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
static TexturePtr sEyeTextures[] = { &D_060014C8, &D_060018C8, &D_06001CC8 };
|
||||||
|
EnBaguo* this = THIS;
|
||||||
|
Gfx* gfx;
|
||||||
|
s32 eyeIndex;
|
||||||
|
void* virtualAddress;
|
||||||
|
|
||||||
|
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||||
|
|
||||||
|
func_8012C28C(globalCtx->state.gfxCtx);
|
||||||
|
|
||||||
|
gfx = POLY_OPA_DISP;
|
||||||
|
|
||||||
|
eyeIndex = this->eyeIndex;
|
||||||
|
virtualAddress = Lib_SegmentedToVirtual(sEyeTextures[eyeIndex]);
|
||||||
|
gSPSegment(&gfx[0], 0x08, virtualAddress);
|
||||||
|
|
||||||
|
POLY_OPA_DISP = &gfx[1];
|
||||||
|
|
||||||
|
SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, EnBaguo_PostLimbDraw,
|
||||||
|
&this->actor);
|
||||||
|
|
||||||
|
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
||||||
|
|
||||||
|
EnBaguo_DrawRockParticles(this, globalCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_InitializeParticle(EnBaguo* this, Vec3f* position, Vec3f* velocity, Vec3f* acceleration, f32 scale,
|
||||||
|
s16 timer) {
|
||||||
|
s16 i;
|
||||||
|
NejironParticle* particle = this->particles;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_COUNT(this->particles); i++, particle++) {
|
||||||
|
if (!particle->isVisible) {
|
||||||
|
particle->isVisible = true;
|
||||||
|
particle->position = *position;
|
||||||
|
particle->velocity = *velocity;
|
||||||
|
particle->acceleration = *acceleration;
|
||||||
|
particle->scale = scale;
|
||||||
|
particle->timer = timer;
|
||||||
|
particle->rotation.x = (s16)randPlusMinusPoint5Scaled(30000.0f);
|
||||||
|
particle->rotation.y = (s16)randPlusMinusPoint5Scaled(30000.0f);
|
||||||
|
particle->rotation.z = (s16)randPlusMinusPoint5Scaled(30000.0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_UpdateParticles(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
s32 i;
|
||||||
|
NejironParticle* particle = this->particles;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_COUNT(this->particles); i++, particle++) {
|
||||||
|
if (particle->isVisible) {
|
||||||
|
particle->position.x += particle->velocity.x;
|
||||||
|
particle->position.y += particle->velocity.y;
|
||||||
|
particle->position.z += particle->velocity.z;
|
||||||
|
particle->rotation.x += 0xBB8;
|
||||||
|
particle->rotation.y += 0xBB8;
|
||||||
|
particle->rotation.z += 0xBB8;
|
||||||
|
particle->velocity.x += particle->acceleration.x;
|
||||||
|
particle->velocity.y += particle->acceleration.y;
|
||||||
|
particle->velocity.z += particle->acceleration.z;
|
||||||
|
if (particle->position.y < (this->actor.world.pos.y - 10.0f)) {
|
||||||
|
Math_ApproachZeroF(&particle->scale, 0.2f, 0.001f);
|
||||||
|
if (particle->scale <= 0.0001f) {
|
||||||
|
particle->timer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (particle->timer != 0) {
|
||||||
|
particle->timer--;
|
||||||
|
} else {
|
||||||
|
particle->isVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnBaguo_DrawRockParticles(EnBaguo* this, GlobalContext* globalCtx) {
|
||||||
|
s16 i;
|
||||||
|
NejironParticle* particle = this->particles;
|
||||||
|
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
|
||||||
|
|
||||||
|
OPEN_DISPS(gfxCtx);
|
||||||
|
func_8012C28C(globalCtx->state.gfxCtx);
|
||||||
|
for (i = 0; i < ARRAY_COUNT(this->particles); i++, particle++) {
|
||||||
|
if (particle->isVisible) {
|
||||||
|
Matrix_InsertTranslation(particle->position.x, particle->position.y, particle->position.z, MTXMODE_NEW);
|
||||||
|
Matrix_InsertXRotation_s(particle->rotation.x, MTXMODE_APPLY);
|
||||||
|
Matrix_RotateY(particle->rotation.y, MTXMODE_APPLY);
|
||||||
|
Matrix_InsertZRotation_s(particle->rotation.z, MTXMODE_APPLY);
|
||||||
|
Matrix_Scale(particle->scale, particle->scale, particle->scale, MTXMODE_APPLY);
|
||||||
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
gDPSetPrimColor(POLY_OPA_DISP++, 0, 1, 255, 255, 255, 255);
|
||||||
|
gSPDisplayList(POLY_OPA_DISP++, &D_0401FA40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CLOSE_DISPS(gfxCtx);
|
||||||
|
}
|
||||||
|
|
|
@ -7,11 +7,53 @@ struct EnBaguo;
|
||||||
|
|
||||||
typedef void (*EnBaguoActionFunc)(struct EnBaguo*, GlobalContext*);
|
typedef void (*EnBaguoActionFunc)(struct EnBaguo*, GlobalContext*);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* 0x0 */ NEJIRON_ACTION_INACTIVE, // The Nejiron is either underground or emerging from underground
|
||||||
|
/* 0x1 */ NEJIRON_ACTION_ACTIVE, // The Nejiron is above ground and actively chasing the player
|
||||||
|
/* 0x2 */ NEJIRON_ACTION_RETREATING, // The Nejiron is burrowing back underground
|
||||||
|
/* 0x3 */ NEJIRON_ACTION_EXPLODING // The Nejiron has detonated
|
||||||
|
} NejironAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These directions are relative to the Nejiron.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/* 0x0 */ NEJIRON_DIRECTION_RIGHT,
|
||||||
|
/* 0x1 */ NEJIRON_DIRECTION_LEFT
|
||||||
|
} NejironRollDirection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a Nejiron explodes, rock particles fly out from where it exploded.
|
||||||
|
* This struct governs how these rock particles behave.
|
||||||
|
*/
|
||||||
|
typedef struct NejironParticle {
|
||||||
|
/* 0x00 */ u8 isVisible;
|
||||||
|
/* 0x04 */ Vec3f position;
|
||||||
|
/* 0x10 */ Vec3f velocity;
|
||||||
|
/* 0x1C */ Vec3f acceleration;
|
||||||
|
/* 0x28 */ Vec3s rotation;
|
||||||
|
/* 0x30 */ f32 scale;
|
||||||
|
/* 0x34 */ s16 timer;
|
||||||
|
} NejironParticle; // size = 0x38
|
||||||
|
|
||||||
typedef struct EnBaguo {
|
typedef struct EnBaguo {
|
||||||
/* 0x0000 */ Actor actor;
|
/* 0x000 */ Actor actor;
|
||||||
/* 0x0144 */ char unk_144[0x68];
|
/* 0x144 */ SkelAnime skelAnime;
|
||||||
/* 0x01AC */ EnBaguoActionFunc actionFunc;
|
/* 0x188 */ Vec3s jointTable[3];
|
||||||
/* 0x01B0 */ char unk_1B0[0x71C];
|
/* 0x19A */ Vec3s morphTable[3];
|
||||||
|
/* 0x1AC */ EnBaguoActionFunc actionFunc;
|
||||||
|
/* 0x1B0 */ s16 eyeIndex;
|
||||||
|
/* 0x1B2 */ s16 blinkTimer;
|
||||||
|
/* 0x1B4 */ s16 timer;
|
||||||
|
/* 0x1B6 */ s16 action;
|
||||||
|
/* 0x1B8 */ s16 zRollDirection;
|
||||||
|
/* 0x1BC */ f32 maxDistanceFromHome;
|
||||||
|
/* 0x1C0 */ u8 hardHitFlag;
|
||||||
|
/* 0x1C4 */ Vec3f currentRotation;
|
||||||
|
/* 0x1D0 */ Vec3f targetRotation;
|
||||||
|
/* 0x1DC */ ColliderJntSph collider;
|
||||||
|
/* 0x1FC */ ColliderJntSphElement colliderElements[1];
|
||||||
|
/* 0x23C */ NejironParticle particles[30];
|
||||||
} EnBaguo; // size = 0x8CC
|
} EnBaguo; // size = 0x8CC
|
||||||
|
|
||||||
extern const ActorInit En_Baguo_InitVars;
|
extern const ActorInit En_Baguo_InitVars;
|
||||||
|
|
|
@ -10297,20 +10297,20 @@
|
||||||
0x80A3AEC8:("DmTsg_Draw",),
|
0x80A3AEC8:("DmTsg_Draw",),
|
||||||
0x80A3B080:("EnBaguo_Init",),
|
0x80A3B080:("EnBaguo_Init",),
|
||||||
0x80A3B1F4:("EnBaguo_Destroy",),
|
0x80A3B1F4:("EnBaguo_Destroy",),
|
||||||
0x80A3B220:("func_80A3B220",),
|
0x80A3B220:("EnBaguo_UndergroundIdle",),
|
||||||
0x80A3B2CC:("func_80A3B2CC",),
|
0x80A3B2CC:("EnBaguo_EmergeFromUnderground",),
|
||||||
0x80A3B3E0:("func_80A3B3E0",),
|
0x80A3B3E0:("EnBaguo_Idle",),
|
||||||
0x80A3B5E0:("func_80A3B5E0",),
|
0x80A3B5E0:("EnBaguo_Roll",),
|
||||||
0x80A3B794:("func_80A3B794",),
|
0x80A3B794:("EnBaguo_SetupRetreatUnderground",),
|
||||||
0x80A3B7B8:("func_80A3B7B8",),
|
0x80A3B7B8:("EnBaguo_RetreatUnderground",),
|
||||||
0x80A3B8F8:("func_80A3B8F8",),
|
0x80A3B8F8:("EnBaguo_PostDetonation",),
|
||||||
0x80A3B958:("func_80A3B958",),
|
0x80A3B958:("EnBaguo_CheckForDetonation",),
|
||||||
0x80A3BC88:("EnBaguo_Update",),
|
0x80A3BC88:("EnBaguo_Update",),
|
||||||
0x80A3BE24:("func_80A3BE24",),
|
0x80A3BE24:("EnBaguo_PostLimbDraw",),
|
||||||
0x80A3BE60:("func_80A3BE60",),
|
0x80A3BE60:("EnBaguo_DrawBody",),
|
||||||
0x80A3BF0C:("func_80A3BF0C",),
|
0x80A3BF0C:("EnBaguo_InitializeParticle",),
|
||||||
0x80A3C008:("func_80A3C008",),
|
0x80A3C008:("EnBaguo_UpdateParticles",),
|
||||||
0x80A3C17C:("func_80A3C17C",),
|
0x80A3C17C:("EnBaguo_DrawRockParticles",),
|
||||||
0x80A3C4E0:("func_80A3C4E0",),
|
0x80A3C4E0:("func_80A3C4E0",),
|
||||||
0x80A3C560:("func_80A3C560",),
|
0x80A3C560:("func_80A3C560",),
|
||||||
0x80A3C658:("func_80A3C658",),
|
0x80A3C658:("func_80A3C658",),
|
||||||
|
|
|
@ -1514,6 +1514,9 @@ D_060092A0 = 0x060092A0;
|
||||||
|
|
||||||
// ovl_En_Baguo
|
// ovl_En_Baguo
|
||||||
|
|
||||||
|
D_060014C8 = 0x060014C8;
|
||||||
|
D_060018C8 = 0x060018C8;
|
||||||
|
D_06001CC8 = 0x06001CC8;
|
||||||
D_060020E8 = 0x060020E8;
|
D_060020E8 = 0x060020E8;
|
||||||
|
|
||||||
// ovl_En_Baisen
|
// ovl_En_Baisen
|
||||||
|
|
Loading…
Reference in New Issue