mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
39cc86c260
subrepo: subdir: "soh" merged: "ba904bbd0" upstream: origin: "https://github.com/HarbourMasters/soh.git" branch: "master" commit: "ba904bbd0" git-subrepo: version: "0.4.1" origin: "???" commit: "???"
1422 lines
48 KiB
C
1422 lines
48 KiB
C
/*
|
|
* File: z_en_owl.c
|
|
* Overlay: ovl_En_Owl
|
|
* Description: Owl
|
|
*/
|
|
|
|
#include "z_en_owl.h"
|
|
#include "objects/object_owl/object_owl.h"
|
|
#include "scenes/overworld/spot06/spot06_scene.h"
|
|
#include "scenes/overworld/spot16/spot16_scene.h"
|
|
#include "vt.h"
|
|
|
|
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
|
|
|
|
void EnOwl_Init(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnOwl_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnOwl_Update(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnOwl_Draw(Actor* thisx, GlobalContext* globalCtx);
|
|
void EnOwl_ChangeMode(EnOwl* this, EnOwlActionFunc, OwlFunc, SkelAnime*, AnimationHeader*, f32);
|
|
void EnOwl_WaitDefault(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACC540(EnOwl* this);
|
|
void EnOwl_WaitOutsideKokiri(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitHyruleCastle(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitKakariko(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitGerudo(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitLakeHylia(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitZoraRiver(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitHyliaShortcut(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitDeathMountainShortcut(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACB3E0(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitLWPreSaria(EnOwl* this, GlobalContext* globalCtx);
|
|
void EnOwl_WaitLWPostSaria(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACD4D4(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACD130(EnOwl* this, GlobalContext* globalCtx, s32 arg2);
|
|
void func_80ACBAB8(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACD2CC(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACAA54(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACAC6C(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACADF0(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACAF74(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACC30C(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACB4FC(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACB680(EnOwl* this, GlobalContext* globalCtx);
|
|
void func_80ACC460(EnOwl* this);
|
|
void func_80ACBEA0(EnOwl*, GlobalContext*);
|
|
|
|
typedef enum {
|
|
/* 0x00 */ OWL_DEFAULT,
|
|
/* 0x01 */ OWL_OUTSIDE_KOKIRI,
|
|
/* 0x02 */ OWL_HYRULE_CASTLE,
|
|
/* 0x03 */ OWL_KAKARIKO,
|
|
/* 0x04 */ OWL_HYLIA_GERUDO,
|
|
/* 0x05 */ OWL_LAKE_HYLIA,
|
|
/* 0x06 */ OWL_ZORA_RIVER,
|
|
/* 0x07 */ OWL_HYLIA_SHORTCUT,
|
|
/* 0x08 */ OWL_DEATH_MOUNTAIN,
|
|
/* 0x09 */ OWL_DEATH_MOUNTAIN2,
|
|
/* 0x0A */ OWL_DESSERT_COLOSSUS,
|
|
/* 0x0B */ OWL_LOST_WOODS_PRESARIA,
|
|
/* 0x0C */ OWL_LOST_WOODS_POSTSARIA
|
|
} EnOwlType;
|
|
|
|
typedef enum {
|
|
/* 0x00 */ OWL_REPEAT,
|
|
/* 0x01 */ OWL_OK
|
|
} EnOwlMessageChoice;
|
|
|
|
const ActorInit En_Owl_InitVars = {
|
|
ACTOR_EN_OWL,
|
|
ACTORCAT_NPC,
|
|
FLAGS,
|
|
OBJECT_OWL,
|
|
sizeof(EnOwl),
|
|
(ActorFunc)EnOwl_Init,
|
|
(ActorFunc)EnOwl_Destroy,
|
|
(ActorFunc)EnOwl_Update,
|
|
(ActorFunc)EnOwl_Draw,
|
|
NULL,
|
|
};
|
|
|
|
static ColliderCylinderInit sOwlCylinderInit = {
|
|
{
|
|
COLTYPE_NONE,
|
|
AT_NONE,
|
|
AC_ON | AC_TYPE_ENEMY,
|
|
OC1_ON | OC1_TYPE_ALL,
|
|
OC2_TYPE_1,
|
|
COLSHAPE_CYLINDER,
|
|
},
|
|
{
|
|
ELEMTYPE_UNK0,
|
|
{ 0x00000000, 0x00, 0x00 },
|
|
{ 0xFFCFFFFF, 0x00, 0x00 },
|
|
TOUCH_NONE,
|
|
BUMP_ON,
|
|
OCELEM_ON,
|
|
},
|
|
{ 30, 40, 0, { 0, 0, 0 } },
|
|
};
|
|
|
|
static InitChainEntry sInitChain[] = {
|
|
ICHAIN_VEC3F_DIV1000(scale, 25, ICHAIN_CONTINUE),
|
|
ICHAIN_F32(uncullZoneForward, 1400, ICHAIN_CONTINUE),
|
|
ICHAIN_F32(uncullZoneScale, 2000, ICHAIN_CONTINUE),
|
|
ICHAIN_F32(uncullZoneDownward, 2400, ICHAIN_STOP),
|
|
};
|
|
|
|
void EnOwl_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
EnOwl* this = (EnOwl*)thisx;
|
|
ColliderCylinder* collider;
|
|
s32 owlType;
|
|
s32 switchFlag;
|
|
|
|
Actor_ProcessInitChain(&this->actor, sInitChain);
|
|
ActorShape_Init(&this->actor.shape, 0, ActorShadow_DrawCircle, 36.0f);
|
|
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gOwlFlyingSkel, &gOwlFlyAnim, this->jointTable, this->morphTable,
|
|
21);
|
|
SkelAnime_InitFlex(globalCtx, &this->skelAnime2, &gOwlPerchingSkel, &gOwlPerchAnim, this->jointTable2,
|
|
this->morphTable2, 16);
|
|
Collider_InitCylinder(globalCtx, &this->collider);
|
|
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sOwlCylinderInit);
|
|
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
|
this->actor.minVelocityY = -10.0f;
|
|
this->actor.targetArrowOffset = 500.0f;
|
|
EnOwl_ChangeMode(this, EnOwl_WaitDefault, func_80ACC540, &this->skelAnime2, &gOwlPerchAnim, 0.0f);
|
|
this->actionFlags = this->unk_406 = this->unk_409 = 0;
|
|
this->unk_405 = 4;
|
|
this->unk_404 = this->unk_407 = 0;
|
|
this->unk_408 = 4;
|
|
owlType = (this->actor.params & 0xFC0) >> 6;
|
|
switchFlag = (this->actor.params & 0x3F);
|
|
if (this->actor.params == 0xFFF) {
|
|
owlType = OWL_OUTSIDE_KOKIRI;
|
|
switchFlag = 0x20;
|
|
}
|
|
// "conversation owl %4x no = %d, sv = %d"
|
|
osSyncPrintf(VT_FGCOL(CYAN) " 会話フクロウ %4x no = %d, sv = %d\n" VT_RST, this->actor.params, owlType, switchFlag);
|
|
|
|
if ((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(globalCtx, switchFlag)) {
|
|
osSyncPrintf("savebitでフクロウ退避\n"); // "Save owl with savebit"
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
|
|
this->unk_3EE = 0;
|
|
this->unk_400 = this->actor.world.rot.y;
|
|
|
|
switch (owlType) {
|
|
case OWL_DEFAULT:
|
|
this->actionFunc = EnOwl_WaitDefault;
|
|
this->actor.uncullZoneForward = 4000.0f;
|
|
this->unk_40A = 0;
|
|
break;
|
|
case OWL_OUTSIDE_KOKIRI:
|
|
this->actionFunc = EnOwl_WaitOutsideKokiri;
|
|
break;
|
|
case OWL_HYRULE_CASTLE:
|
|
this->actionFlags |= 2;
|
|
this->unk_3EE = 0x20;
|
|
this->actionFunc = EnOwl_WaitHyruleCastle;
|
|
break;
|
|
case OWL_KAKARIKO:
|
|
if (gSaveContext.eventChkInf[4] & 1) {
|
|
// has zelda's letter
|
|
osSyncPrintf("フクロウ退避\n"); // "Owl evacuation"
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
|
|
this->actionFunc = EnOwl_WaitKakariko;
|
|
break;
|
|
case OWL_HYLIA_GERUDO:
|
|
if (gSaveContext.eventChkInf[4] & 8) {
|
|
// has ocarina of time
|
|
osSyncPrintf("フクロウ退避\n"); // "Owl evacuation"
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
this->actionFunc = EnOwl_WaitGerudo;
|
|
break;
|
|
case OWL_LAKE_HYLIA:
|
|
this->actionFunc = EnOwl_WaitLakeHylia;
|
|
break;
|
|
case OWL_ZORA_RIVER:
|
|
if ((gSaveContext.eventChkInf[3] & 0x200) || !(gSaveContext.eventChkInf[4] & 1)) {
|
|
// opened zora's domain or has zelda's letter
|
|
osSyncPrintf("フクロウ退避\n"); // "Owl evacuation"
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
|
|
this->actionFunc = EnOwl_WaitZoraRiver;
|
|
break;
|
|
case OWL_HYLIA_SHORTCUT:
|
|
this->actionFunc = EnOwl_WaitHyliaShortcut;
|
|
Flags_UnsetSwitch(globalCtx, 0x23);
|
|
return;
|
|
case OWL_DEATH_MOUNTAIN:
|
|
this->actionFunc = EnOwl_WaitDeathMountainShortcut;
|
|
break;
|
|
case OWL_DEATH_MOUNTAIN2:
|
|
this->actionFunc = EnOwl_WaitDeathMountainShortcut;
|
|
break;
|
|
case OWL_DESSERT_COLOSSUS:
|
|
this->actionFunc = func_80ACB3E0;
|
|
break;
|
|
case OWL_LOST_WOODS_PRESARIA:
|
|
if (!CHECK_QUEST_ITEM(QUEST_SONG_LULLABY)) {
|
|
osSyncPrintf("フクロウ退避\n"); // "Owl evacuation"
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
this->actionFunc = EnOwl_WaitLWPreSaria;
|
|
break;
|
|
case OWL_LOST_WOODS_POSTSARIA:
|
|
if (!CHECK_QUEST_ITEM(QUEST_SONG_SARIA)) {
|
|
osSyncPrintf("フクロウ退避\n"); // "Owl evacuation"
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
this->actionFunc = EnOwl_WaitLWPostSaria;
|
|
break;
|
|
default:
|
|
// Outside kokiri forest
|
|
osSyncPrintf(VT_FGCOL(CYAN));
|
|
osSyncPrintf("no = %d \n", owlType);
|
|
// "Unfinished owl unfinished owl unfinished owl"
|
|
osSyncPrintf("未完成のフクロウ未完成のフクロウ未完成のフクロウ\n");
|
|
osSyncPrintf(VT_RST);
|
|
this->actionFlags |= 2;
|
|
this->unk_3EE = 0x20;
|
|
this->actionFunc = EnOwl_WaitOutsideKokiri;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EnOwl_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
EnOwl* this = (EnOwl*)thisx;
|
|
|
|
Collider_DestroyCylinder(globalCtx, &this->collider);
|
|
}
|
|
|
|
/**
|
|
* Rotates this to the player instance
|
|
*/
|
|
void EnOwl_LookAtLink(EnOwl* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
this->actor.shape.rot.y = this->actor.world.rot.y =
|
|
Math_Vec3f_Yaw(&this->actor.world.pos, &player->actor.world.pos);
|
|
}
|
|
|
|
/**
|
|
* Checks if link is within `targetDist` units, initalize the camera for the owl.
|
|
* returns 0 if the link is not within `targetDistance`, returns 1 once link is within
|
|
* the distance, and the camera has been initalized.
|
|
*/
|
|
s32 EnOwl_CheckInitTalk(EnOwl* this, GlobalContext* globalCtx, u16 textId, f32 targetDist, u16 flags) {
|
|
s32 timer;
|
|
f32 distCheck;
|
|
|
|
if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
|
|
if (this->actor.params == 0xFFF) {
|
|
this->actionFlags |= 0x40;
|
|
timer = -100;
|
|
} else {
|
|
if (Rand_ZeroOne() < 0.5f) {
|
|
timer = (flags & 1) ? -97 : -99;
|
|
this->actionFlags |= 0x40;
|
|
} else {
|
|
timer = (flags & 1) ? -96 : -98;
|
|
this->actionFlags &= ~0x40;
|
|
}
|
|
}
|
|
this->cameraIdx = OnePointCutscene_Init(globalCtx, 8700, timer, &this->actor, MAIN_CAM);
|
|
return true;
|
|
} else {
|
|
this->actor.textId = textId;
|
|
distCheck = (flags & 2) ? 200.0f : 1000.0f;
|
|
if (this->actor.xzDistToPlayer < targetDist) {
|
|
this->actor.flags |= ACTOR_FLAG_16;
|
|
func_8002F1C4(&this->actor, globalCtx, targetDist, distCheck, 0);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
s32 func_80ACA558(EnOwl* this, GlobalContext* globalCtx, u16 textId) {
|
|
if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
|
|
return true;
|
|
} else {
|
|
this->actor.textId = textId;
|
|
if (this->actor.xzDistToPlayer < 120.0f) {
|
|
func_8002F1C4(&this->actor, globalCtx, 350.0f, 1000.0f, 0);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void func_80ACA5C8(EnOwl* this) {
|
|
EnOwl_ChangeMode(this, func_80ACBEA0, func_80ACC540, &this->skelAnime, &gOwlUnfoldWingsAnim, 0.0f);
|
|
this->eyeTexIndex = 0;
|
|
this->blinkTimer = Rand_S16Offset(60, 60);
|
|
}
|
|
|
|
void func_80ACA62C(EnOwl* this, GlobalContext* globalCtx) {
|
|
s32 switchFlag = this->actor.params & 0x3F;
|
|
|
|
if (switchFlag < 0x20) {
|
|
Flags_SetSwitch(globalCtx, switchFlag);
|
|
osSyncPrintf(VT_FGCOL(CYAN) " Actor_Environment_sw = %d\n" VT_RST, Flags_GetSwitch(globalCtx, switchFlag));
|
|
}
|
|
func_80ACA5C8(this);
|
|
}
|
|
|
|
void func_80ACA690(EnOwl* this, GlobalContext* globalCtx) {
|
|
if ((this->unk_3EE & 0x3F) == 0) {
|
|
func_80ACA62C(this, globalCtx);
|
|
}
|
|
}
|
|
|
|
void func_80ACA6C0(EnOwl* this) {
|
|
if (Rand_CenteredFloat(1.0f) < 0.0f) {
|
|
this->actionFlags |= 0x20;
|
|
} else {
|
|
this->actionFlags &= ~0x20;
|
|
}
|
|
}
|
|
|
|
void func_80ACA71C(EnOwl* this) {
|
|
func_80ACA6C0(this);
|
|
this->unk_3F2 = 0;
|
|
this->actionFlags |= 0x10;
|
|
this->unk_408 = 4;
|
|
this->unk_404 = 0;
|
|
this->unk_406 = 0;
|
|
this->unk_405 = 4;
|
|
this->unk_407 = this->unk_3F2;
|
|
}
|
|
|
|
void func_80ACA76C(EnOwl* this, GlobalContext* globalCtx) {
|
|
func_8002DF54(globalCtx, &this->actor, 8);
|
|
|
|
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
|
|
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF);
|
|
func_80ACA62C(this, globalCtx);
|
|
this->actor.flags &= ~ACTOR_FLAG_16;
|
|
}
|
|
}
|
|
|
|
void func_80ACA7E0(EnOwl* this, GlobalContext* globalCtx) {
|
|
func_8002DF54(globalCtx, &this->actor, 8);
|
|
|
|
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
|
|
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF);
|
|
if ((this->unk_3EE & 0x3F) == 0) {
|
|
func_80ACA62C(this, globalCtx);
|
|
} else {
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
this->actionFunc = func_80ACA690;
|
|
}
|
|
this->actor.flags &= ~ACTOR_FLAG_16;
|
|
}
|
|
}
|
|
|
|
void EnOwl_ConfirmKokiriMessage(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x2065);
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x2067);
|
|
this->actionFunc = func_80ACA76C;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitOutsideKokiri(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x2064, 360.0f, 0)) {
|
|
// Sets BGM
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
|
|
this->actionFunc = EnOwl_ConfirmKokiriMessage;
|
|
// spoke to owl by lost woods
|
|
gSaveContext.eventChkInf[6] |= 0x8000;
|
|
}
|
|
}
|
|
|
|
void func_80ACA998(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x2069);
|
|
this->actionFunc = func_80ACAA54;
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x206B);
|
|
this->actionFunc = func_80ACA7E0;
|
|
break;
|
|
}
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACAA54(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x206A);
|
|
this->actionFunc = func_80ACA998;
|
|
this->actionFlags |= 2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACAAC0(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x2069);
|
|
this->actionFunc = func_80ACAA54;
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitHyruleCastle(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x2068, 540.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACAAC0;
|
|
}
|
|
}
|
|
|
|
void func_80ACAB88(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
// obtained zelda's letter
|
|
if (gSaveContext.eventChkInf[4] & 1) {
|
|
Message_ContinueTextbox(globalCtx, 0x206D);
|
|
} else {
|
|
Message_ContinueTextbox(globalCtx, 0x206C);
|
|
}
|
|
this->actionFunc = func_80ACAC6C;
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x206E);
|
|
this->actionFunc = func_80ACA7E0;
|
|
break;
|
|
}
|
|
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACAC6C(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x206A);
|
|
this->actionFunc = func_80ACAB88;
|
|
this->actionFlags |= 2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitKakariko(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x206C, 480.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACAC6C;
|
|
}
|
|
}
|
|
|
|
void func_80ACAD34(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x206F);
|
|
this->actionFunc = func_80ACADF0;
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x2070);
|
|
this->actionFunc = func_80ACA7E0;
|
|
break;
|
|
}
|
|
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACADF0(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x206A);
|
|
this->actionFunc = func_80ACAD34;
|
|
this->actionFlags |= 2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitGerudo(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x206F, 360.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACADF0;
|
|
}
|
|
}
|
|
|
|
void func_80ACAEB8(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x2071);
|
|
this->actionFunc = func_80ACAF74;
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x2072);
|
|
this->actionFunc = func_80ACA7E0;
|
|
break;
|
|
}
|
|
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACAF74(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x206A);
|
|
this->actionFunc = func_80ACAEB8;
|
|
this->actionFlags |= 2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitLakeHylia(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x2071, 360.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACAF74;
|
|
}
|
|
}
|
|
|
|
void func_80ACB03C(EnOwl* this, GlobalContext* globalCtx) {
|
|
func_8002DF54(globalCtx, &this->actor, 8);
|
|
|
|
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
|
|
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF);
|
|
func_80ACA62C(this, globalCtx);
|
|
this->actor.flags &= ~ACTOR_FLAG_16;
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitZoraRiver(EnOwl* this, GlobalContext* globalCtx) {
|
|
u16 textId;
|
|
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (CHECK_QUEST_ITEM(QUEST_SONG_SARIA)) {
|
|
if (CHECK_QUEST_ITEM(QUEST_SONG_LULLABY)) {
|
|
textId = 0x4031;
|
|
} else {
|
|
textId = 0x4017;
|
|
}
|
|
} else {
|
|
textId = 0x4002;
|
|
}
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, textId, 360.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB03C;
|
|
}
|
|
}
|
|
|
|
void func_80ACB148(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
|
|
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF);
|
|
func_80ACA5C8(this);
|
|
this->actionFunc = func_80ACC30C;
|
|
Flags_SetSwitch(globalCtx, 0x23);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitHyliaShortcut(EnOwl* this, GlobalContext* globalCtx) {
|
|
u16 textId = (gSaveContext.infTable[25] & 0x20) ? 0x4004 : 0x4003;
|
|
|
|
// Spoke to Owl in Lake Hylia
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
if (func_80ACA558(this, globalCtx, textId)) {
|
|
gSaveContext.infTable[25] |= 0x20;
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB148;
|
|
}
|
|
}
|
|
|
|
void func_80ACB22C(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
|
|
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF);
|
|
func_80ACA5C8(this);
|
|
this->actionFunc = func_80ACC30C;
|
|
}
|
|
}
|
|
|
|
void func_80ACB274(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
|
|
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF);
|
|
this->actionFunc = EnOwl_WaitDeathMountainShortcut;
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitDeathMountainShortcut(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (!gSaveContext.magicAcquired) {
|
|
if (func_80ACA558(this, globalCtx, 0x3062)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB274;
|
|
return;
|
|
}
|
|
} else {
|
|
if (func_80ACA558(this, globalCtx, 0x3063)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB22C;
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_80ACB344(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x607A);
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x607C);
|
|
this->actionFunc = func_80ACA7E0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_80ACB3E0(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x6079, 360.0f, 2)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB344;
|
|
}
|
|
}
|
|
|
|
void func_80ACB440(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x10C1);
|
|
this->actionFunc = func_80ACB4FC;
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x10C3);
|
|
this->actionFunc = func_80ACA7E0;
|
|
}
|
|
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACB4FC(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x10C2);
|
|
this->actionFunc = func_80ACB440;
|
|
this->actionFlags |= 2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitLWPreSaria(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x10C0, 190.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB4FC;
|
|
}
|
|
}
|
|
|
|
void func_80ACB5C4(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
|
|
switch (globalCtx->msgCtx.choiceIndex) {
|
|
case OWL_REPEAT:
|
|
Message_ContinueTextbox(globalCtx, 0x10C5);
|
|
this->actionFunc = func_80ACB680;
|
|
break;
|
|
case OWL_OK:
|
|
Message_ContinueTextbox(globalCtx, 0x10C7);
|
|
this->actionFunc = func_80ACA7E0;
|
|
break;
|
|
}
|
|
|
|
this->actionFlags &= ~2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void func_80ACB680(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT && Message_ShouldAdvance(globalCtx)) {
|
|
Message_ContinueTextbox(globalCtx, 0x10C6);
|
|
this->actionFunc = func_80ACB5C4;
|
|
this->actionFlags |= 2;
|
|
func_80ACA71C(this);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitLWPostSaria(EnOwl* this, GlobalContext* globalCtx) {
|
|
EnOwl_LookAtLink(this, globalCtx);
|
|
|
|
if (EnOwl_CheckInitTalk(this, globalCtx, 0x10C4, 360.0f, 0)) {
|
|
Audio_PlayFanfare(NA_BGM_OWL);
|
|
this->actionFunc = func_80ACB680;
|
|
}
|
|
}
|
|
|
|
void func_80ACB748(EnOwl* this, GlobalContext* globalCtx) {
|
|
static Vec3f D_80ACD62C = { 0.0f, 0.0f, 0.0f };
|
|
f32 dist;
|
|
f32 weight;
|
|
s32 owlType = (this->actor.params & 0xFC0) >> 6;
|
|
|
|
dist = Math3D_Vec3f_DistXYZ(&this->eye, &globalCtx->view.eye) / 45.0f;
|
|
this->eye.x = globalCtx->view.eye.x;
|
|
this->eye.y = globalCtx->view.eye.y;
|
|
this->eye.z = globalCtx->view.eye.z;
|
|
|
|
weight = dist;
|
|
if (weight > 1.0f) {
|
|
weight = 1.0f;
|
|
}
|
|
|
|
switch (owlType) {
|
|
case 7:
|
|
func_800F436C(&D_80ACD62C, NA_SE_EV_FLYING_AIR - SFX_FLAG, weight * 2.0f);
|
|
if ((globalCtx->csCtx.frames > 324) ||
|
|
((globalCtx->csCtx.frames >= 142 && (globalCtx->csCtx.frames <= 266)))) {
|
|
func_800F4414(&D_80ACD62C, NA_SE_EN_OWL_FLUTTER, weight * 2.0f);
|
|
}
|
|
if (globalCtx->csCtx.frames == 85) {
|
|
func_800F436C(&D_80ACD62C, NA_SE_EV_PASS_AIR, weight * 2.0f);
|
|
}
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
func_800F436C(&D_80ACD62C, NA_SE_EV_FLYING_AIR - SFX_FLAG, weight * 2.0f);
|
|
if ((globalCtx->csCtx.frames >= 420) ||
|
|
((0xC1 < globalCtx->csCtx.frames && (globalCtx->csCtx.frames <= 280)))) {
|
|
func_800F4414(&D_80ACD62C, NA_SE_EN_OWL_FLUTTER, weight * 2.0f);
|
|
}
|
|
if (globalCtx->csCtx.frames == 217) {
|
|
func_800F436C(&D_80ACD62C, NA_SE_EV_PASS_AIR, weight * 2.0f);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void func_80ACB904(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (globalCtx->csCtx.state != CS_STATE_IDLE && (globalCtx->csCtx.npcActions[7] != NULL)) {
|
|
if (this->unk_40A != globalCtx->csCtx.npcActions[7]->action) {
|
|
func_80ACD130(this, globalCtx, 7);
|
|
func_80ACBAB8(this, globalCtx);
|
|
}
|
|
func_80ACD2CC(this, globalCtx);
|
|
}
|
|
|
|
if (this->actionFlags & 0x80) {
|
|
func_80ACB748(this, globalCtx);
|
|
}
|
|
}
|
|
|
|
void func_80ACB994(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (globalCtx->csCtx.state != CS_STATE_IDLE && (globalCtx->csCtx.npcActions[7] != NULL)) {
|
|
if (this->unk_40A != globalCtx->csCtx.npcActions[7]->action) {
|
|
func_80ACD130(this, globalCtx, 7);
|
|
func_80ACBAB8(this, globalCtx);
|
|
}
|
|
func_80ACD4D4(this, globalCtx);
|
|
}
|
|
|
|
if (this->actionFlags & 0x80) {
|
|
func_80ACB748(this, globalCtx);
|
|
}
|
|
}
|
|
|
|
void EnOwl_WaitDefault(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (globalCtx->csCtx.state != CS_STATE_IDLE && (globalCtx->csCtx.npcActions[7] != NULL)) {
|
|
if (this->unk_40A != globalCtx->csCtx.npcActions[7]->action) {
|
|
this->actionFlags |= 4;
|
|
func_80ACD130(this, globalCtx, 7);
|
|
func_80ACBAB8(this, globalCtx);
|
|
} else {
|
|
this->actor.world.rot.z = globalCtx->csCtx.npcActions[7]->urot.y;
|
|
}
|
|
}
|
|
|
|
if (this->actionFlags & 0x80) {
|
|
func_80ACB748(this, globalCtx);
|
|
}
|
|
}
|
|
|
|
void func_80ACBAB8(EnOwl* this, GlobalContext* globalCtx) {
|
|
switch (globalCtx->csCtx.npcActions[7]->action - 1) {
|
|
case 0:
|
|
EnOwl_ChangeMode(this, func_80ACB904, func_80ACC540, &this->skelAnime, &gOwlFlyAnim, 0.0f);
|
|
break;
|
|
case 1:
|
|
this->actor.draw = EnOwl_Draw;
|
|
EnOwl_ChangeMode(this, EnOwl_WaitDefault, func_80ACC540, &this->skelAnime, &gOwlPerchAnim, 0.0f);
|
|
break;
|
|
case 2:
|
|
this->actor.draw = EnOwl_Draw;
|
|
EnOwl_ChangeMode(this, func_80ACB994, func_80ACC540, &this->skelAnime, &gOwlFlyAnim, 0.0f);
|
|
break;
|
|
case 3:
|
|
this->actor.draw = NULL;
|
|
this->actionFunc = EnOwl_WaitDefault;
|
|
break;
|
|
case 4:
|
|
Actor_Kill(&this->actor);
|
|
break;
|
|
}
|
|
|
|
this->unk_40A = globalCtx->csCtx.npcActions[7]->action;
|
|
}
|
|
|
|
void func_80ACBC0C(EnOwl* this, GlobalContext* globalCtx) {
|
|
this->actor.flags |= ACTOR_FLAG_5;
|
|
|
|
if (this->actor.xzDistToPlayer > 6000.0f && !(this->actionFlags & 0x80)) {
|
|
Actor_Kill(&this->actor);
|
|
}
|
|
|
|
Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_400, 2, 0x80, 0x40);
|
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
|
|
|
if (this->actor.speedXZ < 16.0f) {
|
|
this->actor.speedXZ += 0.5f;
|
|
}
|
|
|
|
if ((this->unk_3F8 + 1000.0f) < this->actor.world.pos.y) {
|
|
if (this->actor.velocity.y > 0.0f) {
|
|
this->actor.velocity.y -= 0.4f;
|
|
}
|
|
} else if (this->actor.velocity.y < 4.0f) {
|
|
this->actor.velocity.y += 0.2f;
|
|
}
|
|
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACBD4C(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (this->skelAnime.curFrame > 10.0f) {
|
|
Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_400, 2, 0x400, 0x40);
|
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
|
}
|
|
|
|
if (this->skelAnime.curFrame > 45.0f) {
|
|
this->actor.velocity.y = 2.0f;
|
|
this->actor.gravity = 0.0f;
|
|
this->actor.speedXZ = 8.0f;
|
|
} else if (this->skelAnime.curFrame > 17.0f) {
|
|
this->actor.velocity.y = 6.0f;
|
|
this->actor.gravity = 0.0f;
|
|
this->actor.speedXZ = 4.0f;
|
|
}
|
|
|
|
if (this->actionFlags & 1) {
|
|
EnOwl_ChangeMode(this, func_80ACBC0C, func_80ACC460, &this->skelAnime, &gOwlFlyAnim, 0.0f);
|
|
this->unk_3FE = 6;
|
|
if (this->actionFlags & 0x40) {
|
|
this->unk_400 += 0x2000;
|
|
} else {
|
|
this->unk_400 -= 0x2000;
|
|
}
|
|
}
|
|
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACBEA0(EnOwl* this, GlobalContext* GlobalContext) {
|
|
if (this->actionFlags & 1) {
|
|
this->unk_3FE = 3;
|
|
EnOwl_ChangeMode(this, func_80ACBD4C, func_80ACC540, &this->skelAnime, &gOwlTakeoffAnim, 0.0f);
|
|
this->unk_3F8 = this->actor.world.pos.y;
|
|
this->actor.velocity.y = 2.0f;
|
|
if (this->actionFlags & 0x40) {
|
|
this->unk_400 = this->actor.world.rot.y + 0x4000;
|
|
} else {
|
|
this->unk_400 = this->actor.world.rot.y - 0x4000;
|
|
}
|
|
}
|
|
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACBF50(EnOwl* this, GlobalContext* globalCtx) {
|
|
Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_400, 2, 0x384, 0x258);
|
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
|
|
|
if (this->actionFlags & 1) {
|
|
EnOwl_ChangeMode(this, func_80ACBC0C, func_80ACC460, &this->skelAnime, &gOwlFlyAnim, 0.0f);
|
|
this->unk_3FE = 6;
|
|
this->actor.velocity.y = 2.0f;
|
|
this->actor.gravity = 0.0f;
|
|
this->actor.speedXZ = 4.0f;
|
|
}
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACC00C(EnOwl* this, GlobalContext* globalCtx) {
|
|
s32 owlType;
|
|
s32 temp_v0;
|
|
s32 temp_v0_2;
|
|
|
|
Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_400, 2, 0x384, 0x258);
|
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
|
|
|
if (this->actor.xzDistToPlayer < 50.0f) {
|
|
if (!Gameplay_InCsMode(globalCtx)) {
|
|
owlType = (this->actor.params & 0xFC0) >> 6;
|
|
osSyncPrintf(VT_FGCOL(CYAN));
|
|
osSyncPrintf("%dのフクロウ\n", owlType); // "%d owl"
|
|
osSyncPrintf(VT_RST);
|
|
switch (owlType) {
|
|
case 7:
|
|
osSyncPrintf(VT_FGCOL(CYAN));
|
|
osSyncPrintf("SPOT 06 の デモがはしった\n"); // "Demo of SPOT 06 has been completed"
|
|
osSyncPrintf(VT_RST);
|
|
globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(gLakeHyliaOwlCs);
|
|
this->actor.draw = NULL;
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(gDMTOwlCs);
|
|
this->actor.draw = NULL;
|
|
break;
|
|
default:
|
|
ASSERT(0, "0", "../z_en_owl.c", 1693);
|
|
break;
|
|
}
|
|
|
|
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
|
|
gSaveContext.cutsceneTrigger = 1;
|
|
func_800F44EC(0x14, 0xA);
|
|
this->actionFunc = EnOwl_WaitDefault;
|
|
this->unk_40A = 0;
|
|
this->actionFlags |= 0x80;
|
|
gTimeIncrement = 0;
|
|
}
|
|
}
|
|
|
|
if (this->skelAnime.curFrame >= 37.0f) {
|
|
if (this->unk_3FE > 0) {
|
|
this->skelAnime.curFrame = 21.0f;
|
|
this->unk_3FE--;
|
|
} else {
|
|
this->actionFunc = func_80ACBF50;
|
|
}
|
|
}
|
|
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACC23C(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (this->skelAnime.curFrame < 20.0f) {
|
|
this->actor.speedXZ = 1.5f;
|
|
} else {
|
|
this->actor.speedXZ = 0.0f;
|
|
Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_400, 2, 0x384, 0x258);
|
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
|
}
|
|
|
|
if (this->skelAnime.curFrame >= 37.0f) {
|
|
this->skelAnime.curFrame = 21.0f;
|
|
this->actionFunc = func_80ACC00C;
|
|
this->unk_3FE = 5;
|
|
this->actor.velocity.y = 0.0f;
|
|
this->actor.gravity = 0.0f;
|
|
this->actor.speedXZ = 0.0f;
|
|
}
|
|
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACC30C(EnOwl* this, GlobalContext* globalCtx) {
|
|
if (this->actionFlags & 1) {
|
|
this->unk_3FE = 3;
|
|
EnOwl_ChangeMode(this, func_80ACC23C, func_80ACC540, &this->skelAnime, &gOwlTakeoffAnim, 0.0f);
|
|
this->unk_3F8 = this->actor.world.pos.y;
|
|
this->actor.velocity.y = 0.2f;
|
|
}
|
|
|
|
this->actionFlags |= 8;
|
|
}
|
|
|
|
void func_80ACC390(EnOwl* this) {
|
|
SkelAnime_Update(this->curSkelAnime);
|
|
|
|
if (this->unk_3FE > 0) {
|
|
this->unk_3FE--;
|
|
this->actor.shape.rot.z = Math_SinS(this->unk_3FE * 0x333) * 1000.0f;
|
|
} else {
|
|
this->unk_410 = func_80ACC460;
|
|
this->unk_3FE = 6;
|
|
Animation_Change(this->curSkelAnime, &gOwlFlyAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gOwlFlyAnim), 2, 5.0f);
|
|
}
|
|
}
|
|
|
|
void func_80ACC460(EnOwl* this) {
|
|
if (SkelAnime_Update(this->curSkelAnime)) {
|
|
if (this->unk_3FE > 0) {
|
|
this->unk_3FE--;
|
|
Animation_Change(this->curSkelAnime, this->curSkelAnime->animation, 1.0f, 0.0f,
|
|
Animation_GetLastFrame(this->curSkelAnime->animation), ANIMMODE_ONCE, 0.0f);
|
|
} else {
|
|
this->unk_3FE = 0xA0;
|
|
this->unk_410 = func_80ACC390;
|
|
Animation_Change(this->curSkelAnime, &gOwlGlideAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gOwlGlideAnim), 0,
|
|
5.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
void func_80ACC540(EnOwl* this) {
|
|
if (SkelAnime_Update(this->curSkelAnime)) {
|
|
Animation_Change(this->curSkelAnime, this->curSkelAnime->animation, 1.0f, 0.0f,
|
|
Animation_GetLastFrame(this->curSkelAnime->animation), ANIMMODE_ONCE, 0.0f);
|
|
this->actionFlags |= 1;
|
|
} else {
|
|
this->actionFlags &= ~1;
|
|
}
|
|
}
|
|
|
|
s32 func_80ACC5CC(EnOwl* this) {
|
|
s32 phi_v1 = (this->actionFlags & 2) ? 0x20 : 0;
|
|
|
|
if (phi_v1 == (this->unk_3EE & 0x3F)) {
|
|
return true;
|
|
} else {
|
|
if (this->actionFlags & 0x20) {
|
|
this->unk_3EE += 4;
|
|
} else {
|
|
this->unk_3EE -= 4;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
s32 func_80ACC624(EnOwl* this, GlobalContext* globalCtx) {
|
|
s32 switchFlag = (this->actor.params & 0xFC0) >> 6;
|
|
|
|
if (globalCtx->sceneNum != SCENE_SPOT11) {
|
|
return true;
|
|
} else if (switchFlag == 0xA) {
|
|
return true;
|
|
} else if (globalCtx->csCtx.frames >= 300 && globalCtx->csCtx.frames <= 430) {
|
|
return true;
|
|
} else if (globalCtx->csCtx.frames >= 1080 && globalCtx->csCtx.frames <= 1170) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void EnOwl_Update(Actor* thisx, GlobalContext* globalCtx) {
|
|
s32 pad;
|
|
EnOwl* this = (EnOwl*)thisx;
|
|
s16 phi_a1;
|
|
|
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
|
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
|
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 10.0f, 10.0f, 10.0f, 5);
|
|
this->unk_410(this);
|
|
this->actionFlags &= ~8;
|
|
this->actionFunc(this, globalCtx);
|
|
if (this->actor.update == NULL) {
|
|
// "Owl disappears"
|
|
osSyncPrintf("フクロウ消滅!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
|
return;
|
|
}
|
|
|
|
if (!(this->actionFlags & 0x80) && func_80ACC624(this, globalCtx)) {
|
|
if ((this->skelAnime.animation == &gOwlTakeoffAnim &&
|
|
(this->skelAnime.curFrame == 2.0f || this->skelAnime.curFrame == 9.0f ||
|
|
this->skelAnime.curFrame == 23.0f || this->skelAnime.curFrame == 40.0f ||
|
|
this->skelAnime.curFrame == 58.0f)) ||
|
|
(this->skelAnime.animation == &gOwlFlyAnim && this->skelAnime.curFrame == 4.0f)) {
|
|
Audio_PlayActorSound2(&this->actor, NA_SE_EN_OWL_FLUTTER);
|
|
}
|
|
}
|
|
|
|
if (this->actor.draw != NULL) {
|
|
Actor_MoveForward(&this->actor);
|
|
}
|
|
|
|
if (this->actionFlags & 2) {
|
|
this->eyeTexIndex = 2;
|
|
} else {
|
|
if (DECR(this->blinkTimer) == 0) {
|
|
this->blinkTimer = Rand_S16Offset(60, 60);
|
|
}
|
|
|
|
this->eyeTexIndex = this->blinkTimer;
|
|
|
|
if (this->eyeTexIndex >= 3) {
|
|
this->eyeTexIndex = 0;
|
|
}
|
|
}
|
|
|
|
if (!(this->actionFlags & 8)) {
|
|
phi_a1 = 0;
|
|
if (this->actionFlags & 0x10) {
|
|
switch (this->unk_404) {
|
|
case 0:
|
|
this->unk_404 = 1;
|
|
this->unk_405 = 6;
|
|
break;
|
|
case 1:
|
|
this->unk_405--;
|
|
|
|
if (this->unk_405 != 0) {
|
|
phi_a1 = Math_CosS(this->unk_405 * 8192) * 4096.0f;
|
|
} else {
|
|
if (this->actionFlags & 2) {
|
|
this->unk_3EE = 0;
|
|
} else {
|
|
this->unk_3EE = 0x20;
|
|
}
|
|
|
|
if (this->actionFlags & 0x20) {
|
|
this->unk_3EE -= 4;
|
|
} else {
|
|
this->unk_3EE += 4;
|
|
}
|
|
this->unk_404++;
|
|
}
|
|
|
|
if (this->actionFlags & 0x20) {
|
|
phi_a1 = -phi_a1;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (func_80ACC5CC(this)) {
|
|
this->actionFlags &= ~0x10;
|
|
this->unk_406 = (s32)Rand_ZeroFloat(20.0f) + 0x3C;
|
|
this->unk_404 = 0;
|
|
func_80ACA6C0(this);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
if (this->unk_406 > 0) {
|
|
this->unk_406--;
|
|
} else {
|
|
if (this->unk_404 == 0) {
|
|
if (Rand_ZeroOne() < 0.3f) {
|
|
this->unk_404 = 4;
|
|
this->unk_405 = 0xC;
|
|
} else {
|
|
this->unk_404 = 1;
|
|
this->unk_405 = 4;
|
|
}
|
|
}
|
|
|
|
this->unk_405--;
|
|
|
|
switch (this->unk_404) {
|
|
case 1:
|
|
phi_a1 = Math_SinS((-this->unk_405 * 4096) + 0x4000) * 5000.0f;
|
|
if (this->unk_405 <= 0) {
|
|
this->unk_405 = (s32)(Rand_ZeroFloat(15.0f) + 5.0f);
|
|
this->unk_404 = 2;
|
|
}
|
|
break;
|
|
case 2:
|
|
phi_a1 = 0x1388;
|
|
if (this->unk_405 <= 0) {
|
|
this->unk_404 = 3;
|
|
this->unk_405 = 4;
|
|
}
|
|
break;
|
|
case 3:
|
|
phi_a1 = Math_SinS(this->unk_405 * 4096) * 5000.0f;
|
|
if (this->unk_405 <= 0) {
|
|
this->unk_406 = (s32)Rand_ZeroFloat(20.0f) + 0x3C;
|
|
this->unk_404 = 0;
|
|
func_80ACA6C0(this);
|
|
}
|
|
break;
|
|
case 4:
|
|
phi_a1 = Math_SinS(this->unk_405 * 8192) * 5000.0f;
|
|
if (this->unk_405 <= 0) {
|
|
this->unk_406 = (s32)Rand_ZeroFloat(20.0f) + 0x3C;
|
|
this->unk_404 = 0;
|
|
func_80ACA6C0(this);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (this->actionFlags & 0x20) {
|
|
phi_a1 = -phi_a1;
|
|
}
|
|
}
|
|
|
|
if (this->unk_409 > 0) {
|
|
this->unk_409--;
|
|
} else {
|
|
this->unk_408--;
|
|
switch (this->unk_407) {
|
|
case 0:
|
|
this->unk_3F2 = (-this->unk_408 * 0x5DC) + 0x1770;
|
|
if (this->unk_408 <= 0) {
|
|
this->unk_407 = 1;
|
|
this->unk_408 = (s32)(Rand_ZeroFloat(15.0f) + 5.0f);
|
|
}
|
|
break;
|
|
case 1:
|
|
this->unk_3F2 = 0x1770;
|
|
if (this->unk_408 <= 0) {
|
|
this->unk_407 = 2;
|
|
this->unk_408 = 4;
|
|
}
|
|
break;
|
|
case 2:
|
|
this->unk_3F2 = this->unk_408 * 0x5DC;
|
|
if (this->unk_408 <= 0) {
|
|
this->unk_407 = 0;
|
|
this->unk_408 = 4;
|
|
this->unk_409 = (s32)Rand_ZeroFloat(40.0f) + 0xA0;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (phi_a1) {}
|
|
this->unk_3F0 = (u16)((this->unk_3EE << 2) << 8) + phi_a1;
|
|
this->unk_3EC = ABS(this->unk_3F0) >> 3;
|
|
} else {
|
|
this->unk_3F2 = 0;
|
|
if (this->actionFlags & 2) {
|
|
this->unk_3F0 = -0x8000;
|
|
} else {
|
|
this->unk_3F0 = 0;
|
|
}
|
|
|
|
this->unk_3EC = ABS(this->unk_3F0) >> 3;
|
|
}
|
|
}
|
|
|
|
s32 EnOwl_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** gfx, Vec3f* pos, Vec3s* rot, void* thisx) {
|
|
EnOwl* this = (EnOwl*)thisx;
|
|
|
|
switch (limbIndex) {
|
|
case 3:
|
|
rot->x += this->unk_3F0;
|
|
rot->z += this->unk_3EC;
|
|
rot->z -= this->unk_3F2;
|
|
break;
|
|
case 2:
|
|
rot->z += this->unk_3F2;
|
|
break;
|
|
case 4:
|
|
if (!(this->actionFlags & 8)) {
|
|
rot->y -= (s16)(this->unk_3EC * 1.5f);
|
|
}
|
|
break;
|
|
case 5:
|
|
if (!(this->actionFlags & 8)) {
|
|
rot->y += (s16)(this->unk_3EC * 1.5f);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void EnOwl_PostLimbUpdate(GlobalContext* globalCtx, s32 limbIndex, Gfx** gfx, Vec3s* rot, void* thisx) {
|
|
EnOwl* this = (EnOwl*)thisx;
|
|
Vec3f vec;
|
|
|
|
vec.z = 0.0f;
|
|
if (this->actionFlags & 2) {
|
|
vec.x = 700.0f;
|
|
vec.y = 400.0f;
|
|
} else {
|
|
vec.y = 0.0f;
|
|
vec.x = 1400.0f;
|
|
}
|
|
if (limbIndex == 3) {
|
|
Matrix_MultVec3f(&vec, &this->actor.focus.pos);
|
|
}
|
|
}
|
|
|
|
void EnOwl_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
|
static void* eyeTextures[] = { gObjOwlEyeOpenTex, gObjOwlEyeHalfTex, gObjOwlEyeClosedTex };
|
|
EnOwl* this = (EnOwl*)thisx;
|
|
s32 pad;
|
|
|
|
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_owl.c", 2247);
|
|
|
|
func_800943C8(globalCtx->state.gfxCtx);
|
|
gSPSegment(POLY_OPA_DISP++, 8, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeTexIndex]));
|
|
SkelAnime_DrawFlexOpa(globalCtx, this->curSkelAnime->skeleton, this->curSkelAnime->jointTable,
|
|
this->curSkelAnime->dListCount, EnOwl_OverrideLimbDraw, EnOwl_PostLimbUpdate, this);
|
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_owl.c", 2264);
|
|
}
|
|
|
|
void EnOwl_ChangeMode(EnOwl* this, EnOwlActionFunc actionFunc, OwlFunc arg2, SkelAnime* skelAnime,
|
|
AnimationHeader* animation, f32 morphFrames) {
|
|
this->curSkelAnime = skelAnime;
|
|
Animation_Change(this->curSkelAnime, animation, 1.0f, 0.0f, Animation_GetLastFrame(animation), ANIMMODE_ONCE,
|
|
morphFrames);
|
|
this->actionFunc = actionFunc;
|
|
this->unk_410 = arg2;
|
|
}
|
|
|
|
void func_80ACD130(EnOwl* this, GlobalContext* globalCtx, s32 idx) {
|
|
Vec3f startPos;
|
|
|
|
startPos.x = globalCtx->csCtx.npcActions[idx]->startPos.x;
|
|
startPos.y = globalCtx->csCtx.npcActions[idx]->startPos.y;
|
|
startPos.z = globalCtx->csCtx.npcActions[idx]->startPos.z;
|
|
this->actor.world.pos = startPos;
|
|
this->actor.world.rot.y = this->actor.shape.rot.y = globalCtx->csCtx.npcActions[idx]->rot.y;
|
|
this->actor.shape.rot.z = globalCtx->csCtx.npcActions[idx]->urot.z;
|
|
}
|
|
|
|
f32 func_80ACD1C4(GlobalContext* globalCtx, s32 idx) {
|
|
f32 ret = Environment_LerpWeight(globalCtx->csCtx.npcActions[idx]->endFrame,
|
|
globalCtx->csCtx.npcActions[idx]->startFrame, globalCtx->csCtx.frames);
|
|
|
|
ret = CLAMP_MAX(ret, 1.0f);
|
|
return ret;
|
|
}
|
|
|
|
void func_80ACD220(EnOwl* this, Vec3f* arg1, f32 arg2) {
|
|
Vec3f rpy;
|
|
|
|
rpy.x = (arg1->x - this->actor.world.pos.x) * arg2;
|
|
rpy.y = (arg1->y - this->actor.world.pos.y) * arg2;
|
|
rpy.z = (arg1->z - this->actor.world.pos.z) * arg2;
|
|
|
|
Math_StepToF(&this->actor.velocity.y, rpy.y, 1.0f);
|
|
this->actor.speedXZ = sqrtf(SQ(rpy.x) + SQ(rpy.z));
|
|
this->actor.world.rot.y = Math_Vec3f_Yaw(&this->actor.world.pos, arg1);
|
|
this->actor.shape.rot.y = this->actor.world.rot.y;
|
|
}
|
|
|
|
void func_80ACD2CC(EnOwl* this, GlobalContext* globalCtx) {
|
|
Vec3f pos;
|
|
s32 angle;
|
|
f32 t = func_80ACD1C4(globalCtx, 7);
|
|
|
|
pos.x = globalCtx->csCtx.npcActions[7]->startPos.x;
|
|
pos.y = globalCtx->csCtx.npcActions[7]->startPos.y;
|
|
pos.z = globalCtx->csCtx.npcActions[7]->startPos.z;
|
|
angle = (s16)globalCtx->csCtx.npcActions[7]->rot.y - this->actor.world.rot.z;
|
|
if (angle < 0) {
|
|
angle += 0x10000;
|
|
}
|
|
angle = (s16)((t * angle) + this->actor.world.rot.z);
|
|
angle = (u16)angle;
|
|
if (this->actionFlags & 4) {
|
|
f32 phi_f2 = globalCtx->csCtx.npcActions[7]->urot.x;
|
|
|
|
phi_f2 *= 10.0f * (360.0f / 0x10000);
|
|
if (phi_f2 < 0.0f) {
|
|
phi_f2 += 360.0f;
|
|
}
|
|
pos.x -= Math_SinS(angle) * phi_f2;
|
|
pos.z += Math_CosS(angle) * phi_f2;
|
|
this->unk_3F8 = phi_f2;
|
|
this->actor.world.pos = pos;
|
|
this->actor.draw = EnOwl_Draw;
|
|
this->actionFlags &= ~4;
|
|
this->actor.speedXZ = 0.0f;
|
|
} else {
|
|
pos.x -= Math_SinS(angle) * this->unk_3F8;
|
|
pos.z += Math_CosS(angle) * this->unk_3F8;
|
|
func_80ACD220(this, &pos, 1.0f);
|
|
}
|
|
}
|
|
|
|
void func_80ACD4D4(EnOwl* this, GlobalContext* globalCtx) {
|
|
Vec3f pos;
|
|
Vec3f endPosf;
|
|
f32 temp_ret = func_80ACD1C4(globalCtx, 7);
|
|
|
|
pos.x = globalCtx->csCtx.npcActions[7]->startPos.x;
|
|
pos.y = globalCtx->csCtx.npcActions[7]->startPos.y;
|
|
pos.z = globalCtx->csCtx.npcActions[7]->startPos.z;
|
|
endPosf.x = globalCtx->csCtx.npcActions[7]->endPos.x;
|
|
endPosf.y = globalCtx->csCtx.npcActions[7]->endPos.y;
|
|
endPosf.z = globalCtx->csCtx.npcActions[7]->endPos.z;
|
|
pos.x = (endPosf.x - pos.x) * temp_ret + pos.x;
|
|
pos.y = (endPosf.y - pos.y) * temp_ret + pos.y;
|
|
pos.z = (endPosf.z - pos.z) * temp_ret + pos.z;
|
|
func_80ACD220(this, &pos, 1.0f);
|
|
}
|