Shipwright/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c

384 lines
13 KiB
C

/*
* File: z_en_mk.c
* Overlay: ovl_En_Mk
* Description: Lakeside Professor
*/
#include "z_en_mk.h"
#include "objects/object_mk/object_mk.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
void EnMk_Init(Actor* thisx, GlobalContext* globalCtx);
void EnMk_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnMk_Update(Actor* thisx, GlobalContext* globalCtx);
void EnMk_Draw(Actor* thisx, GlobalContext* globalCtx);
void EnMk_Wait(EnMk* this, GlobalContext* globalCtx);
const ActorInit En_Mk_InitVars = {
ACTOR_EN_MK,
ACTORCAT_NPC,
FLAGS,
OBJECT_MK,
sizeof(EnMk),
(ActorFunc)EnMk_Init,
(ActorFunc)EnMk_Destroy,
(ActorFunc)EnMk_Update,
(ActorFunc)EnMk_Draw,
NULL,
};
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 },
{ 0xFFCFFFFF, 0x00, 0x00 },
TOUCH_NONE,
BUMP_ON,
OCELEM_ON,
},
{ 30, 40, 0, { 0, 0, 0 } },
};
void EnMk_Init(Actor* thisx, GlobalContext* globalCtx) {
EnMk* this = (EnMk*)thisx;
s32 swimFlag;
this->actor.minVelocityY = -4.0f;
this->actor.gravity = -1.0f;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 36.0f);
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_mk_Skel_005DF0, &object_mk_Anim_000D88, this->jointTable,
this->morphTable, 13);
Animation_PlayLoop(&this->skelAnime, &object_mk_Anim_000D88);
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
this->actor.colChkInfo.mass = 0xFF;
Actor_SetScale(&this->actor, 0.01f);
this->actionFunc = EnMk_Wait;
this->flags = 0;
this->swimFlag = 0;
this->actor.targetMode = 6;
if (gSaveContext.itemGetInf[1] & 1) {
this->flags |= 4;
}
}
void EnMk_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnMk* this = (EnMk*)thisx;
Collider_DestroyCylinder(globalCtx, &this->collider);
}
void func_80AACA40(EnMk* this, GlobalContext* globalCtx) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
this->actor.flags &= ~ACTOR_FLAG_16;
this->actionFunc = EnMk_Wait;
}
this->flags |= 1;
}
void func_80AACA94(EnMk* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx) != 0) {
this->actor.parent = NULL;
this->actionFunc = func_80AACA40;
func_80088AA0(240);
gSaveContext.eventInf[1] &= ~1;
} else {
func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f);
}
}
void func_80AACB14(EnMk* this, GlobalContext* globalCtx) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
this->actionFunc = func_80AACA94;
func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f);
}
}
void func_80AACB6C(EnMk* this, GlobalContext* globalCtx) {
if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
this->actionFunc = func_80AACB14;
}
this->flags |= 1;
}
void func_80AACBAC(EnMk* this, GlobalContext* globalCtx) {
if (this->timer > 0) {
this->timer--;
this->actor.shape.rot.y -= 0x800;
} else {
this->actionFunc = func_80AACB6C;
Message_ContinueTextbox(globalCtx, 0x4030);
}
}
void func_80AACC04(EnMk* this, GlobalContext* globalCtx) {
if (this->timer > 0) {
this->timer--;
} else {
this->timer = 16;
this->actionFunc = func_80AACBAC;
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
this->flags &= ~2;
}
}
void func_80AACCA0(EnMk* this, GlobalContext* globalCtx) {
if (this->timer > 0) {
this->timer--;
this->actor.shape.rot.y += 0x800;
} else {
this->timer = 120;
this->actionFunc = func_80AACC04;
Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f);
this->flags &= ~2;
}
}
void func_80AACD48(EnMk* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) {
Message_CloseTextbox(globalCtx);
this->actionFunc = func_80AACCA0;
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
player->exchangeItemId = EXCH_ITEM_NONE;
this->timer = 16;
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
this->flags &= ~2;
}
this->flags |= 1;
}
void func_80AACE2C(EnMk* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) {
Message_ContinueTextbox(globalCtx, 0x4001);
Animation_Change(&this->skelAnime, &object_mk_Anim_000AC0, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000AC0), ANIMMODE_ONCE, -4.0f);
this->flags &= ~2;
this->actionFunc = func_80AACD48;
}
this->flags |= 1;
}
void func_80AACEE8(EnMk* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) {
Message_ContinueTextbox(globalCtx, 0x4000);
Animation_Change(&this->skelAnime, &object_mk_Anim_000AC0, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000AC0), ANIMMODE_LOOP, -4.0f);
this->flags &= ~2;
this->actionFunc = func_80AACE2C;
}
this->flags |= 1;
}
void func_80AACFA0(EnMk* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx)) {
this->actor.parent = NULL;
this->actionFunc = func_80AACA40;
gSaveContext.itemGetInf[1] |= 1;
} else {
// not sure when/how/if this is getting called
if (!gSaveContext.n64ddFlag) {
func_8002F434(&this->actor, globalCtx, GI_HEART_PIECE, 10000.0f, 50.0f);
} else {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 10000.0f, 50.0f);
}
}
}
void func_80AAD014(EnMk* this, GlobalContext* globalCtx) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
this->actionFunc = func_80AACFA0;
if (!gSaveContext.n64ddFlag) {
func_8002F434(&this->actor, globalCtx, GI_HEART_PIECE, 10000.0f, 50.0f);
} else {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 10000.0f, 50.0f);
}
}
this->flags |= 1;
}
void EnMk_Wait(EnMk* this, GlobalContext* globalCtx) {
s16 angle;
s32 swimFlag;
Player* player = GET_PLAYER(globalCtx);
s32 playerExchangeItem;
if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
playerExchangeItem = func_8002F368(globalCtx);
if (this->actor.textId != 0x4018) {
player->actor.textId = this->actor.textId;
this->actionFunc = func_80AACA40;
} else {
if (INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS) {
player->actor.textId = 0x4032;
this->actionFunc = func_80AACA40;
} else {
switch (playerExchangeItem) {
case EXCH_ITEM_NONE:
if (this->swimFlag >= 8) {
if (gSaveContext.itemGetInf[1] & 1) {
player->actor.textId = 0x4075;
this->actionFunc = func_80AACA40;
} else {
player->actor.textId = 0x4074;
this->actionFunc = func_80AAD014;
this->swimFlag = 0;
}
} else {
if (this->swimFlag == 0) {
player->actor.textId = 0x4018;
this->actionFunc = func_80AACA40;
} else {
player->actor.textId = 0x406C + this->swimFlag;
this->actionFunc = func_80AACA40;
}
}
break;
case EXCH_ITEM_FROG:
player->actor.textId = 0x4019;
this->actionFunc = func_80AACEE8;
Animation_Change(&this->skelAnime, &object_mk_Anim_000368, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000368), ANIMMODE_ONCE, -4.0f);
this->flags &= ~2;
gSaveContext.timer2State = 0;
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
break;
default:
player->actor.textId = 0x4018;
this->actionFunc = func_80AACA40;
break;
}
}
}
} else {
this->actor.textId = Text_GetFaceReaction(globalCtx, 0x1A);
if (this->actor.textId == 0) {
this->actor.textId = 0x4018;
}
angle = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
if ((ABS(angle) < 0x2151) && (this->actor.xzDistToPlayer < 100.0f)) {
func_8002F298(&this->actor, globalCtx, 100.0f, EXCH_ITEM_FROG);
this->flags |= 1;
}
}
}
void EnMk_Update(Actor* thisx, GlobalContext* globalCtx) {
EnMk* this = (EnMk*)thisx;
s32 pad;
Vec3s vec;
Player* player;
s16 swimFlag;
Collider_UpdateCylinder(&this->actor, &this->collider);
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
Actor_MoveForward(&this->actor);
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
if ((!(this->flags & 2)) && (SkelAnime_Update(&this->skelAnime))) {
this->flags |= 2;
}
this->actionFunc(this, globalCtx);
if (this->flags & 1) {
func_80038290(globalCtx, &this->actor, &this->headRotation, &vec, this->actor.focus.pos);
} else {
Math_SmoothStepToS(&this->headRotation.x, 0, 6, 6200, 100);
Math_SmoothStepToS(&this->headRotation.y, 0, 6, 6200, 100);
}
player = GET_PLAYER(globalCtx);
if (this->flags & 8) {
if (!(player->stateFlags2 & 0x400)) {
this->flags &= ~8;
}
} else {
if (player->currentBoots == PLAYER_BOOTS_IRON) {
this->flags |= 8;
} else if (player->stateFlags2 & 0x400) {
swimFlag = player->actor.yDistToWater;
if (swimFlag > 0) {
if (swimFlag >= 320) {
if (swimFlag >= 355) {
swimFlag = 8;
} else {
swimFlag = 7;
}
} else if (swimFlag < 80) {
swimFlag = 1;
} else {
swimFlag *= 0.025f;
}
if (this->swimFlag < swimFlag) {
this->swimFlag = swimFlag;
if ((!(this->flags & 4)) && (this->swimFlag >= 8)) {
this->flags |= 4;
func_80078884(NA_SE_SY_CORRECT_CHIME);
}
}
}
}
}
}
s32 EnMk_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
EnMk* this = (EnMk*)thisx;
if (limbIndex == 11) {
rot->y -= this->headRotation.y;
rot->z += this->headRotation.x;
}
return false;
}
void EnMk_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
static Vec3f D_80AAD64C = { 1000.0f, -100.0f, 0.0f };
EnMk* this = (EnMk*)thisx;
if (limbIndex == 11) {
Matrix_MultVec3f(&D_80AAD64C, &this->actor.focus.pos);
}
}
void EnMk_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnMk* this = (EnMk*)thisx;
func_800943C8(globalCtx->state.gfxCtx);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
EnMk_OverrideLimbDraw, EnMk_PostLimbDraw, &this->actor);
}