mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
Merge pull request #223 from takhlaq/pcb_reader
added planmap loading to pcb_reader
This commit is contained in:
commit
b4b02cf6ab
3 changed files with 125 additions and 104 deletions
|
@ -60,6 +60,16 @@ enum class LgbEntryType : uint32_t
|
||||||
SphereCastRange = 75,
|
SphereCastRange = 75,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LGB_ENTRY_HEADER
|
||||||
|
{
|
||||||
|
LgbEntryType type;
|
||||||
|
uint32_t unknown;
|
||||||
|
uint32_t nameOffset;
|
||||||
|
vec3 translation;
|
||||||
|
vec3 rotation;
|
||||||
|
vec3 scale;
|
||||||
|
};
|
||||||
|
|
||||||
class LGB_MODEL_ENTRY
|
class LGB_MODEL_ENTRY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -80,14 +90,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LGB_BGPARTS_HEADER
|
struct LGB_BGPARTS_HEADER : public LGB_ENTRY_HEADER
|
||||||
{
|
{
|
||||||
LgbEntryType type;
|
|
||||||
uint32_t unknown2;
|
|
||||||
uint32_t nameOffset;
|
|
||||||
vec3 translation;
|
|
||||||
vec3 rotation;
|
|
||||||
vec3 scale;
|
|
||||||
uint32_t modelFileOffset;
|
uint32_t modelFileOffset;
|
||||||
uint32_t collisionFileOffset;
|
uint32_t collisionFileOffset;
|
||||||
uint32_t unknown4;
|
uint32_t unknown4;
|
||||||
|
@ -112,22 +116,9 @@ public:
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
modelFileName = std::string( buf + offset + header.modelFileOffset );
|
modelFileName = std::string( buf + offset + header.modelFileOffset );
|
||||||
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
|
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
|
||||||
//std::cout << "BGPARTS_ENTRY " << name << "\n";
|
|
||||||
//std::cout << " " << modelFileName << "\n";
|
|
||||||
//std::cout << " " << collisionFileName << "\n";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LGB_ENTRY_HEADER
|
|
||||||
{
|
|
||||||
LgbEntryType type;
|
|
||||||
uint32_t unknown;
|
|
||||||
uint32_t nameOffset;
|
|
||||||
vec3 translation;
|
|
||||||
vec3 rotation;
|
|
||||||
vec3 scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LGB_GIMMICK_HEADER : public LGB_ENTRY_HEADER
|
struct LGB_GIMMICK_HEADER : public LGB_ENTRY_HEADER
|
||||||
{
|
{
|
||||||
uint32_t gimmickFileOffset;
|
uint32_t gimmickFileOffset;
|
||||||
|
@ -146,6 +137,7 @@ public:
|
||||||
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
|
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
|
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
|
||||||
|
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,6 +157,7 @@ public:
|
||||||
{
|
{
|
||||||
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
|
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
|
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -183,7 +176,7 @@ public:
|
||||||
LGB_EOBJ_ENTRY( char* buf, uint32_t offset )
|
LGB_EOBJ_ENTRY( char* buf, uint32_t offset )
|
||||||
{
|
{
|
||||||
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
|
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
|
||||||
std::cout << header.eobjId << std::endl;
|
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -218,7 +211,7 @@ struct LGB_GROUP
|
||||||
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
|
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.groupNameOffset );
|
name = std::string( buf + offset + header.groupNameOffset );
|
||||||
//entries.resize( header.entryCount );
|
//entries.resize( header.entryCount );
|
||||||
std::cout << name << std::endl;
|
//std::cout << name << "\n\t unknown: " << header.unknown << "\n";
|
||||||
const auto entriesOffset = offset + header.entriesOffset;
|
const auto entriesOffset = offset + header.entriesOffset;
|
||||||
for( auto i = 0; i < header.entryCount; ++i )
|
for( auto i = 0; i < header.entryCount; ++i )
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
std::string gamePath("C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv");
|
std::string gamePath("C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv");
|
||||||
std::unordered_map< uint32_t, std::string > eobjNameMap;
|
std::unordered_map< uint32_t, std::string > eobjNameMap;
|
||||||
|
xiv::dat::GameData* data1 = nullptr;
|
||||||
|
xiv::exd::ExdData* eData = nullptr;
|
||||||
|
|
||||||
enum class TerritoryTypeExdIndexes : size_t
|
enum class TerritoryTypeExdIndexes : size_t
|
||||||
{
|
{
|
||||||
|
@ -37,6 +39,12 @@ struct face
|
||||||
int32_t f1, f2, f3;
|
int32_t f1, f2, f3;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void initExd( const std::string& gamePath )
|
||||||
|
{
|
||||||
|
data1 = data1 ? data1 : new xiv::dat::GameData( gamePath );
|
||||||
|
eData = eData ? eData : new xiv::exd::ExdData( *data1 );
|
||||||
|
}
|
||||||
|
|
||||||
int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff )
|
int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff )
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
@ -95,14 +103,12 @@ int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff
|
||||||
|
|
||||||
void dumpLevelExdEntries( uint32_t zoneId, const std::string& name = std::string() )
|
void dumpLevelExdEntries( uint32_t zoneId, const std::string& name = std::string() )
|
||||||
{
|
{
|
||||||
xiv::dat::GameData dat( gamePath );
|
auto& cat = eData->get_category( "Level" );
|
||||||
xiv::exd::ExdData eData( dat );
|
|
||||||
auto& cat = eData.get_category( "Level" );
|
|
||||||
auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::none ) );
|
auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::none ) );
|
||||||
|
|
||||||
std::string fileName( name + "_" + std::to_string( zoneId ) + "_Level" + ".csv" );
|
std::string fileName( name + "_" + std::to_string( zoneId ) + "_Level" + ".csv" );
|
||||||
std::ofstream outfile( fileName, std::ios::trunc );
|
std::ofstream outfile( fileName, std::ios::trunc );
|
||||||
|
std::cout << "[Info] Writing level.exd entries to " << fileName << "\n";
|
||||||
if( outfile.good() )
|
if( outfile.good() )
|
||||||
{
|
{
|
||||||
outfile.close();
|
outfile.close();
|
||||||
|
@ -198,9 +204,7 @@ std::string zoneNameToPath( const std::string& name )
|
||||||
|
|
||||||
void loadEobjNames()
|
void loadEobjNames()
|
||||||
{
|
{
|
||||||
xiv::dat::GameData dat( gamePath );
|
auto& cat = eData->get_category( "EObjName" );
|
||||||
xiv::exd::ExdData eData( dat );
|
|
||||||
auto& cat = eData.get_category( "EObjName" );
|
|
||||||
auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::en ) );
|
auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::en ) );
|
||||||
for( auto& row : exd.get_rows() )
|
for( auto& row : exd.get_rows() )
|
||||||
{
|
{
|
||||||
|
@ -244,7 +248,6 @@ int main( int argc, char* argv[] )
|
||||||
|
|
||||||
// todo: support expansions
|
// todo: support expansions
|
||||||
std::string zoneName = "r1f1";
|
std::string zoneName = "r1f1";
|
||||||
|
|
||||||
if( argc > 1 )
|
if( argc > 1 )
|
||||||
{
|
{
|
||||||
zoneName = argv[1];
|
zoneName = argv[1];
|
||||||
|
@ -254,24 +257,28 @@ int main( int argc, char* argv[] )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initExd( gamePath );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto& zonePath = zoneNameToPath( zoneName );
|
const auto& zonePath = zoneNameToPath( zoneName );
|
||||||
std::string listPcbPath( zonePath + "/collision/list.pcb" );
|
std::string listPcbPath( zonePath + "/collision/list.pcb" );
|
||||||
std::string bgLgbPath( zonePath + "/level/planmap.lgb" );
|
std::string bgLgbPath( zonePath + "/level/bg.lgb" );
|
||||||
|
std::string planmapLgbPath( zonePath + "/level/planmap.lgb" );
|
||||||
std::string collisionFilePath( zonePath + "/collision/" );
|
std::string collisionFilePath( zonePath + "/collision/" );
|
||||||
std::vector< char > section;
|
std::vector< char > section;
|
||||||
std::vector< char > section1;
|
std::vector< char > section1;
|
||||||
|
std::vector< char > section2;
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
xiv::dat::GameData data1( gamePath );
|
const xiv::dat::Cat& test = data1->get_category( "bg" );
|
||||||
xiv::exd::ExdData eData( data1 );
|
|
||||||
const xiv::dat::Cat& test = data1.get_category( "bg" );
|
|
||||||
|
|
||||||
auto test_file = data1.get_file( bgLgbPath );
|
auto test_file = data1->get_file( bgLgbPath );
|
||||||
section = test_file->access_data_sections().at( 0 );
|
section = test_file->access_data_sections().at( 0 );
|
||||||
|
|
||||||
auto test_file1 = data1.get_file( listPcbPath );
|
auto planmap_file = data1->get_file( planmapLgbPath );
|
||||||
|
section2 = planmap_file->access_data_sections().at( 0 );
|
||||||
|
|
||||||
|
auto test_file1 = data1->get_file( listPcbPath );
|
||||||
section1 = test_file1->access_data_sections().at( 0 );
|
section1 = test_file1->access_data_sections().at( 0 );
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
@ -280,9 +287,6 @@ int main( int argc, char* argv[] )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32_t list_offset = *( uint32_t* )§ion[0x18];
|
|
||||||
int32_t size = *( uint32_t* )§ion[4];
|
|
||||||
|
|
||||||
std::vector< std::string > stringList;
|
std::vector< std::string > stringList;
|
||||||
|
|
||||||
uint32_t offset1 = 0x20;
|
uint32_t offset1 = 0x20;
|
||||||
|
@ -314,6 +318,9 @@ int main( int argc, char* argv[] )
|
||||||
}
|
}
|
||||||
|
|
||||||
LGB_FILE bgLgb( §ion[0] );
|
LGB_FILE bgLgb( §ion[0] );
|
||||||
|
LGB_FILE planmapLgb( §ion2[0] );
|
||||||
|
|
||||||
|
std::vector< LGB_FILE > lgbList { bgLgb, planmapLgb };
|
||||||
uint32_t max_index = 0;
|
uint32_t max_index = 0;
|
||||||
|
|
||||||
// dont bother if we cant write to a file
|
// dont bother if we cant write to a file
|
||||||
|
@ -342,10 +349,15 @@ int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if( fileName.find( '.' ) == std::string::npos )
|
||||||
|
return false;
|
||||||
|
else if( fileName.substr(fileName.find_last_of('.')) != ".pcb" )
|
||||||
|
throw std::runtime_error( "Not a PCB file." );
|
||||||
|
|
||||||
char* dataSection = nullptr;
|
char* dataSection = nullptr;
|
||||||
//std::cout << fileName << " ";
|
//std::cout << fileName << " ";
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
auto file = data1.get_file( fileName );
|
auto file = data1->get_file( fileName );
|
||||||
auto sections = file->get_data_sections();
|
auto sections = file->get_data_sections();
|
||||||
dataSection = §ions.at( 0 )[0];
|
dataSection = §ions.at( 0 )[0];
|
||||||
#else
|
#else
|
||||||
|
@ -397,7 +409,7 @@ int main( int argc, char* argv[] )
|
||||||
char* dataSection = nullptr;
|
char* dataSection = nullptr;
|
||||||
//std::cout << fileName << " ";
|
//std::cout << fileName << " ";
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
auto file = data1.get_file( fileName );
|
auto file = data1->get_file( fileName );
|
||||||
auto sections = file->get_data_sections();
|
auto sections = file->get_data_sections();
|
||||||
dataSection = §ions.at( 0 )[0];
|
dataSection = §ions.at( 0 )[0];
|
||||||
#else
|
#else
|
||||||
|
@ -508,80 +520,83 @@ int main( int argc, char* argv[] )
|
||||||
std::cout << "[Info] " << bgLgb.groups.size() << " groups " << "\n";
|
std::cout << "[Info] " << bgLgb.groups.size() << " groups " << "\n";
|
||||||
uint32_t totalGroups = 0;
|
uint32_t totalGroups = 0;
|
||||||
uint32_t totalGroupEntries = 0;
|
uint32_t totalGroupEntries = 0;
|
||||||
for( const auto& group : bgLgb.groups )
|
|
||||||
|
for( const auto& lgb : lgbList )
|
||||||
{
|
{
|
||||||
//std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n";
|
for( const auto& group : bgLgb.groups )
|
||||||
totalGroups++;
|
|
||||||
for( const auto& pEntry : group.entries )
|
|
||||||
{
|
{
|
||||||
auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() );
|
//std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n";
|
||||||
auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() );
|
totalGroups++;
|
||||||
auto pEventObj = dynamic_cast< LGB_EOBJ_ENTRY* >( pEntry.get() );
|
for( const auto& pEntry : group.entries )
|
||||||
|
|
||||||
std::string fileName( "" );
|
|
||||||
fileName.resize( 256 );
|
|
||||||
totalGroupEntries++;
|
|
||||||
|
|
||||||
// write files
|
|
||||||
auto writeOutput = [&]( const std::string& fileName, const vec3* scale, const vec3* rotation, const vec3* translation, const SGB_MODEL_ENTRY* pModel = nullptr) -> bool
|
|
||||||
{
|
{
|
||||||
{
|
auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() );
|
||||||
const auto& it = pcbFiles.find( fileName );
|
auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() );
|
||||||
if( it == pcbFiles.end() )
|
auto pEventObj = dynamic_cast< LGB_EOBJ_ENTRY* >( pEntry.get() );
|
||||||
{
|
|
||||||
if( fileName.empty() || !loadPcbFile( fileName ) )
|
|
||||||
return false;
|
|
||||||
//std::cout << "\t\tLoaded PCB File " << pBgParts->collisionFileName << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto& it = pcbFiles.find( fileName );
|
|
||||||
if( it != pcbFiles.end() )
|
|
||||||
{
|
|
||||||
const auto& pcb_file = it->second;
|
|
||||||
pushVerts( pcb_file, fileName, scale, rotation, translation, pModel );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if( pBgParts )
|
std::string fileName( "" );
|
||||||
{
|
fileName.resize( 256 );
|
||||||
fileName = pBgParts->collisionFileName;
|
totalGroupEntries++;
|
||||||
writeOutput( fileName, &pBgParts->header.scale, &pBgParts->header.rotation, &pBgParts->header.translation );
|
|
||||||
}
|
|
||||||
|
|
||||||
// gimmick entry
|
// write files
|
||||||
if( pGimmick )
|
auto writeOutput = [&]( const std::string& fileName, const vec3* scale, const vec3* rotation, const vec3* translation, const SGB_MODEL_ENTRY* pModel = nullptr) -> bool
|
||||||
{
|
|
||||||
{
|
{
|
||||||
const auto& it = sgbFiles.find( pGimmick->gimmickFileName );
|
|
||||||
if( it == sgbFiles.end() )
|
|
||||||
{
|
{
|
||||||
//std::cout << "\tGIMMICK:\n\t\t" << pGimmick->name << " " << pGimmick->gimmickFileName << "\n";
|
const auto& it = pcbFiles.find( fileName );
|
||||||
loadSgbFile( pGimmick->gimmickFileName );
|
if( it == pcbFiles.end() )
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto& it = sgbFiles.find( pGimmick->gimmickFileName );
|
|
||||||
if( it != sgbFiles.end() )
|
|
||||||
{
|
|
||||||
const auto& sgbFile = it->second;
|
|
||||||
|
|
||||||
for( const auto& group : sgbFile.entries )
|
|
||||||
{
|
|
||||||
for( const auto& pEntry : group.entries )
|
|
||||||
{
|
{
|
||||||
auto pModel = dynamic_cast< SGB_MODEL_ENTRY* >( pEntry.get() );
|
if( fileName.empty() || !loadPcbFile( fileName ) )
|
||||||
fileName = pModel->collisionFileName;
|
return false;
|
||||||
writeOutput( fileName, &pGimmick->header.scale, &pGimmick->header.rotation, &pGimmick->header.translation, pModel );
|
//std::cout << "\t\tLoaded PCB File " << pBgParts->collisionFileName << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& it = pcbFiles.find( fileName );
|
||||||
|
if( it != pcbFiles.end() )
|
||||||
|
{
|
||||||
|
const auto& pcb_file = it->second;
|
||||||
|
pushVerts( pcb_file, fileName, scale, rotation, translation, pModel );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( pBgParts )
|
||||||
|
{
|
||||||
|
fileName = pBgParts->collisionFileName;
|
||||||
|
writeOutput( fileName, &pBgParts->header.scale, &pBgParts->header.rotation, &pBgParts->header.translation );
|
||||||
|
}
|
||||||
|
|
||||||
|
// gimmick entry
|
||||||
|
if( pGimmick )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const auto& it = sgbFiles.find( pGimmick->gimmickFileName );
|
||||||
|
if( it == sgbFiles.end() )
|
||||||
|
{
|
||||||
|
// std::cout << "\tGIMMICK:\n\t\t" << pGimmick->gimmickFileName << "\n";
|
||||||
|
loadSgbFile( pGimmick->gimmickFileName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& it = sgbFiles.find( pGimmick->gimmickFileName );
|
||||||
|
if( it != sgbFiles.end() )
|
||||||
|
{
|
||||||
|
const auto& sgbFile = it->second;
|
||||||
|
for( const auto& group : sgbFile.entries )
|
||||||
|
{
|
||||||
|
for( const auto& pEntry : group.entries )
|
||||||
|
{
|
||||||
|
auto pModel = dynamic_cast< SGB_MODEL_ENTRY* >( pEntry.get() );
|
||||||
|
fileName = pModel->collisionFileName;
|
||||||
|
writeOutput( fileName, &pGimmick->header.scale, &pGimmick->header.rotation, &pGimmick->header.translation, pModel );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( pEventObj )
|
if( pEventObj )
|
||||||
{
|
{
|
||||||
fileName = pEventObj->name.empty() ? eobjNameMap[pEventObj->header.eobjId] : pEventObj->name;
|
fileName = pEventObj->name.empty() ? eobjNameMap[pEventObj->header.eobjId] : pEventObj->name;
|
||||||
writeEobjEntry( eobjOut, pEventObj, fileName );
|
writeEobjEntry( eobjOut, pEventObj, fileName );
|
||||||
writeOutput( fileName, &pEventObj->header.scale, &pEventObj->header.rotation, &pEventObj->header.translation );
|
//writeOutput( fileName, &pEventObj->header.scale, &pEventObj->header.rotation, &pEventObj->header.translation );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,5 +613,10 @@ int main( int argc, char* argv[] )
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
|
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( eData )
|
||||||
|
delete eData;
|
||||||
|
if( data1 )
|
||||||
|
delete data1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ public:
|
||||||
virtual ~SGB_GROUP_ENTRY() {};
|
virtual ~SGB_GROUP_ENTRY() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SGB_MODEL_HEADER
|
struct SGB_ENTRY_HEADER
|
||||||
{
|
{
|
||||||
SgbGroupEntryType type;
|
SgbGroupEntryType type;
|
||||||
uint32_t unknown2;
|
uint32_t unknown2;
|
||||||
|
@ -86,6 +86,10 @@ struct SGB_MODEL_HEADER
|
||||||
vec3 translation;
|
vec3 translation;
|
||||||
vec3 rotation;
|
vec3 rotation;
|
||||||
vec3 scale;
|
vec3 scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SGB_MODEL_HEADER : public SGB_ENTRY_HEADER
|
||||||
|
{
|
||||||
int32_t modelFileOffset;
|
int32_t modelFileOffset;
|
||||||
int32_t collisionFileOffset;
|
int32_t collisionFileOffset;
|
||||||
};
|
};
|
||||||
|
@ -132,6 +136,10 @@ struct SGB_GROUP
|
||||||
{
|
{
|
||||||
entries.push_back( std::make_shared< SGB_MODEL_ENTRY >( buf, entryOffset ) );
|
entries.push_back( std::make_shared< SGB_MODEL_ENTRY >( buf, entryOffset ) );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// std::cout << "\t\tUnknown SGB entry! Group: " << name << " type: " << type << " index: " << i << " entryOffset: " << entryOffset << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue