From 8f2b39469a30f6b7702ac472935ebce5941405cd Mon Sep 17 00:00:00 2001 From: parax0 Date: Sun, 14 Aug 2016 04:56:51 -0600 Subject: [PATCH] Added versioning support to the serializer; began restructuring CWorld and getting world cooking/serialization working for other games; gave CAssetID an alternate input stream constructor that takes an EGame instead of an EIDLength --- src/Common/CAssetID.cpp | 5 + src/Common/CAssetID.h | 5 + src/Common/Common.pro | 3 +- src/Common/EGame.cpp | 29 +++ src/Common/EGame.h | 8 + src/Common/Serialization/CXMLReader.h | 8 +- src/Common/Serialization/CXMLWriter.h | 11 +- src/Common/Serialization/IArchive.h | 15 +- src/Core/GameProject/CResourceEntry.cpp | 2 +- src/Core/GameProject/DependencyListBuilders.h | 2 + src/Core/Resource/Area/CGameArea.h | 2 - src/Core/Resource/CWorld.cpp | 44 +++-- src/Core/Resource/CWorld.h | 23 +-- src/Core/Resource/Cooker/CAreaCooker.cpp | 2 +- src/Core/Resource/Cooker/CWorldCooker.cpp | 185 ++++++++++++------ src/Core/Resource/Factory/CAreaLoader.cpp | 7 +- .../Factory/CDependencyGroupLoader.cpp | 3 +- src/Core/Resource/Factory/CScriptLoader.cpp | 2 +- .../Factory/CUnsupportedFormatLoader.cpp | 10 +- .../Factory/CUnsupportedParticleLoader.cpp | 5 +- src/Core/Resource/Factory/CWorldLoader.cpp | 72 ++----- src/Editor/PropertyEdit/CPropertyView.cpp | 2 +- src/Editor/Undo/CDeleteSelectionCommand.cpp | 2 +- src/Editor/Undo/CPasteNodesCommand.cpp | 2 +- src/Editor/WorldEditor/CPoiMapEditDialog.cpp | 2 +- src/Editor/WorldEditor/CWorldEditor.cpp | 6 +- src/Editor/WorldEditor/CWorldEditor.h | 2 +- src/Editor/WorldEditor/WInstancesTab.cpp | 6 +- src/FileIO/IInputStream.cpp | 9 + src/FileIO/IInputStream.h | 1 + src/FileIO/IOutputStream.cpp | 6 + src/FileIO/IOutputStream.h | 1 + templates/mp3/Script/DefenseMechanoid.xml | 2 +- templates/mp3/Script/GragnolFlyer.xml | 2 +- templates/mp3/Script/Korakk.xml | 2 +- templates/mp3/Script/MinorIng.xml | 2 +- templates/mp3/Script/Rundas.xml | 2 +- templates/mp3/Script/ShellBug.xml | 2 +- templates/mp3/Script/SpacePirate.xml | 2 +- templates/mp3/Script/SteamDrone.xml | 2 +- templates/mp3/Structs/SeedBoss3Data.xml | 6 +- 41 files changed, 304 insertions(+), 200 deletions(-) create mode 100644 src/Common/EGame.cpp diff --git a/src/Common/CAssetID.cpp b/src/Common/CAssetID.cpp index d766e834..23d12506 100644 --- a/src/Common/CAssetID.cpp +++ b/src/Common/CAssetID.cpp @@ -53,6 +53,11 @@ CAssetID::CAssetID(IInputStream& rInput, EIDLength Length) else mID = rInput.ReadLongLong(); } +CAssetID::CAssetID(IInputStream& rInput, EGame Game) +{ + *this = CAssetID(rInput, (Game <= eEchoes ? e32Bit : e64Bit)); +} + TString CAssetID::ToString() const { if (mLength == e32Bit) diff --git a/src/Common/CAssetID.h b/src/Common/CAssetID.h index c713e511..e67c4629 100644 --- a/src/Common/CAssetID.h +++ b/src/Common/CAssetID.h @@ -1,6 +1,7 @@ #ifndef CASSETID_H #define CASSETID_H +#include "EGame.h" #include "TString.h" #include "types.h" #include @@ -23,6 +24,7 @@ public: CAssetID(u64 ID, EIDLength Length); CAssetID(const char* pkID); CAssetID(IInputStream& rInput, EIDLength Length); + CAssetID(IInputStream& rInput, EGame Game); void Write(IOutputStream& rOutput) const; TString ToString() const; bool IsValid() const; @@ -49,6 +51,9 @@ public: static CAssetID FromString(const TString& rkString); static CAssetID RandomID(); + inline static CAssetID InvalidID(EIDLength IDLength) { return (IDLength == e32Bit ? skInvalidID32 : skInvalidID64); } + inline static CAssetID InvalidID(EGame Game) { return InvalidID(Game <= eEchoes ? e32Bit : e64Bit); } + static CAssetID skInvalidID32; static CAssetID skInvalidID64; }; diff --git a/src/Common/Common.pro b/src/Common/Common.pro index 988f2608..f49e190e 100644 --- a/src/Common/Common.pro +++ b/src/Common/Common.pro @@ -91,4 +91,5 @@ SOURCES += \ TString.cpp \ Log.cpp \ FileUtil.cpp \ - CAssetID.cpp + CAssetID.cpp \ + EGame.cpp diff --git a/src/Common/EGame.cpp b/src/Common/EGame.cpp new file mode 100644 index 00000000..3901e5dd --- /dev/null +++ b/src/Common/EGame.cpp @@ -0,0 +1,29 @@ +#include "EGame.h" +#include "CFourCC.h" + +CFourCC GetGameID(EGame Game) +{ + switch (Game) + { + case ePrimeDemo: return "MP1D"; + case ePrime: return "MP1 "; + case eEchoesDemo: return "MP2D"; + case eEchoes: return "MP2E"; + case eCorruptionProto: return "MP3P"; + case eCorruption: return "MP3C"; + case eReturns: return "DKCR"; + default: return "UNKN"; + } +} + +EGame GetGameForID(const CFourCC& rkID) +{ + if (rkID == "MP1D") return ePrimeDemo; + if (rkID == "MP1 ") return ePrime; + if (rkID == "MP2D") return eEchoesDemo; + if (rkID == "MP2E") return eEchoes; + if (rkID == "MP3P") return eCorruptionProto; + if (rkID == "MP3C") return eCorruption; + if (rkID == "DKCR") return eReturns; + return eUnknownGame; +} diff --git a/src/Common/EGame.h b/src/Common/EGame.h index c7e03e98..77a9acc4 100644 --- a/src/Common/EGame.h +++ b/src/Common/EGame.h @@ -1,6 +1,11 @@ #ifndef EGAME_H #define EGAME_H +#include "TString.h" +#include "types.h" + +class CFourCC; + enum EGame { ePrimeDemo, @@ -13,4 +18,7 @@ enum EGame eUnknownGame = -1 }; +CFourCC GetGameID(EGame Game); +EGame GetGameForID(const CFourCC& rkID); + #endif // EGAME_H diff --git a/src/Common/Serialization/CXMLReader.h b/src/Common/Serialization/CXMLReader.h index a7d28b96..1226abf6 100644 --- a/src/Common/Serialization/CXMLReader.h +++ b/src/Common/Serialization/CXMLReader.h @@ -15,9 +15,15 @@ public: : IArchive() , mJustEndedParam(false) { - // Load XML and set current element to the root element + // Load XML and set current element to the root element; read version mDoc.LoadFile(*rkFileName); mpCurElem = mDoc.FirstChildElement(); + ASSERT(mpCurElem != nullptr); + + mFileVersion = TString( mpCurElem->Attribute("FileVer") ).ToInt32(10); + mArchiveVersion = TString( mpCurElem->Attribute("ArchiveVer") ).ToInt32(10); + const char *pkGameAttr = mpCurElem->Attribute("Game"); + mGame = pkGameAttr ? eUnknownGame : GetGameForID( CFourCC(pkGameAttr) ); } protected: diff --git a/src/Common/Serialization/CXMLWriter.h b/src/Common/Serialization/CXMLWriter.h index 1162b891..b467aeeb 100644 --- a/src/Common/Serialization/CXMLWriter.h +++ b/src/Common/Serialization/CXMLWriter.h @@ -2,6 +2,7 @@ #define CXMLWRITER #include "IArchive.h" +#include "Common/CFourCC.h" #include #include @@ -12,16 +13,24 @@ class CXMLWriter : public IArchive tinyxml2::XMLElement *mpCurElem; public: - CXMLWriter(const TString& rkRootName, const TString& rkFileName) + CXMLWriter(const TString& rkFileName, const TString& rkRootName, u32 FileVersion, EGame Game = eUnknownGame) : IArchive() , mOutFilename(rkFileName) { + mFileVersion = FileVersion; + mGame = Game; + // Create declaration and root node tinyxml2::XMLDeclaration *pDecl = mDoc.NewDeclaration(); mDoc.LinkEndChild(pDecl); mpCurElem = mDoc.NewElement(*rkRootName); mDoc.LinkEndChild(mpCurElem); + + // Write version data + mpCurElem->SetAttribute("FileVer", (int) FileVersion); + mpCurElem->SetAttribute("ArchiveVer", (int) skCurrentArchiveVersion); + if (Game != eUnknownGame) mpCurElem->SetAttribute("Game", *GetGameID(Game).ToString()); } ~CXMLWriter() diff --git a/src/Common/Serialization/IArchive.h b/src/Common/Serialization/IArchive.h index 179bd574..0e995bc5 100644 --- a/src/Common/Serialization/IArchive.h +++ b/src/Common/Serialization/IArchive.h @@ -3,6 +3,7 @@ #include "Common/AssertMacro.h" #include "Common/CAssetID.h" +#include "Common/EGame.h" #include "Common/TString.h" #include "Common/types.h" @@ -164,8 +165,15 @@ public: // Actual archive class class IArchive { +protected: + s32 mFileVersion; + s32 mArchiveVersion; + EGame mGame; + public: - IArchive() {} + static const u32 skCurrentArchiveVersion = 0; + + IArchive() : mFileVersion(0), mArchiveVersion(skCurrentArchiveVersion), mGame(eUnknownGame) {} virtual ~IArchive() {} #define ENABLE_FOR_SERIAL_TYPE(SType) typename std::enable_if::Type == SerialType::##SType, int>::type = 0 @@ -381,6 +389,11 @@ public: virtual void SerializeHexPrimitive(u32& rValue) = 0; virtual void SerializeHexPrimitive(s64& rValue) = 0; virtual void SerializeHexPrimitive(u64& rValue) = 0; + + // Accessors + inline u32 FileVersion() const { return mFileVersion; } + inline u32 ArchiveVersion() const { return mArchiveVersion; } + inline EGame Game() const { return mGame; } }; // Container serialize methods diff --git a/src/Core/GameProject/CResourceEntry.cpp b/src/Core/GameProject/CResourceEntry.cpp index 5ff19dcc..22ca9466 100644 --- a/src/Core/GameProject/CResourceEntry.cpp +++ b/src/Core/GameProject/CResourceEntry.cpp @@ -244,7 +244,7 @@ bool CResourceEntry::Save() TString Dir = Path.GetFileDirectory(); FileUtil::CreateDirectory(Dir.ToUTF16()); - CXMLWriter Writer(GetResourceSerialName(ResourceType()), Path); + CXMLWriter Writer(Path, GetResourceSerialName(ResourceType()), 0, mGame); mpResource->Serialize(Writer); } diff --git a/src/Core/GameProject/DependencyListBuilders.h b/src/Core/GameProject/DependencyListBuilders.h index f506ca52..b4cd81bd 100644 --- a/src/Core/GameProject/DependencyListBuilders.h +++ b/src/Core/GameProject/DependencyListBuilders.h @@ -234,6 +234,8 @@ public: // For PlayerActor animsets we want to include only the empty suit (char 5) in the dependency list. This is to // accomodate the dynamic loading the game does for PlayerActors to avoid having assets for suits the player // doesn't have in memory. We want common assets (animations, etc) in the list but not per-character assets. + // The reason to include empty suit is to make sure resources that are stored as per-character data but are + // actually common to every character, such as particle effects, are still included in the list. ASSERT(pEntry->ResourceType() == eAnimSet); CAnimSetDependencyTree *pTree = static_cast(pEntry->Dependencies()); mLayerUsedAssets.insert(pTree->ID()); diff --git a/src/Core/Resource/Area/CGameArea.h b/src/Core/Resource/Area/CGameArea.h index 8c85dc63..b01156b0 100644 --- a/src/Core/Resource/Area/CGameArea.h +++ b/src/Core/Resource/Area/CGameArea.h @@ -24,7 +24,6 @@ class CGameArea : public CResource friend class CAreaLoader; friend class CAreaCooker; - EGame mVersion; u32 mWorldIndex; u32 mVertexCount; u32 mTriangleCount; @@ -84,7 +83,6 @@ public: void DeleteInstance(CScriptObject *pInstance); // Inline Accessors - inline EGame Version() const { return mVersion; } inline u32 WorldIndex() const { return mWorldIndex; } inline CTransform4f Transform() const { return mTransform; } inline u32 NumWorldModels() const { return mWorldModels.size(); } diff --git a/src/Core/Resource/CWorld.cpp b/src/Core/Resource/CWorld.cpp index abc455c5..15cfa970 100644 --- a/src/Core/Resource/CWorld.cpp +++ b/src/Core/Resource/CWorld.cpp @@ -4,7 +4,6 @@ CWorld::CWorld(CResourceEntry *pEntry /*= 0*/) : CResource(pEntry) - , mWorldVersion(eUnknownGame) , mpWorldName(nullptr) , mpDarkWorldName(nullptr) , mpSaveWorld(nullptr) @@ -56,24 +55,32 @@ void CWorld::SetAreaLayerInfo(CGameArea *pArea) SArea::SLayer& rLayerInfo = AreaInfo.Layers[iLyr]; pLayer->SetName(rLayerInfo.LayerName); - pLayer->SetActive(rLayerInfo.EnabledByDefault); + pLayer->SetActive(rLayerInfo.Active); } } // ************ SERIALIZATION ************ void CWorld::Serialize(IArchive& rArc) { - rArc << SERIAL("WorldNameSTRG", mpWorldName) - << SERIAL("DarkWorldNameSTRG", mpDarkWorldName) - << SERIAL("WorldSaveInfo", mpSaveWorld) - << SERIAL("DefaultSkyCMDL", mpDefaultSkybox) - << SERIAL("MapWorld", mpMapWorld) - << SERIAL("Unknown1", mUnknown1) - << SERIAL("UnknownAreas", mUnknownAreas) - << SERIAL("UnknownAGSC", mUnknownAGSC) - << SERIAL_CONTAINER("MemoryRelays", mMemoryRelays, "MemoryRelay") - << SERIAL_CONTAINER("Areas", mAreas, "Area") - << SERIAL_CONTAINER("AudioGroups", mAudioGrps, "AudioGroup"); + rArc << SERIAL("WorldNameSTRG", mpWorldName); + + if (rArc.Game() == eEchoesDemo || rArc.Game() == eEchoes) + rArc << SERIAL("DarkWorldNameSTRG", mpDarkWorldName); + + rArc << SERIAL("WorldSaveInfo", mpSaveWorld) + << SERIAL("WorldMap", mpMapWorld) + << SERIAL("DefaultSkyCMDL", mpDefaultSkybox); + + if (rArc.Game() >= eEchoesDemo && rArc.Game() <= eCorruption) + rArc << SERIAL("TempleKeyWorldIndex", mTempleKeyWorldIndex); + + if (rArc.Game() == ePrime) + rArc << SERIAL_CONTAINER("MemoryRelays", mMemoryRelays, "MemoryRelay"); + + rArc << SERIAL_CONTAINER("Areas", mAreas, "Area"); + + if (rArc.Game() <= ePrime) + rArc << SERIAL_CONTAINER("AudioGroups", mAudioGrps, "AudioGroup"); } void Serialize(IArchive& rArc, CWorld::SMemoryRelay& rMemRelay) @@ -81,7 +88,7 @@ void Serialize(IArchive& rArc, CWorld::SMemoryRelay& rMemRelay) rArc << SERIAL_HEX("MemoryRelayID", rMemRelay.InstanceID) << SERIAL_HEX("TargetID", rMemRelay.TargetID) << SERIAL("Message", rMemRelay.Message) - << SERIAL("Unknown", rMemRelay.Unknown); + << SERIAL("Active", rMemRelay.Active); } void Serialize(IArchive& rArc, CWorld::SArea& rArea) @@ -91,13 +98,11 @@ void Serialize(IArchive& rArc, CWorld::SArea& rArea) << SERIAL("Transform", rArea.Transform) << SERIAL("BoundingBox", rArea.AetherBox) << SERIAL("AreaMREA", rArea.AreaResID) - << SERIAL_HEX("AreaID", rArea.AreaID) + << SERIAL("AreaID", rArea.AreaID) << SERIAL("AllowPakDuplicates", rArea.AllowPakDuplicates) << SERIAL_CONTAINER("AttachedAreas", rArea.AttachedAreaIDs, "AreaIndex") - << SERIAL_CONTAINER("Dependencies", rArea.Dependencies, "Dependency") << SERIAL_CONTAINER("RelModules", rArea.RelFilenames, "Module") << SERIAL_CONTAINER("RelOffsets", rArea.RelOffsets, "Offset") - << SERIAL("CommonDependsStart", rArea.CommonDependenciesStart) << SERIAL_CONTAINER("Docks", rArea.Docks, "Dock") << SERIAL_CONTAINER("Layers", rArea.Layers, "Layer"); } @@ -117,12 +122,11 @@ void Serialize(IArchive& rArc, CWorld::SArea::SDock::SConnectingDock& rDock) void Serialize(IArchive& rArc, CWorld::SArea::SLayer& rLayer) { rArc << SERIAL("Name", rLayer.LayerName) - << SERIAL("DefaultEnabled", rLayer.EnabledByDefault) - << SERIAL("LayerDependsStart", rLayer.LayerDependenciesStart); + << SERIAL("Active", rLayer.Active); } void Serialize(IArchive& rArc, CWorld::SAudioGrp& rAudioGrp) { - rArc << SERIAL("StudioID", rAudioGrp.Unknown) + rArc << SERIAL("GroupID", rAudioGrp.GroupID) << SERIAL("AGSC", rAudioGrp.ResID); } diff --git a/src/Core/Resource/CWorld.h b/src/Core/Resource/CWorld.h index 5051cf52..9160a2de 100644 --- a/src/Core/Resource/CWorld.h +++ b/src/Core/Resource/CWorld.h @@ -14,21 +14,17 @@ class CWorld : public CResource friend class CWorldCooker; // Instances of CResource pointers are placeholders for unimplemented resource types (eg CMapWorld) - EGame mWorldVersion; TResPtr mpWorldName; TResPtr mpDarkWorldName; TResPtr mpSaveWorld; TResPtr mpDefaultSkybox; TResPtr mpMapWorld; + u32 mTempleKeyWorldIndex; - u32 mUnknown1; - u32 mUnknownAreas; - - u32 mUnknownAGSC; struct SAudioGrp { CAssetID ResID; - u32 Unknown; + u32 GroupID; }; std::vector mAudioGrps; @@ -37,7 +33,7 @@ class CWorld : public CResource u32 InstanceID; u32 TargetID; u16 Message; - u8 Unknown; + bool Active; }; std::vector mMemoryRelays; @@ -47,15 +43,14 @@ class CWorld : public CResource TResPtr pAreaName; CTransform4f Transform; CAABox AetherBox; - CAssetID AreaResID; // Loading every single area as a CResource would be a very bad idea - u64 AreaID; + CAssetID AreaResID; // Area resource ID + CAssetID AreaID; // Internal area ID (same length as an asset ID) bool AllowPakDuplicates; + std::vector MemoryRelays; // Only needed for MP1 std::vector AttachedAreaIDs; - std::vector Dependencies; - std::vector RelFilenames; + std::vector RelFilenames; // Needs to be removed & generated at cook; temporarily leaving for debugging std::vector RelOffsets; - u32 CommonDependenciesStart; struct SDock { @@ -72,9 +67,8 @@ class CWorld : public CResource struct SLayer { TString LayerName; - bool EnabledByDefault; + bool Active; u8 LayerID[16]; - u32 LayerDependenciesStart; // Offset into Dependencies vector }; std::vector Layers; }; @@ -97,7 +91,6 @@ public: friend void Serialize(IArchive& rArc, SAudioGrp& rAudioGrp); // Accessors - inline EGame Version() const { return mWorldVersion; } inline CStringTable* WorldName() const { return mpWorldName; } inline CStringTable* DarkWorldName() const { return mpDarkWorldName; } inline CResource* SaveWorld() const { return mpSaveWorld; } diff --git a/src/Core/Resource/Cooker/CAreaCooker.cpp b/src/Core/Resource/Cooker/CAreaCooker.cpp index 51d05ac1..e48b7642 100644 --- a/src/Core/Resource/Cooker/CAreaCooker.cpp +++ b/src/Core/Resource/Cooker/CAreaCooker.cpp @@ -310,7 +310,7 @@ void CAreaCooker::WriteCookedArea(CGameArea *pArea, IOutputStream& rOut) { CAreaCooker Cooker; Cooker.mpArea = pArea; - Cooker.mVersion = pArea->Version(); + Cooker.mVersion = pArea->Game(); if (Cooker.mVersion <= eEchoes) Cooker.DetermineSectionNumbersPrime(); diff --git a/src/Core/Resource/Cooker/CWorldCooker.cpp b/src/Core/Resource/Cooker/CWorldCooker.cpp index 684bfd68..fe42c713 100644 --- a/src/Core/Resource/Cooker/CWorldCooker.cpp +++ b/src/Core/Resource/Cooker/CWorldCooker.cpp @@ -9,34 +9,46 @@ CWorldCooker::CWorldCooker() bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL) { ASSERT(rMLVL.IsValid()); + EGame Game = pWorld->Game(); // MLVL Header rMLVL.WriteLong(0xDEAFBABE); rMLVL.WriteLong( GetMLVLVersion(pWorld->Game()) ); - CAssetID WorldNameID = pWorld->mpWorldName ? pWorld->mpWorldName->ID() : CAssetID::skInvalidID32; - CAssetID SaveWorldID = pWorld->mpSaveWorld ? pWorld->mpSaveWorld->ID() : CAssetID::skInvalidID32; - CAssetID DefaultSkyID = pWorld->mpDefaultSkybox ? pWorld->mpDefaultSkybox->ID() : CAssetID::skInvalidID32; + CAssetID WorldNameID = pWorld->mpWorldName ? pWorld->mpWorldName->ID() : CAssetID::InvalidID(Game); + CAssetID DarkWorldNameID = pWorld->mpDarkWorldName ? pWorld->mpDarkWorldName->ID() : CAssetID::InvalidID(Game); + CAssetID SaveWorldID = pWorld->mpSaveWorld ? pWorld->mpSaveWorld->ID() : CAssetID::InvalidID(Game); + CAssetID DefaultSkyID = pWorld->mpDefaultSkybox ? pWorld->mpDefaultSkybox->ID() : CAssetID::InvalidID(Game); WorldNameID.Write(rMLVL); + + if (Game == eEchoesDemo || Game == eEchoes) + { + DarkWorldNameID.Write(rMLVL); + rMLVL.WriteLong(0); + } + SaveWorldID.Write(rMLVL); DefaultSkyID.Write(rMLVL); // Memory Relays - rMLVL.WriteLong( pWorld->mMemoryRelays.size() ); - - for (u32 iMem = 0; iMem < pWorld->mMemoryRelays.size(); iMem++) + if (Game == ePrime) { - CWorld::SMemoryRelay& rRelay = pWorld->mMemoryRelays[iMem]; - rMLVL.WriteLong(rRelay.InstanceID); - rMLVL.WriteLong(rRelay.TargetID); - rMLVL.WriteShort(rRelay.Message); - rMLVL.WriteByte(rRelay.Unknown); + rMLVL.WriteLong( pWorld->mMemoryRelays.size() ); + + for (u32 iMem = 0; iMem < pWorld->mMemoryRelays.size(); iMem++) + { + CWorld::SMemoryRelay& rRelay = pWorld->mMemoryRelays[iMem]; + rMLVL.WriteLong(rRelay.InstanceID); + rMLVL.WriteLong(rRelay.TargetID); + rMLVL.WriteShort(rRelay.Message); + rMLVL.WriteBool(rRelay.Active); + } } // Areas rMLVL.WriteLong(pWorld->mAreas.size()); - rMLVL.WriteLong(1); // Unknown + if (Game <= ePrime) rMLVL.WriteLong(1); // Unknown for (u32 iArea = 0; iArea < pWorld->mAreas.size(); iArea++) { @@ -45,85 +57,123 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL) CResourceEntry *pAreaEntry = gpResourceStore->FindEntry(rArea.AreaResID); ASSERT(pAreaEntry && pAreaEntry->ResourceType() == eArea); - CAssetID AreaNameID = rArea.pAreaName ? rArea.pAreaName->ID() : CAssetID::skInvalidID32; + CAssetID AreaNameID = rArea.pAreaName ? rArea.pAreaName->ID() : CAssetID::InvalidID(Game); AreaNameID.Write(rMLVL); rArea.Transform.Write(rMLVL); rArea.AetherBox.Write(rMLVL); rArea.AreaResID.Write(rMLVL); - rMLVL.WriteLong( (u32) rArea.AreaID ); + rArea.AreaID.Write(rMLVL); // Attached Areas - rMLVL.WriteLong( rArea.AttachedAreaIDs.size() ); + if (Game <= eCorruption) + { + rMLVL.WriteLong( rArea.AttachedAreaIDs.size() ); - for (u32 iAttach = 0; iAttach < rArea.AttachedAreaIDs.size(); iAttach++) - rMLVL.WriteShort(rArea.AttachedAreaIDs[iAttach]); + for (u32 iAttach = 0; iAttach < rArea.AttachedAreaIDs.size(); iAttach++) + rMLVL.WriteShort(rArea.AttachedAreaIDs[iAttach]); + } // Dependencies - std::list Dependencies; - std::list LayerDependsOffsets; - CAreaDependencyListBuilder Builder(pAreaEntry); - Builder.BuildDependencyList(Dependencies, LayerDependsOffsets); - - rMLVL.WriteLong(0); - rMLVL.WriteLong( Dependencies.size() ); - - for (auto Iter = Dependencies.begin(); Iter != Dependencies.end(); Iter++) + if (Game <= eEchoes) { - CAssetID ID = *Iter; - CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); - ID.Write(rMLVL); - pEntry->CookedExtension().Write(rMLVL); - } + std::list Dependencies; + std::list LayerDependsOffsets; + CAreaDependencyListBuilder Builder(pAreaEntry); + Builder.BuildDependencyList(Dependencies, LayerDependsOffsets); - rMLVL.WriteLong(LayerDependsOffsets.size()); + rMLVL.WriteLong(0); + rMLVL.WriteLong( Dependencies.size() ); - for (auto Iter = LayerDependsOffsets.begin(); Iter != LayerDependsOffsets.end(); Iter++) - rMLVL.WriteLong(*Iter); - - // Docks - rMLVL.WriteLong( rArea.Docks.size() ); - - for (u32 iDock = 0; iDock < rArea.Docks.size(); iDock++) - { - CWorld::SArea::SDock& rDock = rArea.Docks[iDock]; - rMLVL.WriteLong( rDock.ConnectingDocks.size() ); - - for (u32 iCon = 0; iCon < rDock.ConnectingDocks.size(); iCon++) + for (auto Iter = Dependencies.begin(); Iter != Dependencies.end(); Iter++) { - CWorld::SArea::SDock::SConnectingDock& rConDock = rDock.ConnectingDocks[iCon]; - rMLVL.WriteLong(rConDock.AreaIndex); - rMLVL.WriteLong(rConDock.DockIndex); + CAssetID ID = *Iter; + CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); + ID.Write(rMLVL); + pEntry->CookedExtension().Write(rMLVL); } - rMLVL.WriteLong( rDock.DockCoordinates.size() ); + rMLVL.WriteLong(LayerDependsOffsets.size()); - for (u32 iCoord = 0; iCoord < rDock.DockCoordinates.size(); iCoord++) - rDock.DockCoordinates[iCoord].Write(rMLVL); + for (auto Iter = LayerDependsOffsets.begin(); Iter != LayerDependsOffsets.end(); Iter++) + rMLVL.WriteLong(*Iter); + } + + // Docks + if (Game <= eCorruption) + { + rMLVL.WriteLong( rArea.Docks.size() ); + + for (u32 iDock = 0; iDock < rArea.Docks.size(); iDock++) + { + CWorld::SArea::SDock& rDock = rArea.Docks[iDock]; + rMLVL.WriteLong( rDock.ConnectingDocks.size() ); + + for (u32 iCon = 0; iCon < rDock.ConnectingDocks.size(); iCon++) + { + CWorld::SArea::SDock::SConnectingDock& rConDock = rDock.ConnectingDocks[iCon]; + rMLVL.WriteLong(rConDock.AreaIndex); + rMLVL.WriteLong(rConDock.DockIndex); + } + + rMLVL.WriteLong( rDock.DockCoordinates.size() ); + + for (u32 iCoord = 0; iCoord < rDock.DockCoordinates.size(); iCoord++) + rDock.DockCoordinates[iCoord].Write(rMLVL); + } + } + + // Module Dependencies + if (Game == eEchoesDemo || Game == eEchoes) + { + std::vector ModuleNames; + std::vector ModuleLayerOffsets; + CAreaDependencyTree *pAreaDeps = static_cast(pAreaEntry->Dependencies()); + pAreaDeps->GetModuleDependencies(Game, ModuleNames, ModuleLayerOffsets); + + rMLVL.WriteLong(ModuleNames.size()); + + for (u32 iMod = 0; iMod < ModuleNames.size(); iMod++) + rMLVL.WriteString(ModuleNames[iMod].ToStdString()); + + rMLVL.WriteLong(ModuleLayerOffsets.size()); + + for (u32 iOff = 0; iOff < ModuleLayerOffsets.size(); iOff++) + rMLVL.WriteLong(ModuleLayerOffsets[iOff]); } } - CAssetID MapWorldID = pWorld->mpMapWorld ? pWorld->mpMapWorld->ID() : CAssetID::skInvalidID32; - MapWorldID.Write(rMLVL); - rMLVL.WriteByte(0); - rMLVL.WriteLong(0); - - // Audio Groups - rMLVL.WriteLong(pWorld->mAudioGrps.size()); - - for (u32 iGrp = 0; iGrp < pWorld->mAudioGrps.size(); iGrp++) + if (Game <= eCorruption) { - CWorld::SAudioGrp& rAudioGroup = pWorld->mAudioGrps[iGrp]; - rMLVL.WriteLong(rAudioGroup.Unknown); - rAudioGroup.ResID.Write(rMLVL); + // World Map + CAssetID MapWorldID = pWorld->mpMapWorld ? pWorld->mpMapWorld->ID() : CAssetID::skInvalidID32; + MapWorldID.Write(rMLVL); + + // Script Layer - unused in all retail builds but this will need to be supported eventually to properly support the MP1 demo + rMLVL.WriteByte(0); + rMLVL.WriteLong(0); } - rMLVL.WriteByte(0); + // Audio Groups + if (Game <= ePrime) + { + rMLVL.WriteLong(pWorld->mAudioGrps.size()); + + for (u32 iGrp = 0; iGrp < pWorld->mAudioGrps.size(); iGrp++) + { + CWorld::SAudioGrp& rAudioGroup = pWorld->mAudioGrps[iGrp]; + rMLVL.WriteLong(rAudioGroup.GroupID); + rAudioGroup.ResID.Write(rMLVL); + } + + rMLVL.WriteByte(0); + } // Layers rMLVL.WriteLong(pWorld->mAreas.size()); std::vector LayerNames; std::vector LayerNameOffsets; + // Layer Flags for (u32 iArea = 0; iArea < pWorld->mAreas.size(); iArea++) { CWorld::SArea& rArea = pWorld->mAreas[iArea]; @@ -135,7 +185,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL) for (u32 iLyr = 0; iLyr < rArea.Layers.size(); iLyr++) { CWorld::SArea::SLayer& rLayer = rArea.Layers[iLyr]; - if (!rLayer.EnabledByDefault) + if (!rLayer.Active) LayerActiveFlags &= ~(1 << iLyr); LayerNames.push_back(rLayer.LayerName); @@ -144,11 +194,18 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL) rMLVL.WriteLongLong(LayerActiveFlags); } + // Layer Names rMLVL.WriteLong(LayerNames.size()); for (u32 iLyr = 0; iLyr < LayerNames.size(); iLyr++) rMLVL.WriteString(LayerNames[iLyr].ToStdString()); + // todo: Layer Saved State IDs go here for MP3/DKCR; need support for saved state IDs to implement + if (Game == eCorruption || Game == eReturns) + { + } + + // Layer Name Offsets rMLVL.WriteLong(LayerNameOffsets.size()); for (u32 iOff = 0; iOff < LayerNameOffsets.size(); iOff++) diff --git a/src/Core/Resource/Factory/CAreaLoader.cpp b/src/Core/Resource/Factory/CAreaLoader.cpp index 80f414a3..625719f8 100644 --- a/src/Core/Resource/Factory/CAreaLoader.cpp +++ b/src/Core/Resource/Factory/CAreaLoader.cpp @@ -590,19 +590,19 @@ void CAreaLoader::ReadCollision() void CAreaLoader::ReadPATH() { mpSectionMgr->ToSection(mPathBlockNum); - mpArea->mPathID = CAssetID(*mpMREA, (mVersion <= eEchoes ? e32Bit : e64Bit)); + mpArea->mPathID = CAssetID(*mpMREA, mVersion); } void CAreaLoader::ReadPTLA() { mpSectionMgr->ToSection(this->mPTLABlockNum); - mpArea->mPortalAreaID = CAssetID(*mpMREA, (mVersion <= eEchoes ? e32Bit : e64Bit)); + mpArea->mPortalAreaID = CAssetID(*mpMREA, mVersion); } void CAreaLoader::ReadEGMC() { mpSectionMgr->ToSection(mEGMCBlockNum); - CAssetID EGMC(*mpMREA, (mVersion <= eEchoes ? e32Bit : e64Bit)); + CAssetID EGMC(*mpMREA, mVersion); mpArea->mpPoiToWorldMap = gpResourceStore->LoadResource(EGMC, "EGMC"); } @@ -669,7 +669,6 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry) u32 Version = MREA.ReadLong(); Loader.mVersion = GetFormatVersion(Version); Loader.mpArea->SetGame(Loader.mVersion); - Loader.mpArea->mVersion = Loader.mVersion; Loader.mpMREA = &MREA; switch (Loader.mVersion) diff --git a/src/Core/Resource/Factory/CDependencyGroupLoader.cpp b/src/Core/Resource/Factory/CDependencyGroupLoader.cpp index 096b889d..c8e79c74 100644 --- a/src/Core/Resource/Factory/CDependencyGroupLoader.cpp +++ b/src/Core/Resource/Factory/CDependencyGroupLoader.cpp @@ -34,7 +34,6 @@ CDependencyGroup* CDependencyGroupLoader::LoadDGRP(IInputStream& rDGRP, CResourc u32 NumDependencies = rDGRP.ReadLong(); EGame Game = VersionTest(rDGRP, NumDependencies); - EIDLength IDLength = (Game < eCorruptionProto ? e32Bit : e64Bit); CDependencyGroup *pGroup = new CDependencyGroup(pEntry); pGroup->SetGame(Game); @@ -42,7 +41,7 @@ CDependencyGroup* CDependencyGroupLoader::LoadDGRP(IInputStream& rDGRP, CResourc for (u32 iDep = 0; iDep < NumDependencies; iDep++) { rDGRP.Seek(0x4, SEEK_CUR); // Skip dependency type - CAssetID AssetID(rDGRP, IDLength); + CAssetID AssetID(rDGRP, Game); pGroup->AddDependency(AssetID); } diff --git a/src/Core/Resource/Factory/CScriptLoader.cpp b/src/Core/Resource/Factory/CScriptLoader.cpp index 5df4b332..c8538f5c 100644 --- a/src/Core/Resource/Factory/CScriptLoader.cpp +++ b/src/Core/Resource/Factory/CScriptLoader.cpp @@ -110,7 +110,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY { TFileProperty *pFileCast = static_cast(pProp); - CAssetID ResID = (mVersion < eCorruptionProto ? rSCLY.ReadLong() : rSCLY.ReadLongLong()); + CAssetID ResID(rSCLY, mVersion); const TStringList& rkExtensions = static_cast(pTemp)->Extensions(); CResourceInfo Info(ResID, CFourCC(!rkExtensions.empty() ? rkExtensions.front() : "UNKN")); diff --git a/src/Core/Resource/Factory/CUnsupportedFormatLoader.cpp b/src/Core/Resource/Factory/CUnsupportedFormatLoader.cpp index ba3a5078..428cf23c 100644 --- a/src/Core/Resource/Factory/CUnsupportedFormatLoader.cpp +++ b/src/Core/Resource/Factory/CUnsupportedFormatLoader.cpp @@ -190,8 +190,6 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadHINT(IInputStream& rHINT, CResou return nullptr; } - EIDLength IDLength = (Game <= eEchoes ? e32Bit : e64Bit); - // Read main file CDependencyGroup *pGroup = new CDependencyGroup(pEntry); u32 NumHints = rHINT.ReadLong(); @@ -200,15 +198,15 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadHINT(IInputStream& rHINT, CResou { rHINT.ReadString(); // Skip hint name rHINT.Seek(0x8, SEEK_CUR); // Skip unknown + appear time - pGroup->AddDependency( CAssetID(rHINT, IDLength) ); // Pop-up STRG + pGroup->AddDependency( CAssetID(rHINT, Game) ); // Pop-up STRG rHINT.Seek(0x8, SEEK_CUR); // Skip unknowns if (Game <= eEchoes) { - pGroup->AddDependency( CAssetID(rHINT, IDLength) ); // Target MLVL - pGroup->AddDependency( CAssetID(rHINT, IDLength) ); // Target MREA + pGroup->AddDependency( CAssetID(rHINT, Game) ); // Target MLVL + pGroup->AddDependency( CAssetID(rHINT, Game) ); // Target MREA rHINT.Seek(0x4, SEEK_CUR); // Skip target room index - pGroup->AddDependency( CAssetID(rHINT, IDLength) ); // Map STRG + pGroup->AddDependency( CAssetID(rHINT, Game) ); // Map STRG } } diff --git a/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp b/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp index d03423db..26d673ec 100644 --- a/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp +++ b/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp @@ -997,7 +997,7 @@ void CUnsupportedParticleLoader::ParseAssetFunction(IInputStream& rFile) break; case kAssetCNST: - mpGroup->AddDependency( CAssetID(rFile, mpGroup->Game() <= eEchoes ? e32Bit : e64Bit) ); + mpGroup->AddDependency( CAssetID(rFile, mpGroup->Game()) ); break; default: @@ -1015,7 +1015,6 @@ void CUnsupportedParticleLoader::ParseSpawnSystemKeyframeData(IInputStream& rFil rFile.Seek(0x10, SEEK_CUR); // Skip unneeded values u32 Count = rFile.ReadLong(); - EIDLength IDLength = (mpGroup->Game() <= eEchoes ? e32Bit : e64Bit); for (u32 iKey = 0; iKey < Count; iKey++) { @@ -1024,7 +1023,7 @@ void CUnsupportedParticleLoader::ParseSpawnSystemKeyframeData(IInputStream& rFil for (u32 iInfo = 0; iInfo < InfoCount; iInfo++) { - mpGroup->AddDependency( CAssetID(rFile, IDLength) ); + mpGroup->AddDependency( CAssetID(rFile, mpGroup->Game()) ); rFile.Seek(0xC, SEEK_CUR); // Skip unknown/unneeded values } } diff --git a/src/Core/Resource/Factory/CWorldLoader.cpp b/src/Core/Resource/Factory/CWorldLoader.cpp index f278d530..74558aa1 100644 --- a/src/Core/Resource/Factory/CWorldLoader.cpp +++ b/src/Core/Resource/Factory/CWorldLoader.cpp @@ -17,7 +17,7 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) { mpWorld->mpWorldName = gpResourceStore->LoadResource(rMLVL.ReadLong(), "STRG"); if (mVersion == eEchoes) mpWorld->mpDarkWorldName = gpResourceStore->LoadResource(rMLVL.ReadLong(), "STRG"); - if (mVersion >= eEchoes) mpWorld->mUnknown1 = rMLVL.ReadLong(); + if (mVersion >= eEchoes) mpWorld->mTempleKeyWorldIndex = rMLVL.ReadLong(); if (mVersion >= ePrime) mpWorld->mpSaveWorld = gpResourceStore->LoadResource(rMLVL.ReadLong(), "SAVW"); mpWorld->mpDefaultSkybox = gpResourceStore->LoadResource(rMLVL.ReadLong(), "CMDL"); } @@ -42,40 +42,25 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) MemRelay.InstanceID = rMLVL.ReadLong(); MemRelay.TargetID = rMLVL.ReadLong(); MemRelay.Message = rMLVL.ReadShort(); - MemRelay.Unknown = rMLVL.ReadByte(); + MemRelay.Active = rMLVL.ReadBool(); mpWorld->mMemoryRelays.push_back(MemRelay); } } // Areas - here's the real meat of the file u32 NumAreas = rMLVL.ReadLong(); - if (mVersion == ePrime) mpWorld->mUnknownAreas = rMLVL.ReadLong(); + if (mVersion == ePrime) rMLVL.Seek(0x4, SEEK_CUR); mpWorld->mAreas.resize(NumAreas); for (u32 iArea = 0; iArea < NumAreas; iArea++) { // Area header CWorld::SArea *pArea = &mpWorld->mAreas[iArea]; - - if (mVersion < eCorruptionProto) - pArea->pAreaName = gpResourceStore->LoadResource(rMLVL.ReadLong(), "STRG"); - else - pArea->pAreaName = gpResourceStore->LoadResource(rMLVL.ReadLongLong(), "STRG"); - + pArea->pAreaName = gpResourceStore->LoadResource( CAssetID(rMLVL, mVersion), "STRG" ); pArea->Transform = CTransform4f(rMLVL); pArea->AetherBox = CAABox(rMLVL); - - if (mVersion < eCorruptionProto) - { - pArea->AreaResID = rMLVL.ReadLong() & 0xFFFFFFFF; - pArea->AreaID = rMLVL.ReadLong() & 0xFFFFFFFF; - } - - else - { - pArea->AreaResID = rMLVL.ReadLongLong(); - pArea->AreaID = rMLVL.ReadLongLong(); - } + pArea->AreaResID = CAssetID(rMLVL, mVersion); + pArea->AreaID = CAssetID(rMLVL, mVersion); // Attached areas u32 NumAttachedAreas = rMLVL.ReadLong(); @@ -83,36 +68,15 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) for (u32 iAttached = 0; iAttached < NumAttachedAreas; iAttached++) pArea->AttachedAreaIDs.push_back( rMLVL.ReadShort() ); - if (mVersion < eCorruptionProto) - rMLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value (always 0) - - // Dependencies + // Skip dependency list - this is very fast to regenerate so there's no use in caching it if (mVersion < eCorruptionProto) { + rMLVL.Seek(0x4, SEEK_CUR); u32 NumDependencies = rMLVL.ReadLong(); - pArea->Dependencies.reserve(NumDependencies); + rMLVL.Seek(NumDependencies * 8, SEEK_CUR); - for (u32 iDep = 0; iDep < NumDependencies; iDep++) - { - pArea->Dependencies.push_back( CAssetID(rMLVL, e32Bit) ); - rMLVL.Seek(0x4, SEEK_CUR); - } - - /** - * Dependency offsets - indicates an offset into the dependency list where each layer's dependencies start - * The count is the layer count + 1 because the last offset is for common dependencies, like terrain textures - */ u32 NumDependencyOffsets = rMLVL.ReadLong(); - pArea->Layers.resize(NumDependencyOffsets - 1); - - for (u32 iOff = 0; iOff < NumDependencyOffsets; iOff++) - { - u32 *pTarget; - if (iOff == NumDependencyOffsets - 1) pTarget = &pArea->CommonDependenciesStart; - else pTarget = &pArea->Layers[iOff].LayerDependenciesStart; - - *pTarget = rMLVL.ReadLong(); - } + rMLVL.Seek(NumDependencyOffsets * 4, SEEK_CUR); } // Docks @@ -161,16 +125,15 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) } } - // Footer + // Internal name - MP1 doesn't have this so reuse the area's real name if (mVersion >= eEchoesDemo) pArea->InternalName = rMLVL.ReadString(); + else + pArea->InternalName = (pArea->pAreaName ? pArea->pAreaName->String("ENGL", 0).ToUTF8() : ""); } // MapWorld - if (mVersion < eCorruptionProto) - mpWorld->mpMapWorld = gpResourceStore->LoadResource(rMLVL.ReadLong(), "MAPW"); - else - mpWorld->mpMapWorld = gpResourceStore->LoadResource(rMLVL.ReadLongLong(), "MAPW"); + mpWorld->mpMapWorld = gpResourceStore->LoadResource( CAssetID(rMLVL, mVersion), "MAPW" ); rMLVL.Seek(0x5, SEEK_CUR); // Unknown values which are always 0 // AudioGrps @@ -182,7 +145,7 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) for (u32 iGrp = 0; iGrp < NumAudioGrps; iGrp++) { CWorld::SAudioGrp AudioGrp; - AudioGrp.Unknown = rMLVL.ReadLong(); + AudioGrp.GroupID = rMLVL.ReadLong(); AudioGrp.ResID = rMLVL.ReadLong() & 0xFFFFFFFF; mpWorld->mAudioGrps.push_back(AudioGrp); } @@ -200,7 +163,7 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) u64 LayerFlags = rMLVL.ReadLongLong(); for (u32 iLayer = 0; iLayer < NumLayers; iLayer++) - pArea->Layers[iLayer].EnabledByDefault = (((LayerFlags >> iLayer) & 0x1) == 1); + pArea->Layers[iLayer].Active = (((LayerFlags >> iLayer) & 0x1) == 1); } // Layer names @@ -262,7 +225,7 @@ void CWorldLoader::LoadReturnsMLVL(IInputStream& rMLVL) u64 LayerFlags = rMLVL.ReadLongLong(); for (u32 iLayer = 0; iLayer < NumLayers; iLayer++) - pArea->Layers[iLayer].EnabledByDefault = (((LayerFlags >> iLayer) & 0x1) == 1); + pArea->Layers[iLayer].Active = (((LayerFlags >> iLayer) & 0x1) == 1); } // Layer names @@ -303,7 +266,6 @@ CWorld* CWorldLoader::LoadMLVL(IInputStream& rMLVL, CResourceEntry *pEntry) CWorldLoader Loader; Loader.mpWorld = new CWorld(pEntry); Loader.mpWorld->SetGame(Version); - Loader.mpWorld->mWorldVersion = Version; Loader.mVersion = Version; if (Version != eReturns) diff --git a/src/Editor/PropertyEdit/CPropertyView.cpp b/src/Editor/PropertyEdit/CPropertyView.cpp index 1d220bd1..e07355af 100644 --- a/src/Editor/PropertyEdit/CPropertyView.cpp +++ b/src/Editor/PropertyEdit/CPropertyView.cpp @@ -95,7 +95,7 @@ void CPropertyView::SetInstance(CScriptObject *pObj) void CPropertyView::UpdateEditorProperties(const QModelIndex& rkParent) { // Check what game this is - EGame Game = mpEditor->ActiveArea()->Version(); + EGame Game = mpEditor->CurrentGame(); // Iterate over all properties and update if they're an editor property. for (int iRow = 0; iRow < mpModel->rowCount(rkParent); iRow++) diff --git a/src/Editor/Undo/CDeleteSelectionCommand.cpp b/src/Editor/Undo/CDeleteSelectionCommand.cpp index 013e85e6..d979f6df 100644 --- a/src/Editor/Undo/CDeleteSelectionCommand.cpp +++ b/src/Editor/Undo/CDeleteSelectionCommand.cpp @@ -95,7 +95,7 @@ void CDeleteSelectionCommand::undo() mpEditor->NotifyNodeAboutToBeSpawned(); CMemoryInStream Mem(rNode.InstanceData.data(), rNode.InstanceData.size(), IOUtil::eBigEndian); - CScriptObject *pInstance = CScriptLoader::LoadInstance(Mem, rNode.pArea, rNode.pLayer, rNode.pArea->Version(), true); + CScriptObject *pInstance = CScriptLoader::LoadInstance(Mem, rNode.pArea, rNode.pLayer, rNode.pArea->Game(), true); CScriptNode *pNode = mpEditor->Scene()->CreateScriptNode(pInstance, rNode.NodeID); rNode.pArea->AddInstanceToArea(pInstance); rNode.pLayer->AddInstance(pInstance, rNode.LayerIndex); diff --git a/src/Editor/Undo/CPasteNodesCommand.cpp b/src/Editor/Undo/CPasteNodesCommand.cpp index 0955d788..b8c2e6a9 100644 --- a/src/Editor/Undo/CPasteNodesCommand.cpp +++ b/src/Editor/Undo/CPasteNodesCommand.cpp @@ -55,7 +55,7 @@ void CPasteNodesCommand::redo() if (rkNode.Type == eScriptNode) { CMemoryInStream In(rkNode.InstanceData.data(), rkNode.InstanceData.size(), IOUtil::eBigEndian); - CScriptObject *pInstance = CScriptLoader::LoadInstance(In, pArea, mpLayer, pArea->Version(), true); + CScriptObject *pInstance = CScriptLoader::LoadInstance(In, pArea, mpLayer, pArea->Game(), true); pArea->AddInstanceToArea(pInstance); mpLayer->AddInstance(pInstance); diff --git a/src/Editor/WorldEditor/CPoiMapEditDialog.cpp b/src/Editor/WorldEditor/CPoiMapEditDialog.cpp index 48302b05..2b72bbab 100644 --- a/src/Editor/WorldEditor/CPoiMapEditDialog.cpp +++ b/src/Editor/WorldEditor/CPoiMapEditDialog.cpp @@ -343,7 +343,7 @@ void CPoiMapEditDialog::StopPicking() void CPoiMapEditDialog::OnInstanceListButtonClicked() { - EGame Game = mpEditor->ActiveArea()->Version(); + EGame Game = mpEditor->CurrentGame(); CScriptTemplate *pPoiTemplate = CMasterTemplate::MasterForGame(Game)->TemplateByID("POIN"); CPoiListDialog Dialog(pPoiTemplate, &mSourceModel, mpEditor->Scene(), this); diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index e708bd79..d0b1f631 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -212,16 +212,16 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) UpdateCameraOrbit(); // Default bloom to Fake Bloom for Metroid Prime 3; disable for other games - bool AllowBloom = (mpWorld->Version() == eCorruptionProto || mpWorld->Version() == eCorruption); + bool AllowBloom = (mpWorld->Game() == eCorruptionProto || mpWorld->Game() == eCorruption); AllowBloom ? SetFakeBloom() : SetNoBloom(); ui->menuBloom->setEnabled(AllowBloom); // Disable EGMC editing for Prime 1 and DKCR - bool AllowEGMC = ( (mpWorld->Version() >= eEchoesDemo) && (mpWorld->Version() <= eCorruption) ); + bool AllowEGMC = ( (mpWorld->Game() >= eEchoesDemo) && (mpWorld->Game() <= eCorruption) ); ui->ActionEditPoiToWorldMap->setEnabled(AllowEGMC); // Set up sidebar tabs - CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(mpArea->Version()); + CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(mpArea->Game()); ui->CreateTabContents->SetMaster(pMaster); ui->InstancesTabContents->SetMaster(pMaster); diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index b666c900..a38d413c 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -59,7 +59,7 @@ public: bool HasAnyScriptNodesSelected() const; inline CGameArea* ActiveArea() const { return mpArea; } - inline EGame CurrentGame() const { return mpArea ? mpArea->Version() : eUnknownGame; } + inline EGame CurrentGame() const { return mpArea ? mpArea->Game() : eUnknownGame; } inline CLinkDialog* LinkDialog() const { return mpLinkDialog; } CSceneViewport* Viewport() const; diff --git a/src/Editor/WorldEditor/WInstancesTab.cpp b/src/Editor/WorldEditor/WInstancesTab.cpp index 4858b49a..8f7c5883 100644 --- a/src/Editor/WorldEditor/WInstancesTab.cpp +++ b/src/Editor/WorldEditor/WInstancesTab.cpp @@ -313,7 +313,7 @@ void WInstancesTab::OnHideAllExceptTypeAction() else { - EGame Game = mpEditor->ActiveArea()->Version(); + EGame Game = mpEditor->CurrentGame(); CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game); for (u32 iTemp = 0; iTemp < pMaster->NumScriptTemplates(); iTemp++) @@ -344,7 +344,7 @@ void WInstancesTab::OnUnhideAllTypes() else { - EGame Game = mpEditor->ActiveArea()->Version(); + EGame Game = mpEditor->CurrentGame(); CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game); for (u32 iTemp = 0; iTemp < pMaster->NumScriptTemplates(); iTemp++) @@ -378,7 +378,7 @@ void WInstancesTab::OnUnhideAll() if (TypesRoot.isValid()) { - EGame Game = mpEditor->ActiveArea()->Version(); + EGame Game = mpEditor->CurrentGame(); CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game); for (u32 iTemp = 0; iTemp < pMaster->NumScriptTemplates(); iTemp++) diff --git a/src/FileIO/IInputStream.cpp b/src/FileIO/IInputStream.cpp index 9379acf5..b4759e36 100644 --- a/src/FileIO/IInputStream.cpp +++ b/src/FileIO/IInputStream.cpp @@ -1,9 +1,18 @@ #include "IInputStream.h" +#include IInputStream::~IInputStream() { } +bool IInputStream::ReadBool() +{ + char Val; + ReadBytes(&Val, 1); + assert(Val == 0 || Val == 1); + return (Val != 0 ? true : false); +} + char IInputStream::ReadByte() { char Val; diff --git a/src/FileIO/IInputStream.h b/src/FileIO/IInputStream.h index 2ff87527..1378567f 100644 --- a/src/FileIO/IInputStream.h +++ b/src/FileIO/IInputStream.h @@ -12,6 +12,7 @@ protected: std::string mDataSource; public: + bool ReadBool(); char ReadByte(); short ReadShort(); long ReadLong(); diff --git a/src/FileIO/IOutputStream.cpp b/src/FileIO/IOutputStream.cpp index 1c2eedee..56bf5233 100644 --- a/src/FileIO/IOutputStream.cpp +++ b/src/FileIO/IOutputStream.cpp @@ -4,6 +4,12 @@ IOutputStream::~IOutputStream() { } +void IOutputStream::WriteBool(bool Val) +{ + char ChrVal = (Val ? 1 : 0); + WriteBytes(&ChrVal, 1); +} + void IOutputStream::WriteByte(char Val) { WriteBytes(&Val, 1); diff --git a/src/FileIO/IOutputStream.h b/src/FileIO/IOutputStream.h index 205fb1bf..67e52e43 100644 --- a/src/FileIO/IOutputStream.h +++ b/src/FileIO/IOutputStream.h @@ -11,6 +11,7 @@ protected: std::string mDataDest; public: + void WriteBool(bool Val); void WriteByte(char Val); void WriteShort(short Val); void WriteLong(long Val); diff --git a/templates/mp3/Script/DefenseMechanoid.xml b/templates/mp3/Script/DefenseMechanoid.xml index c5de0f6c..41861554 100644 --- a/templates/mp3/Script/DefenseMechanoid.xml +++ b/templates/mp3/Script/DefenseMechanoid.xml @@ -38,7 +38,7 @@ never - + never diff --git a/templates/mp3/Script/GragnolFlyer.xml b/templates/mp3/Script/GragnolFlyer.xml index 3e23b16b..ff691e85 100644 --- a/templates/mp3/Script/GragnolFlyer.xml +++ b/templates/mp3/Script/GragnolFlyer.xml @@ -267,7 +267,7 @@ never - + never diff --git a/templates/mp3/Script/Korakk.xml b/templates/mp3/Script/Korakk.xml index 9128329d..d12acf1a 100644 --- a/templates/mp3/Script/Korakk.xml +++ b/templates/mp3/Script/Korakk.xml @@ -99,7 +99,7 @@ never - + never diff --git a/templates/mp3/Script/MinorIng.xml b/templates/mp3/Script/MinorIng.xml index fea0ffaf..7b12b2d7 100644 --- a/templates/mp3/Script/MinorIng.xml +++ b/templates/mp3/Script/MinorIng.xml @@ -209,7 +209,7 @@ never - + never diff --git a/templates/mp3/Script/Rundas.xml b/templates/mp3/Script/Rundas.xml index 5a6fdfa2..6df2e4dc 100644 --- a/templates/mp3/Script/Rundas.xml +++ b/templates/mp3/Script/Rundas.xml @@ -91,7 +91,7 @@ never - + never diff --git a/templates/mp3/Script/ShellBug.xml b/templates/mp3/Script/ShellBug.xml index 884a090d..1bb450d7 100644 --- a/templates/mp3/Script/ShellBug.xml +++ b/templates/mp3/Script/ShellBug.xml @@ -145,7 +145,7 @@ never - + never diff --git a/templates/mp3/Script/SpacePirate.xml b/templates/mp3/Script/SpacePirate.xml index 7bab2a20..f23e33a0 100644 --- a/templates/mp3/Script/SpacePirate.xml +++ b/templates/mp3/Script/SpacePirate.xml @@ -446,7 +446,7 @@ never - + never diff --git a/templates/mp3/Script/SteamDrone.xml b/templates/mp3/Script/SteamDrone.xml index a952e27a..f41c7a40 100644 --- a/templates/mp3/Script/SteamDrone.xml +++ b/templates/mp3/Script/SteamDrone.xml @@ -193,7 +193,7 @@ never - + never diff --git a/templates/mp3/Structs/SeedBoss3Data.xml b/templates/mp3/Structs/SeedBoss3Data.xml index 0a7933cc..3f09672e 100644 --- a/templates/mp3/Structs/SeedBoss3Data.xml +++ b/templates/mp3/Structs/SeedBoss3Data.xml @@ -434,7 +434,7 @@ never - + never @@ -505,10 +505,10 @@ - + never - + never