mirror of
https://github.com/zeldaret/oot.git
synced 2025-08-07 06:40:15 +00:00
ovl_En_Box OK, documented (#356)
* ovl_En_Box OK, documented * Update spec * Removed useless union * renames, remove comments, move internal enums from header * stylistic changes * Remove unneeded prototypes and use documentation format for doc comments * Misread git's merge solution * EnBox_SetupAction and Actor_SpawnAsChild * Cleanup * Merge effects, defines for movement flags, swap dList and dListHead, cleanup...
This commit is contained in:
parent
174af7384d
commit
e270cd96bf
31 changed files with 680 additions and 2037 deletions
|
@ -4,14 +4,64 @@
|
|||
|
||||
#define THIS ((EnBox*)thisx)
|
||||
|
||||
// movement flags
|
||||
|
||||
/*
|
||||
set on init unless treasure flag is set
|
||||
if clear, chest moves (Actor_MoveForward) (falls, likely)
|
||||
ends up cleared from SWITCH_FLAG_FALL types when switch flag is set
|
||||
*/
|
||||
#define ENBOX_MOVE_IMMOBILE (1 << 0)
|
||||
/*
|
||||
set in the logic for SWITCH_FLAG_FALL types
|
||||
otherwise unused
|
||||
*/
|
||||
#define ENBOX_MOVE_UNUSED (1 << 1)
|
||||
/*
|
||||
set with 50% chance on init for SWITCH_FLAG_FALL types
|
||||
only used for SWITCH_FLAG_FALL types
|
||||
ends up "blinking" (set/clear every frame) once switch flag is set,
|
||||
if some collision-related condition (?) is met
|
||||
only used for signum of z rotation
|
||||
*/
|
||||
#define ENBOX_MOVE_FALL_ANGLE_SIDE (1 << 2)
|
||||
/*
|
||||
when set, gets cleared next EnBox_Update call and clip to the floor
|
||||
*/
|
||||
#define ENBOX_MOVE_STICK_TO_GROUND (1 << 4)
|
||||
|
||||
typedef enum {
|
||||
ENBOX_STATE_0, // waiting for player near / player available / player ? (IDLE)
|
||||
ENBOX_STATE_1, // used only temporarily, maybe "player is ready" ?
|
||||
ENBOX_STATE_2 // waiting for something message context-related
|
||||
} EnBoxStateUnk1FB;
|
||||
|
||||
void EnBox_Init(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBox_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBox_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBox_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
/*
|
||||
void EnBox_FallOnSwitchFlag(EnBox*, GlobalContext*);
|
||||
void func_809C9700(EnBox*, GlobalContext*);
|
||||
void EnBox_AppearOnSwitchFlag(EnBox*, GlobalContext*);
|
||||
void EnBox_AppearOnRoomClear(EnBox*, GlobalContext*);
|
||||
void EnBox_AppearInit(EnBox*, GlobalContext*);
|
||||
void EnBox_AppearAnimation(EnBox*, GlobalContext*);
|
||||
void EnBox_WaitOpen(EnBox*, GlobalContext*);
|
||||
void EnBox_Open(EnBox*, GlobalContext*);
|
||||
|
||||
extern AnimationHeader D_06000128;
|
||||
extern AnimationHeader D_0600024C;
|
||||
extern AnimationHeader D_0600043C;
|
||||
extern Gfx D_060006F0[]; // regular chest base
|
||||
extern Gfx D_06000AE8[]; // boss key chest base
|
||||
extern Gfx D_060010C0[]; // regular chest top
|
||||
extern Gfx D_06001678[]; // boss key chest top
|
||||
extern SkeletonHeader D_060047D8;
|
||||
extern UNK_TYPE D_06005FC8;
|
||||
|
||||
const ActorInit En_Box_InitVars = {
|
||||
Chest,
|
||||
ACTOR_EN_BOX,
|
||||
ACTORTYPE_CHEST,
|
||||
FLAGS,
|
||||
OBJECT_BOX,
|
||||
|
@ -21,47 +71,594 @@ const ActorInit En_Box_InitVars = {
|
|||
(ActorFunc)EnBox_Update,
|
||||
(ActorFunc)EnBox_Draw,
|
||||
};
|
||||
*/
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C8DC0.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C8DC8.s")
|
||||
static AnimationHeader* D_809CA800[4] = { &D_0600024C, &D_06000128, &D_0600043C, &D_0600043C };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/EnBox_Init.s")
|
||||
static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_U8(unk_1F, 0, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/EnBox_Destroy.s")
|
||||
static s32 sUnused;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C92F4.s")
|
||||
void EnBox_SetupAction(EnBox* this, EnBoxActionFunc actionFunc) {
|
||||
this->actionFunc = actionFunc;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C93F8.s")
|
||||
void EnBox_ClipToGround(EnBox* this, GlobalContext* globalCtx) {
|
||||
f32 newY;
|
||||
CollisionPoly* a1;
|
||||
void* a2;
|
||||
Vec3f pos;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C94AC.s")
|
||||
pos = this->dyna.actor.posRot.pos;
|
||||
pos.y += 1.0f;
|
||||
newY = func_8003C9A4(&globalCtx->colCtx, &a1, &a2, &this->dyna.actor, &pos);
|
||||
if (newY != -32000.0f) {
|
||||
this->dyna.actor.posRot.pos.y = newY;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C9630.s")
|
||||
void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
GlobalContext* globalCtx2 = globalCtx;
|
||||
EnBox* this = THIS;
|
||||
AnimationHeader* animHeader;
|
||||
s32 dynaUnk;
|
||||
f32 animFrameStart;
|
||||
f32 animFrameCount;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C9700.s")
|
||||
animFrameStart = 0.0f;
|
||||
animHeader = D_809CA800[((void)0, gSaveContext.linkAge)];
|
||||
dynaUnk = 0;
|
||||
animFrameCount = SkelAnime_GetFrameCount(&animHeader->genericHeader);
|
||||
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C988C.s")
|
||||
DynaPolyInfo_SetActorMove(&this->dyna, 0);
|
||||
DynaPolyInfo_Alloc(&D_06005FC8, &dynaUnk);
|
||||
this->dyna.dynaPolyId =
|
||||
DynaPolyInfo_RegisterActor(globalCtx2, &globalCtx2->colCtx.dyna, &this->dyna.actor, dynaUnk);
|
||||
func_8003ECA8(globalCtx2, &globalCtx2->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C990C.s")
|
||||
this->movementFlags = 0;
|
||||
this->type = thisx->params >> 12 & 0xF;
|
||||
this->iceSmokeTimer = 0;
|
||||
this->unk_1FB = ENBOX_STATE_0;
|
||||
this->dyna.actor.gravity = -5.5f;
|
||||
this->switchFlag = this->dyna.actor.posRot.rot.z;
|
||||
this->dyna.actor.minVelocityY = -50.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C99C4.s")
|
||||
if (globalCtx2) {} // helps the compiler store globalCtx2 into s1
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C9A7C.s")
|
||||
if (Flags_GetTreasure(globalCtx2, this->dyna.actor.params & 0x1F)) {
|
||||
this->alpha = 255;
|
||||
this->iceSmokeTimer = 100;
|
||||
EnBox_SetupAction(this, EnBox_Open);
|
||||
this->movementFlags |= ENBOX_MOVE_STICK_TO_GROUND;
|
||||
animFrameStart = animFrameCount;
|
||||
} else if ((this->type == ENBOX_TYPE_SWITCH_FLAG_FALL_BIG || this->type == ENBOX_TYPE_SWITCH_FLAG_FALL_SMALL) &&
|
||||
!Flags_GetSwitch(globalCtx2, this->switchFlag)) {
|
||||
func_8003EBF8(globalCtx2, &globalCtx2->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
if (Math_Rand_ZeroOne() < 0.5f) {
|
||||
this->movementFlags |= ENBOX_MOVE_FALL_ANGLE_SIDE;
|
||||
}
|
||||
this->unk_1A8 = -12;
|
||||
EnBox_SetupAction(this, EnBox_FallOnSwitchFlag);
|
||||
this->alpha = 0;
|
||||
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
|
||||
this->dyna.actor.flags |= 0x10;
|
||||
} else if ((this->type == ENBOX_TYPE_ROOM_CLEAR_BIG || this->type == ENBOX_TYPE_ROOM_CLEAR_SMALL) &&
|
||||
!Flags_GetClear(globalCtx2, this->dyna.actor.room)) {
|
||||
EnBox_SetupAction(this, EnBox_AppearOnRoomClear);
|
||||
func_8003EBF8(globalCtx2, &globalCtx2->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
|
||||
this->dyna.actor.posRot.pos.y = this->dyna.actor.initPosRot.pos.y - 50.0f;
|
||||
this->alpha = 0;
|
||||
this->dyna.actor.flags |= 0x10;
|
||||
} else if (this->type == ENBOX_TYPE_9 || this->type == ENBOX_TYPE_10) {
|
||||
EnBox_SetupAction(this, func_809C9700);
|
||||
this->dyna.actor.flags |= 0x2000000;
|
||||
func_8003EBF8(globalCtx2, &globalCtx2->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
|
||||
this->dyna.actor.posRot.pos.y = this->dyna.actor.initPosRot.pos.y - 50.0f;
|
||||
this->alpha = 0;
|
||||
this->dyna.actor.flags |= 0x10;
|
||||
} else if (this->type == ENBOX_TYPE_SWITCH_FLAG_BIG && !Flags_GetSwitch(globalCtx2, this->switchFlag)) {
|
||||
EnBox_SetupAction(this, EnBox_AppearOnSwitchFlag);
|
||||
func_8003EBF8(globalCtx2, &globalCtx2->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
|
||||
this->dyna.actor.posRot.pos.y = this->dyna.actor.initPosRot.pos.y - 50.0f;
|
||||
this->alpha = 0;
|
||||
this->dyna.actor.flags |= 0x10;
|
||||
} else {
|
||||
if (this->type == ENBOX_TYPE_4 || this->type == ENBOX_TYPE_6) {
|
||||
this->dyna.actor.flags |= 0x80;
|
||||
}
|
||||
EnBox_SetupAction(this, EnBox_WaitOpen);
|
||||
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
|
||||
this->movementFlags |= ENBOX_MOVE_STICK_TO_GROUND;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C9B28.s")
|
||||
this->dyna.actor.posRot.rot.y += 0x8000;
|
||||
this->dyna.actor.initPosRot.rot.z = this->dyna.actor.posRot.rot.z = this->dyna.actor.shape.rot.z = 0;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C9D70.s")
|
||||
SkelAnime_Init(globalCtx2, &this->skelanime, &D_060047D8, animHeader, this->limbDrawTable,
|
||||
this->transitionDrawTable, 5);
|
||||
SkelAnime_ChangeAnim(&this->skelanime, animHeader, 1.5f, animFrameStart, animFrameCount, 2, 0.0f);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809C9EF8.s")
|
||||
switch (this->type) {
|
||||
case ENBOX_TYPE_SMALL:
|
||||
case ENBOX_TYPE_6:
|
||||
case ENBOX_TYPE_ROOM_CLEAR_SMALL:
|
||||
case ENBOX_TYPE_SWITCH_FLAG_FALL_SMALL:
|
||||
Actor_SetScale(&this->dyna.actor, 0.005f);
|
||||
Actor_SetHeight(&this->dyna.actor, 20.0f);
|
||||
break;
|
||||
default:
|
||||
Actor_SetScale(&this->dyna.actor, 0.01f);
|
||||
Actor_SetHeight(&this->dyna.actor, 40.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/EnBox_Update.s")
|
||||
void EnBox_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBox* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809CA2D8.s")
|
||||
DynaPolyInfo_Free(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809CA448.s")
|
||||
void EnBox_RandomDustKinematic(EnBox* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel) {
|
||||
f32 randomRadius = Math_Rand_ZeroOne() * 25.0f;
|
||||
s16 randomAngle = Math_Rand_ZeroOne() * 0x10000;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809CA4A0.s")
|
||||
*pos = this->dyna.actor.posRot.pos;
|
||||
pos->x += Math_Sins(randomAngle) * randomRadius;
|
||||
pos->z += Math_Coss(randomAngle) * randomRadius;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/func_809CA518.s")
|
||||
velocity->y = 1.0f;
|
||||
velocity->x = Math_Sins(randomAngle);
|
||||
velocity->z = Math_Coss(randomAngle);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Box/EnBox_Draw.s")
|
||||
accel->x = 0.0f;
|
||||
accel->y = 0.0f;
|
||||
accel->z = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns dust randomly around the chest when the chest hits the ground after falling (FALL types)
|
||||
*/
|
||||
void EnBox_SpawnDust(EnBox* this, GlobalContext* globalCtx) {
|
||||
s32 i;
|
||||
Vec3f pos;
|
||||
Vec3f velocity;
|
||||
Vec3f accel;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
EnBox_RandomDustKinematic(this, &pos, &velocity, &accel);
|
||||
func_8002873C(globalCtx, &pos, &velocity, &accel, 100, 30, 15);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used while the chest is falling (FALL types)
|
||||
*/
|
||||
void EnBox_Fall(EnBox* this, GlobalContext* globalCtx) {
|
||||
f32 yDiff;
|
||||
|
||||
this->alpha = 255;
|
||||
this->movementFlags &= ~ENBOX_MOVE_IMMOBILE;
|
||||
if (this->dyna.actor.bgCheckFlags & 1) {
|
||||
this->movementFlags |= ENBOX_MOVE_UNUSED;
|
||||
if (this->movementFlags & ENBOX_MOVE_FALL_ANGLE_SIDE) {
|
||||
this->movementFlags &= ~ENBOX_MOVE_FALL_ANGLE_SIDE;
|
||||
} else {
|
||||
this->movementFlags |= ENBOX_MOVE_FALL_ANGLE_SIDE;
|
||||
}
|
||||
if (this->type == ENBOX_TYPE_SWITCH_FLAG_FALL_BIG) {
|
||||
this->dyna.actor.velocity.y = -this->dyna.actor.velocity.y * 0.55f;
|
||||
} else {
|
||||
this->dyna.actor.velocity.y = -this->dyna.actor.velocity.y * 0.65f;
|
||||
}
|
||||
if (this->dyna.actor.velocity.y < 5.5f) {
|
||||
this->dyna.actor.shape.rot.z = 0;
|
||||
this->dyna.actor.posRot.pos.y = this->dyna.actor.groundY;
|
||||
EnBox_SetupAction(this, EnBox_WaitOpen);
|
||||
func_800803F0(globalCtx, this->unk_1AC);
|
||||
}
|
||||
Audio_PlaySoundGeneral(NA_SE_EV_COFFIN_CAP_BOUND, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
EnBox_SpawnDust(this, globalCtx);
|
||||
}
|
||||
yDiff = this->dyna.actor.posRot.pos.y - this->dyna.actor.groundY;
|
||||
if (this->movementFlags & ENBOX_MOVE_FALL_ANGLE_SIDE) {
|
||||
this->dyna.actor.shape.rot.z = yDiff * 50.0f;
|
||||
} else {
|
||||
this->dyna.actor.shape.rot.z = -yDiff * 50.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_FallOnSwitchFlag(EnBox* this, GlobalContext* globalCtx) {
|
||||
s32 treasureFlag = this->dyna.actor.params & 0x1F;
|
||||
|
||||
if (treasureFlag >= ENBOX_TREASURE_FLAG_UNK_MIN && treasureFlag < ENBOX_TREASURE_FLAG_UNK_MAX) {
|
||||
func_8002F5F0(&this->dyna.actor, globalCtx);
|
||||
}
|
||||
|
||||
if (this->unk_1A8 >= 0) {
|
||||
EnBox_SetupAction(this, EnBox_Fall);
|
||||
this->unk_1AC = func_800800F8(globalCtx, 4500, 9999, &this->dyna.actor, 0);
|
||||
func_8003EC50(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
} else if (this->unk_1A8 >= -11) {
|
||||
this->unk_1A8++;
|
||||
} else if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
|
||||
this->unk_1A8++;
|
||||
}
|
||||
}
|
||||
|
||||
// used for types 9, 10
|
||||
void func_809C9700(EnBox* this, GlobalContext* globalCtx) {
|
||||
s32 treasureFlag = this->dyna.actor.params & 0x1F;
|
||||
Player* player = PLAYER;
|
||||
|
||||
if (treasureFlag >= ENBOX_TREASURE_FLAG_UNK_MIN && treasureFlag < ENBOX_TREASURE_FLAG_UNK_MAX) {
|
||||
func_8002F5F0(&this->dyna.actor, globalCtx);
|
||||
}
|
||||
|
||||
if (Math3D_Vec3fDistSq(&this->dyna.actor.posRot.pos, &player->actor.posRot.pos) > 22500.0f) {
|
||||
this->unk_1FB = ENBOX_STATE_0;
|
||||
} else {
|
||||
if (this->unk_1FB == ENBOX_STATE_0) {
|
||||
if (!(player->stateFlags2 & 0x1000000)) {
|
||||
player->stateFlags2 |= 0x800000;
|
||||
return;
|
||||
}
|
||||
this->unk_1FB = ENBOX_STATE_1;
|
||||
}
|
||||
|
||||
if (this->unk_1FB == ENBOX_STATE_1) {
|
||||
func_8010BD58(globalCtx, 1);
|
||||
this->unk_1FB = ENBOX_STATE_2;
|
||||
} else if (this->unk_1FB == ENBOX_STATE_2 && globalCtx->msgCtx.unk_E3EE == 4) {
|
||||
if ((globalCtx->msgCtx.unk_E3EC == 8 && this->type == ENBOX_TYPE_9) ||
|
||||
(globalCtx->msgCtx.unk_E3EC == 9 && this->type == ENBOX_TYPE_10)) {
|
||||
this->dyna.actor.flags &= ~0x2000000;
|
||||
EnBox_SetupAction(this, EnBox_AppearInit);
|
||||
func_80080480(globalCtx, &this->dyna.actor);
|
||||
this->unk_1A8 = 0;
|
||||
this->unk_1FB = ENBOX_STATE_0;
|
||||
} else {
|
||||
this->unk_1FB = ENBOX_STATE_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_AppearOnSwitchFlag(EnBox* this, GlobalContext* globalCtx) {
|
||||
s32 treasureFlag = this->dyna.actor.params & 0x1F;
|
||||
|
||||
if (treasureFlag >= ENBOX_TREASURE_FLAG_UNK_MIN && treasureFlag < ENBOX_TREASURE_FLAG_UNK_MAX) {
|
||||
func_8002F5F0(&this->dyna.actor, globalCtx);
|
||||
}
|
||||
|
||||
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
|
||||
func_80080480(globalCtx, &this->dyna.actor);
|
||||
EnBox_SetupAction(this, EnBox_AppearInit);
|
||||
this->unk_1A8 = -30;
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_AppearOnRoomClear(EnBox* this, GlobalContext* globalCtx) {
|
||||
s32 treasureFlag = this->dyna.actor.params & 0x1F;
|
||||
|
||||
if (treasureFlag >= ENBOX_TREASURE_FLAG_UNK_MIN && treasureFlag < ENBOX_TREASURE_FLAG_UNK_MAX) {
|
||||
func_8002F5F0(&this->dyna.actor, globalCtx);
|
||||
}
|
||||
|
||||
if (Flags_GetTempClear(globalCtx, this->dyna.actor.room) && !Player_InCsMode(globalCtx)) {
|
||||
Flags_SetClear(globalCtx, this->dyna.actor.room);
|
||||
EnBox_SetupAction(this, EnBox_AppearInit);
|
||||
func_80080480(globalCtx, &this->dyna.actor);
|
||||
if (func_80080728(globalCtx, this->dyna.actor.type)) {
|
||||
this->unk_1A8 = 0;
|
||||
} else {
|
||||
this->unk_1A8 = -30;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The chest is ready to appear, possibly waiting for camera/cutscene-related stuff to happen
|
||||
*/
|
||||
void EnBox_AppearInit(EnBox* this, GlobalContext* globalCtx) {
|
||||
if (func_8005B198() == this->dyna.actor.type || this->unk_1A8 != 0) {
|
||||
EnBox_SetupAction(this, EnBox_AppearAnimation);
|
||||
this->unk_1A8 = 0;
|
||||
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DEMO_KANKYO, this->dyna.actor.initPosRot.pos.x,
|
||||
this->dyna.actor.initPosRot.pos.y, this->dyna.actor.initPosRot.pos.z, 0, 0, 0, 0x0011);
|
||||
Audio_PlaySoundGeneral(NA_SE_EV_TRE_BOX_APPEAR, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||
&D_801333E8);
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_AppearAnimation(EnBox* this, GlobalContext* globalCtx) {
|
||||
func_8003EC50(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
|
||||
|
||||
if (this->unk_1A8 < 0) {
|
||||
this->unk_1A8++;
|
||||
} else if (this->unk_1A8 < 40) {
|
||||
this->unk_1A8++;
|
||||
this->dyna.actor.posRot.pos.y += 1.25f;
|
||||
} else if (this->unk_1A8 < 60) {
|
||||
this->alpha += 12;
|
||||
this->unk_1A8++;
|
||||
this->dyna.actor.posRot.pos.y = this->dyna.actor.initPosRot.pos.y;
|
||||
} else {
|
||||
EnBox_SetupAction(this, EnBox_WaitOpen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Chest is ready to be open
|
||||
*/
|
||||
void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
|
||||
f32 frameCount;
|
||||
AnimationHeader* anim;
|
||||
s32 linkAge;
|
||||
s32 pad;
|
||||
Vec3f sp4C;
|
||||
Player* player;
|
||||
|
||||
this->alpha = 255;
|
||||
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
|
||||
if (this->unk_1F4 != 0) { // unk_1F4 is modified by player code
|
||||
linkAge = gSaveContext.linkAge;
|
||||
anim = D_809CA800[(this->unk_1F4 < 0 ? 2 : 0) + linkAge];
|
||||
frameCount = SkelAnime_GetFrameCount(&anim->genericHeader);
|
||||
SkelAnime_ChangeAnim(&this->skelanime, anim, 1.5f, 0, frameCount, 2, 0.0f);
|
||||
EnBox_SetupAction(this, EnBox_Open);
|
||||
if (this->unk_1F4 > 0) {
|
||||
switch (this->type) {
|
||||
case ENBOX_TYPE_SMALL:
|
||||
case ENBOX_TYPE_6:
|
||||
case ENBOX_TYPE_ROOM_CLEAR_SMALL:
|
||||
case ENBOX_TYPE_SWITCH_FLAG_FALL_SMALL:
|
||||
break;
|
||||
default:
|
||||
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->dyna.actor, globalCtx, ACTOR_DEMO_TRE_LGT,
|
||||
this->dyna.actor.posRot.pos.x, this->dyna.actor.posRot.pos.y,
|
||||
this->dyna.actor.posRot.pos.z, this->dyna.actor.shape.rot.x,
|
||||
this->dyna.actor.shape.rot.y, this->dyna.actor.shape.rot.z, 0xFFFF);
|
||||
func_800F5C64(0x92B);
|
||||
}
|
||||
}
|
||||
osSyncPrintf("Actor_Environment_Tbox_On() %d\n", this->dyna.actor.params & 0x1F);
|
||||
Flags_SetTreasure(globalCtx, this->dyna.actor.params & 0x1F);
|
||||
} else {
|
||||
player = PLAYER;
|
||||
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.posRot.pos);
|
||||
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
|
||||
func_8002DFC8(&this->dyna.actor, 0x3000, globalCtx)) {
|
||||
func_8002F554(&this->dyna.actor, globalCtx, 0 - (this->dyna.actor.params >> 5 & 0x7F));
|
||||
}
|
||||
if (Flags_GetTreasure(globalCtx, this->dyna.actor.params & 0x1F)) {
|
||||
EnBox_SetupAction(this, EnBox_Open);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an animation to its end, playing sounds at key points
|
||||
*/
|
||||
void EnBox_Open(EnBox* this, GlobalContext* globalCtx) {
|
||||
u16 sfxId;
|
||||
|
||||
this->dyna.actor.flags &= ~0x80;
|
||||
|
||||
if (SkelAnime_FrameUpdateMatrix(&this->skelanime)) {
|
||||
if (this->unk_1F4 > 0) {
|
||||
if (this->unk_1F4 < 120) {
|
||||
this->unk_1F4++;
|
||||
} else {
|
||||
Math_ApproxF(&this->unk_1B0, 0.0f, 0.05f);
|
||||
}
|
||||
} else {
|
||||
if (this->unk_1F4 > -120) {
|
||||
this->unk_1F4--;
|
||||
} else {
|
||||
Math_ApproxF(&this->unk_1B0, 0.0f, 0.05f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sfxId = 0;
|
||||
|
||||
if (func_800A56C8(&this->skelanime, 30.0f)) {
|
||||
sfxId = NA_SE_EV_TBOX_UNLOCK;
|
||||
} else if (func_800A56C8(&this->skelanime, 90.0f)) {
|
||||
sfxId = NA_SE_EV_TBOX_OPEN;
|
||||
}
|
||||
|
||||
if (sfxId != 0) {
|
||||
Audio_PlaySoundGeneral(sfxId, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
}
|
||||
|
||||
if (this->skelanime.limbDrawTbl[3].z > 0) {
|
||||
this->unk_1B0 = (0x7D00 - this->skelanime.limbDrawTbl[3].z) * 0.00006f;
|
||||
if (this->unk_1B0 < 0.0f) {
|
||||
this->unk_1B0 = 0.0f;
|
||||
} else if (this->unk_1B0 > 1.0f) {
|
||||
this->unk_1B0 = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_SpawnIceSmoke(EnBox* this, GlobalContext* globalCtx) {
|
||||
Vec3f pos;
|
||||
Vec3f vel = { 0.0f, 1.0f, 0.0f };
|
||||
Vec3f accel = { 0.0f, 0.0f, 0.0f };
|
||||
f32 f0;
|
||||
|
||||
this->iceSmokeTimer++;
|
||||
func_8002F974(&this->dyna.actor, NA_SE_EN_MIMICK_BREATH - SFX_FLAG);
|
||||
if (Math_Rand_ZeroOne() < 0.3f) {
|
||||
f0 = 2.0f * Math_Rand_ZeroOne() - 1.0f;
|
||||
pos = this->dyna.actor.posRot.pos;
|
||||
if (this->type == ENBOX_TYPE_SMALL || this->type == ENBOX_TYPE_6 || this->type == ENBOX_TYPE_ROOM_CLEAR_SMALL ||
|
||||
this->type == ENBOX_TYPE_SWITCH_FLAG_FALL_SMALL) {
|
||||
pos.x += f0 * 10.0f * Math_Sins(this->dyna.actor.posRot.rot.y + 0x4000);
|
||||
pos.z += f0 * 10.0f * Math_Coss(this->dyna.actor.posRot.rot.y + 0x4000);
|
||||
f0 = 2.0f * Math_Rand_ZeroOne() - 1.0f;
|
||||
vel.x = f0 * 0.8f * Math_Sins(this->dyna.actor.posRot.rot.y);
|
||||
vel.y = 1.8f;
|
||||
vel.z = f0 * 0.8f * Math_Coss(this->dyna.actor.posRot.rot.y);
|
||||
} else {
|
||||
pos.x += f0 * 20.0f * Math_Sins(this->dyna.actor.posRot.rot.y + 0x4000);
|
||||
pos.z += f0 * 20.0f * Math_Coss(this->dyna.actor.posRot.rot.y + 0x4000);
|
||||
f0 = 2.0f * Math_Rand_ZeroOne() - 1.0f;
|
||||
vel.x = f0 * 1.6f * Math_Sins(this->dyna.actor.posRot.rot.y);
|
||||
vel.y = 1.8f;
|
||||
vel.z = f0 * 1.6f * Math_Coss(this->dyna.actor.posRot.rot.y);
|
||||
}
|
||||
EffectSsIceSmoke_Spawn(globalCtx, &pos, &vel, &accel, 150);
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBox* this = THIS;
|
||||
|
||||
if (this->movementFlags & ENBOX_MOVE_STICK_TO_GROUND) {
|
||||
this->movementFlags &= ~ENBOX_MOVE_STICK_TO_GROUND;
|
||||
EnBox_ClipToGround(this, globalCtx);
|
||||
}
|
||||
|
||||
this->actionFunc(this, globalCtx);
|
||||
|
||||
if (!(this->movementFlags & ENBOX_MOVE_IMMOBILE)) {
|
||||
Actor_MoveForward(&this->dyna.actor);
|
||||
func_8002E4B4(globalCtx, &this->dyna.actor, 0.0f, 0.0f, 0.0f, 0x1C);
|
||||
}
|
||||
|
||||
switch (this->type) {
|
||||
case ENBOX_TYPE_SMALL:
|
||||
case ENBOX_TYPE_6:
|
||||
case ENBOX_TYPE_ROOM_CLEAR_SMALL:
|
||||
case ENBOX_TYPE_SWITCH_FLAG_FALL_SMALL:
|
||||
Actor_SetHeight(&this->dyna.actor, 20.0f);
|
||||
break;
|
||||
default:
|
||||
Actor_SetHeight(&this->dyna.actor, 40.0f);
|
||||
}
|
||||
|
||||
if ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C && this->actionFunc == EnBox_Open &&
|
||||
this->skelanime.animCurrentFrame > 45 && this->iceSmokeTimer < 100) {
|
||||
EnBox_SpawnIceSmoke(this, globalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
void EnBox_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx, Gfx** gfx) {
|
||||
EnBox* this = THIS;
|
||||
s32 pad;
|
||||
|
||||
if (limbIndex == 1) {
|
||||
gSPMatrix((*gfx)++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_box.c", 1492),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
if (this->type != ENBOX_TYPE_DECORATED_BIG) {
|
||||
gSPDisplayList((*gfx)++, D_060006F0);
|
||||
} else {
|
||||
gSPDisplayList((*gfx)++, D_06000AE8);
|
||||
}
|
||||
} else if (limbIndex == 3) {
|
||||
gSPMatrix((*gfx)++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_box.c", 1502),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
if (this->type != ENBOX_TYPE_DECORATED_BIG) {
|
||||
gSPDisplayList((*gfx)++, D_060010C0);
|
||||
} else {
|
||||
gSPDisplayList((*gfx)++, D_06001678);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Gfx* EnBox_EmptyDList(GraphicsContext* gfxCtx) {
|
||||
Gfx* dListHead;
|
||||
Gfx* dList;
|
||||
|
||||
dList = Graph_Alloc(gfxCtx, sizeof(Gfx));
|
||||
if (dList == NULL) {
|
||||
__assert("gfxp != NULL", "../z_en_box.c", 1528);
|
||||
}
|
||||
|
||||
dListHead = dList;
|
||||
gSPEndDisplayList(dListHead++);
|
||||
|
||||
return dList;
|
||||
}
|
||||
|
||||
// set render mode with a focus on transparency
|
||||
Gfx* func_809CA4A0(GraphicsContext* gfxCtx) {
|
||||
Gfx* dList;
|
||||
Gfx* dListHead;
|
||||
|
||||
dListHead = Graph_Alloc(gfxCtx, 2 * sizeof(Gfx));
|
||||
if (dListHead == NULL) {
|
||||
__assert("gfxp != NULL", "../z_en_box.c", 1546);
|
||||
}
|
||||
|
||||
dList = dListHead;
|
||||
gDPSetRenderMode(dListHead++,
|
||||
AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
||||
GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA),
|
||||
AA_EN | Z_CMP | Z_UPD | IM_RD | CLR_ON_CVG | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
|
||||
GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA));
|
||||
gSPEndDisplayList(dListHead++);
|
||||
|
||||
return dList;
|
||||
}
|
||||
|
||||
Gfx* func_809CA518(GraphicsContext* gfxCtx) {
|
||||
Gfx* dList;
|
||||
Gfx* dListHead;
|
||||
|
||||
dListHead = Graph_Alloc(gfxCtx, 2 * sizeof(Gfx));
|
||||
if (dListHead == NULL) {
|
||||
__assert("gfxp != NULL", "../z_en_box.c", 1564);
|
||||
}
|
||||
|
||||
dList = dListHead;
|
||||
gDPSetRenderMode(dListHead++,
|
||||
AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL |
|
||||
GBL_c1(G_BL_CLR_FOG, G_BL_A_SHADE, G_BL_CLR_IN, G_BL_1MA),
|
||||
G_RM_AA_ZB_OPA_SURF2);
|
||||
gSPEndDisplayList(dListHead++);
|
||||
|
||||
return dList;
|
||||
}
|
||||
|
||||
void EnBox_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBox* this = THIS;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_box.c", 1581);
|
||||
|
||||
/*
|
||||
this->dyna.actor.flags & 0x80 is set by Init (if type is 4 or 6)
|
||||
and cleared by Open
|
||||
*/
|
||||
if ((this->alpha == 255 && !(this->type == ENBOX_TYPE_4 || this->type == ENBOX_TYPE_6)) ||
|
||||
((this->dyna.actor.flags & 0x80) != 0x80 && (this->type == ENBOX_TYPE_4 || this->type == ENBOX_TYPE_6))) {
|
||||
gDPPipeSync(oGfxCtx->polyOpa.p++);
|
||||
gDPSetEnvColor(oGfxCtx->polyOpa.p++, 0, 0, 0, 255);
|
||||
gSPSegment(oGfxCtx->polyOpa.p++, 0x08, EnBox_EmptyDList(globalCtx->state.gfxCtx));
|
||||
func_80093D18(globalCtx->state.gfxCtx);
|
||||
oGfxCtx->polyOpa.p = SkelAnime_Draw2(globalCtx, this->skelanime.skeleton, this->skelanime.limbDrawTbl, NULL,
|
||||
EnBox_PostLimbDraw, &this->dyna.actor, oGfxCtx->polyOpa.p);
|
||||
} else if (this->alpha != 0) {
|
||||
gDPPipeSync(oGfxCtx->polyXlu.p++);
|
||||
func_80093D84(globalCtx->state.gfxCtx);
|
||||
gDPSetEnvColor(oGfxCtx->polyXlu.p++, 0, 0, 0, this->alpha);
|
||||
if (this->type == ENBOX_TYPE_4 || this->type == ENBOX_TYPE_6) {
|
||||
gSPSegment(oGfxCtx->polyXlu.p++, 0x08, func_809CA518(globalCtx->state.gfxCtx));
|
||||
} else {
|
||||
gSPSegment(oGfxCtx->polyXlu.p++, 0x08, func_809CA4A0(globalCtx->state.gfxCtx));
|
||||
}
|
||||
oGfxCtx->polyXlu.p = SkelAnime_Draw2(globalCtx, this->skelanime.skeleton, this->skelanime.limbDrawTbl, NULL,
|
||||
EnBox_PostLimbDraw, &this->dyna.actor, oGfxCtx->polyXlu.p);
|
||||
}
|
||||
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_box.c", 1639);
|
||||
}
|
||||
|
|
|
@ -4,13 +4,47 @@
|
|||
#include "ultra64.h"
|
||||
#include "global.h"
|
||||
|
||||
#define ENBOX_TREASURE_FLAG_UNK_MIN 20
|
||||
#define ENBOX_TREASURE_FLAG_UNK_MAX 32
|
||||
|
||||
struct EnBox;
|
||||
|
||||
typedef void (*EnBoxActionFunc)(struct EnBox*, GlobalContext*);
|
||||
|
||||
typedef enum {
|
||||
/*
|
||||
only values 1-11 are used explicitly, other values (like 0) default to another separate behavior
|
||||
*/
|
||||
/* 0 */ ENBOX_TYPE_BIG_DEFAULT,
|
||||
/* 1 */ ENBOX_TYPE_ROOM_CLEAR_BIG, // appear on room clear, store temp clear as permanent clear
|
||||
/* 2 */ ENBOX_TYPE_DECORATED_BIG, // boss key chest, different look, same as ENBOX_TYPE_BIG_DEFAULT otherwise
|
||||
/* 3 */ ENBOX_TYPE_SWITCH_FLAG_FALL_BIG, // falling, appear on switch flag set
|
||||
/* 4 */ ENBOX_TYPE_4, // big, drawn differently
|
||||
/* 5 */ ENBOX_TYPE_SMALL, // same as ENBOX_TYPE_BIG_DEFAULT but small
|
||||
/* 6 */ ENBOX_TYPE_6, // small, drawn differently
|
||||
/* 7 */ ENBOX_TYPE_ROOM_CLEAR_SMALL, // use room clear, store temp clear as perm clear
|
||||
/* 8 */ ENBOX_TYPE_SWITCH_FLAG_FALL_SMALL, // falling, appear on switch flag set
|
||||
/* 9 */ ENBOX_TYPE_9, // big, has something more to do with player and message context?
|
||||
/* 10 */ ENBOX_TYPE_10, // like 9
|
||||
/* 11 */ ENBOX_TYPE_SWITCH_FLAG_BIG // big, appear on switch flag set
|
||||
} EnBoxType;
|
||||
|
||||
typedef struct EnBox {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ char unk_14C[0xA8];
|
||||
/* 0x01F4 */ s16 unk_1F4;
|
||||
/* 0x01F6 */ char unk_1F6[0x06];
|
||||
/* 0x0000 */ DynaPolyActor dyna;
|
||||
/* 0x0164 */ SkelAnime skelanime;
|
||||
/* 0x01A8 */ s32 unk_1A8; // related to animation delays for types 3 and 8
|
||||
/* 0x01AC */ s32 unk_1AC;
|
||||
/* 0x01B0 */ f32 unk_1B0; // 0-1, rotation-related, apparently unused (in z_en_box.c at least)
|
||||
/* 0x01B4 */ EnBoxActionFunc actionFunc;
|
||||
/* 0x01B8 */ Vec3s limbDrawTable[5];
|
||||
/* 0x01D6 */ Vec3s transitionDrawTable[5];
|
||||
/* 0x01F4 */ s16 unk_1F4; // probably a frame count? set by player code
|
||||
/* 0x01F6 */ u8 movementFlags;
|
||||
/* 0x01F7 */ u8 alpha;
|
||||
/* 0x01F8 */ u8 switchFlag;
|
||||
/* 0x01F9 */ u8 type;
|
||||
/* 0x01FA */ u8 iceSmokeTimer;
|
||||
/* 0x01FB */ u8 unk_1FB;
|
||||
} EnBox; // size = 0x01FC
|
||||
|
||||
extern const ActorInit En_Box_InitVars;
|
||||
|
|
|
@ -5977,10 +5977,10 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
|
|||
this->stateFlags1 |= 0x20000C00;
|
||||
func_8083AE40(this, giEntry->objectId);
|
||||
this->actor.posRot.pos.x =
|
||||
chest->actor.posRot.pos.x - (Math_Sins(chest->actor.shape.rot.y) * 29.434299469f);
|
||||
chest->dyna.actor.posRot.pos.x - (Math_Sins(chest->dyna.actor.shape.rot.y) * 29.434299469f);
|
||||
this->actor.posRot.pos.z =
|
||||
chest->actor.posRot.pos.z - (Math_Coss(chest->actor.shape.rot.y) * 29.434299469f);
|
||||
this->currentYaw = this->actor.shape.rot.y = chest->actor.shape.rot.y;
|
||||
chest->dyna.actor.posRot.pos.z - (Math_Coss(chest->dyna.actor.shape.rot.y) * 29.434299469f);
|
||||
this->currentYaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y;
|
||||
func_80832224(this);
|
||||
|
||||
if ((giEntry->itemId != ITEM_NONE) && (giEntry->gi >= 0) &&
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue