En_Giant OK and mostly documented (#346)

* Migrate data to C

* EnGiant_Destroy OK

* EnGiant_Init OK

* func_80B01A74 OK

* Comment what each of the quest items are

* Put a little comment for myself on func_80B01A74 because it was confusing me lol

* Very early names (they're all bad)

* func_80B01990 OK

* EnGiant_Update OK

* func_80B024AC OK

* func_80B023D0 OK

* func_80B024D8 OK

* func_80B02354 OK (this function is bad!)

* func_80B020A0 OK

* func_80B01EE8 OK

* func_80B01E84 OK

* func_80B0211C OK

* func_80B02234 OK

* unk_250 -> sfxId and label SFX

* func_80B02688 OK

* func_80B026C4 OK

* EnGiant_Draw OK

* Update spec

* Fix up the static data

* unk_24E -> alpha

* Document some of the animation stuff

* Name EnGiant_IsNotFreed

* Document the giant types better

* Minor cleanup

* Add explanatory comment

* Rename the functions in functions.txt too, whoops

* Document sFaceTextures and blink routine

* Document all the various animations

* Name EnGiant_PlaySound

* Document some functions and change an unknown to action

* Add an SFX id I missed

* Name all the action funcs

* Name last two functions

* Mark one case as unused

* Change func_800F5A8C to use arg0, arg1, arg2, etc.

* Move sFaceTextures to EnGiant_Draw and comment what they are

* EnGiant_IsNotFreed -> EnGiant_IsImprisoned

* Use booleans in EnGiant_IsImprisoned

* **/ -> */

* action -> csAction

* Make macros for all type conditional checks

* Add warning about inconsistency

* Document the cs actions

* Add some documentation to animation-changing functions

* Update the function name in functions.txt too

* Improve GIANT_TYPE macros

* Remove an unncessary early return

* Incorporate animation changes
This commit is contained in:
Tom Overton 2021-10-25 05:22:17 -07:00 committed by GitHub
parent 4129e86882
commit bfd1ab28a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 579 additions and 45 deletions

View File

@ -1736,7 +1736,7 @@ void Font_LoadOrderedFont(Font* font);
// void func_800F50D4(void); // void func_800F50D4(void);
void Kankyo_Init(GlobalContext* globalCtx, EnvironmentContext* envCtx); void Kankyo_Init(GlobalContext* globalCtx, EnvironmentContext* envCtx);
u32 func_800F5954(u8* param_1, u32 param_2, u32 param_3, u8 param_4, u8 param_5); u32 func_800F5954(u8* param_1, u32 param_2, u32 param_3, u8 param_4, u8 param_5);
// void func_800F5A8C(void); f32 func_800F5A8C(u16 arg0, u16 arg1, u16 arg2, GlobalContext* globalContext);
// void func_800F5B10(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5); // void func_800F5B10(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5);
// void func_800F5CD0(void); // void func_800F5CD0(void);
// void func_800F6834(void); // void func_800F6834(void);

View File

@ -29,7 +29,11 @@ typedef struct {
/* 0x00 */ u16 unk0; // action; // "dousa" /* 0x00 */ u16 unk0; // action; // "dousa"
/* 0x02 */ u16 startFrame; /* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame; /* 0x04 */ u16 endFrame;
/* 0x06 */ UNK_TYPE1 pad6[0x2A]; /* 0x06 */ UNK_TYPE1 pad6[0xA];
/* 0x10 */ s32 unk10;
/* 0x14 */ UNK_TYPE1 pad14[0x8];
/* 0x1C */ s32 unk1C;
/* 0x20 */ UNK_TYPE1 pad20[0x10];
} CsCmdActorAction; // size = 0x30 } CsCmdActorAction; // size = 0x30
typedef struct { typedef struct {

3
spec
View File

@ -3889,8 +3889,7 @@ beginseg
name "ovl_En_Giant" name "ovl_En_Giant"
compress compress
include "build/src/overlays/actors/ovl_En_Giant/z_en_giant.o" include "build/src/overlays/actors/ovl_En_Giant/z_en_giant.o"
include "build/data/ovl_En_Giant/ovl_En_Giant.data.o" include "build/src/overlays/actors/ovl_En_Giant/ovl_En_Giant_reloc.o"
include "build/data/ovl_En_Giant/ovl_En_Giant.reloc.o"
endseg endseg
beginseg beginseg

View File

@ -1,3 +1,9 @@
/*
* File: z_en_giant.c
* Overlay: ovl_En_Giant
* Description: Giant
*/
#include "z_en_giant.h" #include "z_en_giant.h"
#define FLAGS 0x00000030 #define FLAGS 0x00000030
@ -9,11 +15,10 @@ void EnGiant_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnGiant_Update(Actor* thisx, GlobalContext* globalCtx); void EnGiant_Update(Actor* thisx, GlobalContext* globalCtx);
void EnGiant_Draw(Actor* thisx, GlobalContext* globalCtx); void EnGiant_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80B023D0(EnGiant* this, GlobalContext* globalCtx); void EnGiant_PerformClockTowerSuccessActions(EnGiant* this, GlobalContext* globalCtx);
void func_80B024AC(EnGiant* this, GlobalContext* globalCtx); void EnGiant_PlayClockTowerFailureAnimation(EnGiant* this, GlobalContext* globalCtx);
void func_80B024D8(EnGiant* this, GlobalContext* globalCtx); void EnGiant_PerformCutsceneActions(EnGiant* this, GlobalContext* globalCtx);
#if 0
const ActorInit En_Giant_InitVars = { const ActorInit En_Giant_InitVars = {
ACTOR_EN_GIANT, ACTOR_EN_GIANT,
ACTORCAT_NPC, ACTORCAT_NPC,
@ -26,42 +31,460 @@ const ActorInit En_Giant_InitVars = {
(ActorFunc)EnGiant_Draw, (ActorFunc)EnGiant_Draw,
}; };
#endif extern AnimationHeader D_06002168;
extern Gfx D_06005A80[];
extern Gfx D_06006280[];
extern Gfx D_06007610[];
extern Gfx D_06006A80[];
extern FlexSkeletonHeader D_060079B0;
extern AnimationHeader D_06008394;
extern AnimationHeader D_060096E4;
extern AnimationHeader D_0600A1C4;
extern AnimationHeader D_0600ACA4;
extern AnimationHeader D_0600B784;
extern AnimationHeader D_0600C5D4;
extern AnimationHeader D_0600D040;
extern AnimationHeader D_0600DE84;
extern AnimationHeader D_060102A4;
extern AnimationHeader D_060116E4;
extern AnimationHeader D_06012A38;
extern AnimationHeader D_06013004;
extern AnimationHeader D_06013FE8;
extern AnimationHeader D_06015334;
extern AnimationHeader D_06017944;
extern UNK_TYPE D_06002168; static AnimationHeader* sAnimationTable[] = {
extern UNK_TYPE D_06007610; &D_06008394, &D_060096E4, &D_060102A4, &D_060116E4, &D_06012A38, &D_06013004, &D_06013FE8, &D_06015334,
extern UNK_TYPE D_060116E4; &D_06017944, &D_0600A1C4, &D_0600D040, &D_0600DE84, &D_0600ACA4, &D_0600B784, &D_0600C5D4,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B01990.s") void EnGiant_ChangeAnimation(EnGiant* this, s16 newAnimationId) {
if (newAnimationId >= GIANT_ANIMATION_LOOK_UP_START && newAnimationId < GIANT_ANIMATION_MAX) {
if ((this->animationId == GIANT_ANIMATION_WALKING_LOOP && newAnimationId != GIANT_ANIMATION_WALKING_LOOP) ||
(newAnimationId == GIANT_ANIMATION_WALKING_LOOP && this->animationId != GIANT_ANIMATION_WALKING_LOOP)) {
Animation_Change(&this->skelAnime, sAnimationTable[newAnimationId], 1.0f, 0.0f,
Animation_GetLastFrame(&sAnimationTable[newAnimationId]->common), 2, 10.0f);
} else {
Animation_PlayOnce(&this->skelAnime, sAnimationTable[newAnimationId]);
}
this->animationId = newAnimationId;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B01A74.s") s32 EnGiant_IsImprisoned(EnGiant* this) {
switch (GIANT_TYPE(&this->actor)) {
case GIANT_TYPE_SWAMP_TERMINA_FIELD:
case GIANT_TYPE_SWAMP_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_SWAMP_GIANTS_CHAMBER_AND_ENDING:
case GIANT_TYPE_SWAMP_CLOCK_TOWER_FAILURE:
if (!CHECK_QUEST_ITEM(0)) {
return true;
}
break;
case GIANT_TYPE_MOUNTAIN_TERMINA_FIELD:
case GIANT_TYPE_MOUNTAIN_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_MOUNTAIN_GIANTS_CHAMBER_AND_ENDING:
case GIANT_TYPE_MOUNTAIN_CLOCK_TOWER_FAILURE:
if (!CHECK_QUEST_ITEM(1)) {
return true;
}
break;
case GIANT_TYPE_OCEAN_TERMINA_FIELD:
case GIANT_TYPE_OCEAN_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_OCEAN_GIANTS_CHAMBER_AND_ENDING:
case GIANT_TYPE_OCEAN_CLOCK_TOWER_FAILURE:
if (!CHECK_QUEST_ITEM(2)) {
return true;
}
break;
case GIANT_TYPE_CANYON_TERMINA_FIELD:
case GIANT_TYPE_CANYON_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_CANYON_GIANTS_CHAMBER_AND_ENDING:
case GIANT_TYPE_CANYON_CLOCK_TOWER_FAILURE:
if (!CHECK_QUEST_ITEM(3)) {
return true;
}
break;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/EnGiant_Init.s") return false;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/EnGiant_Destroy.s") void EnGiant_Init(Actor* thisx, GlobalContext* globalCtx) {
EnGiant* this = THIS;
s32 type = GIANT_TYPE(thisx);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B01E84.s") this->actor.uncullZoneForward = 4000.0f;
this->actor.uncullZoneScale = 2000.0f;
this->actor.uncullZoneDownward = 2400.0f;
Actor_SetScale(&this->actor, 0.32f);
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &D_060079B0, &D_06002168, this->jointTable, this->morphTable, 16);
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_IDLE_LOOP);
this->csAction = GIANT_CS_ACTION_NONE;
this->actionFunc = EnGiant_PerformCutsceneActions;
this->actor.draw = NULL;
this->alpha = 0;
this->actor.velocity.y = -10.0f;
this->actor.minVelocityY = -10.0f;
this->actor.gravity = -5.0f;
switch (type) {
case GIANT_TYPE_CANYON_TERMINA_FIELD:
case GIANT_TYPE_CANYON_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_CANYON_GIANTS_CHAMBER_AND_ENDING:
this->unk_24A = 0x1C6;
break;
case GIANT_TYPE_SWAMP_TERMINA_FIELD:
case GIANT_TYPE_SWAMP_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_SWAMP_GIANTS_CHAMBER_AND_ENDING:
this->unk_24A = 0x1C7;
break;
case GIANT_TYPE_OCEAN_TERMINA_FIELD:
case GIANT_TYPE_OCEAN_CLOCK_TOWER_SUCCESS:
case GIANT_TYPE_OCEAN_GIANTS_CHAMBER_AND_ENDING:
this->unk_24A = 0x1C8;
break;
default:
this->unk_24A = 0x1C5;
break;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B01EE8.s") if (GIANT_TYPE_IS_CLOCK_TOWER_SUCCESS(type)) {
if (!(gSaveContext.weekEventReg[0x19] & 2)) {
Actor_MarkForDeath(&this->actor);
return;
}
this->unk_24A = 0x1C5;
Actor_SetScale(&this->actor, 0.32f);
this->actionFunc = EnGiant_PerformClockTowerSuccessActions;
Animation_Change(&this->skelAnime, &D_060116E4, 0.0f, Animation_GetLastFrame(&D_060116E4) - 1.0f,
Animation_GetLastFrame(&D_060116E4), 2, 0.0f);
this->actor.draw = EnGiant_Draw;
this->actor.velocity.y = 0.0f;
this->actor.minVelocityY = 0.0f;
this->actor.gravity = 0.0f;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B020A0.s") if (GIANT_TYPE_IS_CLOCK_TOWER_FAILURE(type)) {
Actor_SetScale(&this->actor, 0.32f);
this->actionFunc = EnGiant_PlayClockTowerFailureAnimation;
Animation_Change(&this->skelAnime, &D_06013FE8, 1.0f, 0.0f, Animation_GetLastFrame(&D_06013004), 0, 0.0f);
this->actor.draw = EnGiant_Draw;
this->actor.velocity.y = 0.0f;
this->actor.minVelocityY = 0.0f;
this->actor.gravity = 0.0f;
if (EnGiant_IsImprisoned(this)) {
Actor_MarkForDeath(&this->actor);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B0211C.s") if (GIANT_TYPE_IS_NOT_TERMINA_FIELD(type)) {
this->alpha = 255;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B02234.s") this->sfxId = 0xFFFF;
if (GIANT_TYPE_IS_CHAMBER_OR_ENDING(type)) {
switch (gSaveContext.sceneSetupIndex) {
case 0:
case 10:
this->sfxId = NA_SE_EV_KYOJIN_GRATITUDE2 - SFX_FLAG;
break;
case 1:
case 2:
case 3:
this->sfxId = NA_SE_EV_KYOJIN_GRATITUDE1 - SFX_FLAG;
break;
default:
this->sfxId = NA_SE_EV_KYOJIN_GRATITUDE0 - SFX_FLAG;
break;
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B02354.s") void EnGiant_Destroy(Actor* thisx, GlobalContext* globalCtx) {
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B023D0.s") /**
* The animations in sAnimationTable are organized such that looping animations
* appear immediately after their respective starting animations. The point of
* this function is to play the requested start animation if it has not been
* played yet and play the respetive looping animation otherwise.
*/
void EnGiant_ChangeToStartOrLoopAnimation(EnGiant* this, s16 requestedAnimationId) {
s16 nextAnimationId = requestedAnimationId + 1;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B024AC.s") if (this->animationId != nextAnimationId) {
if (this->animationId != requestedAnimationId) {
EnGiant_ChangeAnimation(this, requestedAnimationId);
} else {
EnGiant_ChangeAnimation(this, nextAnimationId);
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B024D8.s") /**
* Immediately switches to the specified animation for this cutscene action.
*/
void EnGiant_ChangeAnimationBasedOnCsAction(EnGiant* this) {
switch (this->csAction) {
case GIANT_CS_ACTION_IDLE:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_IDLE_LOOP);
break;
case GIANT_CS_ACTION_WALKING:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_WALKING_LOOP);
break;
case GIANT_CS_ACTION_STRUGGLING:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_STRUGGLE_START);
break;
case GIANT_CS_ACTION_FALLING_OVER:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_FALLING_OVER);
break;
case GIANT_CS_ACTION_IDLE_FADE_IN:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_IDLE_LOOP);
this->alpha = 0;
break;
case GIANT_CS_ACTION_TALKING:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_BIG_CALL_START);
break;
case GIANT_CS_ACTION_DONE_TALKING:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_BIG_CALL_END);
break;
case GIANT_CS_ACTION_TEACHING_OATH_TO_ORDER:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_SMALL_CALL_START);
break;
case GIANT_CS_ACTION_PLAYER_LEARNED_OATH_TO_ORDER:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_SMALL_CALL_END);
break;
case GIANT_CS_ACTION_UNKNOWN_12:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_IDLE_LOOP);
break;
case GIANT_CS_ACTION_UNKNOWN_13:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_WALKING_LOOP);
break;
case GIANT_CS_ACTION_UNKNOWN_14:
if (this->animationId != GIANT_ANIMATION_WALKING_LOOP) {
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_WALKING_LOOP);
}
break;
case GIANT_CS_ACTION_HOLDING_UP_MOON_IN_CLOCK_TOWER:
Animation_Change(&this->skelAnime, &D_060116E4, 0.0f, Animation_GetLastFrame(&D_060116E4) - 1.0f,
Animation_GetLastFrame(&D_060116E4), 2, 0.0f);
break;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/EnGiant_Update.s") void EnGiant_UpdateAlpha(EnGiant* this) {
switch (this->csAction) {
case GIANT_CS_ACTION_FALLING_OVER:
if (this->skelAnime.curFrame >= 90.0f && this->alpha > 0) {
this->alpha -= 12;
}
break;
case GIANT_CS_ACTION_UNKNOWN_14:
this->alpha -= 12;
break;
default:
if (this->alpha < 255) {
this->alpha += 8;
}
break;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B02688.s") /**
* Plays the currently specified animation and, if the animation is done playing,
* switches to the animation appropriate for the current cutscene action. This
* function can be used to play the appropriate starting or looping animation for
* a given cutscene action, depending on what animation has already been played.
*/
void EnGiant_PlayAndUpdateAnimation(EnGiant* this) {
if (SkelAnime_Update(&this->skelAnime) &&
(this->animationId != GIANT_ANIMATION_FALLING_OVER || this->csAction != GIANT_CS_ACTION_FALLING_OVER)) {
EnGiant_ChangeAnimation(this, this->animationId);
switch (this->csAction) {
case GIANT_CS_ACTION_LOOKING_UP:
EnGiant_ChangeToStartOrLoopAnimation(this, GIANT_ANIMATION_LOOK_UP_START);
break;
case GIANT_CS_ACTION_RAISING_ARMS:
EnGiant_ChangeToStartOrLoopAnimation(this, GIANT_ANIMATION_RAISED_ARMS_START);
break;
case GIANT_CS_ACTION_STRUGGLING:
EnGiant_ChangeToStartOrLoopAnimation(this, GIANT_ANIMATION_STRUGGLE_START);
break;
case GIANT_CS_ACTION_FALLING_OVER:
// Unused
EnGiant_ChangeToStartOrLoopAnimation(this, GIANT_ANIMATION_FALLING_OVER);
break;
case GIANT_CS_ACTION_TALKING:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_BIG_CALL_LOOP);
break;
case GIANT_CS_ACTION_DONE_TALKING:
case GIANT_CS_ACTION_PLAYER_LEARNED_OATH_TO_ORDER:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_IDLE_LOOP);
break;
case GIANT_CS_ACTION_TEACHING_OATH_TO_ORDER:
EnGiant_ChangeAnimation(this, GIANT_ANIMATION_SMALL_CALL_LOOP);
break;
}
SkelAnime_Update(&this->skelAnime);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/func_80B026C4.s") void EnGiant_PlaySound(EnGiant* this) {
if (this->actor.draw != NULL && this->alpha > 0) {
if (this->animationId == GIANT_ANIMATION_WALKING_LOOP &&
(Animation_OnFrame(&this->skelAnime, 40.0f) || Animation_OnFrame(&this->skelAnime, 100.0f))) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_KYOJIN_WALK);
}
if (this->animationId == GIANT_ANIMATION_FALLING_OVER && Animation_OnFrame(&this->skelAnime, 40.0f)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_KYOJIN_VOICE_FAIL);
}
if (this->sfxId != 0xFFFF &&
((this->animationId == GIANT_ANIMATION_BIG_CALL_START && this->skelAnime.curFrame >= 18.0f) ||
this->animationId == GIANT_ANIMATION_BIG_CALL_LOOP)) {
func_800B9010(&this->actor, this->sfxId);
}
if ((this->animationId == GIANT_ANIMATION_SMALL_CALL_START && this->skelAnime.curFrame >= 18.0f) ||
this->animationId == GIANT_ANIMATION_SMALL_CALL_LOOP) {
func_800B9010(&this->actor, NA_SE_EV_KYOJIN_SIGN - SFX_FLAG);
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Giant/EnGiant_Draw.s") void EnGiant_UpdatePosition(EnGiant* this, GlobalContext* globalCtx, u32 actionIndex) {
CsCmdActorAction* actorAction = globalCtx->csCtx.npcActions[actionIndex];
f32 floatUnk10 = actorAction->unk10;
s32 pad[2];
f32 floatUnk1C = actorAction->unk1C;
f32 functionTemp;
functionTemp = func_800F5A8C(actorAction->endFrame, actorAction->startFrame, globalCtx->csCtx.frames, globalCtx);
this->actor.world.pos.y = ((floatUnk1C - floatUnk10) * functionTemp) + floatUnk10;
}
void EnGiant_PerformClockTowerSuccessActions(EnGiant* this, GlobalContext* globalCtx) {
if (func_800EE29C(globalCtx, this->unk_24A)) {
EnGiant_UpdatePosition(this, globalCtx, func_800EE200(globalCtx, this->unk_24A));
if (this->csAction != globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0) {
this->csAction = globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0;
EnGiant_ChangeAnimationBasedOnCsAction(this);
}
EnGiant_UpdateAlpha(this);
}
EnGiant_PlaySound(this);
if (this->csAction == GIANT_CS_ACTION_STRUGGLING) {
func_800B9010(&this->actor, NA_SE_IT_KYOJIN_BEARING - SFX_FLAG);
}
EnGiant_PlayAndUpdateAnimation(this);
}
void EnGiant_PlayClockTowerFailureAnimation(EnGiant* this, GlobalContext* globalCtx) {
SkelAnime_Update(&this->skelAnime);
}
void EnGiant_PerformCutsceneActions(EnGiant* this, GlobalContext* globalCtx) {
this->actor.draw = EnGiant_Draw;
if (func_800EE29C(globalCtx, this->unk_24A)) {
func_800EDF24(&this->actor, globalCtx, func_800EE200(globalCtx, this->unk_24A));
if (this->csAction != globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0) {
this->csAction = globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0;
EnGiant_ChangeAnimationBasedOnCsAction(this);
}
EnGiant_UpdateAlpha(this);
}
if (GIANT_TYPE_IS_TERMINA_FIELD(GIANT_TYPE(&this->actor)) && EnGiant_IsImprisoned(this)) {
this->actor.draw = NULL;
}
EnGiant_PlaySound(this);
EnGiant_PlayAndUpdateAnimation(this);
}
void EnGiant_Update(Actor* thisx, GlobalContext* globalCtx) {
EnGiant* this = THIS;
s32 blinkTimerTemp;
this->actionFunc(this, globalCtx);
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
if (this->blinkTimer == 0) {
blinkTimerTemp = 0;
} else {
this->blinkTimer--;
blinkTimerTemp = this->blinkTimer;
}
if (!blinkTimerTemp) {
this->blinkTimer = Rand_S16Offset(60, 60);
}
this->faceIndex = this->blinkTimer;
if (this->faceIndex >= 3) {
this->faceIndex = 0;
}
}
void EnGiant_PostLimbDrawOpa(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
if (limbIndex == 1) {
OPEN_DISPS(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, D_06007610);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
}
void EnGiant_PostLimbDrawXlu(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx,
Gfx** gfx) {
EnGiant* this = THIS;
if (limbIndex == 1) {
Matrix_CopyCurrentState(&this->unk_254);
}
}
void EnGiant_Draw(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnGiant* this = THIS;
/**
* 0 = eyes fully open face
* 1 = eyes half-closed face
* 2 = eyes fully closed face
*/
static TexturePtr sFaceTextures[] = { D_06005A80, D_06006280, D_06006A80 };
if (this->alpha > 0) {
OPEN_DISPS(globalCtx->state.gfxCtx);
if (this->alpha >= 255) {
func_8012C28C(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sFaceTextures[this->faceIndex]));
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
Scene_SetRenderModeXlu(globalCtx, 0, 1);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable,
this->skelAnime.dListCount, NULL, EnGiant_PostLimbDrawOpa, thisx);
} else if (this->alpha > 0) {
if (this->alpha >= 129) {
func_8012C2B4(POLY_XLU_DISP++);
Scene_SetRenderModeXlu(globalCtx, 2, 2);
} else {
func_8012C304(POLY_XLU_DISP++);
Scene_SetRenderModeXlu(globalCtx, 1, 2);
}
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sFaceTextures[this->faceIndex]));
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha);
POLY_XLU_DISP =
SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable,
this->skelAnime.dListCount, NULL, EnGiant_PostLimbDrawXlu, thisx, POLY_XLU_DISP);
Matrix_InsertMatrix(&this->unk_254, MTXMODE_NEW);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, D_06007610);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
}

View File

@ -3,14 +3,107 @@
#include "global.h" #include "global.h"
#define GIANT_TYPE(thisx) ((thisx)->params & 0xF)
#define GIANT_TYPE_IS_NOT_TERMINA_FIELD(type) (type > GIANT_TYPE_OCEAN_TERMINA_FIELD)
#define GIANT_TYPE_IS_TERMINA_FIELD(type) (type <= GIANT_TYPE_OCEAN_TERMINA_FIELD)
#define GIANT_TYPE_IS_CLOCK_TOWER_SUCCESS(type) (type >= GIANT_TYPE_MOUNTAIN_CLOCK_TOWER_SUCCESS && type <= GIANT_TYPE_OCEAN_CLOCK_TOWER_SUCCESS)
#define GIANT_TYPE_IS_CHAMBER_OR_ENDING(type) (type >= GIANT_TYPE_MOUNTAIN_GIANTS_CHAMBER_AND_ENDING && type <= GIANT_TYPE_OCEAN_GIANTS_CHAMBER_AND_ENDING)
#define GIANT_TYPE_IS_CLOCK_TOWER_FAILURE(type) (type >= GIANT_TYPE_MOUNTAIN_CLOCK_TOWER_FAILURE && type <= GIANT_TYPE_OCEAN_CLOCK_TOWER_FAILURE)
/**
* The giants are divided into types based on where in the game they appear.
* - TERMINA_FIELD: These appear in all non-ending cutscenes that take place in Termina Field.
* - CLOCK_TOWER_SUCCESS: These appear in the Clock Tower when the Oath to Order is played and all giants are freed.
* - GIANTS_CHAMBER_AND_ENDING: These giants appear in the Giant's Chamber or in all cutscenes that play after defeating Majora.
* - CLOCK_TOWER_FAILURE: These appear in the Clock Tower when the Oath to Order is played and all giants are NOT freed.
*
* The SWAMP, MOUNTAIN, OCEAN, and CANYON signifiers are used to identify which of the four giants it is,
* but the devs were not always consistent about this. For example, the giants in the Giant's Chamber are
* always GIANT_TYPE_MOUNTAIN_GIANTS_CHAMBER_AND_ENDING, regardless of which boss was just defeated. These
* are named such that EnGiant_IsImprisoned has the expected behavior; the devs were only inconsistent in
* the cases where they weren't calling this function.
*/
typedef enum {
/* 0 */ GIANT_TYPE_MOUNTAIN_TERMINA_FIELD,
/* 1 */ GIANT_TYPE_CANYON_TERMINA_FIELD,
/* 2 */ GIANT_TYPE_SWAMP_TERMINA_FIELD,
/* 3 */ GIANT_TYPE_OCEAN_TERMINA_FIELD,
/* 4 */ GIANT_TYPE_MOUNTAIN_CLOCK_TOWER_SUCCESS,
/* 5 */ GIANT_TYPE_CANYON_CLOCK_TOWER_SUCCESS,
/* 6 */ GIANT_TYPE_SWAMP_CLOCK_TOWER_SUCCESS,
/* 7 */ GIANT_TYPE_OCEAN_CLOCK_TOWER_SUCCESS,
/* 8 */ GIANT_TYPE_MOUNTAIN_GIANTS_CHAMBER_AND_ENDING,
/* 9 */ GIANT_TYPE_CANYON_GIANTS_CHAMBER_AND_ENDING,
/* 10 */ GIANT_TYPE_SWAMP_GIANTS_CHAMBER_AND_ENDING,
/* 11 */ GIANT_TYPE_OCEAN_GIANTS_CHAMBER_AND_ENDING,
/* 12 */ GIANT_TYPE_MOUNTAIN_CLOCK_TOWER_FAILURE,
/* 13 */ GIANT_TYPE_CANYON_CLOCK_TOWER_FAILURE,
/* 14 */ GIANT_TYPE_SWAMP_CLOCK_TOWER_FAILURE,
/* 15 */ GIANT_TYPE_OCEAN_CLOCK_TOWER_FAILURE,
} GiantType;
/**
* These values are used to index into sAnimationTable to pick the appropriate animation.
*/
typedef enum {
/* 0 */ GIANT_ANIMATION_LOOK_UP_START,
/* 1 */ GIANT_ANIMATION_LOOK_UP_LOOP,
/* 2 */ GIANT_ANIMATION_FALLING_OVER,
/* 3 */ GIANT_ANIMATION_RAISED_ARMS_START,
/* 4 */ GIANT_ANIMATION_RAISED_ARMS_LOOP,
/* 5 */ GIANT_ANIMATION_STRUGGLE_START,
/* 6 */ GIANT_ANIMATION_STRUGGLE_LOOP,
/* 7 */ GIANT_ANIMATION_IDLE_LOOP,
/* 8 */ GIANT_ANIMATION_WALKING_LOOP,
/* 9 */ GIANT_ANIMATION_BIG_CALL_START,
/* 10 */ GIANT_ANIMATION_BIG_CALL_LOOP,
/* 11 */ GIANT_ANIMATION_BIG_CALL_END,
/* 12 */ GIANT_ANIMATION_SMALL_CALL_START,
/* 13 */ GIANT_ANIMATION_SMALL_CALL_LOOP,
/* 14 */ GIANT_ANIMATION_SMALL_CALL_END,
/* 15 */ GIANT_ANIMATION_MAX
} GiantAnimationIndex;
/**
* Used as values for csAction. The UNKNOWN ones are never used in-game.
*/
typedef enum {
/* 0 */ GIANT_CS_ACTION_NONE,
/* 1 */ GIANT_CS_ACTION_IDLE,
/* 2 */ GIANT_CS_ACTION_WALKING,
/* 3 */ GIANT_CS_ACTION_LOOKING_UP,
/* 4 */ GIANT_CS_ACTION_RAISING_ARMS,
/* 5 */ GIANT_CS_ACTION_STRUGGLING,
/* 6 */ GIANT_CS_ACTION_FALLING_OVER,
/* 7 */ GIANT_CS_ACTION_IDLE_FADE_IN,
/* 8 */ GIANT_CS_ACTION_TALKING,
/* 9 */ GIANT_CS_ACTION_DONE_TALKING,
/* 10 */ GIANT_CS_ACTION_TEACHING_OATH_TO_ORDER,
/* 11 */ GIANT_CS_ACTION_PLAYER_LEARNED_OATH_TO_ORDER,
/* 12 */ GIANT_CS_ACTION_UNKNOWN_12,
/* 13 */ GIANT_CS_ACTION_UNKNOWN_13,
/* 14 */ GIANT_CS_ACTION_UNKNOWN_14,
/* 15 */ GIANT_CS_ACTION_HOLDING_UP_MOON_IN_CLOCK_TOWER
} GiantCsActionIndex;
struct EnGiant; struct EnGiant;
typedef void (*EnGiantActionFunc)(struct EnGiant*, GlobalContext*); typedef void (*EnGiantActionFunc)(struct EnGiant*, GlobalContext*);
typedef struct EnGiant { typedef struct EnGiant {
/* 0x0000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x0144 */ char unk_144[0x154]; /* 0x144 */ SkelAnime skelAnime;
/* 0x0298 */ EnGiantActionFunc actionFunc; /* 0x188 */ Vec3s jointTable[16];
/* 0x1E8 */ Vec3s morphTable[16];
/* 0x248 */ s16 animationId;
/* 0x24A */ u16 unk_24A;
/* 0x24C */ u16 csAction;
/* 0x24E */ s16 alpha;
/* 0x250 */ u16 sfxId;
/* 0x254 */ MtxF unk_254;
/* 0x294 */ s16 faceIndex;
/* 0x296 */ s16 blinkTimer;
/* 0x298 */ EnGiantActionFunc actionFunc;
} EnGiant; // size = 0x29C } EnGiant; // size = 0x29C
extern const ActorInit En_Giant_InitVars; extern const ActorInit En_Giant_InitVars;

View File

@ -12869,22 +12869,22 @@
0x80B00F08:("func_80B00F08",), 0x80B00F08:("func_80B00F08",),
0x80B00F64:("func_80B00F64",), 0x80B00F64:("func_80B00F64",),
0x80B01040:("EnTalkGibud_Draw",), 0x80B01040:("EnTalkGibud_Draw",),
0x80B01990:("func_80B01990",), 0x80B01990:("EnGiant_ChangeAnimation",),
0x80B01A74:("func_80B01A74",), 0x80B01A74:("EnGiant_IsImprisoned",),
0x80B01B30:("EnGiant_Init",), 0x80B01B30:("EnGiant_Init",),
0x80B01E74:("EnGiant_Destroy",), 0x80B01E74:("EnGiant_Destroy",),
0x80B01E84:("func_80B01E84",), 0x80B01E84:("EnGiant_ChangeToStartOrLoopAnimation",),
0x80B01EE8:("func_80B01EE8",), 0x80B01EE8:("EnGiant_ChangeAnimationBasedOnCsAction",),
0x80B020A0:("func_80B020A0",), 0x80B020A0:("EnGiant_UpdateAlpha",),
0x80B0211C:("func_80B0211C",), 0x80B0211C:("EnGiant_PlayAndUpdateAnimation",),
0x80B02234:("func_80B02234",), 0x80B02234:("EnGiant_PlaySound",),
0x80B02354:("func_80B02354",), 0x80B02354:("EnGiant_UpdatePosition",),
0x80B023D0:("func_80B023D0",), 0x80B023D0:("EnGiant_PerformClockTowerSuccessActions",),
0x80B024AC:("func_80B024AC",), 0x80B024AC:("EnGiant_PlayClockTowerFailureAnimation",),
0x80B024D8:("func_80B024D8",), 0x80B024D8:("EnGiant_PerformCutsceneActions",),
0x80B025CC:("EnGiant_Update",), 0x80B025CC:("EnGiant_Update",),
0x80B02688:("func_80B02688",), 0x80B02688:("EnGiant_PostLimbDrawOpa",),
0x80B026C4:("func_80B026C4",), 0x80B026C4:("EnGiant_PostLimbDrawXlu",),
0x80B026FC:("EnGiant_Draw",), 0x80B026FC:("EnGiant_Draw",),
0x80B02CD0:("func_80B02CD0",), 0x80B02CD0:("func_80B02CD0",),
0x80B02D58:("func_80B02D58",), 0x80B02D58:("func_80B02D58",),

View File

@ -2321,11 +2321,26 @@ D_0600F6C0 = 0x0600F6C0;
// ovl_En_Giant // ovl_En_Giant
D_06002168 = 0x06002168; D_06002168 = 0x06002168;
D_06005A80 = 0x06005A80;
D_06006280 = 0x06006280;
D_06006A80 = 0x06006A80;
D_06007610 = 0x06007610; D_06007610 = 0x06007610;
D_060079B0 = 0x060079B0; D_060079B0 = 0x060079B0;
D_06008394 = 0x06008394;
D_060096E4 = 0x060096E4;
D_0600A1C4 = 0x0600A1C4;
D_0600ACA4 = 0x0600ACA4;
D_0600B784 = 0x0600B784;
D_0600C5D4 = 0x0600C5D4;
D_0600D040 = 0x0600D040;
D_0600DE84 = 0x0600DE84;
D_060102A4 = 0x060102A4;
D_060116E4 = 0x060116E4; D_060116E4 = 0x060116E4;
D_06012A38 = 0x06012A38;
D_06013004 = 0x06013004; D_06013004 = 0x06013004;
D_06013FE8 = 0x06013FE8; D_06013FE8 = 0x06013FE8;
D_06015334 = 0x06015334;
D_06017944 = 0x06017944;
// ovl_En_Ginko_Man // ovl_En_Ginko_Man