mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-21 02:39:17 +00:00
Lots of work to get MP2 repacking functional
This commit is contained in:
@@ -57,6 +57,7 @@ struct SSetCharacter
|
||||
std::vector<CAssetID> EffectParticles;
|
||||
CAssetID IceModel;
|
||||
CAssetID IceSkin;
|
||||
CAssetID SpatialPrimitives;
|
||||
std::set<u32> UsedAnimationIndices;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ CGameArea::CGameArea(CResourceEntry *pEntry /*= 0*/)
|
||||
, mOriginalWorldMeshCount(0)
|
||||
, mUsesCompression(false)
|
||||
, mpMaterialSet(nullptr)
|
||||
, mpGeneratorLayer(nullptr)
|
||||
, mpCollision(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -21,7 +20,6 @@ CGameArea::~CGameArea()
|
||||
ClearTerrain();
|
||||
|
||||
delete mpCollision;
|
||||
delete mpGeneratorLayer;
|
||||
|
||||
for (u32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
||||
delete mScriptLayers[iSCLY];
|
||||
@@ -54,8 +52,6 @@ CDependencyTree* CGameArea::BuildDependencyTree() const
|
||||
for (u32 iLayer = 0; iLayer < mScriptLayers.size(); iLayer++)
|
||||
pTree->AddScriptLayer(mScriptLayers[iLayer]);
|
||||
|
||||
pTree->AddScriptLayer(mpGeneratorLayer);
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
@@ -134,8 +130,6 @@ void CGameArea::ClearScriptLayers()
|
||||
for (auto it = mScriptLayers.begin(); it != mScriptLayers.end(); it++)
|
||||
delete *it;
|
||||
mScriptLayers.clear();
|
||||
delete mpGeneratorLayer;
|
||||
mpGeneratorLayer = nullptr;
|
||||
}
|
||||
|
||||
u32 CGameArea::TotalInstanceCount() const
|
||||
|
||||
@@ -49,7 +49,6 @@ class CGameArea : public CResource
|
||||
std::vector<CStaticModel*> mStaticWorldModels; // StaticTerrainModels is the merged terrain for faster rendering in the world editor
|
||||
// Script
|
||||
std::vector<CScriptLayer*> mScriptLayers;
|
||||
CScriptLayer *mpGeneratorLayer;
|
||||
std::unordered_map<u32, CScriptObject*> mObjectMap;
|
||||
// Collision
|
||||
CCollisionMeshGroup *mpCollision;
|
||||
@@ -92,7 +91,6 @@ public:
|
||||
inline CCollisionMeshGroup* Collision() const { return mpCollision; }
|
||||
inline u32 NumScriptLayers() const { return mScriptLayers.size(); }
|
||||
inline CScriptLayer* ScriptLayer(u32 Index) const { return mScriptLayers[Index]; }
|
||||
inline CScriptLayer* GeneratedObjectsLayer() const { return mpGeneratorLayer; }
|
||||
inline u32 NumLightLayers() const { return mLightLayers.size(); }
|
||||
inline u32 NumLights(u32 LayerIndex) const { return (LayerIndex < mLightLayers.size() ? mLightLayers[LayerIndex].size() : 0); }
|
||||
inline CLight* Light(u32 LayerIndex, u32 LightIndex) const { return mLightLayers[LayerIndex][LightIndex]; }
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "CResource.h"
|
||||
#include "CStringTable.h"
|
||||
#include "TResPtr.h"
|
||||
#include "Core/Resource/Animation/CAnimationParameters.h"
|
||||
#include <Common/EGame.h>
|
||||
|
||||
class CScan : public CResource
|
||||
@@ -22,15 +23,34 @@ public:
|
||||
eResearch
|
||||
};
|
||||
|
||||
struct SScanInfoSecondaryModel
|
||||
{
|
||||
CAssetID ModelID;
|
||||
CAnimationParameters AnimParams;
|
||||
TString AttachBoneName;
|
||||
};
|
||||
|
||||
private:
|
||||
EGame mVersion;
|
||||
CAssetID mFrameID;
|
||||
// Common
|
||||
TResPtr<CStringTable> mpStringTable;
|
||||
bool mIsSlow;
|
||||
bool mIsImportant;
|
||||
ELogbookCategory mCategory;
|
||||
|
||||
// MP1
|
||||
CAssetID mFrameID;
|
||||
CAssetID mScanImageTextures[4];
|
||||
std::vector<CAssetID> mLogbookAssets;
|
||||
|
||||
// MP2/3
|
||||
bool mUseLogbookModelPostScan;
|
||||
CAssetID mPostOverrideTexture;
|
||||
float mLogbookDefaultRotX;
|
||||
float mLogbookDefaultRotZ;
|
||||
float mLogbookScale;
|
||||
CAssetID mLogbookModel;
|
||||
CAnimationParameters mLogbookAnimParams;
|
||||
CAnimationParameters mUnknownAnimParams;
|
||||
std::vector<SScanInfoSecondaryModel> mSecondaryModels;
|
||||
|
||||
public:
|
||||
CScan(CResourceEntry *pEntry = 0)
|
||||
@@ -43,23 +63,41 @@ public:
|
||||
|
||||
CDependencyTree* BuildDependencyTree() const
|
||||
{
|
||||
// note: not handling Corruption yet
|
||||
if (Game() >= eCorruptionProto)
|
||||
Log::Warning("CScan::BuildDependencyTree not handling Corruption dependencies");
|
||||
|
||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
||||
pTree->AddDependency(mFrameID);
|
||||
|
||||
if (Game() <= ePrime)
|
||||
pTree->AddDependency(mFrameID);
|
||||
|
||||
pTree->AddDependency(mpStringTable);
|
||||
|
||||
for (u32 iImg = 0; iImg < 4; iImg++)
|
||||
pTree->AddDependency(mScanImageTextures[iImg]);
|
||||
if (Game() <= ePrime)
|
||||
{
|
||||
for (u32 iImg = 0; iImg < 4; iImg++)
|
||||
pTree->AddDependency(mScanImageTextures[iImg]);
|
||||
}
|
||||
|
||||
for (u32 iLog = 0; iLog < mLogbookAssets.size(); iLog++)
|
||||
pTree->AddDependency(mLogbookAssets[iLog]);
|
||||
else if (Game() <= eEchoes)
|
||||
{
|
||||
pTree->AddDependency(mPostOverrideTexture);
|
||||
pTree->AddDependency(mLogbookModel);
|
||||
pTree->AddCharacterDependency(mLogbookAnimParams);
|
||||
pTree->AddCharacterDependency(mUnknownAnimParams);
|
||||
|
||||
for (u32 iSec = 0; iSec < mSecondaryModels.size(); iSec++)
|
||||
{
|
||||
const SScanInfoSecondaryModel& rkSecModel = mSecondaryModels[iSec];
|
||||
pTree->AddDependency(rkSecModel.ModelID);
|
||||
pTree->AddCharacterDependency(rkSecModel.AnimParams);
|
||||
}
|
||||
}
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
EGame Version() const { return mVersion; }
|
||||
CStringTable* ScanText() const { return mpStringTable; }
|
||||
bool IsImportant() const { return mIsImportant; }
|
||||
bool IsSlow() const { return mIsSlow; }
|
||||
|
||||
@@ -200,10 +200,11 @@ void CAreaCooker::WritePrimeSCLY(IOutputStream& rOut)
|
||||
// SCGN
|
||||
if (mVersion == eEchoesDemo)
|
||||
{
|
||||
rOut.WriteString("SCGN", 4);
|
||||
// IMPORTANT TODO - REGENERATE SCGN LAYER
|
||||
/*rOut.WriteString("SCGN", 4);
|
||||
rOut.WriteByte(1);
|
||||
CScriptCooker::WriteLayer(mVersion, mpArea->mpGeneratorLayer, rOut);
|
||||
FinishSection(false);
|
||||
FinishSection(false);*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,9 +221,10 @@ void CAreaCooker::WriteEchoesSCLY(IOutputStream& rOut)
|
||||
}
|
||||
|
||||
// SCGN
|
||||
// IMPORTANT TODO - REGENERATE SCGN
|
||||
rOut.WriteString("SCGN", 4);
|
||||
rOut.WriteByte(0x1);
|
||||
CScriptCooker::WriteLayer(mVersion, mpArea->mpGeneratorLayer, rOut);
|
||||
//CScriptCooker::WriteLayer(mVersion, mpArea->mpGeneratorLayer, rOut);
|
||||
FinishSection(true);
|
||||
}
|
||||
|
||||
@@ -276,7 +278,7 @@ void CAreaCooker::FinishBlock()
|
||||
|
||||
if (EnableCompression)
|
||||
{
|
||||
bool Success = CompressionUtil::CompressSegmentedData((u8*) mCompressedData.Data(), mCompressedData.Size(), CompressedBuf.data(), CompressedSize, UseZlib);
|
||||
bool Success = CompressionUtil::CompressSegmentedData((u8*) mCompressedData.Data(), mCompressedData.Size(), CompressedBuf.data(), CompressedSize, UseZlib, true);
|
||||
u32 PadBytes = (32 - (CompressedSize % 32)) & 0x1F;
|
||||
WriteCompressedData = Success && (CompressedSize + PadBytes < (u32) mCompressedData.Size());
|
||||
}
|
||||
|
||||
@@ -141,6 +141,10 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
|
||||
for (u32 iOff = 0; iOff < ModuleLayerOffsets.size(); iOff++)
|
||||
rMLVL.WriteLong(ModuleLayerOffsets[iOff]);
|
||||
}
|
||||
|
||||
// Internal Name
|
||||
if (Game >= eEchoesDemo)
|
||||
rMLVL.WriteString(rArea.InternalName.ToStdString());
|
||||
}
|
||||
|
||||
if (Game <= eCorruption)
|
||||
|
||||
@@ -33,7 +33,7 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
|
||||
return pSet;
|
||||
}
|
||||
|
||||
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar)
|
||||
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
|
||||
{
|
||||
// For now, just parse the data; don't store it
|
||||
rPAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
|
||||
@@ -68,11 +68,7 @@ void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar)
|
||||
}
|
||||
|
||||
for (u32 iInfo = 0; iInfo < AnimInfoCount; iInfo++)
|
||||
{
|
||||
u32 MetaAnimID = rPAS4.ReadLong();
|
||||
rPAS4.Seek(Skip, SEEK_CUR);
|
||||
pChar->UsedAnimationIndices.insert(MetaAnimID);
|
||||
}
|
||||
rPAS4.Seek(0x4 + Skip, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +317,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
||||
}
|
||||
|
||||
// PAS Database
|
||||
Loader.LoadPASDatabase(rANCS, pChar);
|
||||
Loader.LoadPASDatabase(rANCS);
|
||||
|
||||
// Particles
|
||||
u32 ParticleCount = rANCS.ReadLong();
|
||||
@@ -394,7 +390,8 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
||||
|
||||
if (Loader.mVersion == eEchoes)
|
||||
{
|
||||
rANCS.Seek(0x5, SEEK_CUR);
|
||||
pChar->SpatialPrimitives = rANCS.ReadLong();
|
||||
rANCS.Seek(0x1, SEEK_CUR);
|
||||
u32 UnknownCount2 = rANCS.ReadLong();
|
||||
rANCS.Seek(UnknownCount2 * 0x1C, SEEK_CUR);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class CAnimSetLoader
|
||||
CAnimSetLoader();
|
||||
CAnimSet* LoadCorruptionCHAR(IInputStream& rCHAR);
|
||||
CAnimSet* LoadReturnsCHAR(IInputStream& rCHAR);
|
||||
void LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar);
|
||||
void LoadPASDatabase(IInputStream& rPAS4);
|
||||
|
||||
void LoadAnimationSet(IInputStream& rANCS);
|
||||
void ProcessPrimitives();
|
||||
|
||||
@@ -158,9 +158,8 @@ void CAreaLoader::ReadSCLYPrime()
|
||||
|
||||
if (pLayer)
|
||||
{
|
||||
mpArea->mpGeneratorLayer = pLayer;
|
||||
pLayer->SetName("Generated Objects");
|
||||
pLayer->SetActive(true);
|
||||
MergeGeneratedLayer(pLayer);
|
||||
delete pLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,6 +310,7 @@ void CAreaLoader::ReadSCLYEchoes()
|
||||
}
|
||||
|
||||
// SCGN
|
||||
// we want to regenerate the SCGN layer on cook - for now just move everything back to its original layer
|
||||
CFourCC SCGN(*mpMREA);
|
||||
if (SCGN != "SCGN")
|
||||
{
|
||||
@@ -319,12 +319,12 @@ void CAreaLoader::ReadSCLYEchoes()
|
||||
}
|
||||
|
||||
mpMREA->Seek(0x1, SEEK_CUR); // Skipping unknown
|
||||
mpArea->mpGeneratorLayer = CScriptLoader::LoadLayer(*mpMREA, mpArea, mVersion);
|
||||
CScriptLayer *pGeneratedLayer = CScriptLoader::LoadLayer(*mpMREA, mpArea, mVersion);
|
||||
|
||||
if (mpArea->mpGeneratorLayer)
|
||||
if (pGeneratedLayer)
|
||||
{
|
||||
mpArea->mpGeneratorLayer->SetName("Generated Objects");
|
||||
mpArea->mpGeneratorLayer->SetActive(true);
|
||||
MergeGeneratedLayer(pGeneratedLayer);
|
||||
delete pGeneratedLayer;
|
||||
}
|
||||
|
||||
SetUpObjects();
|
||||
@@ -606,19 +606,37 @@ void CAreaLoader::ReadEGMC()
|
||||
mpArea->mpPoiToWorldMap = gpResourceStore->LoadResource(EGMC, "EGMC");
|
||||
}
|
||||
|
||||
void CAreaLoader::SetUpObjects()
|
||||
void CAreaLoader::MergeGeneratedLayer(CScriptLayer *pLayer)
|
||||
{
|
||||
// Iterate over all objects
|
||||
for (u32 iLyr = 0; iLyr < mpArea->NumScriptLayers() + 1; iLyr++)
|
||||
while (pLayer->NumInstances() != 0)
|
||||
{
|
||||
CScriptLayer *pLayer;
|
||||
if (iLyr < mpArea->NumScriptLayers()) pLayer = mpArea->mScriptLayers[iLyr];
|
||||
CScriptObject *pObj = pLayer->InstanceByIndex(0);
|
||||
u32 InstanceID = pObj->InstanceID();
|
||||
|
||||
// Check if this is a duplicate of an existing instance (this only happens with DKCR GenericCreature as far as I'm aware)
|
||||
CScriptObject *pDupe = mpArea->InstanceByID(InstanceID);
|
||||
|
||||
if (pDupe)
|
||||
{
|
||||
Log::Write("Duplicate SCGN object: [" + pObj->Template()->Name() + "] " + pObj->InstanceName() + " (" + TString::HexString(pObj->InstanceID(), 8, false) + ")");
|
||||
pLayer->RemoveInstance(pObj);
|
||||
delete pObj;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
pLayer = mpArea->GeneratedObjectsLayer();
|
||||
if (!pLayer) break;
|
||||
u32 LayerIdx = (InstanceID >> 26) & 0x3F;
|
||||
pObj->SetLayer( mpArea->ScriptLayer(LayerIdx) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAreaLoader::SetUpObjects()
|
||||
{
|
||||
// Iterate over all objects
|
||||
for (u32 iLyr = 0; iLyr < mpArea->NumScriptLayers(); iLyr++)
|
||||
{
|
||||
CScriptLayer *pLayer = mpArea->mScriptLayers[iLyr];
|
||||
|
||||
for (u32 iObj = 0; iObj < pLayer->NumInstances(); iObj++)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ class CAreaLoader
|
||||
void ReadPATH();
|
||||
void ReadPTLA();
|
||||
void ReadEGMC();
|
||||
void MergeGeneratedLayer(CScriptLayer *pLayer);
|
||||
void SetUpObjects();
|
||||
|
||||
public:
|
||||
|
||||
@@ -27,28 +27,33 @@ CAudioGroup* CAudioGroupLoader::LoadAGSC(IInputStream& rAGSC, CResourceEntry *pE
|
||||
}
|
||||
|
||||
// Read needed data from the Proj chunk
|
||||
u32 ProjStart = rAGSC.Tell();
|
||||
rAGSC.Seek(0x4, SEEK_CUR);
|
||||
u16 GroupID = rAGSC.ReadShort();
|
||||
u16 GroupType = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x14, SEEK_CUR);
|
||||
u32 SfxTableStart = rAGSC.ReadLong();
|
||||
u16 Peek = rAGSC.PeekShort();
|
||||
|
||||
if (Game == ePrime)
|
||||
pOut->mGroupID = GroupID;
|
||||
else
|
||||
ASSERT(pOut->mGroupID == GroupID);
|
||||
|
||||
if (GroupType == 1)
|
||||
if (Peek != 0xFFFF)
|
||||
{
|
||||
rAGSC.Seek(ProjStart + SfxTableStart, SEEK_SET);
|
||||
u16 NumSounds = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x2, SEEK_CUR);
|
||||
u32 ProjStart = rAGSC.Tell();
|
||||
rAGSC.Seek(0x4, SEEK_CUR);
|
||||
u16 GroupID = rAGSC.ReadShort();
|
||||
u16 GroupType = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x14, SEEK_CUR);
|
||||
u32 SfxTableStart = rAGSC.ReadLong();
|
||||
|
||||
for (u32 iSfx = 0; iSfx < NumSounds; iSfx++)
|
||||
if (Game == ePrime)
|
||||
pOut->mGroupID = GroupID;
|
||||
else
|
||||
ASSERT(pOut->mGroupID == GroupID);
|
||||
|
||||
if (GroupType == 1)
|
||||
{
|
||||
pOut->mDefineIDs.push_back( rAGSC.ReadShort() );
|
||||
rAGSC.Seek(0x8, SEEK_CUR);
|
||||
rAGSC.Seek(ProjStart + SfxTableStart, SEEK_SET);
|
||||
u16 NumSounds = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x2, SEEK_CUR);
|
||||
|
||||
for (u32 iSfx = 0; iSfx < NumSounds; iSfx++)
|
||||
{
|
||||
pOut->mDefineIDs.push_back( rAGSC.ReadShort() );
|
||||
rAGSC.Seek(0x8, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +75,10 @@ CStringList* CAudioGroupLoader::LoadSTLC(IInputStream& rSTLC, CResourceEntry *pE
|
||||
{
|
||||
CStringList *pOut = new CStringList(pEntry);
|
||||
u32 NumStrings = rSTLC.ReadLong();
|
||||
pOut->mStringList.reserve(NumStrings);
|
||||
|
||||
for (u32 iStr = 0; iStr < NumStrings; iStr++)
|
||||
pOut->mStringList[iStr] = rSTLC.ReadString();
|
||||
pOut->mStringList.push_back( rSTLC.ReadString() );
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ CScan* CScanLoader::LoadScanMP1(IInputStream& rSCAN)
|
||||
rSCAN.Seek(0x18, SEEK_CUR);
|
||||
}
|
||||
|
||||
mpScan->mVersion = ePrime;
|
||||
mpScan->SetGame(ePrime);
|
||||
return mpScan;
|
||||
}
|
||||
|
||||
@@ -67,26 +67,29 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
|
||||
case 0xB:
|
||||
mpScan = new CScan(mpEntry);
|
||||
mpScan->SetGame(eEchoes);
|
||||
LoadParamsMP2(rSCAN);
|
||||
LoadParamsMP2(rSCAN, NumProperties);
|
||||
break;
|
||||
case 0x12:
|
||||
case 0x16:
|
||||
mpScan = new CScan(mpEntry);
|
||||
mpScan->SetGame(eCorruption);
|
||||
LoadParamsMP3(rSCAN);
|
||||
LoadParamsMP3(rSCAN, NumProperties);
|
||||
break;
|
||||
default:
|
||||
Log::FileError(rSCAN.GetSourceString(), rSCAN.Tell() - 2, "Invalid SNFO property count: " + TString::HexString(NumProperties));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mpScan->SetGame(eEchoes);
|
||||
return mpScan;
|
||||
}
|
||||
|
||||
void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
|
||||
void CScanLoader::LoadParamsMP2(IInputStream& rSCAN, u16 NumProperties)
|
||||
{
|
||||
// Function begins after the SNFO property count
|
||||
for (u32 iProp = 0; iProp < 20; iProp++)
|
||||
mpScan->mSecondaryModels.resize(9);
|
||||
|
||||
for (u32 iProp = 0; iProp < NumProperties; iProp++)
|
||||
{
|
||||
u32 PropertyID = rSCAN.ReadLong();
|
||||
u16 PropertySize = rSCAN.ReadShort();
|
||||
@@ -103,39 +106,75 @@ void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
|
||||
break;
|
||||
|
||||
case 0x7B714814:
|
||||
mpScan->mIsImportant = (rSCAN.ReadByte() != 0);
|
||||
mpScan->mIsImportant = rSCAN.ReadBool();
|
||||
break;
|
||||
|
||||
case 0x1733B1EC:
|
||||
mpScan->mUseLogbookModelPostScan = rSCAN.ReadBool();
|
||||
break;
|
||||
|
||||
// Override texture and logbook model/animsets
|
||||
case 0x53336141:
|
||||
case 0xB7ADC418:
|
||||
case 0x15694EE1:
|
||||
case 0x58F9FE99:
|
||||
mpScan->mLogbookAssets.push_back( CAssetID(rSCAN, eEchoes) );
|
||||
mpScan->mPostOverrideTexture = CAssetID(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x3DE0BA64:
|
||||
mpScan->mLogbookDefaultRotX = rSCAN.ReadFloat();
|
||||
break;
|
||||
|
||||
case 0x2ADD6628:
|
||||
mpScan->mLogbookDefaultRotZ = rSCAN.ReadFloat();
|
||||
break;
|
||||
|
||||
case 0xD0C15066:
|
||||
mpScan->mLogbookScale = rSCAN.ReadFloat();
|
||||
break;
|
||||
|
||||
case 0xB7ADC418:
|
||||
mpScan->mLogbookModel = CAssetID(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x15694EE1:
|
||||
mpScan->mLogbookAnimParams = CAnimationParameters(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x58F9FE99:
|
||||
mpScan->mUnknownAnimParams = CAnimationParameters(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
// ScanInfoSecondaryModels
|
||||
case 0x1C5B4A3A:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[0] );
|
||||
break;
|
||||
|
||||
case 0x8728A0EE:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[1] );
|
||||
break;
|
||||
|
||||
case 0xF1CD99D3:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[2] );
|
||||
break;
|
||||
|
||||
case 0x6ABE7307:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[3] );
|
||||
break;
|
||||
|
||||
case 0x1C07EBA9:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[4] );
|
||||
break;
|
||||
|
||||
case 0x8774017D:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[5] );
|
||||
break;
|
||||
|
||||
case 0xF1913840:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[6] );
|
||||
break;
|
||||
|
||||
case 0x6AE2D294:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[7] );
|
||||
break;
|
||||
|
||||
case 0x1CE2091C:
|
||||
u16 NumSubProps = rSCAN.ReadShort();
|
||||
|
||||
for (u32 iSub = 0; iSub < NumSubProps; iSub++)
|
||||
{
|
||||
u32 SubPropertyID = rSCAN.ReadLong();
|
||||
u32 Next = rSCAN.Tell() + rSCAN.ReadShort();
|
||||
|
||||
if (SubPropertyID == 0x1F7921BC || SubPropertyID == 0xCDD202D1)
|
||||
mpScan->mLogbookAssets.push_back( CAssetID(rSCAN, eEchoes) );
|
||||
|
||||
rSCAN.Seek(Next, SEEK_SET);
|
||||
}
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[8] );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -143,15 +182,12 @@ void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
|
||||
}
|
||||
|
||||
mpScan->mCategory = CScan::eNone;
|
||||
mpScan->mVersion = eEchoes;
|
||||
}
|
||||
|
||||
void CScanLoader::LoadParamsMP3(IInputStream& rSCAN)
|
||||
void CScanLoader::LoadParamsMP3(IInputStream& rSCAN, u16 NumProperties)
|
||||
{
|
||||
// Function begins after the SNFO property count
|
||||
// Function is near-identical to the MP2 one, but when I add support
|
||||
// for the other params, there will be more differences
|
||||
for (u32 iProp = 0; iProp < 20; iProp++)
|
||||
for (u32 iProp = 0; iProp < NumProperties; iProp++)
|
||||
{
|
||||
u32 PropertyID = rSCAN.ReadLong();
|
||||
u16 PropertySize = rSCAN.ReadShort();
|
||||
@@ -176,7 +212,35 @@ void CScanLoader::LoadParamsMP3(IInputStream& rSCAN)
|
||||
}
|
||||
|
||||
mpScan->mCategory = CScan::eNone;
|
||||
mpScan->mVersion = eCorruption;
|
||||
}
|
||||
|
||||
void CScanLoader::LoadScanInfoSecondaryModel(IInputStream& rSCAN, CScan::SScanInfoSecondaryModel& rSecondaryModel)
|
||||
{
|
||||
u16 NumProperties = rSCAN.ReadShort();
|
||||
|
||||
for (u32 iProp = 0; iProp < NumProperties; iProp++)
|
||||
{
|
||||
u32 PropertyID = rSCAN.ReadLong();
|
||||
u16 PropertySize = rSCAN.ReadShort();
|
||||
u32 Next = rSCAN.Tell() + PropertySize;
|
||||
|
||||
switch (PropertyID)
|
||||
{
|
||||
case 0x1F7921BC:
|
||||
rSecondaryModel.ModelID = CAssetID(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0xCDD202D1:
|
||||
rSecondaryModel.AnimParams = CAnimationParameters(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x3EA2BED8:
|
||||
rSecondaryModel.AttachBoneName = rSCAN.ReadString();
|
||||
break;
|
||||
}
|
||||
|
||||
rSCAN.Seek(Next, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC/PUBLIC ************
|
||||
|
||||
@@ -13,8 +13,9 @@ class CScanLoader
|
||||
CScanLoader();
|
||||
CScan* LoadScanMP1(IInputStream& rSCAN);
|
||||
CScan* LoadScanMP2(IInputStream& rSCAN);
|
||||
void LoadParamsMP2(IInputStream& rSCAN);
|
||||
void LoadParamsMP3(IInputStream& rSCAN);
|
||||
void LoadParamsMP2(IInputStream& rSCAN, u16 NumProperties);
|
||||
void LoadParamsMP3(IInputStream& rSCAN, u16 NumProperties);
|
||||
void LoadScanInfoSecondaryModel(IInputStream& rSCAN, CScan::SScanInfoSecondaryModel& rSecondaryModel);
|
||||
|
||||
public:
|
||||
static CScan* LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry);
|
||||
|
||||
@@ -59,7 +59,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
|
||||
|
||||
u32 Check = pBitfieldCast->Get() & ~Mask;
|
||||
if (Check != 0)
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + TString::HexString(Check));
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->FullName() + "\" + (" + pBitfieldTemp->IDString(true) + ") has flags set that aren't in the template: " + TString::HexString(Check));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
|
||||
|
||||
// Validate
|
||||
u32 Index = pEnumTemp->EnumeratorIndex(ID);
|
||||
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has invalid enumerator value: " + TString::HexString(ID));
|
||||
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->FullName() + "\" (" + pEnumTemp->IDString(true) + ") has invalid enumerator value: " + TString::HexString(ID));
|
||||
|
||||
pEnumCast->Set(ID);
|
||||
break;
|
||||
@@ -140,7 +140,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
|
||||
}
|
||||
|
||||
if (!Valid)
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - ID.Length(), "Asset property " + pTemp->IDString(true) + " in object " + pTemp->ScriptTemplate()->Name() + " has a reference to an illegal asset type: " + CookedExt);
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - ID.Length(), "Asset property \"" + pTemp->FullName() + "\" (" + pTemp->IDString(true) + ") has a reference to an illegal asset type: " + CookedExt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ void CScriptLoader::LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct,
|
||||
TIDString IDString = pTemp->IDString(true);
|
||||
if (!IDString.IsEmpty()) IDString = " (" + IDString + ")";
|
||||
|
||||
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->Name() + "\"" + IDString + " template prop count doesn't match file; template is " + TString::HexString(PropCount, 2) + ", file is " + TString::HexString(FilePropCount, 2));
|
||||
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->FullName() + "\" (" + IDString + ") template prop count doesn't match file; template is " + TString::HexString(PropCount, 2) + ", file is " + TString::HexString(FilePropCount, 2));
|
||||
Version = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
||||
pParams = pParams->NextSiblingElement();
|
||||
}
|
||||
|
||||
// File-specific parameters
|
||||
// Asset-specific parameters
|
||||
if (Type == eAssetProperty)
|
||||
{
|
||||
TString ExtensionsAttr = pElem->Attribute("extensions");
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define CSCRIPTLAYER_H
|
||||
|
||||
#include "CScriptObject.h"
|
||||
#include "Core/Resource/CDependencyGroup.h"
|
||||
#include <Common/types.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -107,9 +108,6 @@ public:
|
||||
return iLyr;
|
||||
}
|
||||
|
||||
if (mpArea->GeneratedObjectsLayer() == this)
|
||||
return mpArea->NumScriptLayers();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,11 +70,13 @@ bool CScriptObject::IsEditorProperty(IProperty *pProp)
|
||||
|
||||
void CScriptObject::SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex)
|
||||
{
|
||||
ASSERT(pLayer != nullptr);
|
||||
|
||||
if (pLayer != mpLayer)
|
||||
{
|
||||
if (mpLayer) mpLayer->RemoveInstance(this);
|
||||
mpLayer = pLayer;
|
||||
if (mpLayer) mpLayer->AddInstance(this, NewLayerIndex);
|
||||
mpLayer->AddInstance(this, NewLayerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,20 +20,25 @@ bool IPropertyTemplate::IsInVersion(u32 Version) const
|
||||
return false;
|
||||
}
|
||||
|
||||
TString IPropertyTemplate::FullName() const
|
||||
{
|
||||
return mpParent ? mpParent->FullName() + "::" + Name() : Name();
|
||||
}
|
||||
|
||||
TIDString IPropertyTemplate::IDString(bool FullPath) const
|
||||
{
|
||||
if (mID != 0xFFFFFFFF)
|
||||
{
|
||||
TIDString out;
|
||||
TIDString Out;
|
||||
|
||||
if (mpParent && FullPath)
|
||||
{
|
||||
out = mpParent->IDString(true);
|
||||
if (!out.IsEmpty()) out += ":";
|
||||
Out = mpParent->IDString(true);
|
||||
if (!Out.IsEmpty()) Out += ":";
|
||||
}
|
||||
|
||||
out += TIDString::HexString(mID);
|
||||
return out;
|
||||
Out += TIDString::HexString(mID);
|
||||
return Out;
|
||||
}
|
||||
else return "";
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ public:
|
||||
|
||||
EGame Game() const;
|
||||
bool IsInVersion(u32 Version) const;
|
||||
TString FullName() const;
|
||||
TIDString IDString(bool FullPath) const;
|
||||
bool IsDescendantOf(const CStructTemplate *pStruct) const;
|
||||
bool IsFromStructTemplate() const;
|
||||
|
||||
Reference in New Issue
Block a user