#pragma once #include #include #include #include #include #include #include #include #include "Runtime/CBasics.hpp" #include "Runtime/CRandom16.hpp" #include "Runtime/CSortedLists.hpp" #include "Runtime/CToken.hpp" #include "Runtime/rstl.hpp" #include "Runtime/Camera/CCameraFilter.hpp" #include "Runtime/Camera/CCameraManager.hpp" #include "Runtime/Camera/CCameraShakeData.hpp" #include "Runtime/GameObjectLists.hpp" #include "Runtime/Input/CFinalInput.hpp" #include "Runtime/Input/CRumbleManager.hpp" #include "Runtime/Weapon/CWeaponMgr.hpp" #include "Runtime/World/CActorModelParticles.hpp" #include "Runtime/World/CAi.hpp" #include "Runtime/World/CEnvFxManager.hpp" #include "Runtime/World/CFluidPlaneManager.hpp" #include "Runtime/World/ScriptLoader.hpp" #include "Runtime/World/ScriptObjectSupport.hpp" #include "Runtime/World/CScriptMazeNode.hpp" #include #include #include namespace metaforce { class CActor; class CActorModelParticles; class CDamageInfo; class CEnvFxManager; class CFluidPlaneManager; class CLight; class CMapWorldInfo; class CMaterialFilter; class CObjectList; class CPlayer; class CPlayerState; class CProjectedShadow; class CScriptMailbox; class CRumbleManager; class CSortedListManager; class CTexture; class CWorld; class CScriptLayerManager; class CWorldTransManager; struct CFinalInput; namespace MP1 { class CMFGameLoader; } struct SScriptObjectStream { // CEntity* x0_obj; EScriptObjectType x0_type; u32 x4_position; u32 x8_length; }; struct SOnScreenTex { CAssetId x0_id; zeus::CVector2i x4_origin; zeus::CVector2i xc_extent; }; enum class EStateManagerTransition { InGame, MapScreen, PauseGame, LogBook, SaveGame, MessageScreen }; enum class EThermalDrawFlag { Hot, Cold, Bypass }; class CStateManager { friend class MP1::CMFGameLoader; public: enum class EGameState { Running, SoftPaused, Paused }; private: s16 x0_nextFreeIndex = 0; std::array x4_idxArr{}; /* std::unique_ptr x80c_allObjs; std::unique_ptr x814_actorObjs; std::unique_ptr x81c_physActorObjs; std::unique_ptr x824_cameraObjs; std::unique_ptr x82c_lightObjs; std::unique_ptr x834_listenAiObjs; std::unique_ptr x83c_aiWaypointObjs; std::unique_ptr x844_platformAndDoorObjs; */ std::array, 8> x808_objLists{ std::make_unique(EGameObjectList::All), std::make_unique(), std::make_unique(), std::make_unique(), std::make_unique(), std::make_unique(), std::make_unique(), std::make_unique(), }; std::unique_ptr x84c_player; std::unique_ptr x850_world; /* Used to be a list of 32-element reserved_vectors */ std::vector x854_objectGraveyard; struct CStateManagerContainer { CCameraManager x0_cameraManager; CSortedListManager x3c0_sortedListManager; CWeaponMgr xe3d8_weaponManager; CFluidPlaneManager xe3ec_fluidPlaneManager; CEnvFxManager xe510_envFxManager; CActorModelParticles xf168_actorModelParticles; CRumbleManager xf250_rumbleManager; u32 xf344_ = 0; rstl::reserved_vector xf370_; rstl::reserved_vector xf39c_renderLast; }; std::unique_ptr x86c_stateManagerContainer; CCameraManager* x870_cameraManager = nullptr; CSortedListManager* x874_sortedListManager = nullptr; CWeaponMgr* x878_weaponManager = nullptr; CFluidPlaneManager* x87c_fluidPlaneManager = nullptr; CEnvFxManager* x880_envFxManager = nullptr; CActorModelParticles* x884_actorModelParticles = nullptr; CRumbleManager* x88c_rumbleManager = nullptr; std::multimap x890_scriptIdMap; std::map x8a4_loadedScriptObjects; std::shared_ptr x8b8_playerState; std::shared_ptr x8bc_mailbox; std::shared_ptr x8c0_mapWorldInfo; std::shared_ptr x8c4_worldTransManager; std::shared_ptr x8c8_worldLayerState; TAreaId x8cc_nextAreaId = 0; TAreaId x8d0_prevAreaId = kInvalidAreaId; // u32 x8d0_extFrameIdx = 0; u32 x8d4_inputFrameIdx = 0; u32 x8d8_updateFrameIdx = 0; u32 x8dc_objectDrawToken = 0; std::vector x8e0_dynamicLights; TLockedToken x8f0_shadowTex; /* DefaultShadow in MiscData */ CRandom16 x8fc_random; CRandom16* x900_activeRandom = nullptr; EGameState x904_gameState = EGameState::Running; rstl::reserved_vector x90c_loaderFuncs; enum class EInitPhase { LoadWorld, LoadFirstArea, Done } xb3c_initPhase = EInitPhase::LoadWorld; std::set xb40_uniqueInstanceNames; CFinalInput xb54_finalInput; static constexpr size_t numCameraPasses = 9; std::array xb84_camFilterPasses; // size: 0x2c std::array xd14_camBlurPasses; // size: 0x34 s32 xeec_hintIdx = -1; u32 xef0_hintPeriods = 0; SOnScreenTex xef4_pendingScreenTex; CAssetId xf08_pauseHudMessage; float xf0c_escapeTimer = 0.f; float xf10_escapeTotalTime = 0.f; float xf14_curTimeMod900 = 0.f; TUniqueId xf18_bossId = kInvalidUniqueId; float xf1c_totalBossEnergy = 0.f; u32 xf20_bossStringIdx = 0; float xf24_thermColdScale1 = 0.f; float xf28_thermColdScale2 = 0.f; zeus::CVector2f xf2c_viewportScale = {1.f, 1.f}; EThermalDrawFlag xf34_thermalFlag = EThermalDrawFlag::Bypass; TUniqueId xf38_skipCineSpecialFunc = kInvalidUniqueId; std::list xf3c_activeFlickerBats; std::list xf54_activeParasites; TUniqueId xf6c_playerActorHead = kInvalidUniqueId; std::unique_ptr xf70_currentMaze; TUniqueId xf74_lastTrigger = kInvalidUniqueId; TUniqueId xf76_lastRelay = kInvalidUniqueId; float xf78_hudMessageTime = 0.f; CProjectedShadow* xf7c_projectedShadow = nullptr; u32 xf80_hudMessageFrameCount = 0; s32 xf84_ = -1; CAssetId xf88_; float xf8c_ = 0.f; EStateManagerTransition xf90_deferredTransition = EStateManagerTransition::InGame; bool xf94_24_readyToRender : 1 = false; bool xf94_25_quitGame : 1 = false; bool xf94_26_generatingObject : 1 = false; bool xf94_27_inMapScreen : 1 = false; bool xf94_28_inSaveUI : 1 = false; bool xf94_29_cinematicPause : 1 = false; bool xf94_30_fullThreat : 1 = false; bool m_warping = false; std::map> m_incomingConnections; bool m_logScripting = false; std::optional> m_logScriptingReference; void UpdateThermalVisor(); static void RendererDrawCallback(void*, void*, int); public: CStateManager(const std::weak_ptr&, const std::weak_ptr&, const std::weak_ptr&, const std::weak_ptr&, const std::weak_ptr&); ~CStateManager(); u32 GetInputFrameIdx() const { return x8d4_inputFrameIdx; } bool RenderLast(TUniqueId); void AddDrawableActorPlane(CActor& actor, const zeus::CPlane&, const zeus::CAABox& aabb) const; void AddDrawableActor(CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const; bool SpecialSkipCinematic(); TAreaId GetVisAreaId() const; s32 GetWeaponIdCount(TUniqueId, EWeaponType) const; void RemoveWeaponId(TUniqueId, EWeaponType); void AddWeaponId(TUniqueId, EWeaponType); void UpdateEscapeSequenceTimer(float); float GetEscapeSequenceTimer() const { return xf0c_escapeTimer; } void ResetEscapeSequenceTimer(float); void SetupParticleHook(const CActor& actor) const; void MurderScriptInstanceNames(); std::string HashInstanceName(CInputStream& in); void SetActorAreaId(CActor& actor, TAreaId); void TouchSky() const; void TouchPlayerActor(); void DrawSpaceWarp(const zeus::CVector3f&, float) const; void DrawReflection(const zeus::CVector3f&); static void ReflectionDrawer(void*, const zeus::CVector3f&); void CacheReflection(); bool CanCreateProjectile(TUniqueId, EWeaponType, int) const; const std::vector& GetDynamicLightList() const { return x8e0_dynamicLights; } void BuildDynamicLightListForWorld(); void DrawDebugStuff() const; void RenderCamerasAndAreaLights(); void DrawE3DeathEffect(); void DrawAdditionalFilters(); zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const; zeus::CFrustum SetupViewForDraw(const SViewport& vp) const; void ResetViewAfterDraw(const SViewport& backupViewport, const zeus::CTransform& backupViewMatrix) const; void DrawWorld(); void SetupFogForArea3XRange(TAreaId area) const; void SetupFogForArea(TAreaId area) const; void SetupFogForAreaNonCurrent(TAreaId area) const; void SetupFogForArea3XRange(const CGameArea& area) const; void SetupFogForArea(const CGameArea& area) const; void SetupFogForAreaNonCurrent(const CGameArea& area) const; bool SetupFogForDraw() const; void PreRender(); void GetCharacterRenderMaskAndTarget(bool thawed, int& mask, int& target) const; bool GetVisSetForArea(TAreaId, TAreaId, CPVSVisSet& setOut) const; void RecursiveDrawTree(TUniqueId); void SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg); void SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg); void SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMessage msg, EScriptObjectState state); void SendScriptMsgAlways(TUniqueId dest, TUniqueId src, EScriptObjectMessage); void FreeScriptObjects(TAreaId); void FreeScriptObject(TUniqueId); std::pair GetBuildForScript(TEditorId) const; TEditorId GetEditorIdForUniqueId(TUniqueId) const; TUniqueId GetIdForScript(TEditorId) const; std::pair::const_iterator, std::multimap::const_iterator> GetIdListForScript(TEditorId) const; std::multimap::const_iterator GetIdListEnd() const { return x890_scriptIdMap.cend(); } void LoadScriptObjects(TAreaId, CInputStream& in, std::vector& idsOut); void InitializeScriptObjects(const std::vector& objIds); std::pair LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in); std::pair GenerateObject(TEditorId); void InitScriptObjects(const std::vector& ids); void InformListeners(const zeus::CVector3f&, EListenNoiseType); void ApplyKnockBack(CActor& actor, const CDamageInfo& info, const CDamageVulnerability&, const zeus::CVector3f&, float); void KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos, float power, float resistance); void ApplyDamageToWorld(TUniqueId, const CActor&, const zeus::CVector3f&, const CDamageInfo& info, const CMaterialFilter&); void ProcessRadiusDamage(const CActor&, CActor&, TUniqueId senderId, const CDamageInfo& info, const CMaterialFilter&); void ApplyRadiusDamage(const CActor&, const zeus::CVector3f&, CActor&, const CDamageInfo& info); bool TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee, const EntityList& nearList) const; bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, const CMaterialFilter& filter, const CActor* damagee) const; bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, const EntityList& nearList, const CMaterialFilter& filter, const CActor* damagee) const; bool RayCollideWorldInternal(const zeus::CVector3f& start, const zeus::CVector3f& end, const CMaterialFilter& filter, const EntityList& nearList, const CActor* damagee) const; bool MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter) const; void TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee); bool ApplyLocalDamage(const zeus::CVector3f&, const zeus::CVector3f&, CActor&, float, const CWeaponMode&); bool ApplyDamage(TUniqueId damagerId, TUniqueId damageeId, TUniqueId radiusSender, const CDamageInfo& info, const CMaterialFilter& filter, const zeus::CVector3f& knockbackVec); void UpdateAreaSounds(); void FrameEnd(); void ProcessPlayerInput(); void SetGameState(EGameState state); EGameState GetGameState() const { return x904_gameState; } void ProcessInput(const CFinalInput& input); void UpdateGraphicsTiming(float dt); void Update(float dt); void UpdateGameState(); void UpdateHintState(float dt); void PreThinkObjects(float dt); void MovePlatforms(float dt); void MoveActors(float dt); void CrossTouchActors(); void Think(float dt); void PostUpdatePlayer(float dt); void ShowPausedHUDMemo(CAssetId strg, float time); void ClearGraveyard(); void FrameBegin(s32 frameCount); void InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId); void CreateStandardGameObjects(); const std::unique_ptr& GetObjectList() const { return x808_objLists[0]; } CObjectList* ObjectListById(EGameObjectList type); const CObjectList* GetObjectListById(EGameObjectList type) const; void RemoveObject(TUniqueId); void UpdateRoomAcoustics(TAreaId); TAreaId GetNextAreaId() const { return x8cc_nextAreaId; } void SetCurrentAreaId(TAreaId); CEntity* ObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } const CEntity* GetObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } void AreaUnloaded(TAreaId); void PrepareAreaUnload(TAreaId); void AreaLoaded(TAreaId); void BuildNearList(EntityList& listOut, const zeus::CVector3f&, const zeus::CVector3f&, float, const CMaterialFilter&, const CActor*) const; void BuildColliderList(EntityList& listOut, const CActor&, const zeus::CAABox&) const; void BuildNearList(EntityList& listOut, const zeus::CAABox&, const CMaterialFilter&, const CActor*) const; void UpdateActorInSortedLists(CActor&); void UpdateSortedLists(); std::optional CalculateObjectBounds(const CActor&); void AddObject(CEntity&); void AddObject(CEntity*); CRayCastResult RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length, const CMaterialFilter& filter) const; CRayCastResult RayWorldIntersection(TUniqueId& idOut, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length, const CMaterialFilter& filter, const EntityList& list) const; void UpdateObjectInLists(CEntity&); TUniqueId AllocateUniqueId(); void DeferStateTransition(EStateManagerTransition t); EStateManagerTransition GetDeferredStateTransition() const { return xf90_deferredTransition; } bool CanShowMapScreen() const; TUniqueId GetSkipCinematicSpecialFunction() const { return xf38_skipCineSpecialFunc; } void SetSkipCinematicSpecialFunction(TUniqueId id) { xf38_skipCineSpecialFunc = id; } float GetHUDMessageTime() const { return xf78_hudMessageTime; } u32 GetHUDMessageFrameCount() const { return xf80_hudMessageFrameCount; } CAssetId GetPauseHUDMessage() const { return xf08_pauseHudMessage; } void IncrementHUDMessageFrameCounter() { ++xf80_hudMessageFrameCount; } bool ShouldQuitGame() const { return xf94_25_quitGame; } void SetShouldQuitGame(bool should) { xf94_25_quitGame = should; } void SetInSaveUI(bool b) { xf94_28_inSaveUI = b; } bool GetInSaveUI() const { return xf94_28_inSaveUI; } void SetInMapScreen(bool b) { xf94_27_inMapScreen = b; } bool GetInMapScreen() const { return xf94_27_inMapScreen; } bool IsFullThreat() const { return xf94_30_fullThreat; } void SetIsFullThreat(bool v) { xf94_30_fullThreat = v; } const std::shared_ptr& GetPlayerState() const { return x8b8_playerState; } CRandom16* GetActiveRandom() { return x900_activeRandom; } const CRandom16* GetActiveRandom() const { return x900_activeRandom; } zeus::CVector3f Random2f(float scaleMin, float scaleMax); void SetActiveRandomToDefault() { x900_activeRandom = &x8fc_random; } void ClearActiveRandom() { x900_activeRandom = nullptr; } CRumbleManager& GetRumbleManager() { return *x88c_rumbleManager; } const CRumbleManager& GetRumbleManager() const { return *x88c_rumbleManager; } CCameraFilterPass& GetCameraFilterPass(int idx) { return xb84_camFilterPasses[idx]; } const CCameraFilterPass& GetCameraFilterPass(int idx) const { return xb84_camFilterPasses[idx]; } CCameraBlurPass& GetCameraBlurPass(int idx) { return xd14_camBlurPasses[idx]; } const CCameraBlurPass& GetCameraBlurPass(int idx) const { return xd14_camBlurPasses[idx]; } CEnvFxManager* GetEnvFxManager() { return x880_envFxManager; } const CEnvFxManager* GetEnvFxManager() const { return x880_envFxManager; } CWorld* GetWorld() { return x850_world.get(); } const CWorld* GetWorld() const { return x850_world.get(); } CScriptMailbox* GetMailbox() { return x8bc_mailbox.get(); } const CScriptMailbox* GetRelayTracker() const { return x8bc_mailbox.get(); } CCameraManager* GetCameraManager() const { return x870_cameraManager; } CFluidPlaneManager* GetFluidPlaneManager() const { return x87c_fluidPlaneManager; } CActorModelParticles* GetActorModelParticles() const { return x884_actorModelParticles; } const std::shared_ptr& MapWorldInfo() const { return x8c0_mapWorldInfo; } const std::shared_ptr& WorldTransManager() const { return x8c4_worldTransManager; } const std::shared_ptr& WorldLayerState() const { return x8c8_worldLayerState; } std::shared_ptr& WorldLayerState() { return x8c8_worldLayerState; } CPlayer& GetPlayer() const { return *x84c_player; } CPlayer* Player() const { return x84c_player.get(); } CObjectList& GetAllObjectList() const { return *x808_objLists[0]; } CActorList& GetActorObjectList() const { return static_cast(*x808_objLists[1]); } CPhysicsActorList& GetPhysicsActorObjectList() const { return static_cast(*x808_objLists[2]); } CGameCameraList& GetCameraObjectList() const { return static_cast(*x808_objLists[3]); } CGameLightList& GetLightObjectList() const { return static_cast(*x808_objLists[4]); } CListeningAiList& GetListeningAiObjectList() const { return static_cast(*x808_objLists[5]); } CAiWaypointList& GetAiWaypointObjectList() const { return static_cast(*x808_objLists[6]); } CPlatformAndDoorList& GetPlatformAndDoorObjectList() const { return static_cast(*x808_objLists[7]); } std::pair CalculateScanCompletionRate() const; void SetCurrentMaze(std::unique_ptr maze) { xf70_currentMaze = std::move(maze); } void ClearCurrentMaze() { xf70_currentMaze.reset(); } CMazeState* GetCurrentMaze() { return xf70_currentMaze.get(); } void SetLastTriggerId(TUniqueId uid) { xf74_lastTrigger = uid; } TUniqueId GetLastTriggerId() const { return xf74_lastTrigger; } void SetLastRelayId(TUniqueId uid) { xf76_lastRelay = uid; } TUniqueId* GetLastRelayIdPtr() { return &xf76_lastRelay; } TUniqueId GetLastRelayId() const { return xf76_lastRelay; } bool GetIsGeneratingObject() const { return xf94_26_generatingObject; } void SetIsGeneratingObject(bool gen) { xf94_26_generatingObject = gen; } EThermalDrawFlag GetThermalDrawFlag() const { return xf34_thermalFlag; } const CFinalInput& GetFinalInput() const { return xb54_finalInput; } void SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringIdx); TUniqueId GetBossId() const { return xf18_bossId; } float GetTotalBossEnergy() const { return xf1c_totalBossEnergy; } u32 GetBossStringIdx() const { return xf20_bossStringIdx; } void SetPendingOnScreenTex(CAssetId texId, const zeus::CVector2i& origin, const zeus::CVector2i& extent) { xef4_pendingScreenTex.x0_id = texId; xef4_pendingScreenTex.x4_origin = origin; xef4_pendingScreenTex.xc_extent = extent; } const SOnScreenTex& GetPendingScreenTex() const { return xef4_pendingScreenTex; } void SetViewportScale(const zeus::CVector2f& scale) { xf2c_viewportScale = scale; } float GetThermalColdScale1() const { return xf24_thermColdScale1; } float GetThermalColdScale2() const { return xf28_thermColdScale2; } void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; } float IntegrateVisorFog(float f) const; u32 GetUpdateFrameIndex() const { return x8d8_updateFrameIdx; } void SetCinematicPause(bool p) { xf94_29_cinematicPause = p; } void QueueMessage(u32 frameCount, CAssetId msg, float f1) { xf84_ = frameCount; xf88_ = msg; xf8c_ = f1; } TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; } void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; } std::list& GetActiveFlickerBats() { return xf3c_activeFlickerBats; } std::list& GetActiveParasites() { return xf54_activeParasites; } static float g_EscapeShakeCountdown; static bool g_EscapeShakeCountdownInit; void sub_80044098(const CCollisionResponseData& colRespData, const CRayCastResult& rayCast, TUniqueId uid, const CWeaponMode& weaponMode, u32 w1, u8 thermalFlags); const CGameArea* GetCurrentArea() const; void SetWarping(bool warp) { m_warping = warp; } }; } // namespace metaforce