From b8613d61f8d7b658a7f4787002b633fb74b728fa Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 7 Feb 2017 20:48:43 -1000 Subject: [PATCH] Tons of save-related fixes --- Editor/ProjectResourceFactoryBase.cpp | 1 + Editor/ProjectResourceFactoryMP1.cpp | 8 +-- Runtime/AutoMapper/CMapWorldInfo.cpp | 92 ++++++++++++++++++++++++--- Runtime/AutoMapper/CMapWorldInfo.hpp | 14 ++-- Runtime/CGameOptions.cpp | 16 ++--- Runtime/CGameOptions.hpp | 2 +- Runtime/CMemoryCardSys.cpp | 21 ++++-- Runtime/CPakFile.cpp | 42 ++++++++++++ Runtime/CPakFile.hpp | 51 ++++++--------- Runtime/CPlayerState.cpp | 10 +-- Runtime/CResLoader.cpp | 24 +++---- Runtime/CResLoader.hpp | 10 +-- Runtime/CSaveWorld.cpp | 6 +- Runtime/CSaveWorld.hpp | 1 + Runtime/RetroTypes.hpp | 1 + Runtime/World/CWorld.cpp | 13 ++-- Runtime/World/CWorld.hpp | 2 +- 17 files changed, 219 insertions(+), 95 deletions(-) diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 7ca04cbee..99c001ae0 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -884,6 +884,7 @@ void ProjectResourceFactoryBase::EnumerateNamedResources( std::this_thread::sleep_for(std::chrono::milliseconds(2)); lk.lock(); } + lk.unlock(); for (const auto& pair : m_catalogNameToTag) { if (!lambda(pair.first, pair.second)) diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index af6660d5b..7581a7f26 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -63,8 +63,8 @@ public: ResId TranslateOriginalToNew(ResId id) const { - auto search = std::lower_bound(m_origToNew.cbegin(), m_origToNew.cend(), - std::make_pair(id, ResId(0))); + auto search = std::lower_bound(m_origToNew.cbegin(), m_origToNew.cend(), id, + [](const auto& id, ResId test) -> bool { return id.first < test; }); if (search == m_origToNew.cend() || search->first != id) return -1; return search->second; @@ -72,8 +72,8 @@ public: ResId TranslateNewToOriginal(ResId id) const { - auto search = std::lower_bound(m_newToOrig.cbegin(), m_newToOrig.cend(), - std::make_pair(id, ResId(0))); + auto search = std::lower_bound(m_newToOrig.cbegin(), m_newToOrig.cend(), id, + [](const auto& id, ResId test) -> bool { return id.first < test; }); if (search == m_newToOrig.cend() || search->first != id) return -1; return search->second; diff --git a/Runtime/AutoMapper/CMapWorldInfo.cpp b/Runtime/AutoMapper/CMapWorldInfo.cpp index 17298025c..0df6bb6ee 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.cpp +++ b/Runtime/AutoMapper/CMapWorldInfo.cpp @@ -5,43 +5,115 @@ namespace urde { -CMapWorldInfo::CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& saveWorld, ResId mlvlId) +CMapWorldInfo::CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& savw, ResId mlvlId) { - /* TODO: implement */ + const CSaveWorldMemory& worldMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId); - const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); - auto saveWorldMem = std::find_if(memWorlds.cbegin(), memWorlds.cend(), - [&](const auto& test) -> bool { return test.first == mlvlId; }); - - if (saveWorldMem != memWorlds.cend()) + x4_visitedAreas.reserve((worldMem.GetAreaCount() + 31) / 32); + for (int i=0 ; iGetSaveWorldMemory(mlvlId); + for (int i=0 ; i(*this).IsAreaVisted(i), 1); + else + writer.WriteEncoded(0, 1); + } + + for (int i=0 ; i(*this).IsMapped(i), 1); + else + writer.WriteEncoded(0, 1); + } + + for (TEditorId doorId : savw.GetDoors()) + writer.WriteEncoded(IsDoorVisited(doorId), 1); + + writer.WriteEncoded(x38_worldVisited, 1); } void CMapWorldInfo::SetDoorVisited(TEditorId eid, bool visited) { - x14_[eid] = visited; + x28_visitedDoors[eid] = visited; +} + +bool CMapWorldInfo::IsDoorVisited(TEditorId eid) const +{ + return x28_visitedDoors.find(eid) != x28_visitedDoors.end(); } bool CMapWorldInfo::IsAreaVisted(TAreaId aid) { - x4_visitedAreas.resize((aid + 31) / 32); + if (aid + 1 > x0_visitedAreasAllocated) + { + x4_visitedAreas.resize((aid + 31) / 32); + x0_visitedAreasAllocated = aid + 1; + } return (x4_visitedAreas[aid / 32] >> (aid % 32)) & 0x1; } void CMapWorldInfo::SetAreaVisited(TAreaId aid, bool visited) { - x4_visitedAreas.resize((aid + 31) / 32); + if (aid + 1 > x0_visitedAreasAllocated) + { + x4_visitedAreas.resize((aid + 31) / 32); + x0_visitedAreasAllocated = aid + 1; + } if (visited) x4_visitedAreas[aid / 32] |= 1 << (aid % 32); else x4_visitedAreas[aid / 32] &= ~(1 << (aid % 32)); } +bool CMapWorldInfo::IsMapped(TAreaId aid) +{ + if (aid + 1 > x14_mappedAreasAllocated) + { + x18_mappedAreas.resize((aid + 31) / 32); + x14_mappedAreasAllocated = aid + 1; + } + return (x18_mappedAreas[aid / 32] >> (aid % 32)) & 0x1; +} + +void CMapWorldInfo::SetIsMapped(TAreaId aid, bool mapped) +{ + if (aid + 1 > x14_mappedAreasAllocated) + { + x18_mappedAreas.resize((aid + 31) / 32); + x14_mappedAreasAllocated = aid + 1; + } + if (mapped) + x18_mappedAreas[aid / 32] |= 1 << (aid % 32); + else + x18_mappedAreas[aid / 32] &= ~(1 << (aid % 32)); +} + +bool CMapWorldInfo::IsWorldVisible(TAreaId aid) +{ + return x38_worldVisited || IsMapped(aid); +} + } diff --git a/Runtime/AutoMapper/CMapWorldInfo.hpp b/Runtime/AutoMapper/CMapWorldInfo.hpp index 0713740ab..93bc0fa35 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.hpp +++ b/Runtime/AutoMapper/CMapWorldInfo.hpp @@ -9,19 +9,23 @@ class CSaveWorld; class CMapWorldInfo { + u32 x0_visitedAreasAllocated = 0; std::vector x4_visitedAreas; - std::map x14_; - std::vector x18_visitedAreas; + u32 x14_mappedAreasAllocated = 0; + std::vector x18_mappedAreas; + std::map x28_visitedDoors; + bool x38_worldVisited = false; public: CMapWorldInfo()=default; CMapWorldInfo(CBitStreamReader&, const CSaveWorld& saveWorld, ResId mlvlId); void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, ResId mlvlId) const; - bool IsMapped() const; - void SetIsMapped(bool) const; + bool IsMapped(TAreaId); + void SetIsMapped(TAreaId, bool); void SetDoorVisited(TEditorId eid, bool val); - bool IsDoorVisited() const; + bool IsDoorVisited(TEditorId eid) const; bool IsAreaVisted(TAreaId); void SetAreaVisited(TAreaId, bool); + bool IsWorldVisible(TAreaId); }; } diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index 98e3367c6..c8af4f62d 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -161,14 +161,14 @@ void CPersistentOptions::SetCinematicState(ResId mlvlId, TEditorId cineId, bool CGameOptions::CGameOptions(CBitStreamReader& stream) { for (int b=0 ; b<64 ; ++b) - x0_[b] = stream.ReadEncoded(1); + x0_[b] = stream.ReadEncoded(8); x44_soundMode = CAudioSys::ESurroundModes(stream.ReadEncoded(2)); x48_screenBrightness = stream.ReadEncoded(4); - x4c_screenXOffset = stream.ReadEncoded(6); - x50_screenYOffset = stream.ReadEncoded(6); - x54_screenStretch = stream.ReadEncoded(5); + x4c_screenXOffset = stream.ReadEncoded(6) - 30; + x50_screenYOffset = stream.ReadEncoded(6) - 30; + x54_screenStretch = stream.ReadEncoded(5) - 10; x58_sfxVol = stream.ReadEncoded(7); x5c_musicVol = stream.ReadEncoded(7); x60_hudAlpha = stream.ReadEncoded(8); @@ -204,14 +204,14 @@ void CGameOptions::ResetToDefaults() void CGameOptions::PutTo(CBitStreamWriter& writer) const { for (int b=0 ; b<64 ; ++b) - writer.WriteEncoded(x0_[b], 1); + writer.WriteEncoded(x0_[b], 8); writer.WriteEncoded(u32(x44_soundMode), 2); writer.WriteEncoded(x48_screenBrightness, 4); - writer.WriteEncoded(x4c_screenXOffset, 6); - writer.WriteEncoded(x50_screenYOffset, 6); - writer.WriteEncoded(x54_screenStretch, 5); + writer.WriteEncoded(x4c_screenXOffset + 30, 6); + writer.WriteEncoded(x50_screenYOffset + 30, 6); + writer.WriteEncoded(x54_screenStretch + 10, 5); writer.WriteEncoded(x58_sfxVol, 7); writer.WriteEncoded(x5c_musicVol, 7); writer.WriteEncoded(x60_hudAlpha, 8); diff --git a/Runtime/CGameOptions.hpp b/Runtime/CGameOptions.hpp index e259ae9a0..a13b5ec3b 100644 --- a/Runtime/CGameOptions.hpp +++ b/Runtime/CGameOptions.hpp @@ -104,7 +104,7 @@ public: /** Options tracked per game session */ class CGameOptions { - bool x0_[64] = {}; + u8 x0_[64] = {}; CAudioSys::ESurroundModes x44_soundMode = CAudioSys::ESurroundModes::Stereo; u32 x48_screenBrightness = 4; s32 x4c_screenXOffset = 0; diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index 1c035a5eb..4975304b9 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -83,18 +83,29 @@ CMemoryCardSys::CMemoryCardSys() xc_memoryWorlds.reserve(16); x1c_worldInter.emplace(); x1c_worldInter->reserve(16); + + std::vector> orderedMLVLs; + orderedMLVLs.reserve(16); g_ResFactory->EnumerateNamedResources([&](const std::string& name, const SObjectTag& tag) -> bool { if (tag.type == FOURCC('MLVL')) { - if (!HasSaveWorldMemory(tag.id)) - { - xc_memoryWorlds.emplace_back(tag.id, CSaveWorldMemory{}); - x1c_worldInter->emplace_back(tag.id, -1); - } + ResId origId = g_ResFactory->TranslateNewToOriginal(tag.id); + orderedMLVLs.emplace_back(origId, tag.id); } return true; }); + std::sort(orderedMLVLs.begin(), orderedMLVLs.end(), + [](const auto& a, const auto& b) -> bool { return a.first < b.first; }); + + for (const auto& mlvl : orderedMLVLs) + { + if (!HasSaveWorldMemory(mlvl.second)) + { + xc_memoryWorlds.emplace_back(mlvl.second, CSaveWorldMemory{}); + x1c_worldInter->emplace_back(mlvl.second, -1); + } + } } bool CMemoryCardSys::InitializePump() diff --git a/Runtime/CPakFile.cpp b/Runtime/CPakFile.cpp index e69de29bb..4e172b346 100644 --- a/Runtime/CPakFile.cpp +++ b/Runtime/CPakFile.cpp @@ -0,0 +1,42 @@ +#include "CPakFile.hpp" + +namespace urde +{ + +CPakFile::CPakFile(const std::string& filename, bool samusPak, bool worldPak) +: CDvdFile(filename.c_str()) +{ + x28_24_samusPak = samusPak; + x28_26_worldPak = worldPak; +} + +const SObjectTag* CPakFile::GetResIdByName(const char* name) const +{ + for (const std::pair& p : x4c_nameList) + if (!CStringExtras::CompareCaseInsensitive(p.first.c_str(), name)) + return &p.second; + return nullptr; +} + +void CPakFile::AsyncIdle() +{ + if (x2c_asyncLoadPhase == EAsyncPhase::Loaded) + return; + if (x34_dvdReq && x34_dvdReq->IsComplete()) + return; + switch (x2c_asyncLoadPhase) + { + case EAsyncPhase::Warmup: + Warmup(); + break; + case EAsyncPhase::InitialHeader: + InitialHeaderLoad(); + break; + case EAsyncPhase::DataLoad: + DataLoad(); + break; + default: break; + } +} + +} diff --git a/Runtime/CPakFile.hpp b/Runtime/CPakFile.hpp index 29c6b1ea8..43ace1baf 100644 --- a/Runtime/CPakFile.hpp +++ b/Runtime/CPakFile.hpp @@ -22,7 +22,17 @@ public: bool xb_compressed; }; private: - bool x28_b24_ctFlag; + union + { + struct + { + bool x28_24_samusPak; + bool x28_25_aramFile; + bool x28_26_worldPak; + bool x28_27_worldPakInitialized; + }; + u32 _dummy = 0; + }; enum class EAsyncPhase { Warmup = 0, @@ -35,41 +45,16 @@ private: std::vector x5c_depList; std::vector> x6c_resList; public: - CPakFile(const std::string& filename, bool flag) : CDvdFile(filename.c_str()) {} - const std::vector& GetDepList() const {return x5c_depList;} - const SObjectTag* GetResIdByName(const char* name) const - { - for (const std::pair& p : x4c_nameList) - if (!CStringExtras::CompareCaseInsensitive(p.first.c_str(), name)) - return &p.second; - return nullptr; - } - const SResInfo* GetResInfoForLoad(u32 id) {return nullptr;} - const SResInfo* GetResInfo(u32 id) const {return nullptr;} - u32 GetFakeStaticSize() const {return 0;} + CPakFile(const std::string& filename, bool samusPak, bool worldPak); + const std::vector& GetDepList() const { return x5c_depList; } + const SObjectTag* GetResIdByName(const char* name) const; + const SResInfo* GetResInfoForLoad(u32 id) { return nullptr; } + const SResInfo* GetResInfo(u32 id) const { return nullptr; } + u32 GetFakeStaticSize() const { return 0; } void DataLoad() {} void InitialHeaderLoad() {} void Warmup() {} - void AsyncIdle() - { - if (x2c_asyncLoadPhase == EAsyncPhase::Loaded) - return; - if (x34_dvdReq && x34_dvdReq->IsComplete()) - return; - switch (x2c_asyncLoadPhase) - { - case EAsyncPhase::Warmup: - Warmup(); - break; - case EAsyncPhase::InitialHeader: - InitialHeaderLoad(); - break; - case EAsyncPhase::DataLoad: - DataLoad(); - break; - default: break; - } - } + void AsyncIdle(); }; } diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index ad1b7882b..cd0009121 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -101,9 +101,9 @@ void CPlayerState::PutTo(CBitStreamWriter &stream) { stream.WriteEncoded(x4_, 32); float hp = xc_health.GetHP(); - stream.WriteEncoded(*reinterpret_cast(&hp), 32); - stream.WriteEncoded((u32)x8_currentBeam, CBitStreamWriter::GetBitCount(5)); - stream.WriteEncoded((u32)x20_currentSuit, CBitStreamWriter::GetBitCount(4)); + stream.WriteEncoded(*reinterpret_cast(&hp), 32); + stream.WriteEncoded(u32(x8_currentBeam), CBitStreamWriter::GetBitCount(5)); + stream.WriteEncoded(u32(x20_currentSuit), CBitStreamWriter::GetBitCount(4)); for (u32 i = 0; i < x24_powerups.size(); ++i) { const CPowerUp& pup = x24_powerups[i]; @@ -211,7 +211,9 @@ bool CPlayerState::CanVisorSeeFog(const CStateManager& stateMgr) const CPlayerState::EPlayerVisor CPlayerState::GetActiveVisor(const CStateManager& stateMgr) const { - const CFirstPersonCamera* cam = static_cast(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)); + const CFirstPersonCamera* cam = + static_cast( + stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)); return (cam ? x14_currentVisor : EPlayerVisor::Combat); } diff --git a/Runtime/CResLoader.cpp b/Runtime/CResLoader.cpp index d9c905c57..6fae0b1b9 100644 --- a/Runtime/CResLoader.cpp +++ b/Runtime/CResLoader.cpp @@ -7,25 +7,25 @@ namespace urde const std::vector* CResLoader::GetTagListForFile(const std::string& name) const { std::string namePak = name + ".pak"; - for (const std::unique_ptr& pak : x1c_pakLoadedList) + for (const std::unique_ptr& pak : x18_pakLoadedList) if (!CStringExtras::CompareCaseInsensitive(namePak, pak->x18_path)) return &pak->GetDepList(); return nullptr; } -void CResLoader::AddPakFileAsync(const std::string& name, bool flag) +void CResLoader::AddPakFileAsync(const std::string& name, bool samusPak, bool worldPak) { std::string namePak = name + ".pak"; if (CDvdFile::FileExists(namePak.c_str())) { - x34_pakLoadingList.emplace_back(new CPakFile(namePak, flag)); + x30_pakLoadingList.emplace_back(new CPakFile(namePak, samusPak, worldPak)); ++x44_pakLoadingCount; } } -void CResLoader::AddPakFile(const std::string& name, bool flag) +void CResLoader::AddPakFile(const std::string& name, bool samusPak, bool worldPak) { - AddPakFileAsync(name, flag); + AddPakFileAsync(name, samusPak, worldPak); while (x44_pakLoadingCount) AsyncIdlePakLoading(); } @@ -119,7 +119,7 @@ FourCC CResLoader::GetResourceTypeById(u32 id) const const SObjectTag* CResLoader::GetResourceIdByName(const char* name) const { - for (const std::unique_ptr& file : x1c_pakLoadedList) + for (const std::unique_ptr& file : x18_pakLoadedList) { const SObjectTag* id = file->GetResIdByName(name); if (id) @@ -135,15 +135,15 @@ bool CResLoader::AreAllPaksLoaded() const void CResLoader::AsyncIdlePakLoading() { - for (auto it=x34_pakLoadingList.begin(); - it != x34_pakLoadingList.end(); + for (auto it=x30_pakLoadingList.begin(); + it != x30_pakLoadingList.end(); ++it) { (*it)->AsyncIdle(); if ((*it)->x2c_asyncLoadPhase == CPakFile::EAsyncPhase::Loaded) { MoveToCorrectLoadedList(std::move(*it)); - it = x34_pakLoadingList.erase(it); + it = x30_pakLoadingList.erase(it); --x44_pakLoadingCount; } } @@ -151,7 +151,7 @@ void CResLoader::AsyncIdlePakLoading() bool CResLoader::FindResource(u32 id) const { - for (const std::unique_ptr& file : x1c_pakLoadedList) + for (const std::unique_ptr& file : x18_pakLoadedList) if (const_cast(this)->CacheFromPak(*file, id)) return true; return false; @@ -159,7 +159,7 @@ bool CResLoader::FindResource(u32 id) const CPakFile* CResLoader::FindResourceForLoad(u32 id) { - for (std::unique_ptr& file : x1c_pakLoadedList) + for (std::unique_ptr& file : x18_pakLoadedList) if (CacheFromPakForLoad(*file, id)) return file.get(); return nullptr; @@ -196,7 +196,7 @@ bool CResLoader::CacheFromPak(const CPakFile& file, u32 id) void CResLoader::MoveToCorrectLoadedList(std::unique_ptr&& file) { - x1c_pakLoadedList.push_back(std::move(file)); + x18_pakLoadedList.push_back(std::move(file)); } } diff --git a/Runtime/CResLoader.hpp b/Runtime/CResLoader.hpp index 4192fec69..34a2674b7 100644 --- a/Runtime/CResLoader.hpp +++ b/Runtime/CResLoader.hpp @@ -15,16 +15,16 @@ class IDvdRequest; class CResLoader { std::string m_loaderPath; - //std::list> x4_unusedList; - std::list> x1c_pakLoadedList; - std::list> x34_pakLoadingList; + //std::list> x0_aramList; + std::list> x18_pakLoadedList; + std::list> x30_pakLoadingList; u32 x44_pakLoadingCount = 0; u32 x4c_cachedResId = -1; const CPakFile::SResInfo* x50_cachedResInfo = nullptr; public: const std::vector* GetTagListForFile(const std::string& name) const; - void AddPakFileAsync(const std::string& name, bool flag); - void AddPakFile(const std::string& name, bool flag); + void AddPakFileAsync(const std::string& name, bool samusPak, bool worldPak); + void AddPakFile(const std::string& name, bool samusPak, bool worldPak); CInputStream* LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf); void LoadMemResourceSync(const SObjectTag& tag, void** bufOut, int* sizeOut); CInputStream* LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf); diff --git a/Runtime/CSaveWorld.cpp b/Runtime/CSaveWorld.cpp index 4e34b1b9c..9aa3f1ca6 100644 --- a/Runtime/CSaveWorld.cpp +++ b/Runtime/CSaveWorld.cpp @@ -65,7 +65,7 @@ s32 CSaveWorld::GetCinematicIndex(const TEditorId &id) const auto it = std::find(x4_cinematics.begin(), x4_cinematics.end(), id); if (it == x4_cinematics.end()) return -1; - return x4_cinematics.begin() - it; + return it - x4_cinematics.begin(); } u32 CSaveWorld::GetRelayCount() const @@ -78,7 +78,7 @@ s32 CSaveWorld::GetRelayIndex(const TEditorId &id) const auto it = std::find(x14_relays.begin(), x14_relays.end(), id); if (it == x14_relays.end()) return -1; - return x14_relays.begin() - it; + return it - x14_relays.begin(); } TEditorId CSaveWorld::GetRelayEditorId(u32 idx) const @@ -96,7 +96,7 @@ s32 CSaveWorld::GetDoorIndex(const TEditorId &id) const auto it = std::find(x34_doors.begin(), x34_doors.end(), id); if (it == x34_doors.end()) return -1; - return x34_doors.begin() - it; + return it - x34_doors.begin(); } CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, diff --git a/Runtime/CSaveWorld.hpp b/Runtime/CSaveWorld.hpp index 301dd8368..2200c6d7a 100644 --- a/Runtime/CSaveWorld.hpp +++ b/Runtime/CSaveWorld.hpp @@ -37,6 +37,7 @@ public: u32 GetCinematicCount() const; s32 GetCinematicIndex(const TEditorId& id) const; const std::vector& GetCinematics() const { return x4_cinematics; } + const std::vector& GetDoors() const { return x34_doors; } const std::vector& GetScans() const { return x44_scans; } u32 GetRelayCount() const; s32 GetRelayIndex(const TEditorId& id) const; diff --git a/Runtime/RetroTypes.hpp b/Runtime/RetroTypes.hpp index cb6b7671f..ade7590d3 100644 --- a/Runtime/RetroTypes.hpp +++ b/Runtime/RetroTypes.hpp @@ -22,6 +22,7 @@ struct SObjectTag operator bool() const { return (id & 0xffffffff) != 0xffffffff; } bool operator!=(const SObjectTag& other) const { return id != other.id; } bool operator==(const SObjectTag& other) const { return id == other.id; } + bool operator<(const SObjectTag& other) const { return id < other.id; } SObjectTag() = default; SObjectTag(FourCC tp, ResId rid) : type(tp), id(rid) {} SObjectTag(CInputStream& in) diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index 9bf23373a..f31b500bf 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -6,6 +6,7 @@ #include "CInGameTweakManagerBase.hpp" #include "Audio/CAudioGroupSet.hpp" #include "Editor/ProjectResourceFactoryBase.hpp" +#include "CGameState.hpp" namespace urde { @@ -67,8 +68,11 @@ std::vector CWorld::CRelay::ReadMemoryRelays(athena::io::MemoryR return ret; } -CWorldLayers CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r) +void CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, ResId mlvlId) { + if (version <= 14) + return; + CWorldLayers ret; u32 areaCount = r.readUint32Big(); @@ -89,7 +93,8 @@ CWorldLayers CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r) for (u32 i = 0; i < areaCount; ++i) ret.m_areas[i].m_startNameIdx = r.readUint32Big(); - return ret; + CWorldState& wldState = g_GameState->StateForWorld(mlvlId); + wldState.GetLayerState()->InitializeWorldLayers(ret.m_areas); } bool CDummyWorld::ICheckWorldComplete() @@ -139,7 +144,7 @@ bool CDummyWorld::ICheckWorldComplete() if (version > 12) r.readString(); - CWorldLayers::ReadWorldLayers(r); + CWorldLayers::ReadWorldLayers(r, version, xc_mlvlId); if (x4_loadMap) x8_phase = Phase::LoadingMap; @@ -321,7 +326,7 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId) x84_defAudioTrack = g_TweakManager->GetTweakValue(trackKey)->GetAudio().GetFileName(); } - CWorldLayers::ReadWorldLayers(r); + CWorldLayers::ReadWorldLayers(r, version, x8_mlvlId); x4_phase = Phase::LoadingMap; } diff --git a/Runtime/World/CWorld.hpp b/Runtime/World/CWorld.hpp index 7ab957d57..9dbd3aaaa 100644 --- a/Runtime/World/CWorld.hpp +++ b/Runtime/World/CWorld.hpp @@ -194,7 +194,7 @@ struct CWorldLayers }; std::vector m_areas; std::vector m_names; - static CWorldLayers ReadWorldLayers(athena::io::MemoryReader& r); + static void ReadWorldLayers(athena::io::MemoryReader& r, int version, ResId mlvlId); }; }