mirror of https://github.com/zeldaret/mm.git
ovl_En_Kitan (#1535)
* Decompiled * Documented * Suggested changes, mention that on debug there is an assert(false) in EnKitan_GetQuestionMessageId * Format * Update
This commit is contained in:
parent
255c6b850a
commit
7e716e120f
|
@ -1,8 +1,9 @@
|
|||
<Root>
|
||||
<!-- Skeleton & Animations for Keaton -->
|
||||
<File Name="object_kitan" Segment="6">
|
||||
<Animation Name="object_kitan_Anim_000CE8" Offset="0xCE8" /> <!-- Original name is "kt_hohoho" -->
|
||||
<Animation Name="object_kitan_Anim_00190C" Offset="0x190C" /> <!-- Original name is "kt_laugh" -->
|
||||
<Animation Name="object_kitan_Anim_002770" Offset="0x2770" /> <!-- Original name is "kt_wait" -->
|
||||
<Animation Name="gKeatonChuckleAnim" Offset="0xCE8" /> <!-- Original name is "kt_hohoho" -->
|
||||
<Animation Name="gKeatonCelebrateAnim" Offset="0x190C" /> <!-- Original name is "kt_laugh" -->
|
||||
<Animation Name="gKeatonIdleAnim" Offset="0x2770" /> <!-- Original name is "kt_wait" -->
|
||||
<DList Name="object_kitan_DL_004C40" Offset="0x4C40" />
|
||||
<DList Name="object_kitan_DL_004DF0" Offset="0x4DF0" />
|
||||
<DList Name="object_kitan_DL_005160" Offset="0x5160" />
|
||||
|
@ -29,26 +30,26 @@
|
|||
<Texture Name="object_kitan_Tex_007B68" OutName="tex_007B68" Format="ci8" Width="16" Height="16" Offset="0x7B68" />
|
||||
<Texture Name="object_kitan_Tex_007C68" OutName="tex_007C68" Format="ci8" Width="16" Height="16" Offset="0x7C68" />
|
||||
<Texture Name="object_kitan_Tex_007D68" OutName="tex_007D68" Format="ci8" Width="16" Height="16" Offset="0x7D68" />
|
||||
<Limb Name="object_kitan_Standardlimb_007E68" Type="Standard" EnumName="OBJECT_KITAN_LIMB_01" Offset="0x7E68" />
|
||||
<Limb Name="object_kitan_Standardlimb_007E74" Type="Standard" EnumName="OBJECT_KITAN_LIMB_02" Offset="0x7E74" />
|
||||
<Limb Name="object_kitan_Standardlimb_007E80" Type="Standard" EnumName="OBJECT_KITAN_LIMB_03" Offset="0x7E80" />
|
||||
<Limb Name="object_kitan_Standardlimb_007E8C" Type="Standard" EnumName="OBJECT_KITAN_LIMB_04" Offset="0x7E8C" />
|
||||
<Limb Name="object_kitan_Standardlimb_007E98" Type="Standard" EnumName="OBJECT_KITAN_LIMB_05" Offset="0x7E98" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EA4" Type="Standard" EnumName="OBJECT_KITAN_LIMB_06" Offset="0x7EA4" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EB0" Type="Standard" EnumName="OBJECT_KITAN_LIMB_07" Offset="0x7EB0" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EBC" Type="Standard" EnumName="OBJECT_KITAN_LIMB_08" Offset="0x7EBC" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EC8" Type="Standard" EnumName="OBJECT_KITAN_LIMB_09" Offset="0x7EC8" />
|
||||
<Limb Name="object_kitan_Standardlimb_007ED4" Type="Standard" EnumName="OBJECT_KITAN_LIMB_0A" Offset="0x7ED4" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EE0" Type="Standard" EnumName="OBJECT_KITAN_LIMB_0B" Offset="0x7EE0" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EEC" Type="Standard" EnumName="OBJECT_KITAN_LIMB_0C" Offset="0x7EEC" />
|
||||
<Limb Name="object_kitan_Standardlimb_007EF8" Type="Standard" EnumName="OBJECT_KITAN_LIMB_0D" Offset="0x7EF8" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F04" Type="Standard" EnumName="OBJECT_KITAN_LIMB_0E" Offset="0x7F04" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F10" Type="Standard" EnumName="OBJECT_KITAN_LIMB_0F" Offset="0x7F10" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F1C" Type="Standard" EnumName="OBJECT_KITAN_LIMB_10" Offset="0x7F1C" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F28" Type="Standard" EnumName="OBJECT_KITAN_LIMB_11" Offset="0x7F28" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F34" Type="Standard" EnumName="OBJECT_KITAN_LIMB_12" Offset="0x7F34" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F40" Type="Standard" EnumName="OBJECT_KITAN_LIMB_13" Offset="0x7F40" />
|
||||
<Limb Name="object_kitan_Standardlimb_007F4C" Type="Standard" EnumName="OBJECT_KITAN_LIMB_14" Offset="0x7F4C" />
|
||||
<Skeleton Name="object_kitan_Skel_007FA8" Type="Flex" LimbType="Standard" LimbNone="OBJECT_KITAN_LIMB_NONE" LimbMax="OBJECT_KITAN_LIMB_MAX" EnumName="ObjectKitanLimb" Offset="0x7FA8" />
|
||||
<Limb Name="gKeatonLowerBodyLimb" Type="Standard" EnumName="KEATON_LIMB_LOWER_BODY" Offset="0x7E68" />
|
||||
<Limb Name="gKeatonUpperBodyLimb" Type="Standard" EnumName="KEATON_LIMB_UPPER_BODY" Offset="0x7E74" />
|
||||
<Limb Name="gKeatonHeadLimb" Type="Standard" EnumName="KEATON_LIMB_HEAD" Offset="0x7E80" />
|
||||
<Limb Name="gKeatonLeftShoulderLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_SHOULDER" Offset="0x7E8C" />
|
||||
<Limb Name="gKeatonLeftArmLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_ARM" Offset="0x7E98" />
|
||||
<Limb Name="gKeatonRightShoulderLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_SHOULDER" Offset="0x7EA4" />
|
||||
<Limb Name="gKeatonRightArmLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_ARM" Offset="0x7EB0" />
|
||||
<Limb Name="gKeatonRightLegLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_LEG" Offset="0x7EBC" />
|
||||
<Limb Name="gKeatonRightFootLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_FOOT" Offset="0x7EC8" />
|
||||
<Limb Name="gKeatonLeftLegLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_LEG" Offset="0x7ED4" />
|
||||
<Limb Name="gKeatonLeftFootLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_FOOT" Offset="0x7EE0" />
|
||||
<Limb Name="gKeatonRightTailBaseLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_TAIL_BASE" Offset="0x7EEC" />
|
||||
<Limb Name="gKeatonRightTailMidLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_TAIL_MID" Offset="0x7EF8" />
|
||||
<Limb Name="gKeatonRightTailEndLimb" Type="Standard" EnumName="KEATON_LIMB_RIGHT_TAIL_END" Offset="0x7F04" />
|
||||
<Limb Name="gKeatonMiddleTailBaseLimb" Type="Standard" EnumName="KEATON_LIMB_MIDDLE_TAIL_BASE" Offset="0x7F10" />
|
||||
<Limb Name="gKeatonMiddleTailMidLimb" Type="Standard" EnumName="KEATON_LIMB_MIDDLE_TAIL_MID" Offset="0x7F1C" />
|
||||
<Limb Name="gKeatonMiddleTailEndLimb" Type="Standard" EnumName="KEATON_LIMB_MIDDLE_TAIL_END" Offset="0x7F28" />
|
||||
<Limb Name="gKeatonLeftTailBaseLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_TAIL_BASE" Offset="0x7F34" />
|
||||
<Limb Name="gKeatonLeftTailMidLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_TAIL_MID" Offset="0x7F40" />
|
||||
<Limb Name="gKeatonLeftTailEndLimb" Type="Standard" EnumName="KEATON_LIMB_LEFT_TAIL_END" Offset="0x7F4C" />
|
||||
<Skeleton Name="gKeatonSkel" Type="Flex" LimbType="Standard" LimbNone="KEATON_LIMB_NONE" LimbMax="KEATON_LIMB_MAX" EnumName="KeatonLimb" Offset="0x7FA8" />
|
||||
</File>
|
||||
</Root>
|
||||
|
|
3
spec
3
spec
|
@ -4734,8 +4734,7 @@ beginseg
|
|||
name "ovl_En_Kitan"
|
||||
compress
|
||||
include "build/src/overlays/actors/ovl_En_Kitan/z_en_kitan.o"
|
||||
include "build/data/ovl_En_Kitan/ovl_En_Kitan.data.o"
|
||||
include "build/data/ovl_En_Kitan/ovl_En_Kitan.reloc.o"
|
||||
include "build/src/overlays/actors/ovl_En_Kitan/ovl_En_Kitan_reloc.o"
|
||||
endseg
|
||||
|
||||
beginseg
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* File: z_en_kitan.c
|
||||
* Overlay: ovl_En_Kitan
|
||||
* Description:
|
||||
* Description: Keaton
|
||||
*/
|
||||
|
||||
#include "z_en_kitan.h"
|
||||
|
@ -13,8 +13,11 @@
|
|||
void EnKitan_Init(Actor* thisx, PlayState* play);
|
||||
void EnKitan_Destroy(Actor* thisx, PlayState* play);
|
||||
void EnKitan_Update(Actor* thisx, PlayState* play);
|
||||
void EnKitan_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
void EnKitan_Talk(EnKitan* this, PlayState* play);
|
||||
void EnKitan_WaitToAppear(EnKitan* this, PlayState* play);
|
||||
|
||||
#if 0
|
||||
ActorInit En_Kitan_InitVars = {
|
||||
/**/ ACTOR_EN_KITAN,
|
||||
/**/ ACTORCAT_NPC,
|
||||
|
@ -27,50 +30,364 @@ ActorInit En_Kitan_InitVars = {
|
|||
/**/ NULL,
|
||||
};
|
||||
|
||||
// static ColliderCylinderInit sCylinderInit = {
|
||||
static ColliderCylinderInit D_80C09D50 = {
|
||||
{ COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_ENEMY, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
|
||||
{ ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
|
||||
static ColliderCylinderInit sCylinderInit = {
|
||||
{
|
||||
COLTYPE_NONE,
|
||||
AT_NONE,
|
||||
AC_ON | AC_TYPE_ENEMY,
|
||||
OC1_ON | OC1_TYPE_ALL,
|
||||
OC2_TYPE_1,
|
||||
COLSHAPE_CYLINDER,
|
||||
},
|
||||
{
|
||||
ELEMTYPE_UNK0,
|
||||
{ 0x00000000, 0x00, 0x00 },
|
||||
{ 0xF7CFFFFF, 0x00, 0x00 },
|
||||
TOUCH_NONE | TOUCH_SFX_NORMAL,
|
||||
BUMP_ON,
|
||||
OCELEM_ON,
|
||||
},
|
||||
{ 20, 40, 0, { 0, 0, 0 } },
|
||||
};
|
||||
|
||||
#endif
|
||||
void EnKitan_Init(Actor* thisx, PlayState* play) {
|
||||
EnKitan* this = THIS;
|
||||
s32 pad;
|
||||
|
||||
extern ColliderCylinderInit D_80C09D50;
|
||||
Actor_SetScale(&this->actor, 0.0f);
|
||||
this->actionFunc = EnKitan_WaitToAppear;
|
||||
|
||||
extern UNK_TYPE D_06000CE8;
|
||||
extern UNK_TYPE D_06002770;
|
||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 12.0f);
|
||||
SkelAnime_InitFlex(play, &this->skelAnime, &gKeatonSkel, &gKeatonIdleAnim, this->jointTable, this->morphTable,
|
||||
KEATON_LIMB_MAX);
|
||||
Animation_PlayLoop(&this->skelAnime, &gKeatonIdleAnim);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/EnKitan_Init.s")
|
||||
Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
|
||||
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/EnKitan_Destroy.s")
|
||||
this->actor.velocity.y = -9.0f;
|
||||
this->actor.terminalVelocity = -9.0f;
|
||||
this->actor.gravity = -1.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C0923C.s")
|
||||
if ((Player_GetMask(play) != PLAYER_MASK_KEATON) ||
|
||||
Flags_GetCollectible(play, ENKITAN_GET_COLLECT_FLAG(&this->actor))) {
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09390.s")
|
||||
this->timer = 120;
|
||||
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09418.s")
|
||||
void EnKitan_Destroy(Actor* thisx, PlayState* play) {
|
||||
EnKitan* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C094A8.s")
|
||||
Collider_DestroyCylinder(play, &this->collider);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09518.s")
|
||||
void EnKitan_SpawnEffects(EnKitan* this, PlayState* play, s32 numEffects) {
|
||||
static Color_RGBA8 sEffPrimColor = { 255, 255, 255, 255 };
|
||||
static Color_RGBA8 sEffEnvColor = { 255, 255, 200, 255 };
|
||||
s32 i;
|
||||
Vec3f accel;
|
||||
Vec3f velocity;
|
||||
Vec3f pos;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C095C8.s")
|
||||
pos.x = this->actor.world.pos.x;
|
||||
pos.y = this->actor.world.pos.y;
|
||||
pos.z = this->actor.world.pos.z;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09648.s")
|
||||
for (i = 0; i < numEffects; i++) {
|
||||
velocity.x = Rand_CenteredFloat(10.0f);
|
||||
velocity.y = Rand_ZeroFloat(6.0f);
|
||||
velocity.z = Rand_CenteredFloat(10.0f);
|
||||
accel.x = -velocity.x * 0.05f;
|
||||
accel.y = 0.1f;
|
||||
accel.z = -velocity.x * 0.05f;
|
||||
func_800B0F18(play, &pos, &velocity, &accel, &sEffPrimColor, &sEffEnvColor, 400, 20, 20);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09708.s")
|
||||
s32 EnKitan_CanTalk(EnKitan* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09990.s")
|
||||
if (player->stateFlags1 & PLAYER_STATE1_800000) {
|
||||
return false;
|
||||
}
|
||||
if (Player_IsFacingActor(&this->actor, 0x3000, play) && Actor_IsFacingPlayer(&this->actor, 0x3000) &&
|
||||
(this->actor.xzDistToPlayer < 120.0f)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09AA4.s")
|
||||
u16 EnKitan_GetQuestionMessageId(EnKitan* this) {
|
||||
s32 i = 0;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09B50.s")
|
||||
while (true) {
|
||||
s32 rand = Rand_ZeroFloat(30.0f);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/EnKitan_Update.s")
|
||||
// Keep track of which questions have already been asked with a bitset
|
||||
if (!(this->textBitSet & (1 << rand))) {
|
||||
this->textBitSet |= 1 << rand;
|
||||
// 0x04B6 is the start of the question + answer choice textboxes, each question textbox is followed by the
|
||||
// choice textbox containing the answer choices
|
||||
return 0x4B6 + (rand * 2);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09C74.s")
|
||||
i++;
|
||||
if (i > 1000) {
|
||||
// There's an assert(false) here in the debug version to catch any unforeseen issues in testing. It is
|
||||
// assumed that if this function is called there is always at least one question available to be selected.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09C90.s")
|
||||
void EnKitan_Leave(EnKitan* this, PlayState* play) {
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kitan/func_80C09CD0.s")
|
||||
if (this->timer > 0) {
|
||||
// Scale down
|
||||
this->timer--;
|
||||
this->actor.scale.x *= 0.7f;
|
||||
Actor_SetScale(&this->actor, this->actor.scale.x);
|
||||
} else {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_TalkAfterGivingPrize(EnKitan* this, PlayState* play) {
|
||||
s32 pad;
|
||||
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
||||
if (Actor_TalkOfferAccepted(&this->actor, &play->state)) {
|
||||
this->actionFunc = EnKitan_Talk;
|
||||
Message_ContinueTextbox(play, 0x04B5);
|
||||
this->actor.flags &= ~ACTOR_FLAG_10000;
|
||||
Animation_MorphToLoop(&this->skelAnime, &gKeatonChuckleAnim, -5.0f);
|
||||
} else {
|
||||
Actor_OfferTalkExchange(&this->actor, play, 1000.0f, 1000.0f, PLAYER_IA_MINUS1);
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_WaitForPrizeTextboxClosed(EnKitan* this, PlayState* play) {
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
||||
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
||||
this->actor.flags |= ACTOR_FLAG_10000;
|
||||
this->actionFunc = EnKitan_TalkAfterGivingPrize;
|
||||
Actor_OfferTalkExchange(&this->actor, play, 1000.0f, 1000.0f, PLAYER_IA_MINUS1);
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_OfferPrize(EnKitan* this, PlayState* play) {
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
||||
if (Actor_HasParent(&this->actor, play)) {
|
||||
this->actor.parent = NULL;
|
||||
this->actionFunc = EnKitan_WaitForPrizeTextboxClosed;
|
||||
SET_WEEKEVENTREG(WEEKEVENTREG_79_80);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reward the player with a heart piece, or a red rupee if the heart piece was already obtained.
|
||||
if (CHECK_WEEKEVENTREG(WEEKEVENTREG_79_80)) {
|
||||
Actor_OfferGetItem(&this->actor, play, GI_RUPEE_RED, 2000.0f, 1000.0f);
|
||||
} else {
|
||||
Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 2000.0f, 1000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_Talk(EnKitan* this, PlayState* play) {
|
||||
if (SkelAnime_Update(&this->skelAnime)) {
|
||||
Animation_MorphToLoop(&this->skelAnime, &gKeatonIdleAnim, -10.0f);
|
||||
if (play->msgCtx.currentTextId != 0x04B4) {
|
||||
// If the quiz is ongoing, select a question
|
||||
Message_ContinueTextbox(play, EnKitan_GetQuestionMessageId(this));
|
||||
}
|
||||
}
|
||||
|
||||
switch (Message_GetState(&play->msgCtx)) {
|
||||
case TEXT_STATE_CHOICE:
|
||||
if (!Message_ShouldAdvance(play)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((play->msgCtx.choiceIndex + 1) == play->msgCtx.unk1206C) {
|
||||
// Correct answer, continue quiz or end if enough questions have been answered correctly
|
||||
Audio_PlaySfx(NA_SE_SY_QUIZ_CORRECT);
|
||||
|
||||
// Here the timer is being used as a counter for number of correct answers
|
||||
this->timer++;
|
||||
if (this->timer < 5) {
|
||||
play->msgCtx.msgLength = 0;
|
||||
} else {
|
||||
// Enough questions have been answered, continue to prize
|
||||
this->timer = 0;
|
||||
this->textBitSet = 0;
|
||||
Message_ContinueTextbox(play, 0x04B4);
|
||||
}
|
||||
Animation_MorphToPlayOnce(&this->skelAnime, &gKeatonCelebrateAnim, -5.0f);
|
||||
} else {
|
||||
// Wrong answer, end quiz
|
||||
Audio_PlaySfx(NA_SE_SY_QUIZ_INCORRECT);
|
||||
Animation_MorphToLoop(&this->skelAnime, &gKeatonChuckleAnim, -5.0f);
|
||||
Message_ContinueTextbox(play, 0x04B3);
|
||||
this->timer = 0;
|
||||
this->textBitSet = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXT_STATE_EVENT:
|
||||
if (!Message_ShouldAdvance(play)) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (play->msgCtx.currentTextId) {
|
||||
case 0x04B0:
|
||||
case 0x04B1:
|
||||
// Intro text
|
||||
Message_ContinueTextbox(play, play->msgCtx.currentTextId + 1);
|
||||
break;
|
||||
|
||||
case 0x04B2:
|
||||
// Quiz begins
|
||||
Animation_MorphToLoop(&this->skelAnime, &gKeatonIdleAnim, -5.0f);
|
||||
Message_ContinueTextbox(play, EnKitan_GetQuestionMessageId(this));
|
||||
break;
|
||||
|
||||
case 0x04B4:
|
||||
// Won the quiz
|
||||
Message_CloseTextbox(play);
|
||||
this->actionFunc = EnKitan_OfferPrize;
|
||||
EnKitan_OfferPrize(this, play);
|
||||
break;
|
||||
|
||||
case 0x04B3:
|
||||
// Answered a question incorrectly, stop
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, 0);
|
||||
FALLTHROUGH;
|
||||
case 0x04B5:
|
||||
// Keaton leaving
|
||||
Message_CloseTextbox(play);
|
||||
this->actionFunc = EnKitan_Leave;
|
||||
this->timer = 4;
|
||||
EnKitan_SpawnEffects(this, play, 30);
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 30, NA_SE_EN_NPC_FADEAWAY);
|
||||
Flags_SetCollectible(play, ENKITAN_GET_COLLECT_FLAG(&this->actor));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!(play->msgCtx.currentTextId & 1)) {
|
||||
// Even-numbered textboxes are question textboxes
|
||||
// The following textbox contains the associated answer choices for this question
|
||||
Message_ContinueTextbox(play, play->msgCtx.currentTextId + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_WaitForPlayer(EnKitan* this, PlayState* play) {
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
||||
if (Actor_TalkOfferAccepted(&this->actor, &play->state)) {
|
||||
// Began talking
|
||||
this->actionFunc = EnKitan_Talk;
|
||||
Message_StartTextbox(play, 0x04B0, &this->actor);
|
||||
this->timer = 0;
|
||||
Animation_MorphToLoop(&this->skelAnime, &gKeatonChuckleAnim, -5.0f);
|
||||
Audio_PlayFanfare(NA_BGM_KEATON_QUIZ);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((this->timer <= 0) || (Player_GetMask(play) != PLAYER_MASK_KEATON)) {
|
||||
// If the player does not talk quickly enough or the player isn't wearing the keaton mask, leave
|
||||
this->actionFunc = EnKitan_Leave;
|
||||
this->timer = 4;
|
||||
EnKitan_SpawnEffects(this, play, 30);
|
||||
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 30, NA_SE_EN_NPC_FADEAWAY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (EnKitan_CanTalk(this, play)) {
|
||||
// Broadcast talk request for the player to accept
|
||||
Actor_OfferTalk(&this->actor, play, 130.0f);
|
||||
this->timer--;
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_Appear(EnKitan* this, PlayState* play) {
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
||||
if (this->timer > 0) {
|
||||
// Scale up
|
||||
this->timer--;
|
||||
this->actor.scale.x = this->actor.scale.x * 0.3f + 0.0105f;
|
||||
Actor_SetScale(&this->actor, this->actor.scale.x);
|
||||
return;
|
||||
}
|
||||
|
||||
// Done scaling, continue
|
||||
Actor_SetScale(&this->actor, 0.015f);
|
||||
this->actionFunc = EnKitan_WaitForPlayer;
|
||||
this->actor.flags |= ACTOR_FLAG_TARGETABLE;
|
||||
this->timer = 600;
|
||||
}
|
||||
|
||||
void EnKitan_WaitToAppear(EnKitan* this, PlayState* play) {
|
||||
if (this->timer > 0) {
|
||||
this->timer--;
|
||||
return;
|
||||
}
|
||||
EnKitan_SpawnEffects(this, play, 30);
|
||||
Actor_PlaySfx(&this->actor, NA_SE_EN_NPC_APPEAR);
|
||||
this->actor.draw = EnKitan_Draw;
|
||||
this->actionFunc = EnKitan_Appear;
|
||||
this->timer = 20;
|
||||
this->actor.shape.rot.y = this->actor.yawTowardsPlayer;
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||
}
|
||||
|
||||
void EnKitan_Update(Actor* thisx, PlayState* play) {
|
||||
EnKitan* this = THIS;
|
||||
|
||||
if (this->actor.draw != NULL) {
|
||||
CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
|
||||
}
|
||||
Actor_MoveWithGravity(&this->actor);
|
||||
Actor_UpdateBgCheckInfo(play, &this->actor, 40.0f, 25.0f, 40.0f, UPDBGCHECKINFO_FLAG_1 | UPDBGCHECKINFO_FLAG_4);
|
||||
|
||||
// Face the player
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0x1000, 0x200);
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||
|
||||
this->actionFunc(this, play);
|
||||
}
|
||||
|
||||
s32 EnKitan_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void EnKitan_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
|
||||
static Vec3f sFocusOffset = { 0.0f, 0.0f, 0.0f };
|
||||
EnKitan* this = THIS;
|
||||
|
||||
if (limbIndex == KEATON_LIMB_RIGHT_SHOULDER) {
|
||||
Matrix_MultVec3f(&sFocusOffset, &this->actor.focus.pos);
|
||||
}
|
||||
}
|
||||
|
||||
void EnKitan_Draw(Actor* thisx, PlayState* play) {
|
||||
EnKitan* this = THIS;
|
||||
|
||||
Gfx_SetupDL37_Opa(play->state.gfxCtx);
|
||||
SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
|
||||
EnKitan_OverrideLimbDraw, EnKitan_PostLimbDraw, &this->actor);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#define Z_EN_KITAN_H
|
||||
|
||||
#include "global.h"
|
||||
#include "objects/object_kitan/object_kitan.h"
|
||||
|
||||
#define ENKITAN_GET_COLLECT_FLAG(thisx) (((thisx)->params & 0xFE00) >> 9)
|
||||
|
||||
struct EnKitan;
|
||||
|
||||
|
@ -9,7 +12,13 @@ typedef void (*EnKitanActionFunc)(struct EnKitan*, PlayState*);
|
|||
|
||||
typedef struct EnKitan {
|
||||
/* 0x000 */ Actor actor;
|
||||
/* 0x144 */ char unk_144[0x194];
|
||||
/* 0x144 */ SkelAnime skelAnime;
|
||||
/* 0x188 */ Vec3s jointTable[KEATON_LIMB_MAX];
|
||||
/* 0x206 */ Vec3s morphTable[KEATON_LIMB_MAX];
|
||||
/* 0x284 */ ColliderCylinder collider;
|
||||
/* 0x2D0 */ s32 textBitSet;
|
||||
/* 0x2D4 */ UNK_TYPE1 unk2D4[2];
|
||||
/* 0x2D6 */ s16 timer;
|
||||
/* 0x2D8 */ EnKitanActionFunc actionFunc;
|
||||
} EnKitan; // size = 0x2DC
|
||||
|
||||
|
|
|
@ -16632,21 +16632,21 @@
|
|||
0x80C08FEC:("ObjMilkBin_Draw",),
|
||||
0x80C090D0:("EnKitan_Init",),
|
||||
0x80C09210:("EnKitan_Destroy",),
|
||||
0x80C0923C:("func_80C0923C",),
|
||||
0x80C09390:("func_80C09390",),
|
||||
0x80C09418:("func_80C09418",),
|
||||
0x80C094A8:("func_80C094A8",),
|
||||
0x80C09518:("func_80C09518",),
|
||||
0x80C095C8:("func_80C095C8",),
|
||||
0x80C09648:("func_80C09648",),
|
||||
0x80C09708:("func_80C09708",),
|
||||
0x80C09990:("func_80C09990",),
|
||||
0x80C09AA4:("func_80C09AA4",),
|
||||
0x80C09B50:("func_80C09B50",),
|
||||
0x80C0923C:("EnKitan_SpawnEffects",),
|
||||
0x80C09390:("EnKitan_CanTalk",),
|
||||
0x80C09418:("EnKitan_GetQuestionMessageId",),
|
||||
0x80C094A8:("EnKitan_Leave",),
|
||||
0x80C09518:("EnKitan_TalkAfterGivingPrize",),
|
||||
0x80C095C8:("EnKitan_WaitForPrizeTextboxClosed",),
|
||||
0x80C09648:("EnKitan_OfferPrize",),
|
||||
0x80C09708:("EnKitan_Talk",),
|
||||
0x80C09990:("EnKitan_WaitForPlayer",),
|
||||
0x80C09AA4:("EnKitan_Appear",),
|
||||
0x80C09B50:("EnKitan_WaitToAppear",),
|
||||
0x80C09BC8:("EnKitan_Update",),
|
||||
0x80C09C74:("func_80C09C74",),
|
||||
0x80C09C90:("func_80C09C90",),
|
||||
0x80C09CD0:("func_80C09CD0",),
|
||||
0x80C09C74:("EnKitan_OverrideLimbDraw",),
|
||||
0x80C09C90:("EnKitan_PostLimbDraw",),
|
||||
0x80C09CD0:("EnKitan_Draw",),
|
||||
0x80C09ED0:("func_80C09ED0",),
|
||||
0x80C09FEC:("BgAstrBombwall_Init",),
|
||||
0x80C0A0EC:("BgAstrBombwall_Destroy",),
|
||||
|
|
Loading…
Reference in New Issue