diff --git a/src/SB/Core/x/xBehaviour.h b/src/SB/Core/x/xBehaviour.h index 95aab379..b878f651 100644 --- a/src/SB/Core/x/xBehaviour.h +++ b/src/SB/Core/x/xBehaviour.h @@ -129,8 +129,15 @@ struct xPsyche : RyzMemData void SetOwner(xBase*, void*); void KillBrain(xFactory*); void Lobotomy(xFactory*); - void SetSafety(S32); + void SetSafety(S32 goalID) + { + gid_safegoal = goalID; + } void Amnesia(S32); + void SetNotify(xPSYNote* notice) + { + cb_notice = notice; + } xBase* GetClient() { @@ -169,7 +176,11 @@ struct xGoal : xListItem, xFactoryInst xPsyche* GetPsyche() const; void SetCallbacks(xGoalProcessCallback process, xGoalChkRuleCallback chkRule, xGoalPreCalcCallback precalc, void* cbdata); - S32 GetFlags() const; + S32 GetFlags() const + { + return flg_able; + } + void SetPsyche(xPsyche* psyche); const char* Name(); void SetState(en_GOALSTATE state); diff --git a/src/SB/Game/zNPCHazard.h b/src/SB/Game/zNPCHazard.h index bb632898..4e7be300 100644 --- a/src/SB/Game/zNPCHazard.h +++ b/src/SB/Game/zNPCHazard.h @@ -24,6 +24,7 @@ struct UVAModelInfo void UVVelSet(float, float); S32 GetUV(RwTexCoords*& coords, S32& numVertices, RpAtomic* model); void SetColor(iColor_tag); + void Update(F32, xVec2*); }; struct NPCHazard; diff --git a/src/SB/Game/zNPCSupport.cpp b/src/SB/Game/zNPCSupport.cpp index 97931f71..69b44faf 100644 --- a/src/SB/Game/zNPCSupport.cpp +++ b/src/SB/Game/zNPCSupport.cpp @@ -6,6 +6,8 @@ #include "zNPCGlyph.h" #include "zNPCSupplement.h" +#include "xMathInlines.h" + void NPCSupport_Shutdown() { zNPCHazard_Shutdown(); @@ -21,3 +23,23 @@ void NPCWidget_Shutdown() void NPCWidget_ScenePrepare() { } + +F32 NPCC_TmrCycle(float* tmr, float dt, float interval) +{ + F32 parameterized; + + if (*tmr < 0.0f) + { + *tmr = 0.0f; + } + + parameterized = (*tmr / interval); + *tmr += dt; + + if (*tmr > interval) + { + *tmr = xfmod(*tmr,interval); + } + + return parameterized; +} \ No newline at end of file diff --git a/src/SB/Game/zNPCSupport.h b/src/SB/Game/zNPCSupport.h index 66fd3d6a..74199baa 100644 --- a/src/SB/Game/zNPCSupport.h +++ b/src/SB/Game/zNPCSupport.h @@ -42,6 +42,8 @@ struct NPCBlinker { F32 tmr_uvcell; S32 idx_uvcell; + + void Reset(); }; void NPCWidget_Shutdown(); @@ -53,6 +55,7 @@ void NPCSupport_SceneReset(); void NPCSupport_Shutdown(); void NPCSupport_ScenePostInit(); S32 NPCC_LampStatus(); +F32 NPCC_TmrCycle(float* tmr, float dt, float interval); xVec3* NPCC_rightDir(xEnt* ent); xVec3* NPCC_faceDir(xEnt* ent); void NPCC_ang_toXZDir(F32 angle, xVec3* dir); @@ -60,5 +63,6 @@ F32 NPCC_aimVary(xVec3* dir_aim, xVec3* pos_src, xVec3* pos_tgt, F32 dst_vary, S F32 NPCC_ds2_toCam(const xVec3* pos_from, xVec3* delta); void zNPC_SNDStop(_tageNPCSnd snd); void zNPC_SNDPlay3D(_tageNPCSnd snd, xEnt*); +RwRaster* NPCC_FindRWRaster(char*); #endif diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 09e4abe2..81b7e497 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -181,7 +181,7 @@ struct zNPCSettings : xDynAsset S8 allowDetect; U8 allowPatrol; U8 allowWander; - S8 reduceCollide; + U8 reduceCollide; S8 useNavSplines; S8 pad[3]; S8 allowChase; @@ -407,7 +407,9 @@ struct zNPCCommon : xNPCBasic void ModelScaleSet(F32 x, F32 y, F32 z); void ModelScaleSet(F32 unk); void ModelScaleSet(const xVec3* vec); + xModelInstance* ModelAtomicFind(int index, int idx_prev, xModelInstance* mdl_prev); xModelInstance* ModelAtomicHide(int index, xModelInstance* mdl); + xModelInstance* ModelAtomicShow(int index, xModelInstance* mdl); S32 AnimStart(U32 animID, S32 forceRestart); xAnimState* AnimFindState(U32 animID); xAnimState* AnimCurState(); diff --git a/src/SB/Game/zNPCTypeRobot.cpp b/src/SB/Game/zNPCTypeRobot.cpp index fa8499f5..c8d58edb 100644 --- a/src/SB/Game/zNPCTypeRobot.cpp +++ b/src/SB/Game/zNPCTypeRobot.cpp @@ -1,17 +1,17 @@ #include "zNPCTypeRobot.h" #include "zNPCSupplement.h" - +#include "zNPCSupport.h" #include "zNPCGoalRobo.h" #include "zNPCTypes.h" #include "zNPCGoalStd.h" +#include "zGlobals.h" +#include "zNPCGoals.h" #include "xFactory.h" #include "xMath.h" - #include "xAnim.h" #include -#include "zGlobals.h" extern UVAModelInfo g_uvaShield; extern S32 g_cnt_fodbzzt; @@ -42,7 +42,7 @@ extern NPCSndTrax g_sndTrax_Glove[]; extern F32 zNPCRobot_f_0_0; extern F32 zNPCRobot_f_1_0; -S32 rast_blink; // zNPCFodBomb +zNPCSlick* g_slick_slipfx_owner; char* g_strz_roboanim[41] = { @@ -107,10 +107,40 @@ char* g_strz_ttsanim[2] = "TarTar_Slosh01" }; +char* g_strz_flotanim[2] = +{ + "Unknown", + "Wiggle01" +}; + +U32 g_hash_flotanim[2]; +U32 g_hash_nytlytanim[2]; +U32 g_hash_ttsanim[2]; +U32 g_hash_cloudanim[3]; +U32 g_hash_shieldanim[2]; +U32 g_hash_roboanim[41]; + +char* g_strz_cloudanim[3]; + extern char stringBase[]; -void zNPCRobot_Timestep(F32 dt); -void zNPCSleepy_Timestep(F32 dt); +// Scheduling +void zNPCSleepy_Timestep(F32 dt) +{ + static S8 init; + static F32 tmr_cycle; + + if (init == 0) + { + init = 1; + tmr_cycle = 0.0f; + } + + F32 dVar1 = NPCC_TmrCycle(&tmr_cycle, 0.01666667f, 2.63f); + zNPCSleepy::hyt_NightLightCurrent = 4.0f; + zNPCSleepy::hyt_NightLightCurrent += (0.35f * isin(PI * dVar1)); +} + void zNPCFodBzzt_DoTheHokeyPokey(F32 dt); void ZNPC_Destroy_Robot(xFactoryInst* inst); @@ -150,7 +180,21 @@ void zNPCRobot_ScenePostInit() ROBO_PrepRoboCop(); } -void zNPCRobot_Timestep(float dt) +void zNPCRobot::LassoNotify(en_LASSO_EVENT event) +{ + if (!IsDead()) + { + zNPCCommon::LassoNotify(event); + switch (event) + { + case LASS_EVNT_GRABSTART: + psy_instinct->GoalSet(0x4e47525d, 0); // NPC_GOAL_LASSOGRAB?? + break; + } + } +} + +void zNPCRobot_Timestep(xScene* sc, float dt) { if (g_cnt_fodbzzt) { @@ -586,6 +630,11 @@ void zNPCRobot::ParseINI() NPCS_SndTablePrepare(g_sndTrax_Robot); } +void zNPCTubeSlave::Process(xScene* xscn, F32 dt) +{ + zNPCRobot::Process(xscn, dt); +} + void zNPCRobot::Process(xScene* xscn, F32 dt) { psy_instinct->Timestep(dt, NULL); @@ -642,6 +691,23 @@ void zNPCRobot::DuploOwner(zNPCCommon* duper) } } +void zNPCFodBzzt::DiscoReset() +{ + tmr_discoLight = -1.0f; +} + +void zNPCArfDog::BlinkReset() +{ + blinkHead.Reset(); + blinkTail.Reset(); + flg_xtrarend &= ~1; +} + +void zNPCTubelet::PainInTheBand() +{ + tmr_restoreHealth = 2.5f; +} + S32 zNPCRobot::LassoSetup() { S32 param1 = -1; @@ -679,6 +745,53 @@ void zNPCRobot::InflictPain(S32 numHitPoints, S32 giveCreditToPlayer) } } +F32 hyt_NightLightCurrent; + +void zNPCSleepy::NightLightPos(xVec3* vec) +{ + xVec3Copy(vec, Pos()); + vec->y += hyt_NightLightCurrent; +} + +void zNPCCritter::SelfSetup() +{ + zNPCRobot::SelfSetup(); + psy_instinct->SetSafety(NPC_GOAL_IDLE); +} + +void zNPCTubeSlave::DoLaserRendering() +{ + xGoal* goal; + if (tubespot == ROBO_TUBE_PAUL) + { + goal = psy_instinct->GetCurGoal(); + if (goal != NULL && (goal->GetID() == NPC_GOAL_TUBEATTACK)) + { + ((zNPCGoalTubeAttack*)(goal))->LaserRender(); + } + } +} + +void zNPCFodBzzt::Process(xScene* sc, F32 dt) +{ + zNPCRobot::Process(sc, dt); + if (g_needuvincr_bzzt != 0) + { + g_needuvincr_bzzt = 0; + laser.UVScrollUpdate(dt); + } +} + +S32 zNPCTubelet::Respawn(const xVec3* pos, zMovePoint* mvptFirst, zMovePoint* mvptSpawnRef) +{ + S32 rc = zNPCCommon::Respawn(pos, mvptFirst, mvptSpawnRef); + if (rc != 0) + { + PrepTheBand(); + } + return rc; +} + void zNPCFodder::ParseINI() { zNPCCommon::ParseINI(); @@ -769,6 +882,87 @@ void zNPCFodder::LassoModelIndex(S32* idxgrab, S32* idxhold) *idxhold = -1; } +void zNPCSlick::RopePopsShield() +{ + ShieldGeneratorDamaged(); + alf_shieldCurrent = 0.0f; + tmr_repairShield = 5.0f; +} + +bool zNPCSlick::IsShield() const +{ + return alf_shieldDesired == 100.0f/255.0f; +} + +void zNPCSlick::ShieldShow() +{ + alf_shieldDesired = 100.0f/255.0f; +} + +void zNPCSlick::ShieldHide() +{ + alf_shieldDesired = 0.0f; +} + +S32 zNPCTubeSlave::IsDying() +{ + return tub_pete->IsDying(); +} + +S32 zNPCTubelet::IsDying() +{ + return tubestat == TUBE_STAT_DEAD; +} + +zNPCSlick* zNPCSlick::YouOwnSlipFX() +{ + return g_slick_slipfx_owner = this; +} + +void zNPCArfDog::Setup() +{ + zNPCCommon::Setup(); + if (rast_blink == NULL) + { + rast_blink = NPCC_FindRWRaster(stringBase + 0x2e2); // "fx_fodbomb_blinker" + } +} + +void zNPCFodBomb::Setup() +{ + zNPCCommon::Setup(); + if (rast_blink == NULL) + { + rast_blink = NPCC_FindRWRaster(stringBase + 0x2e2); // "fx_fodbomb_blinker" + } +} + +void zNPCFodBomb::BlinkerReset() +{ + blinker.Reset(); + flg_xtrarend &= ~1; +} + +void zNPCSlick::ShieldFX(F32 dt) +{ + if (g_needuvincr_slickshield) + { + g_uvaShield.Update(dt, NULL); + g_needuvincr_slickshield = 0; + } +} + +S32 zNPCSleepy::RepelMissile(F32 dt) +{ + tmr_nextPatriot = MAX(-1.0f, tmr_nextPatriot - dt); + if (haz_patriot != NULL && !(tmr_nextPatriot < 0.0f)) + { + return 1; + } + haz_patriot = NULL; + return 0; +} + void ZNPC_AnimTable_RobotBase(xAnimTable*); void ZNPC_AnimTable_RobotBase(xAnimTable* table) @@ -1188,8 +1382,6 @@ xAnimTable* ZNPC_AnimTable_Tubelet() return pxVar1; } -char* g_strz_flotanim[2]; - xAnimTable* ZNPC_AnimTable_FloatDevice() { xAnimTable *pxVar1 = xAnimTableNew(stringBase + 0x2b3, NULL, 0); // "FloatDevice" @@ -1297,6 +1489,83 @@ void zNPCArfArf::Reset() } } +NPARMgmt* NPAR_PartySetup(en_nparptyp parType, void** userData, NPARXtraData* xtraData); + +void zNPCMonsoon::Init(xEntAsset* asset) +{ + zNPCRobot::Init(asset); + flg_move &= ~2; + flg_move |= 4; + flg_vuln &= 0x9fffffff; + idx_neckBone = -1; + NPAR_PartySetup(NPAR_TYP_MONSOONRAIN, NULL, NULL); +} + +void zNPCTubeSlave::Init(xEntAsset* asset) +{ + zNPCRobot::Init(asset); + flg_move &= 0xfffffffd; + flg_move |= 4; + + flg_vuln &= 0x8fffffff; + flg_vuln &= 0xfeffffff; + + idx_neckBone = -1; + tubespot = ROBO_TUBE_PAUL; + tub_pete = NULL; + + laser.Prepare(); + + xModelInstance* mdl = ModelAtomicFind(1, -1, NULL); + mdl->Flags &= 0xffdf; + mdl->Flags |= 8; +} + +void zNPCChomper::Init(xEntAsset* asset) +{ + zNPCRobot::Init(asset); + flg_move |= 0x10; + flg_vuln &= 0x9effffff; + idx_neckBone = -1; + NPAR_PartySetup(NPAR_TYP_DOGBREATH, NULL, NULL); +} + +void zNPCTubelet::Init(xEntAsset* asset) +{ + zNPCRobot::Init(asset); + + flg_move |= 2; + flg_vuln &= 0x9FFFFFFF; + idx_neckBone = -1; + + psynote.npc = this; + + NPAR_PartySetup(NPAR_TYP_TUBESPIRAL, NULL, NULL); + NPAR_PartySetup(NPAR_TYP_TUBECONFETTI, NULL, NULL); + + xModelInstance* iVar1 = zNPCCommon::ModelAtomicFind(1, -1, NULL); + + iVar1->Flags &= 0xffdf; + iVar1->Flags |= 8; +} + +void zNPCTubeSlave::WeGotAGig() +{ + PartyOn(); + psy_instinct->GoalSet(0x4e47524f, 1); +} + +void zNPCTubelet::Unbonk() +{ + ModelAtomicShow(0, NULL); + ModelAtomicHide(1, NULL); + ModelAtomicHide(4, NULL); + hitpoints = cfg_npc->pts_damage; + // Epilogue weirdness + pflags &= 0xdf; + bonkSpinRate = -1.0; +} + void zNPCTubeSlave::Reset() { zNPCRobot::Reset(); @@ -1304,8 +1573,6 @@ void zNPCTubeSlave::Reset() zNPCTubeSlave::WeGotAGig(); } -U32 g_hash_roboanim[41]; - U32 zNPCSleepy::AnimPick(int gid, en_NPC_GOAL_SPOT gspot, xGoal* rawgoal) { U32 uVar1 = 0; diff --git a/src/SB/Game/zNPCTypeRobot.h b/src/SB/Game/zNPCTypeRobot.h index 29851848..388709ba 100644 --- a/src/SB/Game/zNPCTypeRobot.h +++ b/src/SB/Game/zNPCTypeRobot.h @@ -46,6 +46,8 @@ struct NPCLaser void ColorSet(const RwRGBA*, const RwRGBA*); U32 TextureGet(); static void Render(xVec3&, xVec3&); + void UVScrollUpdate(F32); + void Prepare(); }; struct NPCBattle @@ -166,6 +168,8 @@ struct zNPCFodder : zNPCRobot struct zNPCFodBomb : zNPCRobot { + static RwRaster* rast_blink; + NPCBlinker blinker; zNPCFodBomb(S32 myType); @@ -173,11 +177,14 @@ struct zNPCFodBomb : zNPCRobot void Reset(); void Init(xEntAsset*); void ParseINI(); + void Setup(); + void BlinkerReset(); }; struct zNPCFodBzzt : zNPCRobot { volatile static S32 cnt_alerthokey; + static NPCLaser laser; RwRGBA rgba_discoLight; F32 tmr_discoLight; @@ -189,6 +196,7 @@ struct zNPCFodBzzt : zNPCRobot void Reset(); void DiscoReset(); void ParseINI(); + void Process(xScene* sc, F32 dt); }; struct zNPCChomper : zNPCRobot @@ -200,6 +208,7 @@ struct zNPCChomper : zNPCRobot zNPCLassoInfo* PRIV_GetLassoData(); void Reset(); void ParseINI(); + void Init(xEntAsset*); }; struct zNPCCritter : zNPCRobot @@ -208,6 +217,7 @@ struct zNPCCritter : zNPCRobot zNPCLassoInfo* PRIV_GetLassoData(); void Reset(); void Init(xEntAsset*); + void SelfSetup(); }; struct zNPCHammer : zNPCRobot @@ -239,11 +249,13 @@ struct zNPCMonsoon : zNPCRobot U8 FoulWeather(float); void Reset(); void ParseINI(); + void Init(xEntAsset* asset); }; struct zNPCSleepy : zNPCRobot { static S8 init; + volatile static F32 hyt_NightLightCurrent; S32 flg_sleepy; NPCHazard* haz_patriot; @@ -257,10 +269,14 @@ struct zNPCSleepy : zNPCRobot void Reset(); void ParseINI(); U32 AnimPick(int, en_NPC_GOAL_SPOT, xGoal*); + S32 RepelMissile(float); + void NightLightPos(xVec3*); }; struct zNPCArfDog : zNPCRobot { + static RwRaster* rast_blink; + NPCBlinker blinkHead; NPCBlinker blinkTail; @@ -270,6 +286,7 @@ struct zNPCArfDog : zNPCRobot void BlinkReset(); void Init(xEntAsset*); void ParseINI(); + void Setup(); }; struct zNPCArfArf : zNPCRobot @@ -388,6 +405,11 @@ struct zNPCTubelet : zNPCRobot void ParseINI(); void Reset(); S32 IsDying(); + void PainInTheBand(); + void PrepTheBand(); + S32 Respawn(const xVec3*, zMovePoint*, zMovePoint*); + void Init(xEntAsset* asset); + void Unbonk(); }; enum en_tubespot @@ -416,8 +438,15 @@ struct zNPCTubeSlave : zNPCRobot void Reset(); void WeGotAGig(); void ParseINI(); + S32 IsDying(); + void DoLaserRendering(); + void PartyOn(); + void Process(xScene* xscn, F32 dt); + void Init(xEntAsset* asset); }; +typedef struct zNPCSlick; + struct zNPCSlick : zNPCRobot { F32 rad_shield; @@ -428,7 +457,7 @@ struct zNPCSlick : zNPCRobot zNPCSlick(S32 myType); - void YouOwnSlipFX(); + zNPCSlick* YouOwnSlipFX(); void BUpdate(xVec3* pos); void RopePopsShield(); void ShieldUpdate(F32 dt); @@ -440,6 +469,11 @@ struct zNPCSlick : zNPCRobot void Reset(); void Init(xEntAsset* asset); void LassoModelIndex(S32* idxgrab, S32* idxhold); + void ShieldHide(); + void ShieldShow(); + void ShieldGeneratorDamaged(); + bool IsShield() const; + void ShieldFX(F32 dt); }; void ZNPC_Robot_Startup();