mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
817 lines
27 KiB
C
817 lines
27 KiB
C
#include "z_en_sa.h"
|
|
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
|
|
#include "objects/object_sa/object_sa.h"
|
|
#include "scenes/overworld/spot04/spot04_scene.h"
|
|
#include "scenes/overworld/spot05/spot05_scene.h"
|
|
|
|
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_25)
|
|
|
|
void EnSa_Init(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnSa_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnSa_Update(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnSa_Draw(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void func_80AF6448(EnSa* this, GlobalContext* globalCtx);
|
|
void func_80AF67D0(EnSa* this, GlobalContext* globalCtx);
|
|
void func_80AF683C(EnSa* this, GlobalContext* globalCtx);
|
|
void func_80AF68E4(EnSa* this, GlobalContext* globalCtx);
|
|
void func_80AF6B20(EnSa* this, GlobalContext* globalCtx);
|
|
|
|
typedef enum {
|
|
/* 0 */ SARIA_EYE_OPEN,
|
|
/* 1 */ SARIA_EYE_HALF,
|
|
/* 2 */ SARIA_EYE_CLOSED,
|
|
/* 3 */ SARIA_EYE_SUPRISED,
|
|
/* 4 */ SARIA_EYE_SAD
|
|
} SariaEyeState;
|
|
|
|
typedef enum {
|
|
/* 0 */ SARIA_MOUTH_CLOSED2,
|
|
/* 1 */ SARIA_MOUTH_SUPRISED,
|
|
/* 2 */ SARIA_MOUTH_CLOSED,
|
|
/* 3 */ SARIA_MOUTH_SMILING_OPEN,
|
|
/* 4 */ SARIA_MOUTH_FROWNING
|
|
} SariaMouthState;
|
|
|
|
const ActorInit En_Sa_InitVars = {
|
|
ACTOR_EN_SA,
|
|
ACTORCAT_NPC,
|
|
FLAGS,
|
|
OBJECT_SA,
|
|
sizeof(EnSa),
|
|
(ActorFunc)EnSa_Init,
|
|
(ActorFunc)EnSa_Destroy,
|
|
(ActorFunc)EnSa_Update,
|
|
(ActorFunc)EnSa_Draw,
|
|
NULL,
|
|
};
|
|
|
|
static ColliderCylinderInit sCylinderInit = {
|
|
{
|
|
COLTYPE_NONE,
|
|
AT_NONE,
|
|
AC_NONE,
|
|
OC1_ON | OC1_TYPE_ALL,
|
|
OC2_TYPE_2,
|
|
COLSHAPE_CYLINDER,
|
|
},
|
|
{
|
|
ELEMTYPE_UNK0,
|
|
{ 0x00000000, 0x00, 0x00 },
|
|
{ 0x00000000, 0x00, 0x00 },
|
|
TOUCH_NONE,
|
|
BUMP_NONE,
|
|
OCELEM_ON,
|
|
},
|
|
{ 20, 46, 0, { 0, 0, 0 } },
|
|
};
|
|
|
|
static CollisionCheckInfoInit2 sColChkInfoInit = {
|
|
0, 0, 0, 0, MASS_IMMOVABLE,
|
|
};
|
|
|
|
typedef enum {
|
|
/* 0 */ ENSA_ANIM1_0,
|
|
/* 1 */ ENSA_ANIM1_1,
|
|
/* 2 */ ENSA_ANIM1_2,
|
|
/* 3 */ ENSA_ANIM1_3,
|
|
/* 4 */ ENSA_ANIM1_4,
|
|
/* 5 */ ENSA_ANIM1_5,
|
|
/* 6 */ ENSA_ANIM1_6,
|
|
/* 7 */ ENSA_ANIM1_7,
|
|
/* 8 */ ENSA_ANIM1_8,
|
|
/* 9 */ ENSA_ANIM1_9,
|
|
/* 10 */ ENSA_ANIM1_10,
|
|
/* 11 */ ENSA_ANIM1_11
|
|
} EnSaAnimation1;
|
|
|
|
static AnimationFrameCountInfo sAnimationInfo1[] = {
|
|
{ &gSariaWaitArmsToSideAnim, 1.0f, ANIMMODE_LOOP, 0.0f },
|
|
{ &gSariaLookUpArmExtendedAnim, 1.0f, ANIMMODE_ONCE, -10.0f },
|
|
{ &gSariaWaveAnim, 1.0f, ANIMMODE_LOOP, -10.0f },
|
|
{ &gSariaRunAnim, 1.0f, ANIMMODE_LOOP, -10.0f },
|
|
{ &gSariaWaitArmsToSideAnim, 1.0f, ANIMMODE_LOOP, -10.0f },
|
|
{ &gSariaLookOverShoulderAnim, 1.0f, ANIMMODE_LOOP, -10.0f },
|
|
{ &gSariaPlayingOcarinaAnim, 1.0f, ANIMMODE_LOOP, -10.0f },
|
|
{ &gSariaStopPlayingOcarinaAnim, 1.0f, ANIMMODE_ONCE, -10.0f },
|
|
{ &gSariaOcarinaToMouthAnim, 1.0f, ANIMMODE_ONCE, -10.0f },
|
|
{ &gSariaLinkLearnedSariasSongAnim, 1.0f, ANIMMODE_ONCE, -10.0f },
|
|
{ &gSariaReturnToOcarinaAnim, 1.0f, ANIMMODE_ONCE, -10.0f },
|
|
{ &gSariaPlayingOcarinaAnim, 1.0f, ANIMMODE_LOOP, 0.0f },
|
|
};
|
|
|
|
typedef enum {
|
|
/* 0 */ ENSA_ANIM2_0,
|
|
/* 1 */ ENSA_ANIM2_1,
|
|
/* 2 */ ENSA_ANIM2_2,
|
|
/* 3 */ ENSA_ANIM2_3,
|
|
/* 4 */ ENSA_ANIM2_4,
|
|
/* 5 */ ENSA_ANIM2_5,
|
|
/* 6 */ ENSA_ANIM2_6,
|
|
/* 7 */ ENSA_ANIM2_7,
|
|
/* 8 */ ENSA_ANIM2_8,
|
|
/* 9 */ ENSA_ANIM2_9
|
|
} EnSaAnimation2;
|
|
|
|
static AnimationInfo sAnimationInfo2[] = {
|
|
{ &gSariaTransitionHandsSideToChestToSideAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -1.0f },
|
|
{ &gSariaTransitionHandsSideToBackAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -4.0f },
|
|
{ &gSariaRightArmExtendedWaitAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -1.0f },
|
|
{ &gSariaHandsOutAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -1.0f },
|
|
{ &gSariaStandHandsOnHipsAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -1.0f },
|
|
{ &gSariaExtendRightArmAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -1.0f },
|
|
{ &gSariaTransitionHandsSideToHipsAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -1.0f },
|
|
{ &gSariaHandsBehindBackWaitAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -1.0f },
|
|
{ &gSariaHandsOnFaceAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_ONCE, -1.0f },
|
|
{ &gSariaWaitArmsToSideAnim, 1.0f, 0.0f, -1.0f, ANIMMODE_LOOP, -8.0f },
|
|
};
|
|
|
|
s16 func_80AF5560(EnSa* this, GlobalContext* globalCtx) {
|
|
s16 textState = Message_GetState(&globalCtx->msgCtx);
|
|
|
|
if (this->unk_209 == TEXT_STATE_AWAITING_NEXT || this->unk_209 == TEXT_STATE_EVENT ||
|
|
this->unk_209 == TEXT_STATE_CLOSING || this->unk_209 == TEXT_STATE_DONE_HAS_NEXT) {
|
|
if (textState != this->unk_209) {
|
|
this->unk_208++;
|
|
}
|
|
}
|
|
this->unk_209 = textState;
|
|
return textState;
|
|
}
|
|
|
|
u16 func_80AF55E0(GlobalContext* globalCtx, Actor* thisx) {
|
|
EnSa* this = (EnSa*)thisx;
|
|
u16 reaction = Text_GetFaceReaction(globalCtx, 0x10);
|
|
|
|
if (reaction != 0) {
|
|
return reaction;
|
|
}
|
|
if (CHECK_QUEST_ITEM(QUEST_SONG_SARIA)) {
|
|
return 0x10AD;
|
|
}
|
|
if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
|
|
this->unk_208 = 0;
|
|
this->unk_209 = TEXT_STATE_NONE;
|
|
if (gSaveContext.infTable[0] & 0x20) {
|
|
return 0x1048;
|
|
} else {
|
|
return 0x1047;
|
|
}
|
|
}
|
|
if (gSaveContext.eventChkInf[0] & 4) {
|
|
this->unk_208 = 0;
|
|
this->unk_209 = TEXT_STATE_NONE;
|
|
if (gSaveContext.infTable[0] & 8) {
|
|
return 0x1032;
|
|
} else {
|
|
return 0x1031;
|
|
}
|
|
}
|
|
if (gSaveContext.infTable[0] & 1) {
|
|
this->unk_208 = 0;
|
|
this->unk_209 = TEXT_STATE_NONE;
|
|
if (gSaveContext.infTable[0] & 2) {
|
|
return 0x1003;
|
|
} else {
|
|
return 0x1002;
|
|
}
|
|
}
|
|
return 0x1001;
|
|
}
|
|
|
|
s16 func_80AF56F4(GlobalContext* globalCtx, Actor* thisx) {
|
|
s16 ret = 1;
|
|
EnSa* this = (EnSa*)thisx;
|
|
|
|
switch (func_80AF5560(this, globalCtx)) {
|
|
case TEXT_STATE_CLOSING:
|
|
switch (this->actor.textId) {
|
|
case 0x1002:
|
|
gSaveContext.infTable[0] |= 2;
|
|
ret = 0;
|
|
break;
|
|
case 0x1031:
|
|
gSaveContext.eventChkInf[0] |= 8;
|
|
gSaveContext.infTable[0] |= 8;
|
|
ret = 0;
|
|
break;
|
|
case 0x1047:
|
|
gSaveContext.infTable[0] |= 0x20;
|
|
ret = 0;
|
|
break;
|
|
default:
|
|
ret = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case TEXT_STATE_NONE:
|
|
case TEXT_STATE_DONE_HAS_NEXT:
|
|
case TEXT_STATE_DONE_FADING:
|
|
case TEXT_STATE_CHOICE:
|
|
case TEXT_STATE_EVENT:
|
|
case TEXT_STATE_SONG_DEMO_DONE:
|
|
case TEXT_STATE_8:
|
|
case TEXT_STATE_9:
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void func_80AF57D8(EnSa* this, GlobalContext* globalCtx) {
|
|
if (globalCtx->sceneNum != SCENE_SPOT05 ||
|
|
ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x1555 || this->unk_1E0.unk_00 != 0) {
|
|
func_800343CC(globalCtx, &this->actor, &this->unk_1E0.unk_00, this->collider.dim.radius + 30.0f, func_80AF55E0,
|
|
func_80AF56F4);
|
|
}
|
|
}
|
|
|
|
f32 func_80AF5894(EnSa* this) {
|
|
f32 endFrame = this->skelAnime.endFrame;
|
|
f32 startFrame = this->skelAnime.startFrame;
|
|
|
|
this->skelAnime.startFrame = endFrame;
|
|
this->skelAnime.curFrame = endFrame;
|
|
this->skelAnime.endFrame = startFrame;
|
|
this->skelAnime.playSpeed = -1.0f;
|
|
return startFrame;
|
|
}
|
|
|
|
void func_80AF58B8(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_3);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_2);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF594C(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_8);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_9);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF59E0(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_1);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_7);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF5A74(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_1);
|
|
func_80AF5894(this);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_9);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF5B10(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_6);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_4);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF5BA4(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_6);
|
|
func_80AF5894(this);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_9);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF5C40(EnSa* this) {
|
|
switch (this->unk_20A) {
|
|
case 0:
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_5);
|
|
this->unk_20A++;
|
|
case 1:
|
|
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
|
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo2, ENSA_ANIM2_0);
|
|
this->unk_20A++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80AF5CD4(EnSa* this, u8 arg1) {
|
|
this->unk_20B = arg1;
|
|
this->unk_20A = 0;
|
|
}
|
|
|
|
void func_80AF5CE4(EnSa* this) {
|
|
switch (this->unk_20B) {
|
|
case 1:
|
|
func_80AF58B8(this);
|
|
break;
|
|
case 2:
|
|
func_80AF594C(this);
|
|
break;
|
|
case 3:
|
|
func_80AF59E0(this);
|
|
break;
|
|
case 4:
|
|
func_80AF5A74(this);
|
|
break;
|
|
case 5:
|
|
func_80AF5B10(this);
|
|
break;
|
|
case 6:
|
|
func_80AF5BA4(this);
|
|
break;
|
|
case 7:
|
|
func_80AF5C40(this);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EnSa_ChangeAnim(EnSa* this, s32 index) {
|
|
Animation_Change(&this->skelAnime, sAnimationInfo1[index].animation, 1.0f, 0.0f,
|
|
Animation_GetLastFrame(sAnimationInfo1[index].animation), sAnimationInfo1[index].mode,
|
|
sAnimationInfo1[index].morphFrames);
|
|
}
|
|
|
|
s32 func_80AF5DFC(EnSa* this, GlobalContext* globalCtx) {
|
|
if (gSaveContext.cutsceneIndex >= 0xFFF0 && gSaveContext.cutsceneIndex != 0xFFFD) {
|
|
if (globalCtx->sceneNum == SCENE_SPOT04) {
|
|
return 4;
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_SPOT05) {
|
|
return 5;
|
|
}
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_KOKIRI_HOME5 && !LINK_IS_ADULT &&
|
|
INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_FAIRY && !(gSaveContext.eventChkInf[4] & 1)) {
|
|
return 1;
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_SPOT05 && (gSaveContext.eventChkInf[4] & 1)) {
|
|
return CHECK_QUEST_ITEM(QUEST_SONG_SARIA) ? 2 : 5;
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_SPOT04 && !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
|
|
if (gSaveContext.infTable[0] & 1) {
|
|
return 1;
|
|
}
|
|
return 4;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void func_80AF5F34(EnSa* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
s16 phi_a3 = 0;
|
|
|
|
if (globalCtx->sceneNum == SCENE_SPOT04) {
|
|
phi_a3 = (this->actionFunc == func_80AF68E4) ? 1 : 4;
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_SPOT05) {
|
|
phi_a3 = (this->skelAnime.animation == &gSariaPlayingOcarinaAnim) ? 1 : 3;
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_SPOT05 && this->actionFunc == func_80AF6448 &&
|
|
this->skelAnime.animation == &gSariaStopPlayingOcarinaAnim) {
|
|
phi_a3 = 1;
|
|
}
|
|
if (globalCtx->sceneNum == SCENE_SPOT05 && this->actionFunc == func_80AF68E4 &&
|
|
this->skelAnime.animation == &gSariaOcarinaToMouthAnim) {
|
|
phi_a3 = 1;
|
|
}
|
|
this->unk_1E0.unk_18 = player->actor.world.pos;
|
|
this->unk_1E0.unk_14 = 4.0f;
|
|
func_80034A14(&this->actor, &this->unk_1E0, 2, phi_a3);
|
|
}
|
|
|
|
s32 func_80AF603C(EnSa* this) {
|
|
if (this->skelAnime.animation != &gSariaPlayingOcarinaAnim &&
|
|
this->skelAnime.animation != &gSariaOcarinaToMouthAnim) {
|
|
return 0;
|
|
}
|
|
if (this->unk_1E0.unk_00 != 0) {
|
|
return 0;
|
|
}
|
|
this->unk_20E = 0;
|
|
if (this->rightEyeIndex != SARIA_EYE_CLOSED) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void func_80AF609C(EnSa* this) {
|
|
s16 phi_v1;
|
|
|
|
if (func_80AF603C(this) == 0) {
|
|
if (this->unk_20E == 0) {
|
|
phi_v1 = 0;
|
|
} else {
|
|
this->unk_20E--;
|
|
phi_v1 = this->unk_20E;
|
|
}
|
|
if (phi_v1 == 0) {
|
|
this->rightEyeIndex++;
|
|
if (this->rightEyeIndex < SARIA_EYE_SUPRISED) {
|
|
this->leftEyeIndex = this->rightEyeIndex;
|
|
} else {
|
|
this->unk_20E = Rand_S16Offset(30, 30);
|
|
this->leftEyeIndex = SARIA_EYE_OPEN;
|
|
this->rightEyeIndex = this->leftEyeIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_80AF6130(CsCmdActorAction* csAction, Vec3f* dst) {
|
|
dst->x = csAction->startPos.x;
|
|
dst->y = csAction->startPos.y;
|
|
dst->z = csAction->startPos.z;
|
|
}
|
|
|
|
void func_80AF6170(CsCmdActorAction* csAction, Vec3f* dst) {
|
|
dst->x = csAction->endPos.x;
|
|
dst->y = csAction->endPos.y;
|
|
dst->z = csAction->endPos.z;
|
|
}
|
|
|
|
void EnSa_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
EnSa* this = (EnSa*)thisx;
|
|
s32 pad;
|
|
|
|
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 12.0f);
|
|
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gSariaSkel, NULL, this->jointTable, this->morphTable, 17);
|
|
Collider_InitCylinder(globalCtx, &this->collider);
|
|
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
|
CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
|
|
|
switch (func_80AF5DFC(this, globalCtx)) {
|
|
case 2:
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_11);
|
|
this->actionFunc = func_80AF6448;
|
|
break;
|
|
case 5:
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_11);
|
|
this->actionFunc = func_80AF683C;
|
|
break;
|
|
case 1:
|
|
this->actor.gravity = -1.0f;
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_0);
|
|
this->actionFunc = func_80AF6448;
|
|
break;
|
|
case 4:
|
|
this->unk_210 = 0;
|
|
this->actor.gravity = -1.0f;
|
|
globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(gSpot04Cs_10E20);
|
|
gSaveContext.cutsceneTrigger = 1;
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_4);
|
|
this->actionFunc = func_80AF68E4;
|
|
break;
|
|
case 3:
|
|
this->unk_210 = 0;
|
|
this->actor.gravity = -1.0f;
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_0);
|
|
this->actionFunc = func_80AF68E4;
|
|
break;
|
|
case 0:
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
|
|
Actor_SetScale(&this->actor, 0.01f);
|
|
|
|
this->actor.targetMode = 6;
|
|
this->unk_1E0.unk_00 = 0;
|
|
this->alpha = 255;
|
|
this->unk_21A = this->actor.shape.rot;
|
|
|
|
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ELF, this->actor.world.pos.x,
|
|
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, FAIRY_KOKIRI);
|
|
}
|
|
|
|
void EnSa_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
EnSa* this = (EnSa*)thisx;
|
|
|
|
Collider_DestroyCylinder(globalCtx, &this->collider);
|
|
}
|
|
|
|
void func_80AF6448(EnSa* this, GlobalContext* globalCtx) {
|
|
if (globalCtx->sceneNum == SCENE_SPOT04) {
|
|
if (this->unk_1E0.unk_00 != 0) {
|
|
switch (this->actor.textId) {
|
|
case 0x1002:
|
|
if (this->unk_208 == 0 && this->unk_20B != 1) {
|
|
func_80AF5CD4(this, 1);
|
|
this->mouthIndex = 1;
|
|
}
|
|
if (this->unk_208 == 2 && this->unk_20B != 2) {
|
|
func_80AF5CD4(this, 2);
|
|
this->mouthIndex = 1;
|
|
}
|
|
if (this->unk_208 == 5) {
|
|
this->mouthIndex = 0;
|
|
}
|
|
break;
|
|
case 0x1003:
|
|
if (this->unk_208 == 0 && this->unk_20B != 4) {
|
|
func_80AF5CD4(this, 4);
|
|
}
|
|
break;
|
|
case 0x1031:
|
|
if (this->unk_208 == 0 && this->unk_20B != 4 &&
|
|
this->skelAnime.animation == &gSariaHandsBehindBackWaitAnim) {
|
|
func_80AF5CD4(this, 4);
|
|
this->mouthIndex = 3;
|
|
}
|
|
if (this->unk_208 == 2 && this->unk_20B != 5) {
|
|
func_80AF5CD4(this, 5);
|
|
this->mouthIndex = 2;
|
|
}
|
|
if (this->unk_208 == 4 && this->unk_20B != 6) {
|
|
func_80AF5CD4(this, 6);
|
|
this->mouthIndex = 0;
|
|
}
|
|
break;
|
|
case 0x1032:
|
|
if (this->unk_208 == 0 && this->unk_20B != 4 &&
|
|
this->skelAnime.animation == &gSariaHandsBehindBackWaitAnim) {
|
|
func_80AF5CD4(this, 4);
|
|
}
|
|
break;
|
|
case 0x1047:
|
|
if (this->unk_208 == 1 && this->unk_20B != 7) {
|
|
func_80AF5CD4(this, 7);
|
|
}
|
|
break;
|
|
case 0x1048:
|
|
if (this->unk_208 == 0 && this->unk_20B != 7) {
|
|
func_80AF5CD4(this, 7);
|
|
}
|
|
break;
|
|
}
|
|
} else if (!CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) &&
|
|
((gSaveContext.infTable[0] & 2) || (gSaveContext.infTable[0] & 8))) {
|
|
if (this->unk_20B != 3) {
|
|
func_80AF5CD4(this, 3);
|
|
}
|
|
} else {
|
|
func_80AF5CD4(this, 0);
|
|
}
|
|
func_80AF5CE4(this);
|
|
}
|
|
if (this->skelAnime.animation == &gSariaStopPlayingOcarinaAnim) {
|
|
this->skelAnime.playSpeed = -1.0f;
|
|
if ((s32)this->skelAnime.curFrame == 0) {
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_6);
|
|
}
|
|
}
|
|
if (this->unk_1E0.unk_00 != 0 && globalCtx->sceneNum == SCENE_SPOT05) {
|
|
Animation_Change(&this->skelAnime, &gSariaStopPlayingOcarinaAnim, 1.0f, 0.0f, 10.0f, ANIMMODE_ONCE, -10.0f);
|
|
this->actionFunc = func_80AF67D0;
|
|
}
|
|
}
|
|
|
|
void func_80AF67D0(EnSa* this, GlobalContext* globalCtx) {
|
|
if (this->unk_1E0.unk_00 == 0) {
|
|
Animation_Change(&this->skelAnime, &gSariaStopPlayingOcarinaAnim, 0.0f, 10.0f, 0.0f, ANIMMODE_ONCE, -10.0f);
|
|
this->actionFunc = func_80AF6448;
|
|
}
|
|
}
|
|
|
|
void func_80AF683C(EnSa* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
if (!(player->actor.world.pos.z >= -2220.0f) && !Gameplay_InCsMode(globalCtx)) {
|
|
globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730);
|
|
gSaveContext.cutsceneTrigger = 1;
|
|
this->actionFunc = func_80AF68E4;
|
|
}
|
|
}
|
|
|
|
void func_80AF68E4(EnSa* this, GlobalContext* globalCtx) {
|
|
s16 phi_v0;
|
|
Vec3f startPos;
|
|
Vec3f endPos;
|
|
Vec3f D_80AF7448 = { 0.0f, 0.0f, 0.0f };
|
|
CsCmdActorAction* csAction;
|
|
f32 temp_f0;
|
|
f32 gravity;
|
|
|
|
if ((gSaveContext.cutsceneTrigger != 1) && (globalCtx->csCtx.state == CS_STATE_IDLE)) {
|
|
this->actionFunc = func_80AF6B20;
|
|
return;
|
|
}
|
|
csAction = globalCtx->csCtx.npcActions[1];
|
|
if (csAction != NULL) {
|
|
func_80AF6130(csAction, &startPos);
|
|
func_80AF6170(csAction, &endPos);
|
|
|
|
if (this->unk_210 == 0) {
|
|
this->actor.world.pos = startPos;
|
|
}
|
|
if (this->unk_210 != csAction->action) {
|
|
switch (csAction->action) {
|
|
case 2:
|
|
this->mouthIndex = 1;
|
|
break;
|
|
case 9:
|
|
this->mouthIndex = 1;
|
|
break;
|
|
default:
|
|
this->mouthIndex = 0;
|
|
break;
|
|
}
|
|
EnSa_ChangeAnim(this, csAction->action);
|
|
this->unk_210 = csAction->action;
|
|
}
|
|
//if (phi_v0) {}
|
|
if (csAction->action == 3) {
|
|
if (this->unk_20C == 0) {
|
|
phi_v0 = 0;
|
|
} else {
|
|
this->unk_20C--;
|
|
phi_v0 = this->unk_20C;
|
|
}
|
|
if (phi_v0 == 0) {
|
|
Audio_PlaySoundGeneral(NA_SE_PL_WALK_GROUND, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
|
&D_801333E8);
|
|
this->unk_20C = 8;
|
|
}
|
|
}
|
|
this->actor.shape.rot.x = csAction->urot.x;
|
|
this->actor.shape.rot.y = csAction->urot.y;
|
|
this->actor.shape.rot.z = csAction->urot.z;
|
|
this->actor.velocity = D_80AF7448;
|
|
|
|
if (globalCtx->csCtx.frames < csAction->endFrame) {
|
|
temp_f0 = csAction->endFrame - csAction->startFrame;
|
|
this->actor.velocity.x = (endPos.x - startPos.x) / temp_f0;
|
|
this->actor.velocity.y = (endPos.y - startPos.y) / temp_f0;
|
|
gravity = this->actor.gravity;
|
|
if (globalCtx->sceneNum == SCENE_SPOT05) {
|
|
gravity = 0.0f;
|
|
}
|
|
this->actor.velocity.y += gravity;
|
|
if (this->actor.velocity.y < this->actor.minVelocityY) {
|
|
this->actor.velocity.y = this->actor.minVelocityY;
|
|
}
|
|
this->actor.velocity.z = (endPos.z - startPos.z) / temp_f0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_80AF6B20(EnSa* this, GlobalContext* globalCtx) {
|
|
if (globalCtx->sceneNum == SCENE_SPOT05) {
|
|
Item_Give(globalCtx, ITEM_SONG_SARIA);
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_6);
|
|
}
|
|
|
|
if (globalCtx->sceneNum == SCENE_SPOT04) {
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_4);
|
|
this->actor.world.pos = this->actor.home.pos;
|
|
this->actor.world.rot = this->unk_21A;
|
|
this->mouthIndex = 0;
|
|
gSaveContext.infTable[0] |= 1;
|
|
}
|
|
|
|
this->actionFunc = func_80AF6448;
|
|
}
|
|
|
|
void EnSa_Update(Actor* thisx, GlobalContext* globalCtx) {
|
|
EnSa* this = (EnSa*)thisx;
|
|
s32 pad;
|
|
|
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
|
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
|
SkelAnime_Update(&this->skelAnime);
|
|
|
|
if (this->skelAnime.animation == &gSariaOcarinaToMouthAnim &&
|
|
this->skelAnime.curFrame >= Animation_GetLastFrame(&gSariaOcarinaToMouthAnim)) {
|
|
EnSa_ChangeAnim(this, ENSA_ANIM1_6);
|
|
}
|
|
|
|
if (this->actionFunc != func_80AF68E4) {
|
|
this->alpha = func_80034DD4(&this->actor, globalCtx, this->alpha, 400.0f);
|
|
} else {
|
|
this->alpha = 255;
|
|
}
|
|
|
|
this->actor.shape.shadowAlpha = this->alpha;
|
|
|
|
if (this->actionFunc == func_80AF68E4) {
|
|
this->actor.world.pos.x += this->actor.velocity.x;
|
|
this->actor.world.pos.y += this->actor.velocity.y;
|
|
this->actor.world.pos.z += this->actor.velocity.z;
|
|
} else {
|
|
func_8002D7EC(&this->actor);
|
|
}
|
|
|
|
if (globalCtx->sceneNum != SCENE_SPOT05) {
|
|
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
|
|
}
|
|
|
|
func_80AF609C(this);
|
|
this->actionFunc(this, globalCtx);
|
|
func_80AF57D8(this, globalCtx);
|
|
func_80AF5F34(this, globalCtx);
|
|
}
|
|
|
|
s32 EnSa_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx,
|
|
Gfx** gfx) {
|
|
EnSa* this = (EnSa*)thisx;
|
|
s32 pad;
|
|
Vec3s sp18;
|
|
|
|
if (limbIndex == 16) {
|
|
Matrix_Translate(900.0f, 0.0f, 0.0f, MTXMODE_APPLY);
|
|
sp18 = this->unk_1E0.unk_08;
|
|
Matrix_RotateX(BINANG_TO_RAD(sp18.y), MTXMODE_APPLY);
|
|
Matrix_RotateZ(BINANG_TO_RAD(sp18.x), MTXMODE_APPLY);
|
|
Matrix_Translate(-900.0f, 0.0f, 0.0f, MTXMODE_APPLY);
|
|
}
|
|
|
|
if (limbIndex == 9) {
|
|
sp18 = this->unk_1E0.unk_0E;
|
|
Matrix_RotateY(BINANG_TO_RAD(sp18.y), MTXMODE_APPLY);
|
|
Matrix_RotateX(BINANG_TO_RAD(sp18.x), MTXMODE_APPLY);
|
|
}
|
|
|
|
if (globalCtx->sceneNum == SCENE_SPOT05 && limbIndex == 15) {
|
|
*dList = gSariaRightHandAndOcarinaDL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void EnSa_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx, Gfx** gfx) {
|
|
EnSa* this = (EnSa*)thisx;
|
|
Vec3f D_80AF7454 = { 400.0, 0.0f, 0.0f };
|
|
|
|
if (limbIndex == 16) {
|
|
Matrix_MultVec3f(&D_80AF7454, &this->actor.focus.pos);
|
|
}
|
|
}
|
|
|
|
void EnSa_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
|
static void* mouthTextures[] = {
|
|
gSariaMouthClosed2Tex, gSariaMouthSmilingOpenTex, gSariaMouthFrowningTex,
|
|
gSariaMouthSuprisedTex, gSariaMouthClosedTex,
|
|
};
|
|
static void* eyeTextures[] = {
|
|
gSariaEyeOpenTex, gSariaEyeHalfTex, gSariaEyeClosedTex, gSariaEyeSuprisedTex, gSariaEyeSadTex,
|
|
};
|
|
EnSa* this = (EnSa*)thisx;
|
|
|
|
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_sa.c", 1444);
|
|
|
|
if (this->alpha == 255) {
|
|
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->rightEyeIndex]));
|
|
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(eyeTextures[this->leftEyeIndex]));
|
|
gSPSegment(POLY_OPA_DISP++, 0x0A, SEGMENTED_TO_VIRTUAL(mouthTextures[this->mouthIndex]));
|
|
func_80034BA0(globalCtx, &this->skelAnime, EnSa_OverrideLimbDraw, EnSa_PostLimbDraw, &this->actor, this->alpha);
|
|
} else if (this->alpha != 0) {
|
|
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->rightEyeIndex]));
|
|
gSPSegment(POLY_XLU_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(eyeTextures[this->leftEyeIndex]));
|
|
gSPSegment(POLY_XLU_DISP++, 0x0A, SEGMENTED_TO_VIRTUAL(mouthTextures[this->mouthIndex]));
|
|
func_80034CC4(globalCtx, &this->skelAnime, EnSa_OverrideLimbDraw, EnSa_PostLimbDraw, &this->actor, this->alpha);
|
|
}
|
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_sa.c", 1497);
|
|
}
|