diff --git a/configure.py b/configure.py index 0ee80044..be01b892 100644 --- a/configure.py +++ b/configure.py @@ -468,7 +468,7 @@ def Rel(lib_name: str, objects: List[Object]) -> Dict[str, Any]: Object(Matching, "SB/Game/zNPCTypeTest.cpp"), Object(NonMatching, "SB/Game/zNPCTypeSubBoss.cpp"), Object(NonMatching, "SB/Game/zNPCTypeBoss.cpp"), - Object(NonMatching, "SB/Game/zNPCGoalVillager.cpp"), + Object(NonMatching, "SB/Game/zNPCGoalVillager.cpp", extra_cflags=["-sym on"]), Object(Matching, "SB/Game/zNPCGoalSubBoss.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Core/x/xShadowSimple.cpp"), Object(NonMatching, "SB/Core/x/xUpdateCull.cpp"), diff --git a/src/SB/Game/zEntPlayer.h b/src/SB/Game/zEntPlayer.h index c475a5e5..b0777d78 100644 --- a/src/SB/Game/zEntPlayer.h +++ b/src/SB/Game/zEntPlayer.h @@ -388,6 +388,7 @@ void zEntPlayer_ShadowModelDisable(); void zEntPlayerJumpStart(class xEnt* ent, class zJumpParam* jump); void zEntPlayer_setBoulderMode(U32 mode); +void zEntPlayer_GiveHealth(S32); void zEntPlayer_GiveSpatula(S32); void zEntPlayer_GivePatsSocksCurrentLevel(S32 quantity); diff --git a/src/SB/Game/zNPCGoalStd.h b/src/SB/Game/zNPCGoalStd.h index 3658dadf..0f52b90c 100644 --- a/src/SB/Game/zNPCGoalStd.h +++ b/src/SB/Game/zNPCGoalStd.h @@ -75,8 +75,15 @@ struct zNPCGoalLoopAnim : zNPCGoalCommon U32 origAnimFlags; U32 animWeMolested; - // void* __ct(S32 myType); + zNPCGoalLoopAnim(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags(1 << 1); + } + void LoopCountSet(S32 unk); // return type might be wrong + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; struct zNPCGoalTaunt : zNPCGoalLoopAnim @@ -194,8 +201,13 @@ struct zNPCGoalPushAnim : zNPCGoalCommon S32 flg_pushanim; F32 lastAnimTime; - // void* __ct(S32 myType); - S32 Enter(F32 dt, void* updCtxt); + zNPCGoalPushAnim(S32 myType) : zNPCGoalCommon(myType) + { + SetFlags((1 << 2) | (1 << 1)); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; struct zNPCGoalAttackFodder; diff --git a/src/SB/Game/zNPCGoalVillager.cpp b/src/SB/Game/zNPCGoalVillager.cpp index a3901afb..7d546c6f 100644 --- a/src/SB/Game/zNPCGoalVillager.cpp +++ b/src/SB/Game/zNPCGoalVillager.cpp @@ -1,9 +1,91 @@ #include +#include "xMath.h" +#include "xutil.h" +#include "zEntPickup.h" +#include "zGameExtras.h" #include "zGlobals.h" #include "zNPCGoalVillager.h" +#include "zNPCTypeVillager.h" +#include "zNPCGoals.h" +#include "zGoo.h" +#include "zSurface.h" -extern zGlobals globals; +xFactoryInst* GOALCreate_Villager(S32 who, RyzMemGrow* grow, void*) +{ + xGoal* goal = NULL; + + switch (who) + { + case NPC_GOAL_PLAYERNEAR: + goal = new (who, grow) zNPCGoalPlayerNear(who); + break; + case NPC_GOAL_TALK: + goal = new (who, grow) zNPCGoalTalk(who); + break; + case NPC_GOAL_CHATTER: + goal = new (who, grow) zNPCGoalChatter(who); + break; + case NPC_GOAL_SPEAK: + goal = new (who, grow) zNPCGoalSpeak(who); + break; + case NPC_GOAL_CHEER: + goal = new (who, grow) zNPCGoalCheer(who); + break; + case NPC_GOAL_HURT: + goal = new (who, grow) zNPCGoalHurt(who); + break; + case NPC_GOAL_BALLOON: + goal = new (who, grow) zNPCGoalBalloon(who); + break; + case NPC_GOAL_BOYRIDE: + goal = new (who, grow) zNPCGoalBoyRide(who); + break; + case NPC_GOAL_BOYFALL: + goal = new (who, grow) zNPCGoalBoyFall(who); + break; + case NPC_GOAL_BOYWEEP: + goal = new (who, grow) zNPCGoalBoyWeep(who); + break; + case NPC_GOAL_BOYSWIM: + goal = new (who, grow) zNPCGoalBoySwim(who); + break; + default: + xUtil_idtag2string(who, 0); + break; + } + + return goal; +} + +S32 zNPCGoalPlayerNear::NPCMessage(NPCMsg* mail) +{ + S32 handled = 0; + + switch (mail->msgid) + { + case NPC_MID_TALKSTART: + if (stat == GOAL_STAT_PROCESS) + { + handled = 1; + flg_plyrnear |= (1 << 0); + } + break; + } + + return handled; +} + +void zNPCGoalPlayerNear::ChkCheatMedic() +{ + static S32 cnt_nextMedic = 0; + cnt_nextMedic--; + if (cnt_nextMedic <= 0) + { + cnt_nextMedic = (S32)(5.0f * xurand()) + 5; + zEntPlayer_GiveHealth(1); + } +} void zNPCGoalPlayerNear::DoCheatPanHandle() { @@ -12,3 +94,454 @@ void zNPCGoalPlayerNear::DoCheatPanHandle() globals.player.Inv_Shiny -= 500; } } + +void zNPCGoalPlayerNear::ChkCheatDogTrix(S32* goal, en_trantype* trantype) +{ + // clang-format off + static U32 hashes_sc[] = { + xStrHash("LassoSwing"), + xStrHash("SlipIdle01"), + xStrHash("LCopter01"), + xStrHash("LCopterHeadUp01"), + xStrHash("TailSlide01"), + xStrHash("TailSlideJumpStart01"), + xStrHash("TailSlideJumpApex01"), + xStrHash("TailSlideFall01"), + xStrHash("TailSlideLand01"), + xStrHash("TailSlideDJumpApex01"), + }; + + static U32 hashes_ss[] = { + xStrHash("DJumpStart01"), + xStrHash("DJumpApex01"), + xStrHash("BBounceStrike01"), + 0, + 0, + }; + + static U32 hashes_pa[] = { + xStrHash("DJumpStart01"), + xStrHash("DJumpApex01"), + xStrHash("StunLand"), + }; + // clang-format on + + U32 id = globals.player.ent.model->Anim->Single->State->ID; + S32 match = 0; + if (gCurrentPlayer == eCurrentPlayerSpongeBob) + { + for (U32 i = 0; i < 5; i++) + { + if (id == hashes_ss[i]) + { + match = 1; + break; + } + } + } + else if (gCurrentPlayer == eCurrentPlayerPatrick) + { + for (U32 i = 0; i < 3; i++) + { + if (id == hashes_pa[i]) + { + match = 1; + break; + } + } + } + else if (gCurrentPlayer == eCurrentPlayerSandy) + { + for (U32 i = 0; i < 10; i++) + { + if (id == hashes_sc[i]) + { + match = 1; + break; + } + } + } + + if (match != 0) + { + static const U32 shinies[] = { 4, 3, 2, 1, 4 }; + + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + zEntPickup_SpawnNRewards((U32*)shinies, 5, npc->Center()); + *goal = NPC_GOAL_CHEER; + *trantype = GOAL_TRAN_PUSH; + } +} + +S32 zNPCGoalTalk::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + + sfx_curTalk = NULL; + aid_curSound = 0; + killAndExit = 0; + stopTalking = 0; + StartSFX(sfx_curTalk); + + if (npc->converse == NULL) + { + npc->FindMyConverse(); + } + if (npc->converse != NULL) + { + npc->hithere.npc = npc; + npc->converse->set_callback(&npc->hithere); + npc->converse->start_talk(npc); + } + npc->WonderOfTalking(1, NULL); + tmr_minTalk = 0.25f; + + xVec3Copy(&pos_maintain, xEntGetPos(npc)); + + tmr_cycleAnim = 5.0f * (0.25f * (xurand() - 0.5f)) + 5.0f; + + npc->pflags &= (U8) ~(1 << 2); + + npc->VelStop(); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalTalk::Exit(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->WonderOfTalking(0, NULL); + npc->RestoreColFlags(); + + return xGoal::Enter(dt, updCtxt); +} + +S32 zNPCGoalTalk::NPCMessage(NPCMsg* mail) +{ + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_DAMAGE: + break; + case NPC_MID_TALKON: + killAndExit = 0; + stopTalking = 0; + break; + case NPC_MID_TALKOFF: + killAndExit = 1; + break; + default: + handled = 0; + break; + } + + return handled; +} + +void zNPCGoalTalk::StartSFX(xSFX* sfx) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + + U32 sid = 0; + if (sfx != NULL && sfx_curTalk != NULL) + { + npc->SndPlayFromSFX(sfx, &sid); + } +} + +S32 zNPCGoalSpeak::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->WonderOfTalking(1, NULL); + xVec3Copy(&pos_maintain, xEntGetPos(npc)); + tmr_cycleAnim = 5.0f * (0.25f * (xurand() - 0.5f)) + 5.0f; + npc->pflags &= (U8) ~(1 << 2); + npc->VelStop(); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalSpeak::Exit(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->WonderOfTalking(0, NULL); + npc->RestoreColFlags(); + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalSpeak::NPCMessage(NPCMsg* mail) +{ + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_SYSEVENT: + if (mail->sysevent.toEvent == eEventNPCSetActiveOff) + { + handled = 0; + } + break; + default: + handled = 1; + break; + } + + return handled; +} + +S32 zNPCGoalCheer::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->SndPlayRandom(NPC_STYP_CHEERING); + + return zNPCGoalLoopAnim::Enter(dt, updCtxt); +} + +// Equivalent: regalloc +S32 zNPCGoalCheer::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + xVec3 *npc_pos, *player_pos; + + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + xVec3 dir_plyr = {}; + npc_pos = xEntGetPos(npc); + player_pos = xEntGetPos(&globals.player.ent); + xVec3Sub(&dir_plyr, player_pos, npc_pos); + F32 distance = xVec3Length(&dir_plyr); + + if (distance > 0.25f) + { + xVec3SMulBy(&dir_plyr, 1.0f / distance); + npc->TurnToFace(dt, &dir_plyr, -1.0f); + } + + npc->VelStop(); + + return zNPCGoalLoopAnim::Process(trantype, dt, updCtxt, scene); +} + +S32 zNPCGoalHurt::Enter(F32 dt, void* updCtxt) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->SndPlayRandom(NPC_STYP_EXCLAIM); + + ChkRewardCheat(); + + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalHurt::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + npc->VelStop(); + + return zNPCGoalPushAnim::Process(trantype, dt, updCtxt, scene); +} + +void zNPCGoalHurt::ChkRewardCheat() +{ + static const U32 shinies[] = { 4, 2, 1 }; + + if (zGameExtras_CheatFlags() & (1 << 20)) + { + zNPCVillager* npc = (zNPCVillager*)psyche->clt_owner; + zEntPickup_SpawnNRewards((U32*)shinies, 3, npc->Center()); + } +} + +S32 zNPCGoalBalloon::Enter(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->specialBalloon = 1; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBalloon::Exit(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->specialBalloon = 0; + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBalloon::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + + S32 nextgoal; + if (npc->plat_balloons != NULL) + { + *trantype = GOAL_TRAN_PUSH; + nextgoal = NPC_GOAL_BOYRIDE; + } + else + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOYFALL; + } + + // This is always true + if (*trantype != GOAL_TRAN_NONE) + { + return nextgoal; + } + + if (nextgoal != 0) + { + return nextgoal; + } + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +S32 zNPCGoalBalloon::NPCMessage(NPCMsg* mail) +{ + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_SYSEVENT: + if (mail->sysevent.toEvent != eEventNPCSpecial_PlatformFall && + mail->sysevent.toEvent != eEventNPCSpecial_PlatformSnap) + { + handled = 0; + } + break; + case NPC_MID_DAMAGE: + handled = 1; + break; + default: + handled = 0; + break; + } + + return handled; +} + +S32 zNPCGoalBoyRide::Enter(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->flags2.flg_colCheck = 0; + npc->flags2.flg_penCheck = 0; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBoyRide::Exit(F32 dt, void* updCtxt) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->RestoreColFlags(); + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBoyRide::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + S32 nextgoal = 0; + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + if (npc->plat_balloons == NULL) + { + *trantype = GOAL_TRAN_SWAP; + nextgoal = NPC_GOAL_BOYFALL; + } + + if (nextgoal != 0) + { + return nextgoal; + } + + xVec3Copy(&npc->frame->mat.pos, xEntGetPos(npc->plat_balloons)); + xMat3x3Copy((xMat3x3*)&npc->frame->mat, (xMat3x3*)npc->plat_balloons->model->Mat); + + npc->frame->mode |= 0x41; + + npc->PlatAnimSync(); + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +S32 zNPCGoalBoyRide::NPCMessage(NPCMsg* mail) +{ + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + S32 handled = 1; + + switch (mail->msgid) + { + case NPC_MID_SYSEVENT: + if (mail->sysevent.toEvent == eEventNPCSpecial_PlatformFall) + { + npc->plat_balloons = NULL; + } + else + { + handled = 0; + } + break; + case NPC_MID_DAMAGE: + DoAutoAnim(NPC_GSPOT_ALTA, 0); + npc->PlatAnimSet(BBOY_PLATANIM_HIT); + break; + default: + handled = 0; + break; + } + + return handled; +} + +// Equivalent(???) +S32 zNPCGoalBoyFall::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene) +{ + S32 nextgoal = 0; + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + + if (hitGround != 0) + { + xAnimState* anim_state = npc->AnimCurState(); + if (npc->AnimTimeRemain(anim_state) < dt + 0.001f) + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOYWEEP; + } + else if (anim_state->ID != anid_played) + { + *trantype = GOAL_TRAN_SET; + nextgoal = NPC_GOAL_BOYWEEP; + } + } + + if (nextgoal != 0) + { + return nextgoal; + } + + F32 fVar2 = -(dt * 10.0f - npc->frame->vel.y); + npc->frame->vel.y = (fVar2 > -4.0f) ? fVar2 : -4.0f; + + npc->colFreq = (npc->colFreq < 0) ? npc->colFreq : 0; + + return xGoal::Process(trantype, dt, updCtxt, NULL); +} + +S32 zNPCGoalBoyWeep::Enter(F32 dt, void* updCtxt) +{ + tmr_weep = 300.0f * (0.25f * (xurand() - 0.5f)) + 300.0f; + ang_spinrate = 0.0f; + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +// Equivalent: branching weirdness +S32 zNPCGoalBoyWeep::NPCMessage(NPCMsg* mail) +{ + if (mail->msgid == NPC_MID_DAMAGE && mail->infotype == NPC_MDAT_DAMAGE && + mail->dmgdata.dmg_type == DMGTYP_SIDE) + { + ang_spinrate += 16.0f; + zNPCBalloonBoy* npc = (zNPCBalloonBoy*)psyche->clt_owner; + npc->SndPlayRandom(NPC_STYP_EXCLAIM); + } + return 0; +} diff --git a/src/SB/Game/zNPCGoalVillager.h b/src/SB/Game/zNPCGoalVillager.h index 6ee24141..bbb0da4c 100644 --- a/src/SB/Game/zNPCGoalVillager.h +++ b/src/SB/Game/zNPCGoalVillager.h @@ -1,12 +1,170 @@ #ifndef ZNPCGOALVILLAGER_H #define ZNPCGOALVILLAGER_H +#include "xSFX.h" +#include "zNPCGlyph.h" #include "zNPCGoalCommon.h" +#include "zNPCGoalStd.h" -class zNPCGoalPlayerNear +struct zNPCGoalCheer : zNPCGoalLoopAnim { -public: + zNPCGoalCheer(S32 goalID) : zNPCGoalLoopAnim(goalID) + { + SetFlags(1 << 1); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +struct zNPCGoalHurt : zNPCGoalPushAnim +{ + zNPCGoalHurt(S32 goalID) : zNPCGoalPushAnim(goalID) + { + SetFlags(1 << 1); + } + + void ChkRewardCheat(); + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +// FIXME: Put this in somewhere. +struct NPCWidget; + +struct zNPCGoalPlayerNear : zNPCGoalCommon +{ + S32 flg_plyrnear; + NPCGlyph* talk_glyph; + NPCWidget* talk_font; + F32 tmr_actBored; + + zNPCGoalPlayerNear(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags((1 << 3) | (1 << 2)); + } + + void ChkCheatMedic(); void DoCheatPanHandle(); + void ChkCheatDogTrix(S32* goal, en_trantype* trantype); + + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalTalk : zNPCGoalCommon +{ + F32 tmr_cycleAnim; + F32 tmr_minTalk; + S32 stopTalking; + S32 killAndExit; + xSFX* sfx_curTalk; + U32 aid_curSound; + xVec3 pos_maintain; + void* jawdata; + F32 jawtime; + + zNPCGoalTalk(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } + + void StartSFX(xSFX* sfx); + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalChatter : zNPCGoalCommon +{ + U32 sid_played; + U32 playThisSound; + + zNPCGoalChatter(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } +}; + +struct zNPCGoalSpeak : zNPCGoalCommon +{ + F32 tmr_cycleAnim; + xVec3 pos_maintain; + void* jawdata; + F32 jawtime; + + zNPCGoalSpeak(S32 goalID) : zNPCGoalCommon(goalID) + { + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBalloon : zNPCGoalCommon +{ + zNPCGoalBalloon(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags((1 << 3) | (1 << 2)); + AddFlags(1 << 17); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBoyRide : zNPCGoalCommon +{ + zNPCGoalBoyRide(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBoyFall : zNPCGoalCommon +{ + S32 hitGround; + + zNPCGoalBoyFall(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + flg_npcgable |= (1 << 0); + } + + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual U8 CollReview(void*); +}; + +struct zNPCGoalBoyWeep : zNPCGoalCommon +{ + F32 tmr_weep; + F32 ang_spinrate; + + zNPCGoalBoyWeep(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 NPCMessage(NPCMsg* mail); +}; + +struct zNPCGoalBoySwim : zNPCGoalCommon +{ + zNPCGoalBoySwim(S32 goalID) : zNPCGoalCommon(goalID) + { + SetFlags(1 << 1); + } }; xFactoryInst* GOALCreate_Villager(S32 who, RyzMemGrow* grow, void*); diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 74dc4dfe..2fcaf4c5 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -7,6 +7,7 @@ #include "xEntDrive.h" #include "xBehaveMgr.h" #include "xEnt.h" +#include "xSFX.h" #include "zNPCSndTable.h" #include "zNPCSpawner.h" @@ -405,8 +406,10 @@ struct zNPCCommon : xNPCBasic void ModelScaleSet(F32 unk); void ModelScaleSet(const xVec3* vec); S32 AnimStart(U32 animID, S32 forceRestart); + xAnimState* AnimCurState(); U32 AnimCurStateID(); void GiveReward(); + S32 SndPlayFromSFX(xSFX* sfx, U32* sid_played); S32 SndPlayRandom(en_NPC_SOUND sndtype); S32 SndChanIsBusy(S32 flg_chan); S32 LassoUseGuides(S32 idx_grabmdl, S32 idx_holdmdl); diff --git a/src/SB/Game/zNPCTypeVillager.h b/src/SB/Game/zNPCTypeVillager.h index 3a6bbfa1..a86b76ba 100644 --- a/src/SB/Game/zNPCTypeVillager.h +++ b/src/SB/Game/zNPCTypeVillager.h @@ -22,6 +22,8 @@ struct zNPCVillager : zNPCCommon S32 current_talk_anim; zNPCVillager(S32 myType); + + void FindMyConverse(); U8 ColPenByFlags() const; U8 ColChkByFlags() const; F32 GenShadCacheRad(); @@ -43,6 +45,14 @@ struct zNPCBubbleBuddy : zNPCFish zNPCBubbleBuddy(S32 myType); }; +enum en_BBOY_PLATANIM +{ + BBOY_PLATANIM_MOVE, + BBOY_PLATANIM_HIT, + BBOY_PLATANIM_NOMORE, + BBOY_PLATANIM_FORCE = 0x7FFFFFFF, +}; + struct zNPCBalloonBoy : zNPCFish { S32 specialBalloon; @@ -50,6 +60,9 @@ struct zNPCBalloonBoy : zNPCFish xShadowCache* shadCache; zNPCBalloonBoy(S32 myType); + + void PlatAnimSet(en_BBOY_PLATANIM anim); + void PlatAnimSync(); }; struct zNPCSandyBikini : zNPCVillager diff --git a/src/SB/Game/zSurface.h b/src/SB/Game/zSurface.h index d2f5a3a5..68b11852 100644 --- a/src/SB/Game/zSurface.h +++ b/src/SB/Game/zSurface.h @@ -2,6 +2,7 @@ #define ZSURFACE_H #include "xBase.h" +#include "xCollide.h" #include "xMath3.h" #include "xSurface.h" @@ -121,7 +122,7 @@ struct xScene; void zSurfaceRegisterMapper(U32 assetId); void zSurfaceExit(); xSurface* zSurfaceGetSurface(U32 mat_id); -// xSurface* zSurfaceGetSurface(const xCollis* coll); +xSurface* zSurfaceGetSurface(const xCollis* coll); U32 zSurfaceGetStandOn(const xSurface* surf); void zSurfaceSave(xSurface* ent, xSerial* s); void zSurfaceLoad(xSurface* ent, xSerial* s);