From db12dd2ea2c42ed31d7a7cc86a009f7c6280f8cc Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 23 Mar 2017 19:30:16 -1000 Subject: [PATCH] Implement CStateManager::Update --- DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp | 2 +- DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp | 2 +- Editor/ProjectResourceFactoryMP1.cpp | 4 + Runtime/AutoMapper/CMapArea.cpp | 3 +- Runtime/AutoMapper/CMapArea.hpp | 3 +- Runtime/AutoMapper/CMapUniverse.cpp | 3 +- Runtime/AutoMapper/CMapUniverse.hpp | 3 +- Runtime/CFluidPlaneManager.cpp | 5 + Runtime/CFluidPlaneManager.hpp | 1 + Runtime/CGameOptions.cpp | 68 +++- Runtime/CGameOptions.hpp | 12 +- Runtime/CSortedLists.cpp | 317 +++++++++++++++- Runtime/CSortedLists.hpp | 51 ++- Runtime/CStateManager.cpp | 406 +++++++++++++++++++-- Runtime/CStateManager.hpp | 51 ++- Runtime/Camera/CBallCamera.cpp | 6 + Runtime/Camera/CBallCamera.hpp | 1 + Runtime/Camera/CCameraFilter.cpp | 5 + Runtime/Camera/CCameraFilter.hpp | 2 + Runtime/Camera/CCameraManager.cpp | 34 ++ Runtime/Camera/CCameraManager.hpp | 6 + Runtime/Camera/CFirstPersonCamera.cpp | 5 + Runtime/Camera/CFirstPersonCamera.hpp | 4 +- Runtime/Camera/CGameCamera.cpp | 4 +- Runtime/Camera/CGameCamera.hpp | 7 +- Runtime/Camera/CInterpolationCamera.cpp | 47 +++ Runtime/Camera/CInterpolationCamera.hpp | 23 ++ Runtime/Camera/CMakeLists.txt | 1 + Runtime/Collision/CCollisionActor.cpp | 4 +- Runtime/Collision/CGameCollision.cpp | 5 + Runtime/Collision/CGameCollision.hpp | 5 + Runtime/Input/CFinalInput.hpp | 1 + Runtime/MP1/CSamusHud.cpp | 12 + Runtime/MP1/CSamusHud.hpp | 16 + Runtime/MkCastTo.py | 1 + Runtime/Particle/CDecalManager.cpp | 5 + Runtime/Particle/CDecalManager.hpp | 1 + Runtime/Particle/CElementGen.cpp | 2 + Runtime/Particle/CElementGen.hpp | 2 + Runtime/Particle/CParticleElectric.cpp | 2 + Runtime/Particle/CParticleElectric.hpp | 2 + Runtime/Weapon/CMakeLists.txt | 1 + Runtime/Weapon/CProjectileWeapon.cpp | 9 + Runtime/Weapon/CProjectileWeapon.hpp | 19 + Runtime/World/CActor.cpp | 4 +- Runtime/World/CActorModelParticles.cpp | 5 + Runtime/World/CActorModelParticles.hpp | 1 + Runtime/World/CEnvFxManager.cpp | 5 + Runtime/World/CEnvFxManager.hpp | 2 +- Runtime/World/CGameArea.hpp | 2 + Runtime/World/CPlayer.cpp | 40 ++ Runtime/World/CPlayer.hpp | 15 +- Runtime/World/CScriptActor.cpp | 2 +- Runtime/World/CScriptAiJumpPoint.cpp | 2 +- Runtime/World/CScriptAreaAttributes.cpp | 2 +- Runtime/World/CScriptBeam.cpp | 2 +- Runtime/World/CScriptDistanceFog.cpp | 2 +- Runtime/World/CScriptDock.cpp | 4 +- Runtime/World/CScriptEffect.cpp | 3 + Runtime/World/CScriptEffect.hpp | 8 + Runtime/World/CScriptShadowProjector.cpp | 2 +- Runtime/World/CScriptSound.cpp | 2 +- Runtime/World/CWorld.cpp | 5 + Runtime/World/CWorld.hpp | 1 + Runtime/World/ScriptObjectSupport.hpp | 4 +- amuse | 2 +- hecl | 2 +- specter | 2 +- 68 files changed, 1165 insertions(+), 117 deletions(-) create mode 100644 Runtime/Camera/CInterpolationCamera.cpp create mode 100644 Runtime/Camera/CInterpolationCamera.hpp create mode 100644 Runtime/Weapon/CProjectileWeapon.cpp create mode 100644 Runtime/Weapon/CProjectileWeapon.hpp diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp index ca825c353..13d99836e 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp @@ -20,6 +20,7 @@ struct ITweakPlayer : ITweak virtual float GetX278() const=0; // x278 virtual float GetX27C() const=0; // x27c virtual float GetX124() const=0; // x134 + virtual float GetX184() const=0; // x184 virtual float GetX288() const=0; // x288 virtual float GetX28c() const=0; // x28c virtual float GetX290() const=0; // x290 @@ -28,7 +29,6 @@ struct ITweakPlayer : ITweak virtual float GetX29C() const=0; // x29c virtual float GetX280() const=0; // x280 virtual float GetX2B0() const=0; // x2b0 - virtual float GetX184() const=0; // x184 virtual float GetX138() const=0; // x138 virtual float GetX14C() const=0; // x14c virtual float GetLeftLogicalThreshold() const=0; diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp index cab110af4..68e93cf78 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp @@ -185,6 +185,7 @@ struct CTweakPlayer : ITweakPlayer float GetX278() const { return x278_; } float GetX27C() const { return x27c_playerBallHalfExtent; } float GetX124() const { return x134_; } + float GetX184() const { return x184_; } bool GetX228_24() const { return x228_24_; } float GetX288() const { return x288_; } float GetX28c() const { return x28c_; } @@ -194,7 +195,6 @@ struct CTweakPlayer : ITweakPlayer float GetX29C() const { return x29c_; } float GetX280() const { return x280_; } float GetX2B0() const { return x2b0_; } - float GetX184() const { return x184_; } float GetX138() const { return x138_; } float GetX14C() const { return x14c_; } float GetLeftLogicalThreshold() const {return x150_leftDiv;} diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index 7d875b8f9..d235aab9c 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -25,6 +25,8 @@ #include "Runtime/Collision/CCollisionResponseData.hpp" #include "Runtime/CSaveWorld.hpp" #include "Runtime/AutoMapper/CMapWorld.hpp" +#include "Runtime/AutoMapper/CMapArea.hpp" +#include "Runtime/AutoMapper/CMapUniverse.hpp" #include "Runtime/CScannableObjectInfo.hpp" #include "Audio/CAudioGroupSet.hpp" #include "Audio/CSfxManager.hpp" @@ -123,6 +125,8 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client m_factoryMgr.AddFactory(FOURCC('ELSC'), FFactoryFunc(FParticleElectricDataFactory)); m_factoryMgr.AddFactory(FOURCC('WPSC'), FFactoryFunc(FProjectileWeaponDataFactory)); m_factoryMgr.AddFactory(FOURCC('DPSC'), FFactoryFunc(FDecalDataFactory)); + m_factoryMgr.AddFactory(FOURCC('MAPA'), FFactoryFunc(FMapAreaFactory)); + m_factoryMgr.AddFactory(FOURCC('MAPU'), FFactoryFunc(FMapUniverseFactory)); } void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp) diff --git a/Runtime/AutoMapper/CMapArea.cpp b/Runtime/AutoMapper/CMapArea.cpp index 7098f1363..b8b315392 100644 --- a/Runtime/AutoMapper/CMapArea.cpp +++ b/Runtime/AutoMapper/CMapArea.cpp @@ -117,7 +117,8 @@ void CMapArea::CMapAreaSurface::PostConstruct(const void *) { } -CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&) +CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&, + CObjectReference*) { u32 size = g_ResFactory->ResourceSize(objTag); return TToken::GetIObjObjectFor(std::make_unique(in, size)); diff --git a/Runtime/AutoMapper/CMapArea.hpp b/Runtime/AutoMapper/CMapArea.hpp index 2600b967e..306958785 100644 --- a/Runtime/AutoMapper/CMapArea.hpp +++ b/Runtime/AutoMapper/CMapArea.hpp @@ -49,6 +49,7 @@ public: zeus::CTransform GetAreaPostTransform(const CWorld& world, TAreaId aid) const; }; -CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&); +CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&, + CObjectReference*); } #endif // __URDE_CMAPAREA_HPP__ diff --git a/Runtime/AutoMapper/CMapUniverse.cpp b/Runtime/AutoMapper/CMapUniverse.cpp index 806f1bac9..6e9d1e090 100644 --- a/Runtime/AutoMapper/CMapUniverse.cpp +++ b/Runtime/AutoMapper/CMapUniverse.cpp @@ -43,7 +43,8 @@ CMapUniverse::CMapWorldData::CMapWorldData(CInputStream& in, u32 version) x64_ *= 1.0f / float(x44_areaData.size()); } -CFactoryFnReturn FMapUniverseFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer&) +CFactoryFnReturn FMapUniverseFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer&, + CObjectReference*) { in.readUint32Big(); u32 version = in.readUint32Big(); diff --git a/Runtime/AutoMapper/CMapUniverse.hpp b/Runtime/AutoMapper/CMapUniverse.hpp index 35ab153a8..35741398d 100644 --- a/Runtime/AutoMapper/CMapUniverse.hpp +++ b/Runtime/AutoMapper/CMapUniverse.hpp @@ -77,7 +77,8 @@ public: void Draw(const CMapUniverseDrawParms&, const zeus::CVector3f&, float, float) const; }; -CFactoryFnReturn FMapUniverseFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms); +CFactoryFnReturn FMapUniverseFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, + CObjectReference*); } #endif diff --git a/Runtime/CFluidPlaneManager.cpp b/Runtime/CFluidPlaneManager.cpp index 436bf277f..bccfb5765 100644 --- a/Runtime/CFluidPlaneManager.cpp +++ b/Runtime/CFluidPlaneManager.cpp @@ -16,4 +16,9 @@ void CFluidPlaneManager::StartFrame(bool b) sProfile.Clear(); } +void CFluidPlaneManager::Update(float dt) +{ + +} + } diff --git a/Runtime/CFluidPlaneManager.hpp b/Runtime/CFluidPlaneManager.hpp index b5f87f7fd..5316dd42d 100644 --- a/Runtime/CFluidPlaneManager.hpp +++ b/Runtime/CFluidPlaneManager.hpp @@ -16,6 +16,7 @@ class CFluidPlaneManager public: void StartFrame(bool); void EndFrame() { x121_ = false; } + void Update(float dt); }; } diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index 3638e059e..a1d92a77a 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -10,6 +10,7 @@ #include "Audio/CSfxManager.hpp" #include "Audio/CStreamAudioManager.hpp" #include "Graphics/CMoviePlayer.hpp" +#include "CStateManager.hpp" namespace urde { @@ -544,7 +545,7 @@ CHintOptions::CHintOptions(CBitStreamReader& stream) x0_hintStates.emplace_back(state, time, false); - if (x10_nextHintIdx == -1 && state == EHintState::Two) + if (x10_nextHintIdx == -1 && state == EHintState::Displaying) x10_nextHintIdx = hintIdx; ++hintIdx; } @@ -589,7 +590,7 @@ const CHintOptions::SHintState* CHintOptions::GetCurrentDisplayedHint() const if (hintState.x4_time < 3.f) return &hintState; - if (!hintState.x8_flag) + if (!hintState.x8_dismissed) return &hintState; return nullptr; @@ -619,7 +620,7 @@ void CHintOptions::ActivateImmediateHintTimer(const char* name) if (hintState.x0_state != EHintState::Zero) return; - hintState.x0_state = EHintState::One; + hintState.x0_state = EHintState::Waiting; hintState.x4_time = hint.GetImmediateTime(); } @@ -633,10 +634,69 @@ void CHintOptions::ActivateContinueDelayHintTimer(const char* name) SHintState& hintState = x0_hintStates[idx]; const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx]; - if (hintState.x0_state != EHintState::Two) + if (hintState.x0_state != EHintState::Displaying) return; hintState.x4_time = hint.GetTextTime(); } +void CHintOptions::DismissDisplayedHint() +{ + +} + +u32 CHintOptions::GetNextHintIdx() const +{ + if (g_GameState->GameOptions().GetIsHintSystemEnabled()) + return x10_nextHintIdx; + return -1; +} + +void CHintOptions::Update(float dt, const CStateManager& stateMgr) +{ + x10_nextHintIdx = -1; + int idx = 0; + auto memIt = g_MemoryCardSys->GetHints().begin(); + for (SHintState& state : x0_hintStates) + { + switch (state.x0_state) + { + case EHintState::Waiting: + state.x4_time -= dt; + if (state.x4_time <= 0.f) + { + state.x0_state = EHintState::Displaying; + state.x4_time = memIt->GetTextTime(); + } + break; + case EHintState::Displaying: + if (x10_nextHintIdx == -1) + x10_nextHintIdx = idx; + default: break; + } + ++memIt; + ++idx; + } + + if (x10_nextHintIdx == -1) + return; + + SHintState& state = x0_hintStates[x10_nextHintIdx]; + const CGameHintInfo::CGameHint& data = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; + + state.x4_time = std::max(0.f, state.x4_time - dt); + if (state.x4_time < data.GetTextTime()) + { + for (const CGameHintInfo::SHintLocation& loc : data.GetLocations()) + { + if (loc.x0_mlvlId == stateMgr.GetWorld()->IGetWorldAssetId() && + loc.x8_areaId == stateMgr.GetNextAreaId()) + { + state.x4_time = data.GetNormalTime(); + state.x8_dismissed = true; + } + } + } +} + } diff --git a/Runtime/CGameOptions.hpp b/Runtime/CGameOptions.hpp index d2150c560..148faf00c 100644 --- a/Runtime/CGameOptions.hpp +++ b/Runtime/CGameOptions.hpp @@ -7,6 +7,7 @@ namespace urde { class CFinalInput; +class CStateManager; /** Options presented in UI */ enum class EGameOption @@ -184,19 +185,19 @@ public: enum class EHintState { Zero, - One, - Two, + Waiting, + Displaying, Delayed }; struct SHintState { EHintState x0_state = EHintState::Zero; float x4_time = 0.f; - bool x8_flag = false; + bool x8_dismissed = false; SHintState() = default; SHintState(EHintState state, float time, bool flag) - : x0_state(state), x4_time(time), x8_flag(flag) {} + : x0_state(state), x4_time(time), x8_dismissed(flag) {} bool CanContinue() const { return x4_time / 3.f <= 1.f; } }; @@ -213,6 +214,9 @@ public: void DelayHint(const char* name); void ActivateImmediateHintTimer(const char* name); void ActivateContinueDelayHintTimer(const char* name); + void DismissDisplayedHint(); + u32 GetNextHintIdx() const; + void Update(float dt, const CStateManager& stateMgr); }; } diff --git a/Runtime/CSortedLists.cpp b/Runtime/CSortedLists.cpp index 618fa3058..e5ea189a6 100644 --- a/Runtime/CSortedLists.cpp +++ b/Runtime/CSortedLists.cpp @@ -16,24 +16,323 @@ void CSortedListManager::Reset() xb000_sortedLists[i].Reset(); } -void CSortedListManager::RemoveFromList(ESortedList list, s16 id) +void CSortedListManager::AddToLinkedList(TUniqueId nodeId, TUniqueId& headId, TUniqueId& tailId) const +{ + if (headId == -1) + { + const_cast(x0_nodes[nodeId]).x28_next = headId; + headId = nodeId; + tailId = nodeId; + } + else + { + if (x0_nodes[nodeId].x28_next != -1) + return; + if (tailId == nodeId) + return; + const_cast(x0_nodes[nodeId]).x28_next = headId; + headId = nodeId; + } +} + +void CSortedListManager::RemoveFromList(ESortedList list, s16 idx) { SSortedList& sl = xb000_sortedLists[u32(list)]; + while (idx < sl.x800_size - 1) + { + x0_nodes[sl.x0_ids[idx+1]].x1c_selfIdxs[int(list)] = idx; + sl.x0_ids[idx] = sl.x0_ids[idx+1]; + ++idx; + } + --sl.x800_size; +} + +void CSortedListManager::MoveInList(ESortedList list, s16 idx) +{ + SSortedList& sl = xb000_sortedLists[int(list)]; + while (true) + { + if (idx > 0 || + x0_nodes[sl.x0_ids[idx-1]].x4_box[idx] > x0_nodes[sl.x0_ids[idx]].x4_box[idx]) + { + x0_nodes[sl.x0_ids[idx-1]].x1c_selfIdxs[int(list)] = idx; + x0_nodes[sl.x0_ids[idx]].x1c_selfIdxs[int(list)] = idx - 1; + std::swap(sl.x0_ids[idx], sl.x0_ids[idx-1]); + --idx; + } + else + { + if (idx >= sl.x800_size - 1) + return; + if (x0_nodes[sl.x0_ids[idx+1]].x4_box[int(list)] >= x0_nodes[sl.x0_ids[idx]].x4_box[int(list)]) + return; + x0_nodes[sl.x0_ids[idx+1]].x1c_selfIdxs[int(list)] = idx + 1; + std::swap(sl.x0_ids[idx], sl.x0_ids[idx+1]); + } + } +} + +void CSortedListManager::InsertInList(ESortedList list, SNode& node) +{ + SSortedList& sl = xb000_sortedLists[int(list)]; + int insIdx = 0; + for (int i=sl.x800_size ; i>0 ;) + { + /* Binary search cycle to find insert index */ + if (x0_nodes[sl.x0_ids[insIdx+i/2]].x4_box[int(list)] < node.x4_box[int(list)]) + { + /* Upper */ + insIdx += i / 2 + 1; + i -= i / 2 - 1; + } + else + { + /* Lower */ + i /= 2; + } + } + + /* Shift ids for insert */ + for (int i=sl.x800_size ; i>insIdx ; --i) + { + x0_nodes[sl.x0_ids[i]].x1c_selfIdxs[int(list)] = i; + sl.x0_ids[i] = sl.x0_ids[i-1]; + } + + /* Do insert */ + sl.x0_ids[insIdx] = node.x0_actor->GetUniqueId(); + node.x1c_selfIdxs[int(list)] = insIdx; + ++sl.x800_size; +} + +s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const +{ + const SSortedList& sl = xb000_sortedLists[int(list)]; + int idx = 0; + for (int i=sl.x800_size ; i>0 ;) + { + /* Binary search cycle to find index */ + if (!(val < x0_nodes[sl.x0_ids[idx+i/2]].x4_box[int(list)])) + { + /* Upper */ + idx += i / 2 + 1; + i -= i / 2 - 1; + } + else + { + /* Lower */ + i /= 2; + } + } + return idx; +} + +s16 CSortedListManager::FindInListLower(ESortedList list, float val) const +{ + const SSortedList& sl = xb000_sortedLists[int(list)]; + int idx = 0; + for (int i=sl.x800_size ; i>0 ;) + { + /* Binary search cycle to find index */ + if (x0_nodes[sl.x0_ids[idx+i/2]].x4_box[int(list)] < val) + { + /* Upper */ + idx += i / 2 + 1; + i -= i / 2 - 1; + } + else + { + /* Lower */ + i /= 2; + } + } + return idx; +} + +TUniqueId CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) +{ + int minXa = FindInListLower(ESortedList::MinX, aabb.min.x); + int maxXa = FindInListUpper(ESortedList::MinX, aabb.max.x); + int minXb = FindInListLower(ESortedList::MaxX, aabb.min.x); + int maxXb = FindInListUpper(ESortedList::MaxX, aabb.max.x); + int xEnd = std::min(int(xb000_sortedLists[3].x800_size) - maxXb, minXa) + (maxXb + (maxXa - minXa) - minXb) / 2; + + int minYa = FindInListLower(ESortedList::MinY, aabb.min.y); + int maxYa = FindInListUpper(ESortedList::MinY, aabb.max.y); + int minYb = FindInListLower(ESortedList::MaxY, aabb.min.y); + int maxYb = FindInListUpper(ESortedList::MaxY, aabb.max.y); + int yEnd = std::min(int(xb000_sortedLists[4].x800_size) - maxYb, minYa) + (maxYb + (maxYa - minYa) - minYb) / 2; + + int minZa = FindInListLower(ESortedList::MinZ, aabb.min.z); + int maxZa = FindInListUpper(ESortedList::MinZ, aabb.max.z); + int minZb = FindInListLower(ESortedList::MaxZ, aabb.min.z); + int maxZb = FindInListUpper(ESortedList::MaxZ, aabb.max.z); + int zEnd = std::min(int(xb000_sortedLists[5].x800_size) - maxZb, minZa) + (maxZb + (maxZa - minZa) - minZb) / 2; + + if (xEnd < yEnd && xEnd < zEnd) + { + return CalculateIntersections(ESortedList::MinX, ESortedList::MaxX, minXa, maxXa, minXb, maxXb, + ESortedList::MinY, ESortedList::MaxY, ESortedList::MinZ, ESortedList::MaxZ, aabb); + } + else if (yEnd < zEnd) + { + return CalculateIntersections(ESortedList::MinY, ESortedList::MaxY, minYa, maxYa, minYb, maxYb, + ESortedList::MinX, ESortedList::MaxX, ESortedList::MinZ, ESortedList::MaxZ, aabb); + } + else + { + return CalculateIntersections(ESortedList::MinZ, ESortedList::MaxZ, minZa, maxZa, minZb, maxZb, + ESortedList::MinX, ESortedList::MaxX, ESortedList::MinY, ESortedList::MaxY, aabb); + } +} + +TUniqueId CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s16 a, s16 b, s16 c, s16 d, + ESortedList slA, ESortedList slB, ESortedList slC, ESortedList slD, + const zeus::CAABox& aabb) +{ + TUniqueId headId = kInvalidUniqueId; + TUniqueId tailId = kInvalidUniqueId; + for (int i=a ; i aabb[int(lb)]) + AddToLinkedList(id, headId, tailId); + } + } + else + { + for (int i=d ; i aabb[int(slB)] || + node.x4_box[int(slB)] < aabb[int(slA)] || + node.x4_box[int(slC)] > aabb[int(slD)] || + node.x4_box[int(slD)] < aabb[int(slC)]) + { + /* Not intersecting; remove from chain */ + *id = node.x28_next; + node.x28_next = kInvalidUniqueId; + continue; + } + id = &node.x28_next; + } + + return headId; +} + +void CSortedListManager::BuildNearList(rstl::reserved_vector& out, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, float f1, const CMaterialFilter& filter, + const CActor* actor) const +{ + if (f1 == 0.f) + f1 = 8000.f; + zeus::CVector3f mul = v2 * f1; + zeus::CVector3f sum = mul + v1; + zeus::CVector3f maxs(std::max(v1.z, sum.z), std::max(v1.y, sum.y), std::max(v1.x, sum.x)); + zeus::CVector3f mins(std::min(sum.z, v1.z), std::min(sum.y, v1.y), std::min(sum.y, v1.y)); + BuildNearList(out, zeus::CAABox(mins, maxs), filter, actor); +} + +void CSortedListManager::BuildNearList(rstl::reserved_vector& out, const CActor& actor, + const zeus::CAABox& aabb) const +{ + const CMaterialFilter& filter = actor.GetMaterialFilter(); + TUniqueId id = const_cast(*this).ConstructIntersectionArray(aabb); + while (id != kInvalidUniqueId) + { + const SNode& node = x0_nodes[id]; + if (&actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()) && + node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList())) + out.push_back(node.x0_actor->GetUniqueId()); + + id = node.x28_next; + const_cast(node).x28_next = kInvalidUniqueId; + } +} + +void CSortedListManager::BuildNearList(rstl::reserved_vector& out, const zeus::CAABox& aabb, + const CMaterialFilter& filter, const CActor* actor) const +{ + TUniqueId id = const_cast(*this).ConstructIntersectionArray(aabb); + while (id != kInvalidUniqueId) + { + const SNode& node = x0_nodes[id]; + if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList())) + out.push_back(node.x0_actor->GetUniqueId()); + + id = node.x28_next; + const_cast(node).x28_next = kInvalidUniqueId; + } } void CSortedListManager::Remove(const CActor* act) { SNode& node = x0_nodes[act->GetUniqueId() & 0x3ff]; - if (node.x2a_full == false) + if (node.x2a_populated == false) return; - RemoveFromList(ESortedList::Zero, node.x1c_); - RemoveFromList(ESortedList::Three, node.x22_); - RemoveFromList(ESortedList::One, node.x1e_); - RemoveFromList(ESortedList::Four, node.x24_); - RemoveFromList(ESortedList::Two, node.x20_); - RemoveFromList(ESortedList::Five, node.x26_); - node.x2a_full = false; + RemoveFromList(ESortedList::MinX, node.x1c_selfIdxs[0]); + RemoveFromList(ESortedList::MaxX, node.x1c_selfIdxs[3]); + RemoveFromList(ESortedList::MinY, node.x1c_selfIdxs[1]); + RemoveFromList(ESortedList::MaxY, node.x1c_selfIdxs[4]); + RemoveFromList(ESortedList::MinZ, node.x1c_selfIdxs[2]); + RemoveFromList(ESortedList::MaxZ, node.x1c_selfIdxs[5]); + node.x2a_populated = false; +} + +void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) +{ + SNode& node = x0_nodes[act->GetUniqueId() & 0x3ff]; + node.x4_box = aabb; + + MoveInList(ESortedList::MinX, node.x1c_selfIdxs[0]); + MoveInList(ESortedList::MaxX, node.x1c_selfIdxs[3]); + MoveInList(ESortedList::MinY, node.x1c_selfIdxs[1]); + MoveInList(ESortedList::MaxY, node.x1c_selfIdxs[4]); + MoveInList(ESortedList::MinZ, node.x1c_selfIdxs[2]); + MoveInList(ESortedList::MaxZ, node.x1c_selfIdxs[5]); +} + +void CSortedListManager::Insert(const CActor* act, const zeus::CAABox& aabb) +{ + SNode& node = x0_nodes[act->GetUniqueId() & 0x3ff]; + if (node.x2a_populated) + { + Move(act, aabb); + return; + } + + SNode newNode(act, aabb); + InsertInList(ESortedList::MinX, newNode); + InsertInList(ESortedList::MaxX, newNode); + InsertInList(ESortedList::MinY, newNode); + InsertInList(ESortedList::MaxY, newNode); + InsertInList(ESortedList::MinZ, newNode); + InsertInList(ESortedList::MaxZ, newNode); + node = newNode; +} + +bool CSortedListManager::ActorInLists(const CActor* act) const +{ + if (!act) + return false; + const SNode& node = x0_nodes[act->GetUniqueId() & 0x3ff]; + return node.x2a_populated; } } diff --git a/Runtime/CSortedLists.hpp b/Runtime/CSortedLists.hpp index 3f888b829..d22e52be2 100644 --- a/Runtime/CSortedLists.hpp +++ b/Runtime/CSortedLists.hpp @@ -3,23 +3,24 @@ #include "RetroTypes.hpp" #include "zeus/CAABox.hpp" +#include "Collision/CMaterialFilter.hpp" namespace urde { enum ESortedList { - Zero, - One, - Two, - Three, - Four, - Five + MinX, + MinY, + MinZ, + MaxX, + MaxY, + MaxZ }; struct SSortedList { TUniqueId x0_ids[1024]; - u32 x800_; + u32 x800_size; void Reset() {std::fill(std::begin(x0_ids), std::end(x0_ids), kInvalidUniqueId);} SSortedList() {Reset();} }; @@ -29,24 +30,38 @@ class CSortedListManager { struct SNode { - u32 x0_ = 0; + const CActor* x0_actor = nullptr; zeus::CAABox x4_box = zeus::CAABox::skNullBox; - u16 x1c_; - u16 x1e_; - u16 x20_; - u16 x22_; - u16 x24_; - u16 x26_; - u16 x28_ = -1; - bool x2a_full = false; + u16 x1c_selfIdxs[6] = {-1, -1, -1, -1, -1, -1}; + TUniqueId x28_next = kInvalidUniqueId; + bool x2a_populated = false; + SNode() = default; + SNode(const CActor* act, const zeus::CAABox& aabb) + : x0_actor(act), x4_box(aabb), x2a_populated(true) {} }; SNode x0_nodes[1024]; SSortedList xb000_sortedLists[6]; + void Reset(); + void AddToLinkedList(TUniqueId a, TUniqueId& b, TUniqueId& c) const; + void RemoveFromList(ESortedList, s16); + void MoveInList(ESortedList, s16); + void InsertInList(ESortedList, SNode& node); + s16 FindInListUpper(ESortedList, float) const; + s16 FindInListLower(ESortedList, float) const; + TUniqueId ConstructIntersectionArray(const zeus::CAABox&); + TUniqueId CalculateIntersections(ESortedList, ESortedList, s16, s16, s16, s16, + ESortedList, ESortedList, ESortedList, ESortedList, const zeus::CAABox&); public: CSortedListManager(); - void Reset(); - void RemoveFromList(ESortedList, s16); + void BuildNearList(rstl::reserved_vector&, const zeus::CVector3f&, const zeus::CVector3f&, + float, const CMaterialFilter&, const CActor*) const; + void BuildNearList(rstl::reserved_vector&, const CActor&, const zeus::CAABox&) const; + void BuildNearList(rstl::reserved_vector&, const zeus::CAABox&, + const CMaterialFilter&, const CActor*) const; void Remove(const CActor*); + void Move(const CActor* act, const zeus::CAABox& aabb); + void Insert(const CActor* act, const zeus::CAABox& aabb); + bool ActorInLists(const CActor* act) const; }; } diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index d472498ab..0e4bfbf06 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -31,7 +31,12 @@ #include "Collision/CMaterialFilter.hpp" #include "World/CScriptDock.hpp" #include "Particle/CDecalManager.hpp" +#include "Particle/CParticleElectric.hpp" #include "World/CProjectedShadow.hpp" +#include "Weapon/CProjectileWeapon.hpp" +#include "World/CScriptEffect.hpp" +#include "MP1/CSamusHud.hpp" +#include "Collision/CGameCollision.hpp" #include @@ -42,15 +47,7 @@ CStateManager::CStateManager(const std::weak_ptr& relayTracker, const std::weak_ptr& mwInfo, const std::weak_ptr& playerState, const std::weak_ptr& wtMgr, const std::weak_ptr& layerState) -: x80c_allObjs(new CObjectList(EGameObjectList::All)) -, x814_actorObjs(new CActorList()) -, x81c_physActorObjs(new CPhysicsActorList()) -, x824_cameraObjs(new CGameCameraList()) -, x82c_lightObjs(new CGameLightList()) -, x834_listenAiObjs(new CListeningAiList()) -, x83c_aiWaypointObjs(new CAiWaypointList()) -, x844_platformAndDoorObjs(new CPlatformAndDoorList()) -, x8b8_playerState(playerState) +: x8b8_playerState(playerState) , x8bc_relayTracker(relayTracker) , x8c0_mapWorldInfo(mwInfo) , x8c4_worldTransManager(wtMgr) @@ -419,11 +416,11 @@ void CStateManager::BuildDynamicLightListForWorld() return; } - if (x82c_lightObjs->size() == 0) + if (GetLightObjectList().size() == 0) return; x8e0_dynamicLights.clear(); - for (CEntity* ent : *x82c_lightObjs) + for (CEntity* ent : GetLightObjectList()) { CGameLight& light = static_cast(*ent); if (light.GetActive()) @@ -480,7 +477,7 @@ void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport, void CStateManager::DrawWorld() const { - CTimeProvider timeProvider(xf14_); + CTimeProvider timeProvider(xf14_curTimeMod900); SViewport backupViewport = g_Viewport; zeus::CFrustum frustum = SetupViewForDraw(g_Viewport); zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix; @@ -920,7 +917,7 @@ void CStateManager::SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMe for (auto it = search.first; it != search.second; ++it) { TUniqueId id = it->second; - CEntity* dobj = x80c_allObjs->GetObjectById(id); + CEntity* dobj = GetAllObjectList().GetObjectById(id); SendScriptMsg(dobj, src, msg); } } @@ -959,7 +956,7 @@ void CStateManager::FreeScriptObject(TUniqueId id) return; ent->SetIsInGraveyard(true); - x858_objectGraveyard.push_back(id); + x854_objectGraveyard.push_back(id); ent->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); ent->SetIsScriptingBlocked(true); @@ -1090,7 +1087,7 @@ void CStateManager::InitScriptObjects(const std::vector& ids) if (id == kInvalidEditorId) continue; TUniqueId uid = GetIdForScript(id); - SendScriptMsg(uid, kInvalidUniqueId, EScriptObjectMessage::Constructed); + SendScriptMsg(uid, kInvalidUniqueId, EScriptObjectMessage::InitializedInArea); } MurderScriptInstanceNames(); } @@ -1155,17 +1152,265 @@ bool CStateManager::ApplyDamage(TUniqueId, TUniqueId, TUniqueId, const CDamageIn void CStateManager::UpdateAreaSounds() {} -void CStateManager::FrameEnd() {} +void CStateManager::FrameEnd() +{ + g_SimplePool->Flush(); +} -void CStateManager::ProcessPlayerInput() {} +void CStateManager::ProcessPlayerInput() +{ + if (x84c_player) + x84c_player->ProcessInput(xb54_finalInput, *this); +} -void CStateManager::ProcessInput(const CFinalInput& input) {} +static const CFinalInput s_DisabledFinalInput = {}; -void CStateManager::Update(float dt) {} +void CStateManager::ProcessInput(const CFinalInput& input) +{ + if (input.ControllerIdx() == 0) + { + CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); + bool disableInput = cam->x170_25_disablesInput; + if (x84c_player->x9c6_29_disableInput) + disableInput = true; + if (disableInput) + { + xb54_finalInput = s_DisabledFinalInput; + xb54_finalInput.x0_dt = input.DeltaTime(); + } + else + { + xb54_finalInput = input; + } + } + x870_cameraManager->ProcessInput(input, *this); +} -void CStateManager::UpdateGameState() {} +void CStateManager::Update(float dt) +{ + CElementGen::SetGlobalSeed(x8d8_updateFrameIdx); + CParticleElectric::SetGlobalSeed(x8d8_updateFrameIdx); + CDecal::SetGlobalSeed(x8d8_updateFrameIdx); + CProjectileWeapon::SetGlobalSeed(x8d8_updateFrameIdx); -void CStateManager::FrameBegin(s32 frameCount) {} + xf14_curTimeMod900 += dt; + if (xf14_curTimeMod900 > 900.f) + xf14_curTimeMod900 -= 900.f; + + xf08_pauseHudMessage = -1; + + CScriptEffect::ResetParticleCounts(); + UpdateThermalVisor(); + UpdateGameState(); + + bool _9f4_gt0 = x84c_player->x9f4_ > 0.f; + + if (x904_ == 0) + { + if (!TCastToPtr(x870_cameraManager->GetCurrentCamera(*this))) + { + g_GameState->SetTotalPlayTime(g_GameState->xa0_playTime + dt); + UpdateHintState(dt); + } + + for (int i=0 ; i<9 ; ++i) + { + xb84_camFilterPasses[i].Update(dt); + xd14_camBlurPasses[i].Update(dt); + } + } + + if (x904_ != 2) + { + PreThinkEffects(dt); + x87c_fluidPlaneManager->Update(dt); + } + + if (x904_ == 0) + { + if (!_9f4_gt0) + CDecalManager::Update(dt, *this); + UpdateSortedLists(); + if (!_9f4_gt0) + { + MovePlatforms(dt); + MoveDoors(dt); + } + ProcessPlayerInput(); + if (x904_ != 1) + CGameCollision::Move(*this, *x84c_player, dt, nullptr); + UpdateSortedLists(); + if (!_9f4_gt0) + CrossTouchActors(dt); + } + else + { + ProcessPlayerInput(); + } + + if (!_9f4_gt0 && x904_ == 0) + x884_actorModelParticles->Update(dt, *this); + + if (x904_ == 0 || x904_ == 1) + ThinkEffectsAndActors(dt); + + if (x904_ != 1) + x870_cameraManager->Update(dt, *this); + + while (xf76_lastRelay != kInvalidUniqueId) + { + if (CEntity* ent = ObjectById(xf76_lastRelay)) + { + ent->Think(dt, *this); + } + else + { + xf76_lastRelay = kInvalidUniqueId; + break; + } + } + + if (x904_ != 2) + UpdatePlayer(dt); + + if (xf84_ == xf80_hudMessageFrameCount) + { + ShowPausedHUDMemo(xf88_, xf8c_); + --xf84_; + xf88_ = -1; + } + + if (!_9f4_gt0 && x904_ == 0 && !x870_cameraManager->IsInCinematicCamera()) + UpdateEscapeSequenceTimer(dt); + + x850_world->Update(dt); + x88c_rumbleManager->Update(dt); + + if (!_9f4_gt0) + x880_envFxManager->Update(dt, *this); + + UpdateAreaSounds(); + + xf94_24_ = true; + + if (xf94_27_inMapScreen) + { + if (const CHintOptions::SHintState* hint = g_GameState->HintOptions().GetCurrentDisplayedHint()) + { + if (hint->CanContinue()) + g_GameState->HintOptions().DismissDisplayedHint(); + } + xf94_27_inMapScreen = false; + } + + g_GameState->CurrentWorldState().SetAreaId(x8cc_nextAreaId); + x850_world->TravelToArea(x8cc_nextAreaId, *this, false); + + BringOutYourDead(); + ++x8d8_updateFrameIdx; +} + +void CStateManager::UpdateGameState() +{ + // Intentionally empty +} + +void CStateManager::UpdateHintState(float dt) +{ + CHintOptions& ho = g_GameState->HintOptions(); + ho.Update(dt, *this); + u32 nextHintIdx = -1; + u32 hintPeriods = -1; + if (const CHintOptions::SHintState* state = ho.GetCurrentDisplayedHint()) + { + const CGameHintInfo::CGameHint& next = g_MemoryCardSys->GetHints()[ho.GetNextHintIdx()]; + for (const CGameHintInfo::SHintLocation& loc : next.GetLocations()) + { + const auto& mwInfo = g_GameState->StateForWorld(loc.x0_mlvlId).MapWorldInfo(); + mwInfo->SetIsMapped(loc.x8_areaId, true); + } + if (state->x4_time < next.GetTextTime()) + { + nextHintIdx = ho.GetNextHintIdx(); + hintPeriods = state->x4_time / 3.f; + } + } + + if (xeec_hintIdx != nextHintIdx || xef0_hintPeriods != hintPeriods) + { + if (nextHintIdx == -1) + { + SHudMemoInfo memoInfo = {0.f, true, true, true}; + MP1::CSamusHud::DisplayHudMemo(u"", memoInfo); + } + else + { + const CGameHintInfo::CGameHint& data = g_MemoryCardSys->GetHints()[nextHintIdx]; + SHudMemoInfo memoInfo = {0.f, true, false, true}; + MP1::CSamusHud::DeferHintMemo(data.GetStringID(), hintPeriods, memoInfo); + } + xeec_hintIdx = nextHintIdx; + xef0_hintPeriods = hintPeriods; + } +} + +void CStateManager::PreThinkEffects(float dt) +{ + if (x84c_player->x9f4_ > 0.f) + { + x84c_player->DoPreThink(dt, *this); + return; + } + + if (x904_ == 1) + for (CEntity* ent : GetAllObjectList()) + if (TCastToPtr effect = ent) + effect->PreThink(dt, *this); + + for (CEntity* ent : GetCameraObjectList()) + if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId())) + ent->PreThink(dt, *this); +} + +void CStateManager::MovePlatforms(float dt) +{ + +} + +void CStateManager::MoveDoors(float dt) +{ + +} + +void CStateManager::CrossTouchActors(float dt) +{ + +} + +void CStateManager::ThinkEffectsAndActors(float dt) +{ + +} + +void CStateManager::UpdatePlayer(float dt) +{ + +} + +void CStateManager::ShowPausedHUDMemo(ResId strg, float time) +{ + +} + +void CStateManager::BringOutYourDead() +{ + +} + +void CStateManager::FrameBegin(s32 frameCount) +{ + x8d4_inputFrameIdx = frameCount; +} void CStateManager::InitializeState(ResId mlvlId, TAreaId aid, ResId mreaId) { @@ -1202,10 +1447,10 @@ void CStateManager::InitializeState(ResId mlvlId, TAreaId aid, ResId mreaId) x850_world->TravelToArea(x8cc_nextAreaId, *this, true); UpdateRoomAcoustics(x8cc_nextAreaId); - for (CEntity* ent : *x80c_allObjs) + for (CEntity* ent : GetAllObjectList()) SendScriptMsg(ent, kInvalidUniqueId, EScriptObjectMessage::InternalMessage14); - for (CEntity* ent : *x80c_allObjs) + for (CEntity* ent : GetAllObjectList()) { CScriptSpawnPoint* sp = TCastToPtr(ent); if (sp && sp->x30_24_active && sp->FirstSpawn()) @@ -1266,18 +1511,21 @@ void CStateManager::CreateStandardGameObjects() unk3, CMaterialList(EMaterialTypes::Player, EMaterialTypes::Solid, EMaterialTypes::GroundCollider))); AddObject(*x84c_player); + x870_cameraManager->CreateStandardCameras(*this); } CObjectList* CStateManager::ObjectListById(EGameObjectList type) { - std::unique_ptr* lists = &x80c_allObjs; - return lists[int(type)].get(); + if (type == EGameObjectList::Invalid) + return nullptr; + return x808_objLists[int(type)].get(); } const CObjectList* CStateManager::GetObjectListById(EGameObjectList type) const { - const std::unique_ptr* lists = &x80c_allObjs; - return lists[int(type)].get(); + if (type == EGameObjectList::Invalid) + return nullptr; + return x808_objLists[int(type)].get(); } void CStateManager::RemoveObject(TUniqueId) {} @@ -1316,7 +1564,7 @@ void CStateManager::DeleteObjectRequest(TUniqueId id) entity->SetIsInGraveyard(true); - x858_objectGraveyard.push_back(entity->GetUniqueId()); + x854_objectGraveyard.push_back(entity->GetUniqueId()); entity->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); entity->SetIsScriptingBlocked(true); @@ -1327,8 +1575,8 @@ void CStateManager::DeleteObjectRequest(TUniqueId id) } } -CEntity* CStateManager::ObjectById(TUniqueId uid) { return x80c_allObjs->GetObjectById(uid); } -const CEntity* CStateManager::GetObjectById(TUniqueId uid) const { return x80c_allObjs->GetObjectById(uid); } +CEntity* CStateManager::ObjectById(TUniqueId uid) { return GetAllObjectList().GetObjectById(uid); } +const CEntity* CStateManager::GetObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } void CStateManager::AreaUnloaded(TAreaId) {} @@ -1351,15 +1599,101 @@ void CStateManager::BuildNearList(rstl::reserved_vector& listOu { } -void CStateManager::UpdateActorInSortedLists(CActor&) {} +void CStateManager::UpdateActorInSortedLists(CActor& act) +{ + if (!act.GetUseInSortedLists() || !act.xe4_27_) + return; -void CStateManager::UpdateSortedLists() {} + std::experimental::optional aabb = CalculateObjectBounds(act); + bool actorInLists = x874_sortedListManager->ActorInLists(&act); + if (actorInLists || aabb) + { + act.xe4_27_ = false; + if (actorInLists) + { + if (!act.GetActive() || !aabb) + { + x874_sortedListManager->Remove(&act); + } + else + { + x874_sortedListManager->Move(&act, *aabb); + } + } + else if (act.GetActive() && aabb) + { + x874_sortedListManager->Insert(&act, *aabb); + } + } +} -zeus::CAABox CStateManager::CalculateObjectBounds(const CActor&) { return {}; } +void CStateManager::UpdateSortedLists() +{ + if (!x850_world) + return; + for (CEntity* actor : GetActorObjectList()) + UpdateActorInSortedLists(static_cast(*actor)); +} -void CStateManager::AddObject(CEntity&) {} +std::experimental::optional CStateManager::CalculateObjectBounds(const CActor& actor) +{ + rstl::optional_object bounds = actor.GetTouchBounds(); + if (bounds) + { + zeus::CAABox aabb; + aabb.accumulateBounds(bounds->min); + aabb.accumulateBounds(bounds->max); + if (TCastToConstPtr physAct = actor) + { + zeus::CAABox physAabb = physAct->GetBoundingBox(); + aabb.accumulateBounds(physAabb.min); + aabb.accumulateBounds(physAabb.max); + } + return {aabb}; + } + else + { + if (TCastToConstPtr physAct = actor) + return {physAct->GetBoundingBox()}; + } + return {}; +} -void CStateManager::AddObject(CEntity*) {} +void CStateManager::AddObject(CEntity& ent) +{ + if (ent.GetEditorId() != kInvalidEditorId) + x890_scriptIdMap.insert(std::make_pair(ent.GetEditorId(), ent.GetUniqueId())); + for (auto& list : x808_objLists) + list->AddObject(ent); + + if (ent.GetAreaIdAlways() == kInvalidAreaId && x84c_player && + ent.GetUniqueId() != x84c_player->GetUniqueId()) + ent.x4_areaId = x84c_player->GetAreaIdAlways(); + if (ent.GetAreaIdAlways() != kInvalidAreaId) + { + CGameArea* area = x850_world->GetArea(ent.GetAreaIdAlways()); + if (area->IsPostConstructed()) + area->GetAreaObjects().AddObject(ent); + } + + if (TCastToPtr act = ent) + UpdateActorInSortedLists(*act.GetPtr()); + + ent.AcceptScriptMsg(EScriptObjectMessage::Registered, kInvalidUniqueId, *this); + + if (ent.GetAreaIdAlways() != kInvalidAreaId && x850_world) + { + CGameArea* area = x850_world->GetArea(ent.GetAreaIdAlways()); + if (area->IsValidated()) + SendScriptMsg(&ent, kInvalidUniqueId, EScriptObjectMessage::InitializedInArea); + } +} + +void CStateManager::AddObject(CEntity* ent) +{ + if (ent) + AddObject(*ent); +} bool CStateManager::RayStaticIntersection(const zeus::CVector3f&, const zeus::CVector3f&, float, const CMaterialFilter&) const @@ -1387,7 +1721,7 @@ TUniqueId CStateManager::AllocateUniqueId() if (x0_nextFreeIndex == lastIndex) LogModule.report(logvisor::Fatal, "Object List Full!"); } - while (x80c_allObjs->GetObjectByIndex(ourIndex) != nullptr); + while (GetAllObjectList().GetObjectByIndex(ourIndex) != nullptr); x8_idArr[ourIndex] = (x8_idArr[ourIndex] + 1) & 0x3f; if (((ourIndex | ((x8_idArr[ourIndex]) << 10)) & 0xFFFF) == kInvalidUniqueId) diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp index d3a43e2ae..a43424c31 100644 --- a/Runtime/CStateManager.hpp +++ b/Runtime/CStateManager.hpp @@ -83,6 +83,7 @@ class CStateManager s16 x0_nextFreeIndex = 0; TUniqueId x8_idArr[1024] = {}; + /* std::unique_ptr x80c_allObjs; std::unique_ptr x814_actorObjs; std::unique_ptr x81c_physActorObjs; @@ -91,12 +92,22 @@ class CStateManager std::unique_ptr x834_listenAiObjs; std::unique_ptr x83c_aiWaypointObjs; std::unique_ptr x844_platformAndDoorObjs; + */ + std::unique_ptr x808_objLists[8] = + {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 x858_objectGraveyard; + std::vector x854_objectGraveyard; struct CStateManagerContainer { @@ -132,8 +143,8 @@ class CStateManager TAreaId x8cc_nextAreaId = 0; TAreaId x8d0_prevAreaId = kInvalidAreaId; //u32 x8d0_extFrameIdx = 0; - //u32 x8d4_updateFrameIdx = 0; - //u32 x8d8_drawFrameIdx = 0; + u32 x8d4_inputFrameIdx = 0; + u32 x8d8_updateFrameIdx = 0; u32 x8dc_objectDrawToken = 0; std::vector x8e0_dynamicLights; @@ -183,11 +194,14 @@ class CStateManager u16 _dummy = 0; }; + u32 xeec_hintIdx = -1; + u32 xef0_hintPeriods = 0; + SOnScreenTex xef4_pendingScreenTex; ResId xf08_pauseHudMessage = -1; float xf0c_ = 0.f; float xf10_ = 0.f; - float xf14_ = 0.f; + float xf14_curTimeMod900 = 0.f; TUniqueId xf18_ = kInvalidUniqueId; float xf1c_ = 0.f; u32 xf20_ = 0; @@ -315,10 +329,19 @@ public: void ProcessInput(const CFinalInput& input); void Update(float dt); void UpdateGameState(); + void UpdateHintState(float dt); + void PreThinkEffects(float dt); + void MovePlatforms(float dt); + void MoveDoors(float dt); + void CrossTouchActors(float dt); + void ThinkEffectsAndActors(float dt); + void UpdatePlayer(float dt); + void ShowPausedHUDMemo(ResId strg, float time); + void BringOutYourDead(); void FrameBegin(s32 frameCount); void InitializeState(ResId mlvlId, TAreaId aid, ResId mreaId); void CreateStandardGameObjects(); - const std::unique_ptr& GetObjectList() const { return x80c_allObjs; } + const std::unique_ptr& GetObjectList() const { return x808_objLists[0]; } CObjectList* ObjectListById(EGameObjectList type); const CObjectList* GetObjectListById(EGameObjectList type) const; void RemoveObject(TUniqueId); @@ -342,7 +365,7 @@ public: const zeus::CAABox&, const CMaterialFilter&, const CActor*) const; void UpdateActorInSortedLists(CActor&); void UpdateSortedLists(); - zeus::CAABox CalculateObjectBounds(const CActor&); + std::experimental::optional CalculateObjectBounds(const CActor&); void AddObject(CEntity&); void AddObject(CEntity*); bool RayStaticIntersection(const zeus::CVector3f&, const zeus::CVector3f&, float, @@ -384,14 +407,14 @@ public: CPlayer& GetPlayer() const { return *x84c_player; } CPlayer* Player() const { return x84c_player.get(); } - CObjectList& GetAllObjectList() const { return *x80c_allObjs; } - CActorList& GetActorObjectList() const { return *x814_actorObjs; } - CPhysicsActorList& GetPhysicsActorObjectList() const { return *x81c_physActorObjs; } - CGameCameraList& GetCameraObjectList() const { return *x824_cameraObjs; } - CGameLightList& GetLightObjectList() const { return *x82c_lightObjs; } - CListeningAiList& GetListeningAiObjectList() const { return *x834_listenAiObjs; } - CAiWaypointList& GetAiWaypointObjectList() const { return *x83c_aiWaypointObjs; } - CPlatformAndDoorList& GetPlatformAndDoorObjectList() const { return *x844_platformAndDoorObjs; } + 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 SetLastTriggerId(TUniqueId uid) { xf74_lastTrigger = uid; } TUniqueId GetLastTriggerId() const { return xf74_lastTrigger; } diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index ee5d1b95c..309e026d1 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -1,4 +1,5 @@ #include "CBallCamera.hpp" +#include "TCastTo.hpp" namespace urde { @@ -11,6 +12,11 @@ CBallCamera::CBallCamera(TUniqueId uid, TUniqueId id2, const zeus::CTransform& x { } +void CBallCamera::Accept(IVisitor& visitor) +{ + visitor.Visit(this); +} + void CBallCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) { } diff --git a/Runtime/Camera/CBallCamera.hpp b/Runtime/Camera/CBallCamera.hpp index f8e4eed26..f10c4d568 100644 --- a/Runtime/Camera/CBallCamera.hpp +++ b/Runtime/Camera/CBallCamera.hpp @@ -11,6 +11,7 @@ class CBallCamera : public CGameCamera public: CBallCamera(TUniqueId, TUniqueId, const zeus::CTransform& xf, float, float, float, float); + void Accept(IVisitor& visitor); void ProcessInput(const CFinalInput&, CStateManager& mgr); void Reset(const zeus::CTransform&, CStateManager& mgr); }; diff --git a/Runtime/Camera/CCameraFilter.cpp b/Runtime/Camera/CCameraFilter.cpp index cf5c91e4b..b42a8ff63 100644 --- a/Runtime/Camera/CCameraFilter.cpp +++ b/Runtime/Camera/CCameraFilter.cpp @@ -7,6 +7,11 @@ namespace urde { +void CCameraFilterPass::Update(float dt) +{ + +} + void CCameraFilterPass::DrawFilter(EFilterType type, EFilterShape shape, const zeus::CColor& color, const CTexture* tex, float uvScale) { diff --git a/Runtime/Camera/CCameraFilter.hpp b/Runtime/Camera/CCameraFilter.hpp index 0db3c672c..e86fb7e58 100644 --- a/Runtime/Camera/CCameraFilter.hpp +++ b/Runtime/Camera/CCameraFilter.hpp @@ -42,6 +42,7 @@ private: static void DrawFilterShape(EFilterShape shape, const zeus::CColor& color, const CTexture* tex, float uvScale); public: + void Update(float dt); void SetFilter(EFilterType type, EFilterShape shape, float, const zeus::CColor& color, u32) {} void DisableFilter(float) {} @@ -70,6 +71,7 @@ private: //bool x2d_noPersistentCopy = false; //u32 x30_persistentBuf = 0; +public: void Draw(); void Update(float dt); void SetBlur(EBlurType type, float amount, float duration); diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp index 0d2749fff..e337ae045 100644 --- a/Runtime/Camera/CCameraManager.cpp +++ b/Runtime/Camera/CCameraManager.cpp @@ -15,6 +15,8 @@ #include "CObjectList.hpp" #include "TCastTo.hpp" #include "CCinematicCamera.hpp" +#include "CBallCamera.hpp" +#include "CInterpolationCamera.hpp" namespace urde { @@ -170,6 +172,25 @@ const CGameCamera* CCameraManager::GetCurrentCamera(const CStateManager& stateMg return static_cast(camList->GetObjectById(GetCurrentCameraId())); } +void CCameraManager::CreateStandardCameras(CStateManager& stateMgr) +{ + TUniqueId fpId = stateMgr.AllocateUniqueId(); + x7c_fpCamera = new CFirstPersonCamera(fpId, zeus::CTransform::Identity(), + stateMgr.Player()->GetUniqueId(), g_tweakPlayer->GetX184(), + sFirstPersonFOV, sNearPlane, sFarPlane, sAspect); + stateMgr.AddObject(x7c_fpCamera); + stateMgr.Player()->SetCameraState(CPlayer::EPlayerCameraState::Zero, stateMgr); + SetCurrentCameraId(fpId, stateMgr); + + x80_ballCamera = new CBallCamera(stateMgr.AllocateUniqueId(), stateMgr.Player()->GetUniqueId(), + zeus::CTransform::Identity(), sThirdPersonFOV, + sNearPlane, sFarPlane, sAspect); + stateMgr.AddObject(x80_ballCamera); + + x88_interpCamera = new CInterpolationCamera(stateMgr.AllocateUniqueId(), zeus::CTransform::Identity()); + stateMgr.AddObject(x88_interpCamera); +} + void CCameraManager::SkipCinematic(CStateManager& stateMgr) { TUniqueId camId = GetCurrentCameraId(); @@ -263,4 +284,17 @@ void CCameraManager::SetSpecialCameras(CFirstPersonCamera& fp, CBallCamera& ball x7c_fpCamera = &fp; x80_ballCamera = &ball; } + +void CCameraManager::ProcessInput(const CFinalInput& input, CStateManager& stateMgr) +{ + for (CEntity* ent : stateMgr.GetCameraObjectList()) + { + if (!ent) + continue; + CGameCamera& cam = static_cast(*ent); + if (input.ControllerIdx() != cam.x16c_controllerIdx) + continue; + cam.ProcessInput(input, stateMgr); + } +} } diff --git a/Runtime/Camera/CCameraManager.hpp b/Runtime/Camera/CCameraManager.hpp index c172ce968..4e4e20500 100644 --- a/Runtime/Camera/CCameraManager.hpp +++ b/Runtime/Camera/CCameraManager.hpp @@ -13,6 +13,8 @@ class CStateManager; class CGameCamera; class CCameraShakeData; class CScriptWater; +class CInterpolationCamera; +class CFinalInput; class CCameraManager { @@ -32,6 +34,7 @@ class CCameraManager CFirstPersonCamera* x7c_fpCamera = nullptr; CBallCamera* x80_ballCamera = nullptr; s16 x84_rumbleId = -1; + CInterpolationCamera* x88_interpCamera = nullptr; float x90_ = 0.f; float x94_ = 1.f; float x98_ = 0.f; @@ -87,6 +90,7 @@ public: CGameCamera* GetCurrentCamera(CStateManager& stateMgr) const; const CGameCamera* GetCurrentCamera(const CStateManager& stateMgr) const; void SetCurrentCameraId(TUniqueId id, CStateManager& stateMgr) {x0_curCameraId = id;} + void CreateStandardCameras(CStateManager& stateMgr); TUniqueId GetCurrentCameraId() const { if (x4_cineCameras.size()) @@ -116,6 +120,8 @@ public: void UpdateListener(CStateManager&); float CalculateFogDensity(CStateManager&, const CScriptWater*); + + void ProcessInput(const CFinalInput& input, CStateManager& stateMgr); }; } diff --git a/Runtime/Camera/CFirstPersonCamera.cpp b/Runtime/Camera/CFirstPersonCamera.cpp index 659d89410..618b9a119 100644 --- a/Runtime/Camera/CFirstPersonCamera.cpp +++ b/Runtime/Camera/CFirstPersonCamera.cpp @@ -19,6 +19,11 @@ CFirstPersonCamera::CFirstPersonCamera(TUniqueId uid, const zeus::CTransform& xf { } +void CFirstPersonCamera::Accept(IVisitor& visitor) +{ + visitor.Visit(this); +} + void CFirstPersonCamera::PreThink(float, CStateManager&) {} void CFirstPersonCamera::Think(float, CStateManager&) diff --git a/Runtime/Camera/CFirstPersonCamera.hpp b/Runtime/Camera/CFirstPersonCamera.hpp index 67f610a13..447b08c7c 100644 --- a/Runtime/Camera/CFirstPersonCamera.hpp +++ b/Runtime/Camera/CFirstPersonCamera.hpp @@ -25,8 +25,10 @@ class CFirstPersonCamera : public CGameCamera float x1d4_ = 0.f; public: - CFirstPersonCamera(TUniqueId, const zeus::CTransform& xf, TUniqueId, float, float, float, float, float); + CFirstPersonCamera(TUniqueId, const zeus::CTransform& xf, TUniqueId, float, + float fov, float nearplane, float farplane, float aspect); + void Accept(IVisitor& visitor); void PreThink(float, CStateManager&); void Think(float, CStateManager&); void ProcessInput(const CFinalInput&, CStateManager& mgr); diff --git a/Runtime/Camera/CGameCamera.cpp b/Runtime/Camera/CGameCamera.cpp index e1dfca69d..ad8fde548 100644 --- a/Runtime/Camera/CGameCamera.cpp +++ b/Runtime/Camera/CGameCamera.cpp @@ -8,7 +8,7 @@ namespace urde CGameCamera::CGameCamera(TUniqueId uid, bool active, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, float fovy, float znear, float zfar, float aspect, TUniqueId uid2, - bool b1, u32 w1) + bool b1, u32 controllerIdx) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Unknown), CActorParameters::None(), kInvalidUniqueId) , xe8_watchedObject(uid2) @@ -17,7 +17,7 @@ CGameCamera::CGameCamera(TUniqueId uid, bool active, const std::string& name, co , x160_znear(znear) , x164_zfar(zfar) , x168_aspect(aspect) -, x16c_(w1) +, x16c_controllerIdx(controllerIdx) , x170_24_perspDirty(true) , x170_25_disablesInput(b1) , x180_(fovy) diff --git a/Runtime/Camera/CGameCamera.hpp b/Runtime/Camera/CGameCamera.hpp index 20c9ed72e..f11dba495 100644 --- a/Runtime/Camera/CGameCamera.hpp +++ b/Runtime/Camera/CGameCamera.hpp @@ -10,6 +10,9 @@ class CFinalInput; class CGameCamera : public CActor { + friend class CStateManager; + friend class CCameraManager; + TUniqueId xe8_watchedObject; zeus::CMatrix4f xec_perspectiveMatrix; zeus::CTransform x12c_; @@ -17,7 +20,7 @@ class CGameCamera : public CActor float x160_znear; float x164_zfar; float x168_aspect; - u32 x16c_; + u32 x16c_controllerIdx; bool x170_24_perspDirty : 1; bool x170_25_disablesInput : 1; float x174_ = 0.f; @@ -27,7 +30,7 @@ class CGameCamera : public CActor float x184_fov; public: CGameCamera(TUniqueId, bool active, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, - float fov, float nearz, float farz, float aspect, TUniqueId, bool, u32); + float fov, float nearz, float farz, float aspect, TUniqueId, bool, u32 controllerIdx); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void SetActive(bool active); diff --git a/Runtime/Camera/CInterpolationCamera.cpp b/Runtime/Camera/CInterpolationCamera.cpp new file mode 100644 index 000000000..ffea9411f --- /dev/null +++ b/Runtime/Camera/CInterpolationCamera.cpp @@ -0,0 +1,47 @@ +#include "CInterpolationCamera.hpp" +#include "CCameraManager.hpp" +#include "TCastTo.hpp" + +namespace urde +{ + +CInterpolationCamera::CInterpolationCamera(TUniqueId uid, const zeus::CTransform& xf) +: CGameCamera(uid, false, "Interpolation Camera", + CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList, kInvalidEditorId), + xf, CCameraManager::ThirdPersonFOV(), CCameraManager::NearPlane(), + CCameraManager::FarPlane(), CCameraManager::Aspect(), kInvalidUniqueId, false, 0) +{ + +} + +void CInterpolationCamera::Accept(IVisitor& visitor) +{ + visitor.Visit(this); +} + +void CInterpolationCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) +{ + CGameCamera::AcceptScriptMsg(msg, sender, mgr); +} + +void CInterpolationCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) +{ + // Empty +} + +void CInterpolationCamera::Render(const CStateManager& mgr) const +{ + // Empty +} + +void CInterpolationCamera::Reset(const zeus::CTransform&, CStateManager& mgr) +{ + // Empty +} + +void CInterpolationCamera::Think(float, CStateManager& mgr) +{ + +} + +} diff --git a/Runtime/Camera/CInterpolationCamera.hpp b/Runtime/Camera/CInterpolationCamera.hpp new file mode 100644 index 000000000..dbe2cf754 --- /dev/null +++ b/Runtime/Camera/CInterpolationCamera.hpp @@ -0,0 +1,23 @@ +#ifndef __URDE_CINTERPOLATIONCAMERA_HPP__ +#define __URDE_CINTERPOLATIONCAMERA_HPP__ + +#include "CGameCamera.hpp" + +namespace urde +{ + +class CInterpolationCamera : public CGameCamera +{ +public: + CInterpolationCamera(TUniqueId uid, const zeus::CTransform& xf); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void ProcessInput(const CFinalInput&, CStateManager& mgr); + void Render(const CStateManager&) const; + void Reset(const zeus::CTransform&, CStateManager& mgr); + void Think(float, CStateManager &); +}; + +} + +#endif // __URDE_CINTERPOLATIONCAMERA_HPP__ diff --git a/Runtime/Camera/CMakeLists.txt b/Runtime/Camera/CMakeLists.txt index 599fd59c3..09042a348 100644 --- a/Runtime/Camera/CMakeLists.txt +++ b/Runtime/Camera/CMakeLists.txt @@ -3,6 +3,7 @@ set(CAMERA_SOURCES CGameCamera.hpp CGameCamera.cpp CFirstPersonCamera.hpp CFirstPersonCamera.cpp CBallCamera.hpp CBallCamera.cpp + CInterpolationCamera.hpp CInterpolationCamera.cpp CPathCamera.hpp CPathCamera.cpp CCinematicCamera.hpp CCinematicCamera.cpp CCameraShakeData.hpp CCameraShakeData.cpp diff --git a/Runtime/Collision/CCollisionActor.cpp b/Runtime/Collision/CCollisionActor.cpp index b6b5e4d38..f6b07408f 100644 --- a/Runtime/Collision/CCollisionActor.cpp +++ b/Runtime/Collision/CCollisionActor.cpp @@ -71,11 +71,11 @@ void CCollisionActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, C { case EScriptObjectMessage::ToggleActive: case EScriptObjectMessage::Deleted: - case EScriptObjectMessage::Constructed: + case EScriptObjectMessage::InitializedInArea: break; case EScriptObjectMessage::Alert: case EScriptObjectMessage::InternalMessage10: - case EScriptObjectMessage::InternalMessage11: + case EScriptObjectMessage::Registered: { CEntity* ent = mgr.ObjectById(x25c_owner); if (ent) diff --git a/Runtime/Collision/CGameCollision.cpp b/Runtime/Collision/CGameCollision.cpp index 196bc48ab..ba933f780 100644 --- a/Runtime/Collision/CGameCollision.cpp +++ b/Runtime/Collision/CGameCollision.cpp @@ -45,6 +45,11 @@ void CGameCollision::InitCollision() CCollisionPrimitive::InitEndColliders(); } +void CGameCollision::Move(CStateManager& mgr, CPlayer& player, float dt, const rstl::reserved_vector*) +{ + +} + bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CVector3f& v) { if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::Scannable)) || diff --git a/Runtime/Collision/CGameCollision.hpp b/Runtime/Collision/CGameCollision.hpp index be462226f..78f54279c 100644 --- a/Runtime/Collision/CGameCollision.hpp +++ b/Runtime/Collision/CGameCollision.hpp @@ -1,6 +1,8 @@ #ifndef __URDE_CGAMECOLLISION_HPP__ #define __URDE_CGAMECOLLISION_HPP__ #include "zeus/CVector3f.hpp" +#include "rstl.hpp" +#include "RetroTypes.hpp" namespace urde { @@ -14,6 +16,8 @@ class CCollisionInfo; class CCollisionInfoList; class CMaterialList; class CStateManager; +class CPlayer; + class CGameCollision { public: @@ -24,6 +28,7 @@ public: static bool NullBooleanCollider(const CInternalCollisionStructure&) { return false; } static bool NullCollisionCollider(const CInternalCollisionStructure&, CCollisionInfoList&) { return false; } static void InitCollision(); + static void Move(CStateManager& mgr, CPlayer& player, float dt, const rstl::reserved_vector*); static bool CanBlock(const CMaterialList&, const zeus::CVector3f&); static bool IsFloor(const CMaterialList&, const zeus::CVector3f&); diff --git a/Runtime/Input/CFinalInput.hpp b/Runtime/Input/CFinalInput.hpp index 6db5c6635..b655d33ea 100644 --- a/Runtime/Input/CFinalInput.hpp +++ b/Runtime/Input/CFinalInput.hpp @@ -10,6 +10,7 @@ namespace urde class CFinalInput { + friend class CStateManager; float x0_dt; u32 x4_controllerIdx; float x8_anaLeftX; diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index 8ccf7b3ac..ec14fb8aa 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -5,6 +5,8 @@ namespace urde namespace MP1 { +CSamusHud* CSamusHud::g_SamusHud = nullptr; + CSamusHud::CSamusHud(CStateManager& stateMgr) { @@ -25,5 +27,15 @@ void CSamusHud::Touch() } +void CSamusHud::DisplayHudMemo(const std::u16string& text, const SHudMemoInfo& info) +{ + +} + +void CSamusHud::_DeferHintMemo(ResId strg, u32 timePeriods, const SHudMemoInfo& info) +{ + +} + } } diff --git a/Runtime/MP1/CSamusHud.hpp b/Runtime/MP1/CSamusHud.hpp index 3e9ecaeb2..3fd24ce7a 100644 --- a/Runtime/MP1/CSamusHud.hpp +++ b/Runtime/MP1/CSamusHud.hpp @@ -8,6 +8,14 @@ namespace urde class CGuiFrame; class CStateManager; +struct SHudMemoInfo +{ + float x0_; + bool x4_; + bool x5_; + bool x6_; +}; + namespace MP1 { @@ -15,11 +23,19 @@ class CSamusHud { friend class CInGameGuiManager; CGuiFrame* x274_loadedBaseHud = nullptr; + static CSamusHud* g_SamusHud; public: CSamusHud(CStateManager& stateMgr); bool CheckLoadComplete(CStateManager& stateMgr); void OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr); void Touch(); + static void DisplayHudMemo(const std::u16string& text, const SHudMemoInfo& info); + static void DeferHintMemo(ResId strg, u32 timePeriods, const SHudMemoInfo& info) + { + if (g_SamusHud) + g_SamusHud->_DeferHintMemo(strg, timePeriods, info); + } + void _DeferHintMemo(ResId strg, u32 timePeriods, const SHudMemoInfo& info); }; } diff --git a/Runtime/MkCastTo.py b/Runtime/MkCastTo.py index b72cafd8a..8627b4870 100644 --- a/Runtime/MkCastTo.py +++ b/Runtime/MkCastTo.py @@ -24,6 +24,7 @@ CENTITY_TYPES = ( ('CGameLight', 'World/CGameLight.hpp'), ('CGameProjectile', 'Weapon/CGameProjectile.hpp'), ('CHUDBillboardEffect', 'World/CHUDBillboardEffect.hpp'), + ('CInterpolationCamera', 'Camera/CInterpolationCamera.hpp'), Namespace('MP1'), ('CMetroidPrimeRelay', 'MP1/World/CMetroidPrimeRelay.hpp', 'MP1'), EndNamespace(), diff --git a/Runtime/Particle/CDecalManager.cpp b/Runtime/Particle/CDecalManager.cpp index de35bb00f..b75d45a52 100644 --- a/Runtime/Particle/CDecalManager.cpp +++ b/Runtime/Particle/CDecalManager.cpp @@ -50,4 +50,9 @@ void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateMan } } +void CDecalManager::Update(float dt, CStateManager& mgr) +{ + +} + } diff --git a/Runtime/Particle/CDecalManager.hpp b/Runtime/Particle/CDecalManager.hpp index 819292d77..937988407 100644 --- a/Runtime/Particle/CDecalManager.hpp +++ b/Runtime/Particle/CDecalManager.hpp @@ -33,6 +33,7 @@ public: static void Initialize(); static void Shutdown(); static void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr); + static void Update(float dt, CStateManager& mgr); }; } diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index 9e4fe441f..87b2ed2ed 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -17,6 +17,8 @@ static logvisor::Module Log("urde::CElementGen"); static bool s_inCreateNewParticles = false; +CRandom16 CElementGen::g_GlobalSeed = 99; + int CElementGen::g_ParticleAliveCount; int CElementGen::g_ParticleSystemAliveCount; s32 CElementGen::g_FreeIndex; diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 3339a9dad..8270dc48b 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -25,7 +25,9 @@ class CParticleElectric; class CElementGen : public CParticleGen { + static CRandom16 g_GlobalSeed; public: + static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); } enum class EModelOrientationType { Normal, diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index 311a4e423..d5ab7c46e 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -10,6 +10,8 @@ namespace urde { +CRandom16 CParticleElectric::g_GlobalSeed = 99; + void CParticleElectric::RenderSwooshes() { } diff --git a/Runtime/Particle/CParticleElectric.hpp b/Runtime/Particle/CParticleElectric.hpp index 94c94c108..eb0dbece4 100644 --- a/Runtime/Particle/CParticleElectric.hpp +++ b/Runtime/Particle/CParticleElectric.hpp @@ -13,7 +13,9 @@ class CElementGen; class CParticleElectric : public CParticleGen { + static CRandom16 g_GlobalSeed; public: + static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); } struct CLineManager { std::unique_ptr SSWH; diff --git a/Runtime/Weapon/CMakeLists.txt b/Runtime/Weapon/CMakeLists.txt index 7e3fb96b8..9e935aba4 100644 --- a/Runtime/Weapon/CMakeLists.txt +++ b/Runtime/Weapon/CMakeLists.txt @@ -23,6 +23,7 @@ set(WEAPON_SOURCES CBeamInfo.hpp CBeamInfo.cpp CPlasmaProjectile.hpp CPlasmaProjectile.cpp CEnergyProjectile.cpp CEnergyProjectile.cpp + CProjectileWeapon.hpp CProjectileWeapon.cpp CExplosion.hpp CExplosion.cpp CBomb.hpp CBomb.cpp CPowerBomb.hpp CPowerBomb.cpp) diff --git a/Runtime/Weapon/CProjectileWeapon.cpp b/Runtime/Weapon/CProjectileWeapon.cpp new file mode 100644 index 000000000..e5d8ff630 --- /dev/null +++ b/Runtime/Weapon/CProjectileWeapon.cpp @@ -0,0 +1,9 @@ +#include "CProjectileWeapon.hpp" + +namespace urde +{ + +CRandom16 CProjectileWeapon::g_GlobalSeed = 99; + + +} diff --git a/Runtime/Weapon/CProjectileWeapon.hpp b/Runtime/Weapon/CProjectileWeapon.hpp new file mode 100644 index 000000000..502cbfa34 --- /dev/null +++ b/Runtime/Weapon/CProjectileWeapon.hpp @@ -0,0 +1,19 @@ +#ifndef __URDE_CPROJECTILEWEAPON_HPP__ +#define __URDE_CPROJECTILEWEAPON_HPP__ + +#include "RetroTypes.hpp" +#include "CRandom16.hpp" + +namespace urde +{ + +class CProjectileWeapon +{ + static CRandom16 g_GlobalSeed; +public: + static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); } +}; + +} + +#endif // __URDE_CPROJECTILEWEAPON_HPP__ diff --git a/Runtime/World/CActor.cpp b/Runtime/World/CActor.cpp index 82aa11e17..27577ab05 100644 --- a/Runtime/World/CActor.cpp +++ b/Runtime/World/CActor.cpp @@ -43,7 +43,7 @@ void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMana case EScriptObjectMessage::Decrement: RemoveEmitter(); break; - case EScriptObjectMessage::InternalMessage11: // 33 + case EScriptObjectMessage::Registered: // 33 { if (x98_scanObjectInfo) AddMaterial(EMaterialTypes::Scannable, mgr); @@ -66,7 +66,7 @@ void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMana #endif } break; - case EScriptObjectMessage::Constructed: // 35 + case EScriptObjectMessage::InitializedInArea: // 35 { for (const SConnection& conn : x20_conns) { diff --git a/Runtime/World/CActorModelParticles.cpp b/Runtime/World/CActorModelParticles.cpp index cbdda89d8..5b467fdaa 100644 --- a/Runtime/World/CActorModelParticles.cpp +++ b/Runtime/World/CActorModelParticles.cpp @@ -152,4 +152,9 @@ void CActorModelParticles::AddStragglersToRenderer(const CStateManager& mgr) } } +void CActorModelParticles::Update(float dt, CStateManager& mgr) +{ + +} + } diff --git a/Runtime/World/CActorModelParticles.hpp b/Runtime/World/CActorModelParticles.hpp index c91f156df..a22333712 100644 --- a/Runtime/World/CActorModelParticles.hpp +++ b/Runtime/World/CActorModelParticles.hpp @@ -85,6 +85,7 @@ class CActorModelParticles public: CActorModelParticles(); void AddStragglersToRenderer(const CStateManager& mgr); + void Update(float dt, CStateManager& mgr); }; } diff --git a/Runtime/World/CEnvFxManager.cpp b/Runtime/World/CEnvFxManager.cpp index 74b6ce7e7..04595406a 100644 --- a/Runtime/World/CEnvFxManager.cpp +++ b/Runtime/World/CEnvFxManager.cpp @@ -9,6 +9,11 @@ CEnvFxManager::CEnvFxManager() } +void CEnvFxManager::Update(float, const CStateManager&) +{ + +} + void CEnvFxManager::Render(const CStateManager& mgr) { diff --git a/Runtime/World/CEnvFxManager.hpp b/Runtime/World/CEnvFxManager.hpp index db3ca9dae..e9b39c489 100644 --- a/Runtime/World/CEnvFxManager.hpp +++ b/Runtime/World/CEnvFxManager.hpp @@ -42,7 +42,7 @@ public: CEnvFxManager(); void AsyncLoadResources(CStateManager& mgr); - void Update(float, float, EEnvFxType, const CStateManager&); + void Update(float, const CStateManager&); void Render(const CStateManager& mgr); void SetFxDensity(s32, float); void MoveWrapCells(s32, s32); diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index 62da725c4..c8c6f9d32 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -329,6 +329,8 @@ public: bool IsPostConstructed() const {return xf0_24_postConstructed;} const CPostConstructed* GetPostConstructed() const {return x12c_postConstructed.get();} + bool IsValidated() const { return xf0_28_validated; } + void SetAreaAttributes(const CScriptAreaAttributes* areaAttributes); bool GetActive() const { return xf0_25_active; } void SetActive(bool active) { xf0_25_active = active; } diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index 2eb0950d6..da41e076d 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -6,6 +6,9 @@ #include "CSimplePool.hpp" #include "GameGlobalObjects.hpp" #include "Particle/CGenDescription.hpp" +#include "Camera/CFirstPersonCamera.hpp" +#include "Camera/CBallCamera.hpp" +#include "Camera/CCinematicCamera.hpp" #include "TCastTo.hpp" namespace urde @@ -94,6 +97,13 @@ rstl::optional_object CPlayer::GetTouchBounds() const { return {}; void CPlayer::Touch(CActor&, CStateManager& mgr) {} +void CPlayer::DoPreThink(float dt, CStateManager& mgr) +{ + PreThink(dt, mgr); + if (CEntity* ent = mgr.ObjectById(xa00_)) + ent->PreThink(dt, mgr); +} + void CPlayer::UpdateScanningState(const CFinalInput& input, CStateManager& mgr, float) {} void CPlayer::ValidateScanning(const CFinalInput& input, CStateManager& mgr) {} @@ -328,6 +338,36 @@ void CPlayer::UpdateCinematicState(CStateManager& mgr) } } +void CPlayer::SetCameraState(EPlayerCameraState camState, CStateManager& stateMgr) +{ + if (x2f4_cameraState == camState) + return; + x2f4_cameraState = camState; + CCameraManager* camMgr = stateMgr.GetCameraManager(); + switch (camState) + { + case EPlayerCameraState::Zero: + camMgr->SetCurrentCameraId(camMgr->GetFirstPersonCamera()->GetUniqueId(), stateMgr); + x768_morphball->SetBallLightActive(stateMgr, false); + break; + case EPlayerCameraState::One: + case EPlayerCameraState::Three: + camMgr->SetCurrentCameraId(camMgr->GetBallCamera()->GetUniqueId(), stateMgr); + x768_morphball->SetBallLightActive(stateMgr, true); + break; + case EPlayerCameraState::Two: + break; + case EPlayerCameraState::Four: + { + bool ballLight = false; + if (TCastToPtr cineCam = camMgr->GetCurrentCamera(stateMgr)) + ballLight = x2f8_morphTransState == EPlayerMorphBallState::Morphed && cineCam->GetW1() & 0x40; + x768_morphball->SetBallLightActive(stateMgr, ballLight); + break; + } + } +} + void CPlayer::Touch() {} void CPlayer::CVisorSteam::SetSteam(float a, float b, float c, ResId d, bool e) diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index fc126684d..b4e89f973 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -56,6 +56,15 @@ public: Unmorphing }; + enum class EPlayerCameraState + { + Zero, + One, + Two, + Three, + Four + }; + private: struct CVisorSteam { @@ -100,7 +109,7 @@ private: float x2d4_ = 0.f; zeus::CAABox x2d8_; float x2f0_ = 0.f; - u32 x2f4_cameraState = 0; + EPlayerCameraState x2f4_cameraState = EPlayerCameraState::Zero; EPlayerMorphBallState x2f8_morphTransState = EPlayerMorphBallState::Unmorphed; u32 x2fc_ = 0; float x300_ = 0.f; @@ -248,7 +257,7 @@ private: bool x9c6_26_ : 1; bool x9c6_27_ : 1; bool x9c6_28_ : 1; - bool x9c6_29_ : 1; + bool x9c6_29_disableInput : 1; bool x9c6_30_ : 1; bool x9c6_31_ : 1; bool x9c7_24_ : 1; @@ -309,6 +318,7 @@ public: bool IsUnderBetaMetroidAttack(CStateManager& mgr) const; rstl::optional_object GetTouchBounds() const; void Touch(CActor&, CStateManager& mgr); + void DoPreThink(float dt, CStateManager& mgr); void UpdateScanningState(const CFinalInput& input, CStateManager& mgr, float); void ValidateScanning(const CFinalInput& input, CStateManager& mgr); void SetScanningState(EPlayerScanState, CStateManager& mgr); @@ -413,6 +423,7 @@ public: float Get74C() const { return x74c_; } float GetMapAlpha() const { return x494_mapAlpha; } void UpdateCinematicState(CStateManager& mgr); + void SetCameraState(EPlayerCameraState camState, CStateManager& stateMgr); CPlayerGun* GetPlayerGun() const { return x490_gun.get(); } CMorphBall* GetMorphBall() const { return x768_morphball.get(); } diff --git a/Runtime/World/CScriptActor.cpp b/Runtime/World/CScriptActor.cpp index a543109c3..6255e3cdb 100644 --- a/Runtime/World/CScriptActor.cpp +++ b/Runtime/World/CScriptActor.cpp @@ -58,7 +58,7 @@ void CScriptActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta { CScriptColorModulate::FadeOutHelper(mgr, x8_uid, x2d4_alphaMin); } - else if (msg == EScriptObjectMessage::Constructed) + else if (msg == EScriptObjectMessage::InitializedInArea) { for (const SConnection& conn : x20_conns) { diff --git a/Runtime/World/CScriptAiJumpPoint.cpp b/Runtime/World/CScriptAiJumpPoint.cpp index 5c6ef61d6..be5f82d1c 100644 --- a/Runtime/World/CScriptAiJumpPoint.cpp +++ b/Runtime/World/CScriptAiJumpPoint.cpp @@ -32,7 +32,7 @@ void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId oth { AcceptScriptMsg(msg, other, mgr); - if (msg != EScriptObjectMessage::Constructed) + if (msg != EScriptObjectMessage::InitializedInArea) return; for (SConnection& conn : x20_conns) diff --git a/Runtime/World/CScriptAreaAttributes.cpp b/Runtime/World/CScriptAreaAttributes.cpp index 08445aeab..3bbc16cad 100644 --- a/Runtime/World/CScriptAreaAttributes.cpp +++ b/Runtime/World/CScriptAreaAttributes.cpp @@ -33,7 +33,7 @@ void CScriptAreaAttributes::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId if (x4_areaId == kInvalidAreaId) return; - if (msg == EScriptObjectMessage::Constructed) + if (msg == EScriptObjectMessage::InitializedInArea) { CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); area->SetAreaAttributes(this); diff --git a/Runtime/World/CScriptBeam.cpp b/Runtime/World/CScriptBeam.cpp index d31be1f56..efaf47686 100644 --- a/Runtime/World/CScriptBeam.cpp +++ b/Runtime/World/CScriptBeam.cpp @@ -46,7 +46,7 @@ void CScriptBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CSt else if (msg == EScriptObjectMessage::Decrement) { } - else if (msg == EScriptObjectMessage::InternalMessage11) + else if (msg == EScriptObjectMessage::Registered) { x154_projectileId = mgr.AllocateUniqueId(); mgr.AddObject(new CPlasmaProjectile(xe8_weaponDescription, x10_name + "-Projectile", diff --git a/Runtime/World/CScriptDistanceFog.cpp b/Runtime/World/CScriptDistanceFog.cpp index f20d97230..49305aa7e 100644 --- a/Runtime/World/CScriptDistanceFog.cpp +++ b/Runtime/World/CScriptDistanceFog.cpp @@ -41,7 +41,7 @@ void CScriptDistanceFog::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId obj if (x4_areaId == kInvalidAreaId || !GetActive()) return; - if (msg == EScriptObjectMessage::Constructed) + if (msg == EScriptObjectMessage::InitializedInArea) { if (!x60_explicit) return; diff --git a/Runtime/World/CScriptDock.cpp b/Runtime/World/CScriptDock.cpp index 6afb2ed38..574106ca2 100644 --- a/Runtime/World/CScriptDock.cpp +++ b/Runtime/World/CScriptDock.cpp @@ -90,7 +90,7 @@ void CScriptDock::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat { switch (msg) { - case EScriptObjectMessage::InternalMessage11: + case EScriptObjectMessage::Registered: { CGameArea* area = mgr.WorldNC()->GetArea(x260_area); if (area->GetDockCount() <= x25c_dock) @@ -103,7 +103,7 @@ void CScriptDock::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat case EScriptObjectMessage::Deleted: CleanUp(); break; - case EScriptObjectMessage::Constructed: + case EScriptObjectMessage::InitializedInArea: AreaLoaded(mgr); break; case EScriptObjectMessage::InternalMessage14: diff --git a/Runtime/World/CScriptEffect.cpp b/Runtime/World/CScriptEffect.cpp index 20f482286..935d2f0ad 100644 --- a/Runtime/World/CScriptEffect.cpp +++ b/Runtime/World/CScriptEffect.cpp @@ -7,6 +7,9 @@ namespace urde { +u32 CScriptEffect::g_NumParticlesUpdating = 0; +u32 CScriptEffect::g_NumParticlesRendered = 0; + CScriptEffect::CScriptEffect(TUniqueId uid, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, const zeus::CVector3f& scale, ResId partId, ResId elscId, bool, bool, bool, bool active, diff --git a/Runtime/World/CScriptEffect.hpp b/Runtime/World/CScriptEffect.hpp index 142aa287a..f82bf7df5 100644 --- a/Runtime/World/CScriptEffect.hpp +++ b/Runtime/World/CScriptEffect.hpp @@ -8,6 +8,8 @@ namespace urde class CScriptEffect : public CActor { + static u32 g_NumParticlesUpdating; + static u32 g_NumParticlesRendered; public: CScriptEffect(TUniqueId, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, const zeus::CVector3f& scale, @@ -16,6 +18,12 @@ public: bool, bool, bool, const CLightParameters& lParms, bool); void Accept(IVisitor& visitor); + + static void ResetParticleCounts() + { + g_NumParticlesUpdating = 0; + g_NumParticlesRendered = 0; + } }; } diff --git a/Runtime/World/CScriptShadowProjector.cpp b/Runtime/World/CScriptShadowProjector.cpp index f521f9ae4..4e35f976a 100644 --- a/Runtime/World/CScriptShadowProjector.cpp +++ b/Runtime/World/CScriptShadowProjector.cpp @@ -64,7 +64,7 @@ void CScriptShadowProjector::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId x110_25_shadowInvalidated = true; } - else if (msg == EScriptObjectMessage::Constructed) + else if (msg == EScriptObjectMessage::InitializedInArea) { for (const SConnection& conn : x20_conns) { diff --git a/Runtime/World/CScriptSound.cpp b/Runtime/World/CScriptSound.cpp index 5d5e4769c..e7b69e7e9 100644 --- a/Runtime/World/CScriptSound.cpp +++ b/Runtime/World/CScriptSound.cpp @@ -53,7 +53,7 @@ void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta switch (msg) { - case EScriptObjectMessage::InternalMessage11: + case EScriptObjectMessage::Registered: { } break; diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index c7dce8fc9..3521da993 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -565,6 +565,11 @@ void CWorld::PropogateAreaChain(CGameArea::EOcclusionState occlusionState, CGame area->SetOcclusionState(CGameArea::EOcclusionState::NotOccluded); } +void CWorld::Update(float dt) +{ + +} + void CWorld::PreRender() { for (CGameArea* head = x4c_chainHeads[3] ; diff --git a/Runtime/World/CWorld.hpp b/Runtime/World/CWorld.hpp index 555c27877..3760b6e34 100644 --- a/Runtime/World/CWorld.hpp +++ b/Runtime/World/CWorld.hpp @@ -188,6 +188,7 @@ public: static const CGameArea* GetAliveAreasEnd() { return skGlobalEnd; } static CGameArea* AliveAreasEnd() { return skGlobalNonConstEnd; } + void Update(float dt); void PreRender(); void TouchSky(); void DrawSky(const zeus::CTransform& xf) const; diff --git a/Runtime/World/ScriptObjectSupport.hpp b/Runtime/World/ScriptObjectSupport.hpp index 163654c1e..a41920c03 100644 --- a/Runtime/World/ScriptObjectSupport.hpp +++ b/Runtime/World/ScriptObjectSupport.hpp @@ -210,9 +210,9 @@ enum class EScriptObjectMessage InternalMessage08 = 30, InternalMessage09 = 31, InternalMessage10 = 32, - InternalMessage11 = 33, + Registered = 33, Deleted = 34, - Constructed = 35, + InitializedInArea = 35, InternalMessage14 = 36, InternalMessage15 = 37, InternalMessage16 = 38, diff --git a/amuse b/amuse index 54bbc7399..3d56d5f0c 160000 --- a/amuse +++ b/amuse @@ -1 +1 @@ -Subproject commit 54bbc7399a57a50ced2725094d9a0b8a4ea79c39 +Subproject commit 3d56d5f0ccd10a558f0e47746cfd64126da09380 diff --git a/hecl b/hecl index 63980109f..c3db26f4a 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 63980109fd91e72b4ec668918879af2779255c27 +Subproject commit c3db26f4a195a6db5f28dd160ea9849a707745c3 diff --git a/specter b/specter index d66529af9..614a06918 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit d66529af905afd39da49c6175c8bd9cf5c3a415e +Subproject commit 614a06918ab4ab0b3937f3a7f88ad170138585d3