DmZl OK and some docs of object_zl4 (Child Zelda used in one cutscene) (#834)

* DmZl: start

* DmZl: progress

* DmZl4: progress

* DmZl: OK

* DmZl: data integrated

* DmZl: object docs

* DmZl: more object docs

* DmZl: more docs

* DmZl: Some Zl4 animations

* ObjectZl4: docs

* DmZl: formater pass

* DmZl: more docs

* DmZl: docs

* DmZl: params documentation

* Apply suggestions from code review

Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>

* DmZl: requested changes, minor fixes, formater pass

* Update src/overlays/actors/ovl_Dm_Zl/z_dm_zl.c

Co-authored-by: Tom Overton <tom-overton@users.noreply.github.com>

* Update assets/xml/objects/object_zl4.xml

Co-authored-by: Tom Overton <tom-overton@users.noreply.github.com>

* DmZl: some requested changes

* DmZl: Change Eye Texture names for accuracy, formatter pass

* DmZl: Eye texture indexes specified

* DmZl: fixed struct variable names

* DmZl: some requested changes

* DmZl: removed comment

* DmZl: change to unused index

* DmZl: changed some xml comments

* DmZl: requested changes 1

* Update src/overlays/actors/ovl_Dm_Zl/z_dm_zl.c

Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>

* DmZl: fixing issues, formatter pass

* DmZl: moved switch case

* DmZl: fixed object reference, wrong file

* Update src/overlays/actors/ovl_Dm_Zl/z_dm_zl.c

Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>

* Update assets/xml/objects/object_zl4.xml

Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>

* DmZl: mouth and eye state comments

Co-authored-by: Isghj8 <isghj8@gmail.com>
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
Co-authored-by: Tom Overton <tom-overton@users.noreply.github.com>
Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>
This commit is contained in:
Isghj
2022-06-19 15:36:07 -07:00
committed by GitHub
parent 67345d9be5
commit ab7625db65
5 changed files with 440 additions and 149 deletions
+257 -16
View File
@@ -1,7 +1,7 @@
/*
* File: z_dm_zl.c
* Overlay: ovl_Dm_Zl
* Description: Child Zelda (Cutscenes)
* Description: Child Zelda (Re-learning Song of Time cutscene)
*/
#include "z_dm_zl.h"
@@ -15,9 +15,8 @@ void DmZl_Destroy(Actor* thisx, GlobalContext* globalCtx);
void DmZl_Update(Actor* thisx, GlobalContext* globalCtx);
void DmZl_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80A382FC(DmZl* this, GlobalContext* globalCtx);
void DmZl_DoNothing(DmZl* this, GlobalContext* globalCtx);
#if 0
const ActorInit Dm_Zl_InitVars = {
ACTOR_DM_ZL,
ACTORCAT_ITEMACTION,
@@ -30,27 +29,269 @@ const ActorInit Dm_Zl_InitVars = {
(ActorFunc)DmZl_Draw,
};
#endif
static AnimationInfo sAnimations[] = {
{ &gDmZl4FacingAwayHandsOverEmblemLoop, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -10.0f },
{ &gDmZl4TurningAround2Anim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -10.0f },
{ &gDmZl4HandsOverEmblemLoopAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -10.0f },
{ &gDmZl4GivingItemStartAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -10.0f },
{ &gDmZl4GivingItemLoopAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -10.0f },
{ &gDmZl4RaisingOcarinaToPlayAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -10.0f },
{ &gDmZl4PlayingOcarinaAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -10.0f },
};
extern UNK_TYPE D_0600DE08;
extern UNK_TYPE D_0600E038;
typedef enum {
/* 0 */ ZELDA_ANIM_FACING_AWAY,
/* 1 */ ZELDA_ANIM_TURNING_TOWARD_PLAYER,
/* 2 */ ZELDA_ANIM_FACING_PLAYER,
/* 3 */ ZELDA_ANIM_GIVING_OCARINA_START,
/* 4 */ ZELDA_ANIM_GIVING_OCARINA,
/* 5 */ ZELDA_ANIM_PLAYING_OCARINA_START,
/* 6 */ ZELDA_ANIM_PLAYING_OCARINA,
/* 7 */ ZELDA_ANIM_MAX,
} DmZlAnimations;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/func_80A38190.s")
static TexturePtr sMouthTextures[] = {
gZl4MouthNeutralTex,
gZl4MouthOpenSmilingTex,
gZl4MouthFrowningTex,
gZl4MouthOpenTex,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/DmZl_Init.s")
typedef enum {
/* 0 */ ZELDA_MOUTH_NEUTRAL,
/* 1 */ ZELDA_MOUTH_SMILING,
/* 2 */ ZELDA_MOUTH_FROWNING,
/* 3 */ ZELDA_MOUTH_OPEN,
} DmZlMouthTextures;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/DmZl_Destroy.s")
static TexturePtr sEyeTextures[] = {
gDmZl4EyeOpenNormalTex,
gDmZl4EyeHalfTex,
gDmZl4EyeClosedTex,
gDmZl4EyeWideTex,
gDmZl4EyeHappyTex,
gDmZl4EyeOpenLookingLeftTex,
gDmZl4EyeOpenLookingRightTex,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/func_80A382FC.s")
typedef enum {
/* 0 */ ZELDA_EYE_OPEN_NORMAL,
/* 1 */ ZELDA_EYE_BLINKING,
/* 2 */ ZELDA_EYE_CLOSED,
/* 3 */ ZELDA_EYE_WIDE,
/* 4 */ ZELDA_EYE_HAPPY,
/* 5 */ ZELDA_EYE_OPEN_LOOKING_LEFT,
/* 6 */ ZELDA_EYE_OPEN_LOOKING_RIGHT,
} DmZlEyeTextures;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/func_80A3830C.s")
// Unused in MM
typedef enum {
/* 0 */ ZELDA_EYE_STATE_NORMAL,
/* 1 */ ZELDA_EYE_STATE_CLOSED,
/* 2 */ ZELDA_EYE_STATE_LOOKING_LEFT,
/* 3 */ ZELDA_EYE_STATE_LOOKING_RIGHT,
/* 4 */ ZELDA_EYE_STATE_WIDE,
/* 5 */ ZELDA_EYE_STATE_HAPPY,
/* 6 */ ZELDA_EYE_STATE_CLOSED2,
} DmZlEyeStates;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/func_80A38468.s")
/**
* This function is always called with unusedExtraOffset = 0.
*/
void DmZl_ChangeAnimation(SkelAnime* skelAnime, AnimationInfo animation[], u16 unusedExtraOffset) {
f32 endFrame;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/DmZl_Update.s")
animation += unusedExtraOffset;
endFrame = (animation->frameCount < 0.0f) ? Animation_GetLastFrame(animation->animation) : animation->frameCount;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/func_80A3862C.s")
Animation_Change(skelAnime, animation->animation, animation->playSpeed, animation->startFrame, endFrame,
animation->mode, animation->morphFrames);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/func_80A38648.s")
void DmZl_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
DmZl* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Zl/DmZl_Draw.s")
this->animationIndex = ZELDA_ANIM_FACING_AWAY;
this->unk_2BA = 0;
this->actor.targetArrowOffset = 1000.0f;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 24.0f);
// these three set to NULL should mean they are dynamically allocated
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gZl4Skeleton, NULL, NULL, NULL, 0);
DmZl_ChangeAnimation(&this->skelAnime, &sAnimations[this->animationIndex], 0);
Actor_SetScale(&this->actor, 0.01f);
this->actionFunc = DmZl_DoNothing;
}
void DmZl_Destroy(Actor* thisx, GlobalContext* globalCtx) {
}
void DmZl_DoNothing(DmZl* this, GlobalContext* globalCtx) {
}
void DmZl_UpdateCutscene(DmZl* this, GlobalContext* globalCtx) {
s32 actionIndex;
if (Cutscene_CheckActorAction(globalCtx, 0x66)) {
actionIndex = Cutscene_GetActorActionIndex(globalCtx, 0x66);
if (globalCtx->csCtx.frames == globalCtx->csCtx.actorActions[actionIndex]->startFrame) {
s16 nextAnimationIndex = ZELDA_ANIM_FACING_AWAY;
switch (globalCtx->csCtx.actorActions[actionIndex]->action) {
default:
case 1:
break;
case 2:
nextAnimationIndex = ZELDA_ANIM_TURNING_TOWARD_PLAYER;
break;
case 3:
nextAnimationIndex = ZELDA_ANIM_GIVING_OCARINA_START;
break;
case 4:
nextAnimationIndex = ZELDA_ANIM_PLAYING_OCARINA_START;
break;
}
if (nextAnimationIndex != this->animationIndex) {
this->animationIndex = nextAnimationIndex;
DmZl_ChangeAnimation(&this->skelAnime, &sAnimations[this->animationIndex], 0);
}
}
Cutscene_ActorTranslateAndYaw(&this->actor, globalCtx, actionIndex);
}
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
actionIndex = this->animationIndex;
if ((actionIndex == ZELDA_ANIM_TURNING_TOWARD_PLAYER) || (actionIndex == ZELDA_ANIM_GIVING_OCARINA_START) ||
(actionIndex == ZELDA_ANIM_PLAYING_OCARINA_START)) {
// these animations don't loop at the end, they lead into the next animation
this->animationIndex++;
DmZl_ChangeAnimation(&this->skelAnime, &sAnimations[this->animationIndex], 0);
}
}
}
/**
* Updates the eye blinking and state, and mouth textures.
*/
void DmZl_UpdateFace(DmZl* this) {
if (this->blinkTimer > 0) {
this->blinkTimer--;
} else {
this->blinkTimer = 0;
}
if (this->blinkTimer < 3) {
this->eyeTextureIndexRight = this->blinkTimer;
this->eyeTextureIndexLeft = this->blinkTimer;
}
// nextEyeState is never changed by this actor in MM, only ZELDA_EYE_STATE_NORMAL used.
switch (this->nextEyeState) {
case ZELDA_EYE_STATE_NORMAL:
if (this->blinkTimer == 0) {
this->blinkTimer = Rand_S16Offset(30, 30);
}
break;
case ZELDA_EYE_STATE_CLOSED:
if (this->blinkTimer == 0) {
this->eyeTextureIndexLeft = this->eyeTextureIndexRight = ZELDA_EYE_CLOSED;
}
break;
case ZELDA_EYE_STATE_LOOKING_LEFT:
if (this->blinkTimer == 0) {
this->eyeTextureIndexLeft = ZELDA_EYE_OPEN_LOOKING_LEFT;
this->eyeTextureIndexRight = ZELDA_EYE_OPEN_LOOKING_RIGHT;
}
break;
case ZELDA_EYE_STATE_LOOKING_RIGHT:
if (this->blinkTimer == 0) {
this->eyeTextureIndexLeft = ZELDA_EYE_OPEN_LOOKING_RIGHT;
this->eyeTextureIndexRight = ZELDA_EYE_OPEN_LOOKING_LEFT;
}
break;
case ZELDA_EYE_STATE_WIDE:
if (this->blinkTimer == 0) {
this->eyeTextureIndexLeft = this->eyeTextureIndexRight = ZELDA_EYE_WIDE;
}
break;
case ZELDA_EYE_STATE_HAPPY:
if (this->blinkTimer == 0) {
this->eyeTextureIndexLeft = this->eyeTextureIndexRight = ZELDA_EYE_HAPPY;
}
break;
case ZELDA_EYE_STATE_CLOSED2:
if (this->blinkTimer >= 3) {
this->blinkTimer = 0;
}
break;
}
// nextMouthState is never changed by this actor in MM, only ZELDA_MOUTH_NEUTRAL used.
switch (this->nextMouthState) {
default:
this->mouthTextureIndex = ZELDA_MOUTH_NEUTRAL;
break;
case ZELDA_MOUTH_SMILING:
this->mouthTextureIndex = ZELDA_MOUTH_SMILING;
break;
case ZELDA_MOUTH_FROWNING:
this->mouthTextureIndex = ZELDA_MOUTH_FROWNING;
break;
case ZELDA_MOUTH_OPEN:
this->mouthTextureIndex = ZELDA_MOUTH_OPEN;
break;
}
if (this->animationIndex == ZELDA_ANIM_PLAYING_OCARINA) {
this->eyeTextureIndexLeft = this->eyeTextureIndexRight = ZELDA_EYE_CLOSED;
}
}
void DmZl_Update(Actor* thisx, GlobalContext* globalCtx) {
DmZl* this = THIS;
DmZl_UpdateFace(this);
SkelAnime_Update(&this->skelAnime);
DmZl_UpdateCutscene(this, globalCtx);
this->actionFunc(this, globalCtx);
}
s32 DmZl_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
return false;
}
void DmZl_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
DmZl* this = THIS;
if (limbIndex == ZL4_LIMB_RIGHT_HAND) {
if ((this->animationIndex >= ZELDA_ANIM_GIVING_OCARINA_START) &&
(this->animationIndex <= ZELDA_ANIM_PLAYING_OCARINA)) {
OPEN_DISPS(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, gDmZl4OcarinaDL);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
}
}
void DmZl_Draw(Actor* thisx, GlobalContext* globalCtx) {
DmZl* this = THIS;
OPEN_DISPS(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTextureIndexRight]));
gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTextureIndexLeft]));
gSPSegment(POLY_OPA_DISP++, 0x0A, Lib_SegmentedToVirtual(sMouthTextures[this->mouthTextureIndex]));
func_8012C28C(globalCtx->state.gfxCtx);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
DmZl_OverrideLimbDraw, DmZl_PostLimbDraw, &this->actor);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
+16 -4
View File
@@ -2,16 +2,28 @@
#define Z_DM_ZL_H
#include "global.h"
#include "objects/object_zl4/object_zl4.h"
struct DmZl;
typedef void (*DmZlActionFunc)(struct DmZl*, GlobalContext*);
typedef struct DmZl {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0x11C];
/* 0x0260 */ DmZlActionFunc actionFunc;
/* 0x0264 */ char unk_264[0x70];
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s jointTable[ZL4_LIMB_MAX]; // these tables are not referenced directly, loaded dynamically
/* 0x1F4 */ Vec3s morphTable[ZL4_LIMB_MAX];
/* 0x260 */ DmZlActionFunc actionFunc;
/* 0x264 */ ColliderCylinder collider; // unused, assumed to be here based on OoT documentation
/* 0x2B0 */ s16 animationIndex;
/* 0x2B2 */ u8 eyeTextureIndexLeft;
/* 0x2B3 */ u8 eyeTextureIndexRight;
/* 0x2B4 */ u8 mouthTextureIndex;
/* 0x2B5 */ u8 nextEyeState; // used to control eye state, but not set by our actor, outside of actor?
/* 0x2B6 */ u8 nextMouthState; // used to control mouth state, but not set by our actor, outside of actor?
/* 0x2B8 */ s16 blinkTimer;
/* 0x2BA */ s16 unk_2BA; // set but not used by this actor.
/* 0x2BC */ UNK_TYPE1 pad2BC[0x18]; // unused by DmZl
} DmZl; // size = 0x2D4
extern const ActorInit Dm_Zl_InitVars;