1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 22:57:45 +00:00

Merge branch 'develop' into action

This commit is contained in:
コレット 2020-01-06 00:37:57 +09:00 committed by GitHub
commit 4deac81abd
28 changed files with 826 additions and 4993 deletions

View file

@ -0,0 +1,198 @@
#ifndef SAPPHIRE_LGBTYPES_H
#define SAPPHIRE_LGBTYPES_H
#include "vec3.h"
enum class LgbEntryType : uint32_t
{
BgParts = 1,
Attribute = 2,
Light = 3,
Vfx = 4,
PositionMarker = 5,
Gimmick = 6,
SharedGroup6 = 6,// secondary variable is set to 2
Sound = 7,
EventNpc = 8,
BattleNpc = 9,
RoutePath = 10,
Character = 11,
Aetheryte = 12,
EnvSpace = 13,
Gathering = 14,
SharedGroup15 = 15,// secondary variable is set to 13
Treasure = 16,
Player = 37,
Monster = 38,
Weapon = 39,
PopRange = 40,
ExitRange = 41,
LVB = 42,
MapRange = 43,
NaviMeshRange = 44,
EventObject = 45,
DemiHuman = 46,
EnvLocation = 47,
ControlPoint = 48,
EventRange = 49,
RestBonusRange = 50,
QuestMarker = 51,
TimeLine = 52,
ObjectBehaviorSet = 53,
Movie = 54,
ScenarioEXD = 55,
ScenarioText = 56,
CollisionBox = 57,
DoorRange = 58,
LineVfx = 59,
SoundEnvSet = 60,
CutActionTimeline = 61,
CharaScene = 62,
CutAction = 63,
EquipPreset = 64,
ClientPath = 65,
ServerPath = 66,
GimmickRange = 67,
TargetMarker = 68,
ChairMarker = 69,
ClickableRange = 70,
PrefetchRange = 71,
FateRange = 72,
PartyMember = 73,
KeepRange = 74,
SphereCastRange = 75,
IndoorObject = 76,
OutdoorObject = 77,
EditGroup = 78,
StableChocobo = 79
};
enum PopType : uint32_t
{
PopTypePC = 0x1,
PopTypeNPC = 0x2,
PopTypeBNPC = 0x2,
PopTypeContent = 0x3,
};
struct Transformation
{
vec3 translation;
vec3 rotation;
vec3 scale;
};
struct InstanceObject
{
LgbEntryType type;
uint32_t instanceId;
uint32_t nameOffset;
Transformation transform;
};
struct BgPartsData : public InstanceObject
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
};
struct RelativePositions
{
int32_t Pos;
int32_t PosCount;
};
struct PopRangeData : public InstanceObject
{
PopType popType;
RelativePositions relativePositions;
float innerRadiusRatio;
uint8_t index;
uint8_t padding00[3];
uint32_t reserved;
};
struct GimmickData : public InstanceObject
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
struct ENpcData : public InstanceObject
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
struct EObjData : public InstanceObject
{
uint32_t eobjId;
uint32_t levelHierachyId;
uint8_t unknown1[0xC];
};
enum TriggerBoxShape : uint32_t
{
TriggerBoxShapeBox = 0x1,
TriggerBoxShapeSphere = 0x2,
TriggerBoxShapeCylinder = 0x3,
TriggerBoxShapeBoard = 0x4,
TriggerBoxShapeMesh = 0x5,
TriggerBoxShapeBoardBothSides = 0x6,
};
struct TriggerBoxInstanceObject
{
TriggerBoxShape triggerBoxShape;
int16_t priority;
int8_t enabled;
uint8_t padding;
uint32_t reserved;
};
struct ExitRangeData : public InstanceObject
{
TriggerBoxInstanceObject triggerBoxType;
uint32_t exitType;
uint16_t zoneId;
uint16_t destTerritoryType;
int index;
uint32_t destInstanceObjectId;
uint32_t returnInstanceObjectId;
float direction;
uint32_t reserved;
};
struct MapRangeData : public InstanceObject
{
TriggerBoxInstanceObject triggerBoxType;
uint32_t mapId;
uint32_t placeNameBlock;
uint32_t placeNameSpot;
uint32_t bGM;
uint32_t weather;
uint32_t reserved;
uint32_t reserved2;
uint16_t reserved3;
uint8_t housingBlockId;
int8_t restBonusEffective;
uint8_t discoveryIndex;
int8_t mapEnabled;
int8_t placeNameEnabled;
int8_t discoveryEnabled;
int8_t bGMEnabled;
int8_t weatherEnabled;
int8_t restBonusEnabled;
int8_t bGMPlayZoneInOnly;
int8_t liftEnabled;
int8_t housingEnabled;
uint16_t padding;
};
#endif //SAPPHIRE_LGBTYPES_H

View file

@ -12,87 +12,33 @@
#include "matrix4.h"
#include "vec3.h"
#include "sgb.h"
#include "LgbTypes.h"
// garbage to skip model loading
extern bool ignoreModels;
// all credit to
// https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
// this is simply their work ported to c++ since we dont c#
// based on https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
struct LGB_FILE;
struct LGB_FILE_HEADER;
struct LGB_GROUP;
struct LGB_GROUP_HEADER;
enum class LgbEntryType :
uint32_t
{
BgParts = 1,
Light = 3,
Vfx = 4,
PositionMarker = 5,
Gimmick = 6,
SharedGroup6 = 6,// secondary variable is set to 2
Sound = 7,
EventNpc = 8,
BattleNpc = 9,
Aetheryte = 12,
EnvSpace = 13,
Gathering = 14,
SharedGroup15 = 15,// secondary variable is set to 13
Treasure = 16,
Weapon = 39,
PopRange = 40,
ExitRange = 41,
MapRange = 43,
NaviMeshRange = 44,
EventObject = 45,
EnvLocation = 47,
EventRange = 49,
QuestMarker = 51,
CollisionBox = 57,
DoorRange = 58,
LineVfx = 59,
ClientPath = 65,
ServerPath = 66,
GimmickRange = 67,
TargetMarker = 68,
ChairMarker = 69,
ClickableRange = 70,
PrefetchRange = 71,
FateRange = 72,
SphereCastRange = 75,
};
struct LGB_ENTRY_HEADER
{
LgbEntryType type;
uint32_t unknown;
uint32_t nameOffset;
vec3 translation;
vec3 rotation;
vec3 scale;
};
class LGB_ENTRY
class LgbEntry
{
public:
char* m_buf;
uint32_t m_offset;
LGB_ENTRY_HEADER header;
InstanceObject header;
LGB_ENTRY()
LgbEntry()
{
m_buf = nullptr;
m_offset = 0;
memset( &header, 0, sizeof( header ) );
};
LGB_ENTRY( char* buf, uint32_t offset )
LgbEntry( char* buf, uint32_t offset )
{
m_buf = buf;
m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset );
header = *reinterpret_cast< InstanceObject* >( buf + offset );
};
const LgbEntryType getType() const
@ -100,30 +46,16 @@ public:
return header.type;
};
virtual ~LGB_ENTRY()
virtual ~LgbEntry()
{
};
};
struct LGB_BGPARTS_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
};
class LGB_BGPARTS_ENTRY :
public LGB_ENTRY
class LGB_BGPARTS_ENTRY : public LgbEntry
{
public:
LGB_BGPARTS_HEADER header;
BgPartsData data;
std::string name;
std::string modelFileName;
std::string collisionFileName;
@ -132,124 +64,94 @@ public:
{
};
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset );
data = *reinterpret_cast< BgPartsData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
modelFileName = std::string( buf + offset + data.modelFileOffset );
collisionFileName = std::string( buf + offset + data.collisionFileOffset );
};
};
struct LGB_GIMMICK_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
class LGB_GIMMICK_ENTRY :
public LGB_ENTRY
class LGB_GIMMICK_ENTRY : public LgbEntry
{
public:
LGB_GIMMICK_HEADER header;
GimmickData data;
std::string name;
std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
data = *reinterpret_cast< GimmickData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
gimmickFileName = std::string( buf + offset + data.gimmickFileOffset );
};
};
struct LGB_ENPC_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
class LGB_ENPC_ENTRY :
public LGB_ENTRY
class LGB_ENPC_ENTRY : public LgbEntry
{
public:
LGB_ENPC_HEADER header;
ENpcData data;
std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
};
};
struct LGB_EOBJ_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t eobjId;
uint32_t levelHierachyId;
uint8_t unknown1[0xC];
};
class LGB_EOBJ_ENTRY :
public LGB_ENTRY
{
public:
LGB_EOBJ_HEADER header;
std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
{
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
data = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_MAPRANGE_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t type;
uint8_t unknown2;
uint8_t unknown2_1;
uint16_t unknown3;
uint32_t unknown5;
uint32_t mapId;
uint32_t offsetX;
uint32_t offsetY;
uint32_t unkInts[4];
uint16_t unkShort;
uint8_t unkFlag;
uint8_t unkFlag2;
uint8_t discoveryIndex;
uint8_t unkFlag3;
uint8_t unkFlag4;
uint8_t unknown4[0x09];
};
struct LGB_MAPRANGE_ENTRY :
public LGB_ENTRY
class LGB_EOBJ_ENTRY : public LgbEntry
{
public:
LGB_MAPRANGE_HEADER header;
EObjData data;
std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset );
data = *reinterpret_cast< EObjData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_MAP_RANGE_ENTRY : public LgbEntry
{
public:
MapRangeData data;
std::string name;
LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
data = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_EXIT_RANGE_ENTRY : public LgbEntry
{
public:
ExitRangeData data;
std::string name;
LGB_EXIT_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
data = *reinterpret_cast< ExitRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_POP_RANGE_ENTRY : public LgbEntry
{
public:
PopRangeData data;
LGB_POP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
data = *reinterpret_cast< PopRangeData* >( buf + offset );
};
};
struct LGB_GROUP_HEADER
{
uint32_t id;
@ -272,15 +174,13 @@ struct LGB_GROUP
LGB_FILE* parent;
LGB_GROUP_HEADER header;
std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries;
std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{
parent = parentStruct;
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
name = std::string( buf + offset + header.groupNameOffset );
//entries.resize( header.entryCount );
//std::cout << name << "\n\t unknown: " << header.unknown << "\n";
const auto entriesOffset = offset + header.entriesOffset;
for( auto i = 0; i < header.entryCount; ++i )
{
@ -288,8 +188,7 @@ struct LGB_GROUP
try
{
const auto type = *reinterpret_cast<LgbEntryType*>( buf + entryOffset );
// garbage to skip model loading
const auto type = *reinterpret_cast< LgbEntryType* >( buf + entryOffset );
if( type == LgbEntryType::BgParts )
{
entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) );
@ -306,16 +205,18 @@ struct LGB_GROUP
{
entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) );
}
else if( type == LgbEntryType::ExitRange )
{
entries.push_back( std::make_shared< LGB_EXIT_RANGE_ENTRY >( buf, entryOffset ) );
}
else if( type == LgbEntryType::MapRange )
{
entries.push_back( std::make_shared< LGB_MAPRANGE_ENTRY >( buf, entryOffset ) );
entries.push_back( std::make_shared< LGB_MAP_RANGE_ENTRY >( buf, entryOffset ) );
}
else
{
entries.push_back( std::make_shared< LGB_ENTRY >( buf, entryOffset ) );
entries.push_back( std::make_shared< LgbEntry >( buf, entryOffset ) );
}
}
catch( std::exception& e )
{
@ -344,8 +245,7 @@ struct LGB_FILE
std::vector< LGB_GROUP > groups;
std::string m_name;
LGB_FILE( char* buf, const std::string& name ) :
LGB_FILE( buf )
LGB_FILE( char* buf, const std::string& name ) : LGB_FILE( buf )
{
m_name = name;
}
@ -356,8 +256,6 @@ struct LGB_FILE
if( strncmp( &header.magic[ 0 ], "LGB1", 4 ) != 0 || strncmp( &header.magic2[ 0 ], "LGP1", 4 ) != 0 )
throw std::runtime_error( "Invalid LGB file!" );
//groups.resize(header.groupCount);
constexpr auto baseOffset = sizeof( header );
for( auto i = 0; i < header.groupCount; ++i )
{

View file

@ -22,15 +22,13 @@ struct SGB_GROUP;
struct SGB_GROUP_HEADER;
enum SgbDataType :
uint32_t
enum SgbDataType : uint32_t
{
Unknown0008 = 0x0008,
Group = 0x0100,
};
enum SgbGroupEntryType :
uint32_t
enum SgbGroupEntryType : uint32_t
{
Model = 0x01,
Gimmick = 0x06,
@ -124,15 +122,13 @@ struct SGB_ENTRY_HEADER
vec3 scale;
};
struct SGB_MODEL_HEADER :
public SGB_ENTRY_HEADER
struct SGB_MODEL_HEADER : public SGB_ENTRY_HEADER
{
int32_t modelFileOffset;
int32_t collisionFileOffset;
};
struct SGB_MODEL_ENTRY :
public SGB_GROUP_ENTRY
struct SGB_MODEL_ENTRY : public SGB_GROUP_ENTRY
{
SGB_MODEL_HEADER header;
SgbGroupEntryType type;

View file

@ -84,7 +84,7 @@ Index::Index(const std::experimental::filesystem::path& path) :
// The dat number is found in the offset, last four bits
hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2;
// The offset in the dat file, needs to strip the dat number indicator
hashTableEntry.datOffset = ( indexHashTableEntry.datOffset & 0xFFFFFFF0 ) * 0x08;
hashTableEntry.datOffset = ( indexHashTableEntry.datOffset - ( indexHashTableEntry.datOffset & 0x000F ) ) * 0x08;
hashTableEntry.dirHash = indexHashTableEntry.dirHash;
hashTableEntry.filenameHash = indexHashTableEntry.filenameHash;
}

File diff suppressed because it is too large Load diff

View file

@ -400,13 +400,6 @@ CREATE TABLE `dbupdate` (
PRIMARY KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `discoveryinfo` (
`id` int(10) NOT NULL,
`map_id` int(3) NOT NULL,
`discover_id` int(3) NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `house` (
`HouseId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`LandSetId` int(10) UNSIGNED DEFAULT NULL,

View file

@ -5957,6 +5957,11 @@ struct ZoneSharedGroup
std::shared_ptr< xiv::dat::GameData > m_data;
std::shared_ptr< xiv::exd::ExdData > m_exd_data;
std::shared_ptr< xiv::dat::GameData > getGameData()
{
return m_data;
}
template< class T >
std::shared_ptr< T > get( uint32_t id )
{

View file

@ -295,7 +295,7 @@ namespace Sapphire::Network::Packets
CFRegisterDuty = 0x0071,
CFRegisterRoulette = 0x0072,
CFRegisterRoulette = 0xFF72,
PlayTimeHandler = 0x0276, // updated 5.1
LogoutHandler = 0x015D, // updated 5.18
CancelLogout = 0x008F, // updated 5.1
@ -342,8 +342,8 @@ namespace Sapphire::Network::Packets
PlaceFieldMarker = 0x013C, // updated 5.0
SkillHandler = 0x01BE, // updated 5.18
GMCommand1 = 0x014D, // updated 5.18
GMCommand2 = 0x032C, // updated 5.18
AoESkillHandler = 0x140, // updated 5.0
GMCommand2 = 0x03C2, // updated 5.18
AoESkillHandler = 0x0072, // updated 5.18
UpdatePositionHandler = 0x0318, // updated 5.18
@ -352,7 +352,7 @@ namespace Sapphire::Network::Packets
InventoryEquipRecommendedItems = 0x0149, // updated 5.0
ReqPlaceHousingItem = 0x014B, // updated 5.0
BuildPresetHandler = 0x014F, // updated 5.0
BuildPresetHandler = 0x0150, // updated 5.0
TalkEventHandler = 0x02FD, // updated 5.18
EmoteEventHandler = 0x0183, // updated 5.18

View file

@ -1564,11 +1564,10 @@ namespace Sapphire::Network::Packets::Server
*/
struct FFXIVIpcDiscovery : FFXIVIpcBasePacket< Discovery >
{
/* 0000 */ uint32_t map_part_id;
/* 0004 */ uint32_t map_id;
/* 0000 */ uint32_t mapPartId;
/* 0004 */ uint32_t mapId;
};
/**
* UNKOWN TYPE
*/

View file

@ -39,7 +39,7 @@ public:
return;
// todo: this needs to be done properly and used queued zoning + aethernet animation
// moving a player inside an event will crash the game so we end it hre
// moving a player inside an event will crash the game so we end it here
player.eventFinish( eventId, 1 );
auto playerMgr = framework()->get< Sapphire::World::Manager::PlayerMgr >();

View file

@ -1,6 +1,11 @@
#include <ScriptObject.h>
#include <Actor/Player.h>
#include <datReader/DatCategories/bg/LgbTypes.h>
#include <datReader/DatCategories/bg/Lgb.h>
#include "Territory/InstanceObjectCache.h"
#include <Exd/ExdDataGenerated.h>
#include <Framework.h>
#include <Manager/PlayerMgr.h>
@ -28,11 +33,25 @@ public:
player.eventFinish( getId(), 1 );
auto exdData = framework()->get< Sapphire::Data::ExdDataGenerated >();
auto pPopRange = framework()->get< Sapphire::InstanceObjectCache >();
auto warp = exdData->get< Sapphire::Data::Warp >( getId() );
if( !warp )
return;
auto playerMgr = framework()->get< Sapphire::World::Manager::PlayerMgr >();
auto pPop = pPopRange->getPopRange( warp->level, warp->level );
if( !pPop )
{
std::cout << "not found...";
}
else
{
std::cout << "found!!";
}
playerMgr->movePlayerToLandDestination( player, warp->level, result.param3 );
}
else

View file

@ -36,10 +36,11 @@ struct ZoneInfo
uint16_t id;
std::string name;
std::string path;
uint16_t mapId;
};
// parsing shit
std::string gamePath( "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" );
std::string gamePath( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" );
std::unordered_map< uint32_t, std::string > eobjNameMap;
std::unordered_map< uint16_t, ZoneInfo > zoneInfoMap;
std::unordered_map< uint16_t, std::vector< std::pair< uint16_t, std::string > > > zoneInstanceMap;
@ -60,8 +61,7 @@ struct vec2
float x, y;
};
struct DiscoveryMap :
std::enable_shared_from_this< DiscoveryMap >
struct DiscoveryMap : std::enable_shared_from_this< DiscoveryMap >
{
std::string path;
Image img;
@ -120,11 +120,11 @@ struct DiscoveryMap :
std::map< uint16_t, std::map< uint16_t, std::map< uint16_t, std::shared_ptr< DiscoveryMap > > > > discoveryMaps;
enum class TerritoryTypeExdIndexes :
size_t
enum class TerritoryTypeExdIndexes : size_t
{
TerritoryType = 0,
Path = 1
Path = 1,
Map = 6
};
using namespace std::chrono_literals;
@ -165,6 +165,8 @@ std::string zoneNameToPath( const std::string& name )
info.id = row.first;
info.path = teriPath;
info.name = teriName;
info.mapId = std::get< uint16_t >(
fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Map ) ) );
zoneInfoMap[ row.first ] = info;
if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) )
@ -217,69 +219,31 @@ void loadEobjNames()
}
}
void writeEobjEntry( std::ofstream& out, LGB_ENTRY* pObj )
void writeMapRangeEntry( std::ofstream& out, LgbEntry* pObj )
{
static std::string mapRangeStr( "\"MapRange\", " );
std::ofstream discoverySql( zoneName + "_poprange.txt", std::ios::app );
uint32_t id;
uint32_t unknown2 = 0, unknown2_1 = 0, unknown3 = 0;
std::string name;
std::string typeStr;
uint32_t eobjlevelHierachyId = 0;
static std::map< uint32_t, std::map< uint32_t, uint32_t > > exportedMapRange;
auto pMapRange = reinterpret_cast< LGB_MAP_RANGE_ENTRY* >( pObj );
if( !pMapRange->data.discoveryEnabled )
return;
auto pMapRange = reinterpret_cast< LGB_MAPRANGE_ENTRY* >( pObj );
id = pMapRange->header.unknown;
unknown2 = pMapRange->header.unknown2;
unknown2_1 = pMapRange->header.unknown2_1;
unknown3 = pMapRange->header.unknown3;
typeStr = mapRangeStr;
// discovery shit
vec2 pos{ 0 };
auto subArea = 0;
auto mapId = -1;
auto discoveryIndex = pMapRange->header.discoveryIndex;
auto discoveryIndex = pMapRange->data.discoveryIndex;
vec3 translation = pObj->header.translation;
vec3 translation = pObj->header.transform.translation;
bool found = false;
float scale = 100.f; //pMapRange->header.unknown2
std::string outStr( pMapRange->name + " " + std::to_string( pMapRange->header.unknown ) + " " +
std::to_string( pMapRange->header.translation.x ) + " " +
std::to_string( pMapRange->header.translation.y ) + " " +
std::to_string( pMapRange->header.translation.z ) + " " +
std::to_string( pMapRange->header.rotation.y ) + "\n"
std::string outStr( pMapRange->name + " " + std::to_string( pMapRange->header.instanceId ) + " " +
std::to_string( pMapRange->header.transform.translation.x ) + " " +
std::to_string( pMapRange->header.transform.translation.y ) + " " +
std::to_string( pMapRange->header.transform.translation.z ) + " " +
std::to_string( pMapRange->header.transform.rotation.y ) + " " +
std::to_string( pMapRange->data.mapId ) + " " +
std::to_string( pMapRange->data.discoveryIndex ) + "\n"
);
//std::to_string( pObj->header.translation.x ) + ", " + std::to_string( pObj->header.translation.y ) + ", " + std::to_string( pObj->header.translation.z ) +
//", " + std::to_string( subArea ) + "" + "\n"
//);
discoverySql.write( outStr.c_str(), outStr.size() );
//out.write( outStr.c_str(), outStr.size() );
}
out.write( outStr.c_str(), outStr.size() );
void readFileToBuffer( const std::string& path, std::vector< char >& buf )
{
auto inFile = std::ifstream( path, std::ios::binary );
if( inFile.good() )
{
inFile.seekg( 0, inFile.end );
int32_t fileSize = ( int32_t ) inFile.tellg();
buf.resize( fileSize );
inFile.seekg( 0, inFile.beg );
inFile.read( &buf[ 0 ], fileSize );
inFile.close();
}
else
{
throw std::runtime_error( "Unable to open " + path );
}
}
bool isEx = false;
int main( int argc, char* argv[] )
{
auto startTime = std::chrono::system_clock::now();
@ -288,10 +252,6 @@ int main( int argc, char* argv[] )
std::vector< std::string > argVec( argv + 1, argv + argc );
zoneName = "s1h1";
bool dumpAll = ignoreModels = std::remove_if( argVec.begin(), argVec.end(), []( auto arg )
{ return arg == "--dump-all"; } ) != argVec.end();
dumpAll = true;
ignoreModels = true;
if( argc > 1 )
{
zoneName = argv[ 1 ];
@ -304,118 +264,42 @@ int main( int argc, char* argv[] )
}
initExd( gamePath );
std::ofstream discoverySql( zoneName + "_poprange.txt", std::ios::trunc );
discoverySql.close();
std::ofstream discoverySql( "maprange_export.txt", std::ios::trunc );
if( dumpAll )
zoneNameToPath( "f1f1" );
zoneDumpList.emplace( "f1f1" );
zoneDumpList.emplace( "f1f2" );
for( const auto& zoneName : zoneDumpList )
{
zoneNameToPath( "s1h1" );
zoneDumpList.emplace( "s1h1" );
zoneDumpList.emplace( "f1h1" );
zoneDumpList.emplace( "w1h1" );
zoneDumpList.emplace( "e1h1" );
}
else
{
zoneDumpList.emplace( zoneName );
}
LABEL_DUMP:
entryStartTime = std::chrono::system_clock::now();
zoneName = *zoneDumpList.begin();
discoverySql.open( zoneName + "_poprange.txt", std::ios::trunc );
discoverySql.write( ( zoneName + "\n" ).c_str() , zoneName.size() + 1 );
try
{
const auto zonePath = zoneNameToPath( zoneName );
std::string listPcbPath( zonePath + "/collision/list.pcb" );
std::string bgLgbPath( zonePath + "/level/bg.lgb" );
std::string planmapLgbPath( zonePath + "/level/planmap.lgb" );
std::string collisionFilePath( zonePath + "/collision/" );
isEx = bgLgbPath.find( "ex1" ) != -1 || bgLgbPath.find( "ex2" ) != -1;
std::vector< char > section;
std::vector< char > section1;
std::vector< char > section2;
auto test_file = gameData->getFile( bgLgbPath );
section = test_file->access_data_sections().at( 0 );
auto planmap_file = gameData->getFile( planmapLgbPath );
section2 = planmap_file->access_data_sections().at( 0 );
auto test_file1 = gameData->getFile( listPcbPath );
section1 = test_file1->access_data_sections().at( 0 );
std::vector< std::string > stringList;
uint32_t offset1 = 0x20;
//loadEobjNames();
//getMapExdEntries( zoneId );
std::string eobjFileName( zoneName + "_eobj.csv" );
std::ofstream eobjOut( eobjFileName, std::ios::trunc );
if( !eobjOut.good() )
throw std::string( "Unable to create " + zoneName +
"_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str();
eobjOut.close();
eobjOut.open( eobjFileName, std::ios::app );
if( !eobjOut.good() )
throw std::string( "Unable to create " + zoneName +
"_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str();
if( 0 )
entryStartTime = std::chrono::system_clock::now();
discoverySql.write( ( zoneName + "\n" ).c_str(), zoneName.size() + 1 );
try
{
for( ;; )
{
const auto zonePath = zoneNameToPath( zoneName );
uint16_t trId = *( uint16_t* ) &section1[ offset1 ];
std::string bgLgbPath( zonePath + "/level/bg.lgb" );
std::string planmapLgbPath( zonePath + "/level/planmap.lgb" );
std::vector< char > section;
std::vector< char > section2;
char someString[200];
sprintf( someString, "%str%04d.pcb", collisionFilePath.c_str(), trId );
stringList.push_back( std::string( someString ) );
//std::cout << someString << "\n";
offset1 += 0x20;
auto test_file = gameData->getFile( bgLgbPath );
section = test_file->access_data_sections().at( 0 );
if( offset1 >= section1.size() )
{
break;
}
}
}
LGB_FILE bgLgb( &section[ 0 ], "bg" );
LGB_FILE planmapLgb( &section2[ 0 ], "planmap" );
auto planmap_file = gameData->getFile( planmapLgbPath );
section2 = planmap_file->access_data_sections().at( 0 );
std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb };
uint32_t max_index = 0;
std::vector< std::string > stringList;
// dont bother if we cant write to a file
FILE* fp_out = nullptr;
//auto fp_out = ignoreModels ? ( FILE* )nullptr : fopen( ( zoneName + ".obj" ).c_str(), "w" );
if( fp_out )
{
fprintf( fp_out, "\n" );
fclose( fp_out );
}
else if( /*!ignoreModels*/ false )
{
std::string errorMessage( "Cannot create " + zoneName + ".obj\n" +
" Check no programs have a handle to file and run as admin.\n" );
std::cout << errorMessage;
throw std::runtime_error( errorMessage.c_str() );
return 0;
}
uint32_t offset1 = 0x20;
LGB_FILE bgLgb( &section[ 0 ], "bg" );
LGB_FILE planmapLgb( &section2[ 0 ], "planmap" );
{
std::map< std::string, PCB_FILE > pcbFiles;
std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb };
uint32_t max_index = 0;
std::cout << "[Info] " << ( ignoreModels ? "Dumping MapRange and EObj" : "Writing obj file " ) << "\n";
std::cout << "[Info] " << "Dumping MapRange and EObj" << "\n";
uint32_t totalGroups = 0;
uint32_t totalGroupEntries = 0;
@ -423,48 +307,46 @@ int main( int argc, char* argv[] )
{
for( const auto& group : lgb.groups )
{
//std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n";
totalGroups++;
for( const auto& pEntry : group.entries )
{
if( pEntry->getType() == LgbEntryType::PopRange )
if( pEntry->getType() == LgbEntryType::MapRange )
{
totalGroupEntries++;
writeEobjEntry( eobjOut, pEntry.get() );
writeMapRangeEntry( discoverySql, pEntry.get() );
}
else if( pEntry->getType() == LgbEntryType::ExitRange )
{
auto pExitRange = reinterpret_cast< LGB_EXIT_RANGE_ENTRY* >( pEntry.get() );
}
}
}
}
std::cout << "[Info] " << "Loaded " << pcbFiles.size() << " PCB Files \n";
std::cout << "[Info] " << "Total Groups " << totalGroups << " Total entries " << totalGroupEntries << "\n";
std::cout << "[Success] " << "Exported " << zoneName << " in " <<
std::chrono::duration_cast< std::chrono::seconds >(
std::chrono::system_clock::now() - entryStartTime ).count() << " seconds\n";
}
std::cout << "[Success] " << "Exported " << zoneName << " in " <<
std::chrono::duration_cast< std::chrono::seconds >(
std::chrono::system_clock::now() - entryStartTime ).count() << " seconds\n";
catch( std::exception& e )
{
std::cout << "[Error] " << e.what() << std::endl;
std::cout << "[Error] "
<< "Unable to extract collision data.\n\tIf using standalone ensure your working directory folder layout is \n\tbg/[ffxiv|ex1|ex2]/teri/type/zone/[level|collision]"
<< std::endl;
std::cout << std::endl;
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
}
std::cout << "\n";
if( discoverySql.good() )
discoverySql.flush();
}
catch( std::exception& e )
{
std::cout << "[Error] " << e.what() << std::endl;
std::cout << "[Error] "
<< "Unable to extract collision data.\n\tIf using standalone ensure your working directory folder layout is \n\tbg/[ffxiv|ex1|ex2]/teri/type/zone/[level|collision]"
<< std::endl;
std::cout << std::endl;
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
}
std::cout << "\n\n\n";
if( discoverySql.good() )
discoverySql.flush();
LABEL_NEXT_ZONE_ENTRY:
zoneDumpList.erase( zoneName );
if( !zoneDumpList.empty() )
goto LABEL_DUMP;
std::cout << "\n\n\n[Success] Finished all tasks in " <<
std::cout << "\n[Success] Finished all tasks in " <<
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::system_clock::now() - startTime ).count()
<< " seconds\n";
std::cout << "Press any key to exit...";
getchar();
if( eData )

View file

@ -284,10 +284,10 @@ int main( int argc, char* argv[] )
uint32_t eobjlevelHierachyId = 0;
auto pEobj = reinterpret_cast< LGB_EOBJ_ENTRY* >( pObj );
id = pEobj->header.eobjId;
unknown = pEobj->header.unknown;
id = pEobj->data.eobjId;
unknown = pEobj->header.instanceId;
eobjlevelHierachyId = pEobj->header.levelHierachyId;
eobjlevelHierachyId = pEobj->data.levelHierachyId;
std::string states = "";
std::string gimmickName = "";
@ -295,7 +295,7 @@ int main( int argc, char* argv[] )
{
auto pGObj = pEntry1.get();
if( pGObj->getType() == LgbEntryType::Gimmick &&
pGObj->header.unknown == pEobj->header.levelHierachyId )
pGObj->header.instanceId == pEobj->data.levelHierachyId )
{
auto pGObjR = reinterpret_cast< LGB_GIMMICK_ENTRY* >( pGObj );
char* dataSection = nullptr;
@ -361,13 +361,13 @@ int main( int argc, char* argv[] )
eobjects += " instance.registerEObj( \"" + name + "\", " + std::to_string( id ) +
", " + std::to_string( eobjlevelHierachyId ) + ", " + std::to_string( state ) +
", " +
"{ " + std::to_string( pObj->header.translation.x ) + "f, "
+ std::to_string( pObj->header.translation.y ) + "f, "
+ std::to_string( pObj->header.translation.z ) + "f }, " +
std::to_string( pObj->header.scale.x ) + "f, " +
"{ " + std::to_string( pObj->header.transform.translation.x ) + "f, "
+ std::to_string( pObj->header.transform.translation.y ) + "f, "
+ std::to_string( pObj->header.transform.translation.z ) + "f }, " +
std::to_string( pObj->header.transform.scale.x ) + "f, " +
// the rotation inside the sgbs is the inverse of what the game uses
std::to_string( pObj->header.rotation.y * -1.f ) + "f ); \n" + states;
std::to_string( pObj->header.transform.rotation.y * -1.f ) + "f ); \n" + states;
}
}
}

View file

@ -43,6 +43,11 @@ STRUCTS
std::shared_ptr< xiv::dat::GameData > m_data;
std::shared_ptr< xiv::exd::ExdData > m_exd_data;
std::shared_ptr< xiv::dat::GameData > getGameData()
{
return m_data;
}
template< class T >
std::shared_ptr< T > get( uint32_t id )
{

View file

@ -68,7 +68,7 @@ enum class LgbEntryType :
SphereCastRange = 75,
};
struct LGB_ENTRY_HEADER
struct InstanceObject
{
LgbEntryType type;
uint32_t unknown;
@ -78,25 +78,25 @@ struct LGB_ENTRY_HEADER
vec3 scale;
};
class LGB_ENTRY
class LgbEntry
{
public:
char* m_buf;
uint32_t m_offset;
LGB_ENTRY_HEADER header;
InstanceObject header;
LGB_ENTRY()
LgbEntry()
{
m_buf = nullptr;
m_offset = 0;
memset( &header, 0, sizeof( header ) );
};
LGB_ENTRY( char* buf, uint32_t offset )
LgbEntry( char* buf, uint32_t offset )
{
m_buf = buf;
m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset );
header = *reinterpret_cast< InstanceObject* >( buf + offset );
};
const LgbEntryType getType() const
@ -104,14 +104,14 @@ public:
return header.type;
};
virtual ~LGB_ENTRY()
virtual ~LgbEntry()
{
};
};
struct LGB_BGPARTS_HEADER :
public LGB_ENTRY_HEADER
struct BgPartsData :
public InstanceObject
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
@ -124,10 +124,10 @@ struct LGB_BGPARTS_HEADER :
};
class LGB_BGPARTS_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_BGPARTS_HEADER header;
BgPartsData header;
std::string name;
std::string modelFileName;
std::string collisionFileName;
@ -137,65 +137,65 @@ public:
};
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset );
header = *reinterpret_cast<BgPartsData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
};
};
struct LGB_GIMMICK_HEADER :
public LGB_ENTRY_HEADER
struct GimmickData :
public InstanceObject
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
class LGB_GIMMICK_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_GIMMICK_HEADER header;
GimmickData header;
std::string name;
std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
header = *reinterpret_cast<GimmickData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
};
};
struct LGB_ENPC_HEADER :
public LGB_ENTRY_HEADER
struct ENpcData :
public InstanceObject
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
class LGB_ENPC_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_ENPC_HEADER header;
ENpcData header;
std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
header = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
};
};
struct LGB_EOBJ_HEADER :
public LGB_ENTRY_HEADER
struct EObjData :
public InstanceObject
{
uint32_t eobjId;
uint32_t levelHierachyId;
@ -203,23 +203,23 @@ struct LGB_EOBJ_HEADER :
};
class LGB_EOBJ_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_EOBJ_HEADER header;
EObjData header;
std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
header = *reinterpret_cast< EObjData* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_MAPRANGE_HEADER :
public LGB_ENTRY_HEADER
struct MapRangeData :
public InstanceObject
{
uint32_t type;
uint16_t unknown2;
@ -227,35 +227,35 @@ struct LGB_MAPRANGE_HEADER :
uint8_t unknown4[0x10];
};
struct LGB_MAPRANGE_ENTRY :
public LGB_ENTRY
struct LGB_MAP_RANGE_ENTRY :
public LgbEntry
{
public:
LGB_MAPRANGE_HEADER header;
MapRangeData header;
std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) :
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset );
header = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_COLLISION_BOX_HEADER :
public LGB_ENTRY_HEADER
public InstanceObject
{
uint8_t unk[100];
};
struct LGB_COLLISION_BOX_ENTRY :
public LGB_ENTRY
public LgbEntry
{
LGB_COLLISION_BOX_HEADER header;
std::string name;
LGB_COLLISION_BOX_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_COLLISION_BOX_HEADER* >( buf + offset );
header.type = LgbEntryType::CollisionBox;
@ -305,7 +305,7 @@ struct LGB_GROUP
LGB_FILE* parent;
LGB_GROUP_HEADER header;
std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries;
std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{

View file

@ -257,7 +257,7 @@ bool pcbTransformModel( const std::string& fileName, const vec3* scale, const ve
return true;
};
void exportSgbModel( const std::string& sgbFilePath, LGB_ENTRY* pGimmick, ExportedGroup& exportgroup, bool isEobj = false )
void exportSgbModel( const std::string& sgbFilePath, LgbEntry* pGimmick, ExportedGroup& exportgroup, bool isEobj = false )
{
if( auto pSgbFile = pCache->getSgbFile( sgbFilePath ) )
{

View file

@ -68,7 +68,7 @@ enum class LgbEntryType :
SphereCastRange = 75,
};
struct LGB_ENTRY_HEADER
struct InstanceObject
{
LgbEntryType type;
uint32_t unknown;
@ -78,25 +78,25 @@ struct LGB_ENTRY_HEADER
vec3 scale;
};
class LGB_ENTRY
class LgbEntry
{
public:
char* m_buf;
uint32_t m_offset;
LGB_ENTRY_HEADER header;
InstanceObject header;
LGB_ENTRY()
LgbEntry()
{
m_buf = nullptr;
m_offset = 0;
memset( &header, 0, sizeof( header ) );
};
LGB_ENTRY( char* buf, uint32_t offset )
LgbEntry( char* buf, uint32_t offset )
{
m_buf = buf;
m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset );
header = *reinterpret_cast< InstanceObject* >( buf + offset );
};
const LgbEntryType getType() const
@ -104,14 +104,14 @@ public:
return header.type;
};
virtual ~LGB_ENTRY()
virtual ~LgbEntry()
{
};
};
struct LGB_BGPARTS_HEADER :
public LGB_ENTRY_HEADER
struct BgPartsData :
public InstanceObject
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
@ -124,10 +124,10 @@ struct LGB_BGPARTS_HEADER :
};
class LGB_BGPARTS_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_BGPARTS_HEADER header;
BgPartsData header;
std::string name;
std::string modelFileName;
std::string collisionFileName;
@ -137,65 +137,65 @@ public:
};
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset );
header = *reinterpret_cast<BgPartsData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset );
};
};
struct LGB_GIMMICK_HEADER :
public LGB_ENTRY_HEADER
struct GimmickData :
public InstanceObject
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
class LGB_GIMMICK_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_GIMMICK_HEADER header;
GimmickData header;
std::string name;
std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset );
header = *reinterpret_cast<GimmickData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
};
};
struct LGB_ENPC_HEADER :
public LGB_ENTRY_HEADER
struct ENpcData :
public InstanceObject
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
class LGB_ENPC_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_ENPC_HEADER header;
ENpcData header;
std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
header = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
};
};
struct LGB_EOBJ_HEADER :
public LGB_ENTRY_HEADER
struct EObjData :
public InstanceObject
{
uint32_t eobjId;
uint32_t levelHierachyId;
@ -203,23 +203,23 @@ struct LGB_EOBJ_HEADER :
};
class LGB_EOBJ_ENTRY :
public LGB_ENTRY
public LgbEntry
{
public:
LGB_EOBJ_HEADER header;
EObjData header;
std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
header = *reinterpret_cast< EObjData* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_MAPRANGE_HEADER :
public LGB_ENTRY_HEADER
struct MapRangeData :
public InstanceObject
{
uint32_t type;
uint16_t unknown2;
@ -227,35 +227,34 @@ struct LGB_MAPRANGE_HEADER :
uint8_t unknown4[0x10];
};
struct LGB_MAPRANGE_ENTRY :
public LGB_ENTRY
struct LGB_MAP_RANGE_ENTRY : public LgbEntry
{
public:
LGB_MAPRANGE_HEADER header;
MapRangeData header;
std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) :
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset );
header = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_COLLISION_BOX_HEADER :
public LGB_ENTRY_HEADER
public InstanceObject
{
uint8_t unk[100];
};
struct LGB_COLLISION_BOX_ENTRY :
public LGB_ENTRY
public LgbEntry
{
LGB_COLLISION_BOX_HEADER header;
std::string name;
LGB_COLLISION_BOX_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
LgbEntry( buf, offset )
{
header = *reinterpret_cast< LGB_COLLISION_BOX_HEADER* >( buf + offset );
header.type = LgbEntryType::CollisionBox;
@ -305,7 +304,7 @@ struct LGB_GROUP
LGB_FILE* parent;
LGB_GROUP_HEADER header;
std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries;
std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{

View file

@ -429,7 +429,7 @@ int main( int argc, char* argv[] )
}
return true;
};
auto exportSgbModel = [&]( const std::string& sgbFilePath, LGB_ENTRY* pGimmick, bool isEobj = false )
auto exportSgbModel = [&]( const std::string& sgbFilePath, LgbEntry* pGimmick, bool isEobj = false )
{
if( auto pSgbFile = pCache->getSgbFile( sgbFilePath ) )
{

View file

@ -727,7 +727,7 @@ void Sapphire::Entity::BNpc::calculateStats()
m_baseStats.vit = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierVitality ) / 100 ) );
m_baseStats.inte = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierIntelligence ) / 100 ) );
m_baseStats.mnd = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierMind ) / 100 ) );
m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierPiety ) / 100 ) );
//m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierPiety ) / 100 ) );
m_baseStats.determination = static_cast< uint32_t >( base );
m_baseStats.pie = static_cast< uint32_t >( base );

View file

@ -3,6 +3,9 @@
#include <Util/UtilMath.h>
#include <Logging/Logger.h>
#include <Exd/ExdDataGenerated.h>
#include <datReader/DatCategories/bg/LgbTypes.h>
#include <datReader/DatCategories/bg/Lgb.h>
#include <Network/PacketContainer.h>
#include <Network/CommonActorControl.h>
#include <Network/PacketWrappers/EffectPacket.h>
@ -19,6 +22,7 @@
#include "Territory/Territory.h"
#include "Territory/ZonePosition.h"
#include "Territory/InstanceContent.h"
#include "Territory/InstanceObjectCache.h"
#include "Territory/Land.h"
#include "Network/GameConnection.h"
@ -269,8 +273,8 @@ void Sapphire::Entity::Player::calculateStats()
tribeInfo->iNT );
m_baseStats.mnd = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierMind ) / 100 ) +
tribeInfo->mND );
m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierPiety ) / 100 ) +
tribeInfo->pIE );
/*m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierPiety ) / 100 ) +
tribeInfo->pIE );*/
m_baseStats.determination = static_cast< uint32_t >( base );
m_baseStats.pie = static_cast< uint32_t >( base );
@ -346,12 +350,12 @@ void Sapphire::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type )
auto data = pExdData->get< Sapphire::Data::Aetheryte >( aetheryteId );
if( data == nullptr )
{
return;
}
setStateFlag( PlayerStateFlag::BetweenAreas );
auto targetPos = pTeriMgr->getTerritoryPosition( data->level.at( 0 ) );
auto pInstanceObjectCache = m_pFw->get< InstanceObjectCache >();
auto pop = pInstanceObjectCache->getPopRange( data->territory, data->level[ 0 ] );
Common::FFXIVARR_POSITION3 pos;
pos.x = 0;
@ -359,10 +363,18 @@ void Sapphire::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type )
pos.z = 0;
float rot = 0;
if( targetPos != nullptr )
if( pop )
{
pos = targetPos->getTargetPosition();
rot = targetPos->getTargetRotation();
sendDebug( "Teleport: popRange {0} found!", data->level.at( 0 ) );
pos.x = pop->header.transform.translation.x;
pos.y = pop->header.transform.translation.y;
pos.z = pop->header.transform.translation.z;
rot = pop->header.transform.rotation.y;
}
else
{
sendDebug( "Teleport: popRange {0} not found in {1}!", data->level[ 0 ], data->territory );
}
sendDebug( "Teleport: {0} {1} ({2})",

View file

@ -678,7 +678,9 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId
if( static_cast< InventoryType >( fromInventoryId ) == GearSet0 )
unequipItem( static_cast< GearSetSlot >( fromSlotId ), tmpItem, true );
if( static_cast< InventoryType >( toInventoryId ) == GearSet0 ||
static_cast< InventoryType >( fromInventoryId ) == GearSet0 )
sendStatusEffectUpdate(); // send if any equip is changed
}
bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint8_t slotId, ItemPtr pItem )
@ -813,6 +815,10 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS
updateContainer( toInventoryId, toSlot, fromItem );
updateContainer( fromInventoryId, fromSlotId, toItem );
if( static_cast< InventoryType >( toInventoryId ) == GearSet0 ||
static_cast< InventoryType >( fromInventoryId ) == GearSet0 )
sendStatusEffectUpdate(); // send if any equip is changed
}
void Sapphire::Entity::Player::discardItem( uint16_t fromInventoryId, uint8_t fromSlotId )

View file

@ -217,6 +217,10 @@ bool Sapphire::Entity::Player::load( uint32_t charId, World::SessionPtr pSession
m_modelSubWeapon = 0;
m_lastTickTime = 0;
//m_pInventory->load();
initInventory(); // moved up so we don't lose hp every login
calculateStats();
// first login, run the script event
@ -242,10 +246,6 @@ bool Sapphire::Entity::Player::load( uint32_t charId, World::SessionPtr pSession
setStateFlag( PlayerStateFlag::BetweenAreas );
//m_pInventory->load();
initInventory();
initHateSlotQueue();
initSpawnIdQueue();

View file

@ -209,31 +209,10 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player&
sscanf( params.c_str(), "%i %i", &map_id, &discover_id );
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
discoveryPacket->data().map_id = static_cast< uint32_t >( map_id );
discoveryPacket->data().map_part_id = static_cast< uint32_t >( discover_id );
discoveryPacket->data().mapId = static_cast< uint32_t >( map_id );
discoveryPacket->data().mapPartId = static_cast< uint32_t >( discover_id );
player.queuePacket( discoveryPacket );
}
else if( ( subCommand == "discovery_pos" ) && ( params != "" ) )
{
int32_t map_id;
int32_t discover_id;
int32_t pos_id;
sscanf( params.c_str(), "%i %i %i", &pos_id, &map_id, &discover_id );
std::string query2 = "UPDATE IGNORE `discoveryinfo` SET `discover_id` = '" + std::to_string( discover_id ) +
"' WHERE `discoveryinfo`.`id` = " + std::to_string( pos_id ) + ";";
std::string query1 =
"INSERT IGNORE INTO `discoveryinfo` (`id`, `map_id`, `discover_id`) VALUES ('" + std::to_string( pos_id ) +
"', '" + std::to_string( map_id ) +
"', '" + std::to_string( discover_id ) + "')";
pDb->execute( query1 );
pDb->execute( query2 );
}
else if( subCommand == "discovery_reset" )
{
player.resetDiscovery();

View file

@ -19,55 +19,55 @@ const int levelTable[81][6] =
{
// MAIN,SUB,DIV,HP,ELMT,THREAT
{ 1, 1, 1, 1, 1, 1 },
{ 20, 56, 56, 0, 52, 2 },
{ 21, 57, 57, 0, 54, 2 },
{ 22, 60, 60, 0, 56, 3 },
{ 24, 62, 62, 0, 58, 3 },
{ 26, 65, 65, 0, 60, 3 },
{ 27, 68, 68, 0, 62, 3 },
{ 29, 70, 70, 0, 64, 4 },
{ 31, 73, 73, 0, 66, 4 },
{ 33, 76, 76, 0, 68, 4 },
{ 35, 78, 78, 0, 70, 5 },
{ 36, 82, 82, 0, 73, 5 },
{ 38, 85, 85, 0, 75, 5 },
{ 41, 89, 89, 0, 78, 6 },
{ 44, 93, 93, 0, 81, 6 },
{ 46, 96, 96, 0, 84, 7 },
{ 49, 100, 100, 0, 86, 7 },
{ 52, 104, 104, 0, 89, 8 },
{ 54, 109, 109, 0, 93, 9 },
{ 57, 113, 113, 0, 95, 9 },
{ 60, 116, 116, 0, 98, 10 },
{ 63, 122, 122, 0, 102, 10 },
{ 67, 127, 127, 0, 105, 11 },
{ 71, 133, 133, 0, 109, 12 },
{ 74, 138, 138, 0, 113, 13 },
{ 78, 144, 144, 0, 117, 14 },
{ 81, 150, 150, 0, 121, 15 },
{ 85, 155, 155, 0, 125, 16 },
{ 89, 162, 162, 0, 129, 17 },
{ 92, 168, 168, 0, 133, 18 },
{ 97, 173, 173, 0, 137, 19 },
{ 101, 181, 181, 0, 143, 20 },
{ 106, 188, 188, 0, 148, 22 },
{ 110, 194, 194, 0, 153, 23 },
{ 115, 202, 202, 0, 159, 25 },
{ 119, 209, 209, 0, 165, 27 },
{ 124, 215, 215, 0, 170, 29 },
{ 128, 223, 223, 0, 176, 31 },
{ 134, 229, 229, 0, 181, 33 },
{ 139, 236, 236, 0, 186, 35 },
{ 144, 244, 244, 0, 192, 38 },
{ 150, 253, 253, 0, 200, 40 },
{ 155, 263, 263, 0, 207, 43 },
{ 161, 272, 272, 0, 215, 46 },
{ 166, 283, 283, 0, 223, 49 },
{ 171, 292, 292, 0, 231, 52 },
{ 177, 302, 302, 0, 238, 55 },
{ 183, 311, 311, 0, 246, 58 },
{ 189, 322, 322, 0, 254, 62 },
{ 196, 331, 331, 0, 261, 66 },
{ 20, 56, 56, 86, 52, 2 },
{ 21, 57, 57, 101, 54, 2 },
{ 22, 60, 60, 109, 56, 3 },
{ 24, 62, 62, 116, 58, 3 },
{ 26, 65, 65, 123, 60, 3 },
{ 27, 68, 68, 131, 62, 3 },
{ 29, 70, 70, 138, 64, 4 },
{ 31, 73, 73, 145, 66, 4 },
{ 33, 76, 76, 153, 68, 4 },
{ 35, 78, 78, 160, 70, 5 },
{ 36, 82, 82, 174, 73, 5 },
{ 38, 85, 85, 188, 75, 5 },
{ 41, 89, 89, 202, 78, 6 },
{ 44, 93, 93, 216, 81, 6 },
{ 46, 96, 96, 230, 84, 7 },
{ 49, 100, 100, 244, 86, 7 },
{ 52, 104, 104, 258, 89, 8 },
{ 54, 109, 109, 272, 93, 9 },
{ 57, 113, 113, 286, 95, 9 },
{ 60, 116, 116, 300, 98, 10 },
{ 63, 122, 122, 333, 102, 10 },
{ 67, 127, 127, 366, 105, 11 },
{ 71, 133, 133, 399, 109, 12 },
{ 74, 138, 138, 432, 113, 13 },
{ 78, 144, 144, 465, 117, 14 },
{ 81, 150, 150, 498, 121, 15 },
{ 85, 155, 155, 531, 125, 16 },
{ 89, 162, 162, 564, 129, 17 },
{ 92, 168, 168, 597, 133, 18 },
{ 97, 173, 173, 630, 137, 19 },
{ 101, 181, 181, 669, 143, 20 },
{ 106, 188, 188, 708, 148, 22 },
{ 110, 194, 194, 747, 153, 23 },
{ 115, 202, 202, 786, 159, 25 },
{ 119, 209, 209, 825, 165, 27 },
{ 124, 215, 215, 864, 170, 29 },
{ 128, 223, 223, 903, 176, 31 },
{ 134, 229, 229, 942, 181, 33 },
{ 139, 236, 236, 981, 186, 35 },
{ 144, 244, 244, 1020, 192, 38 },
{ 150, 253, 253, 1088, 200, 40 },
{ 155, 263, 263, 1156, 207, 43 },
{ 161, 272, 272, 1224, 215, 46 },
{ 166, 283, 283, 1292, 223, 49 },
{ 171, 292, 292, 1360, 231, 52 },
{ 177, 302, 302, 1428, 238, 55 },
{ 183, 311, 311, 1496, 246, 58 },
{ 189, 322, 322, 1564, 254, 62 },
{ 196, 331, 331, 1632, 261, 66 },
{ 202, 341, 341, 1700, 269, 70 },
{ 204, 342, 393, 1774, 270, 84 },
{ 205, 344, 444, 1851, 271, 99 },
@ -92,7 +92,7 @@ const int levelTable[81][6] =
// todo: add proper shbr values - hp/elmt/threat
// sub/div added from http://theoryjerks.akhmorning.com/resources/levelmods/
{ 296, 365, 2263, 3600, 466, 466 },
{ 296, 365, 2263, 3600, 295, 466 },
{ 300, 366, 2360, 3600, 295, 466 },
{ 305, 367, 2461, 3600, 295, 466 },
{ 310, 368, 2566, 3600, 295, 466 },
@ -131,7 +131,7 @@ float CalcStats::calculateBaseStat( const Chara& chara )
if( level > Common::MAX_PLAYER_LEVEL )
level = Common::MAX_PLAYER_LEVEL;
return static_cast< float >( levelTable[level][2] );
return static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] );
}
// Leggerless' HP Formula
@ -160,13 +160,16 @@ uint32_t CalcStats::calculateMaxHp( PlayerPtr pPlayer, Sapphire::FrameworkPtr pF
float approxBaseHp = 0.0f; // Read above
// These values are not precise.
/*
if( level >= 60 )
approxBaseHp = static_cast< float >( 2600 + ( level - 60 ) * 100 );
else if( level >= 50 )
approxBaseHp = 1700 + ( ( level - 50 ) * ( 1700 * 1.04325f ) );
else
approxBaseHp = paramGrowthInfo->mpModifier * 0.7667f;
*/
// just use the table at least better than what it was
approxBaseHp = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::HP ] );
uint16_t result = static_cast< uint16_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) +
floor( hpMod / 100.0f * ( vitStat - baseStat ) ) );

View file

@ -9,6 +9,9 @@
#include <Database/DatabaseDef.h>
#include <Util/Util.h>
#include <datReader/DatCategories/bg/LgbTypes.h>
#include <datReader/DatCategories/bg/Lgb.h>
#include <unordered_map>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
#include <Logging/Logger.h>
@ -20,6 +23,7 @@
#include "Territory/Land.h"
#include "Territory/ZonePosition.h"
#include "Territory/House.h"
#include "Territory/InstanceObjectCache.h"
#include "Network/PacketWrappers/PlayerSetupPacket.h"
#include "Network/PacketWrappers/PingPacket.h"
@ -274,45 +278,44 @@ void Sapphire::Network::GameConnection::zoneLineHandler( FrameworkPtr pFw,
const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
{
auto pTeriMgr = pFw->get< TerritoryMgr >();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcZoneLineHandler >( inPacket );
const auto zoneLineId = packet.data().zoneLineId;
player.sendDebug( "Walking ZoneLine#{0}", zoneLineId );
auto pTeriMgr = pFw->get< TerritoryMgr >();
auto pInstanceObjectCache = pFw->get< InstanceObjectCache >();
auto tInfo = player.getCurrentTerritory()->getTerritoryTypeInfo();
auto pZone = player.getCurrentTerritory();
auto pLine = pTeriMgr->getTerritoryPosition( zoneLineId );
auto pExitRange = pInstanceObjectCache->getExitRange( player.getTerritoryTypeId(), zoneLineId );
Common::FFXIVARR_POSITION3 targetPos{};
uint32_t targetZone;
float rotation = 0.0f;
if( pLine != nullptr )
if( pExitRange )
{
player.sendDebug( "ZoneLine #{0} found.", zoneLineId );
targetPos = pLine->getTargetPosition();
targetZone = pLine->getTargetZoneId();
rotation = pLine->getTargetRotation();
auto pPopRange = pInstanceObjectCache->getPopRange( pExitRange->data.destTerritoryType,
pExitRange->data.destInstanceObjectId );
if( pPopRange )
{
targetZone = pExitRange->data.destTerritoryType;
rotation = pPopRange->header.transform.rotation.y;
targetPos = Common::FFXIVARR_POSITION3 { pPopRange->header.transform.translation.x,
pPopRange->header.transform.translation.y,
pPopRange->header.transform.translation.z };
auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() );
preparePacket->data().targetZone = targetZone;
player.sendDebug( "ZoneLine #{0} found.", zoneLineId );
//ActorControlSelfPacket controlPacket( pPlayer, ActorControlType::DespawnZoneScreenMsg,
// 0x03, player.getId(), 0x01, targetZone );
player.queuePacket( preparePacket );
}
else
{
// No zoneline found, revert to last zone
player.sendUrgent( "ZoneLine {0} not found.", zoneLineId );
targetPos.x = 0;
targetPos.y = 0;
targetPos.z = 0;
targetZone = pZone->getTerritoryTypeId();
auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() );
preparePacket->data().targetZone = pExitRange->data.destTerritoryType;
player.queuePacket( preparePacket );
}
}
player.sendDebug( "Walking ZoneLine#{0}", zoneLineId );
player.performZoning( targetZone, targetPos, rotation );
}
@ -321,29 +324,23 @@ void Sapphire::Network::GameConnection::discoveryHandler( FrameworkPtr pFw,
const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
{
auto pInstanceObjectCache = pFw->get< InstanceObjectCache >();
auto tInfo = player.getCurrentTerritory()->getTerritoryTypeInfo();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcDiscoveryHandler >( inPacket );
const auto positionRef = packet.data().positionRef;
auto pDb = pFw->get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
auto pRefInfo = pInstanceObjectCache->getMapRange( player.getTerritoryTypeId(), positionRef );
auto pQR = pDb->query( "SELECT id, map_id, discover_id "
"FROM discoveryinfo "
"WHERE id = " + std::to_string( positionRef ) + ";" );
if( !pQR->next() )
{
player.sendDebug( "Discovery ref pos id#{0} not found!", positionRef );
return;
}
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
discoveryPacket->data().map_id = pQR->getUInt( 2 );
discoveryPacket->data().map_part_id = pQR->getUInt( 3 );
player.queuePacket( discoveryPacket );
player.sendDebug( "Discovery ref pos id#{0}", positionRef );
player.discover( pQR->getUInt16( 2 ), pQR->getUInt16( 3 ) );
if( pRefInfo )
{
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
discoveryPacket->data().mapId = tInfo->map;
discoveryPacket->data().mapPartId = pRefInfo->data.discoveryIndex;
player.queuePacket( discoveryPacket );
player.discover( tInfo->map, pRefInfo->data.discoveryIndex );
}
}

View file

@ -44,6 +44,8 @@
#include "Manager/NaviMgr.h"
#include "Manager/ActionMgr.h"
#include "Territory/InstanceObjectCache.h"
using namespace Sapphire::World::Manager;
Sapphire::World::ServerMgr::ServerMgr( const std::string& configName, FrameworkPtr pFw ) :
@ -171,6 +173,10 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] )
}
framework()->set< Scripting::ScriptMgr >( pScript );
Logger::info( "Setting up InstanceObjectCache" );
auto pInstanceObjCache = std::make_shared< Sapphire::InstanceObjectCache >( framework() );
framework()->set< Sapphire::InstanceObjectCache >( pInstanceObjCache );
auto pActionMgr = std::make_shared< Manager::ActionMgr >( framework() );
framework()->set< Manager::ActionMgr >( pActionMgr );

View file

@ -0,0 +1,125 @@
#include "InstanceObjectCache.h"
#include "Exd/ExdDataGenerated.h"
#include <Framework.h>
#include <datReader/DatCategories/bg/pcb.h>
#include <datReader/DatCategories/bg/lgb.h>
#include <datReader/DatCategories/bg/sgb.h>
#include <GameData.h>
#include <File.h>
#include <DatCat.h>
#include <ExdData.h>
#include <ExdCat.h>
#include <Exd.h>
#include <Logging/Logger.h>
Sapphire::InstanceObjectCache::InstanceObjectCache( std::shared_ptr< Framework > pFramework ) :
m_pFramework( pFramework )
{
auto pExd = pFramework->get< Sapphire::Data::ExdDataGenerated >();
auto idList = pExd->getTerritoryTypeIdList();
size_t count = 0;
for( const auto& id : idList )
{
// show some loading indication...
if( count++ % 10 == 0 )
std::cout << ".";
auto territoryType = pExd->get< Sapphire::Data::TerritoryType >( id );
if( !territoryType )
continue;
auto path = territoryType->bg;
if( path.empty() )
continue;
path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) );
// TODO: it does feel like this needs to be streamlined into the datReader instead of being done here...
std::string bgLgbPath( path + "/level/bg.lgb" );
std::string planmapLgbPath( path + "/level/planmap.lgb" );
std::vector< char > bgSection;
std::vector< char > planmapSection;
std::unique_ptr< xiv::dat::File > bgFile;
std::unique_ptr< xiv::dat::File > planmap_file;
try
{
bgFile = pExd->getGameData()->getFile( bgLgbPath );
planmap_file = pExd->getGameData()->getFile( planmapLgbPath );
}
catch( std::runtime_error& )
{
// ignore files that aren't found
continue;
}
bgSection = bgFile->access_data_sections().at( 0 );
planmapSection = planmap_file->access_data_sections().at( 0 );
std::vector< std::string > stringList;
uint32_t offset1 = 0x20;
LGB_FILE bgLgb( &bgSection[ 0 ], "bg" );
LGB_FILE planmapLgb( &planmapSection[ 0 ], "planmap" );
std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb };
uint32_t max_index = 0;
for( const auto& lgb : lgbList )
{
for( const auto& group : lgb.groups )
{
for( const auto& pEntry : group.entries )
{
if( pEntry->getType() == LgbEntryType::MapRange )
{
auto pMapRange = reinterpret_cast< LGB_MAP_RANGE_ENTRY* >( pEntry.get() );
m_mapRangeCache.insert( id, *pMapRange );
}
else if( pEntry->getType() == LgbEntryType::ExitRange )
{
auto pExitRange = reinterpret_cast< LGB_EXIT_RANGE_ENTRY* >( pEntry.get() );
m_exitRangeCache.insert( id, *pExitRange);
}
else if( pEntry->getType() == LgbEntryType::PopRange )
{
auto pPopRange = reinterpret_cast< LGB_POP_RANGE_ENTRY* >( pEntry.get() );
m_popRangeCache.insert( id, *pPopRange );
}
}
}
}
}
std::cout << "\n";
Logger::debug(
"InstanceObjectCache Cached: MapRange: {} ExitRange: {} PopRange: {}",
m_mapRangeCache.size(), m_exitRangeCache.size(), m_popRangeCache.size()
);
}
Sapphire::InstanceObjectCache::MapRangePtr
Sapphire::InstanceObjectCache::getMapRange( uint16_t zoneId, uint32_t mapRangeId )
{
return m_mapRangeCache.get( zoneId, mapRangeId );
}
Sapphire::InstanceObjectCache::ExitRangePtr
Sapphire::InstanceObjectCache::getExitRange( uint16_t zoneId, uint32_t exitRangeId )
{
return m_exitRangeCache.get( zoneId, exitRangeId );
}
Sapphire::InstanceObjectCache::PopRangePtr
Sapphire::InstanceObjectCache::getPopRange( uint16_t zoneId, uint32_t popRangeId )
{
return m_popRangeCache.get( zoneId, popRangeId );
}

View file

@ -0,0 +1,88 @@
#ifndef SAPPHIRE_INSTANCEOBJECTCACHE_H
#define SAPPHIRE_INSTANCEOBJECTCACHE_H
#include <memory>
#include <unordered_map>
struct LGB_MAP_RANGE_ENTRY;
struct LGB_EXIT_RANGE_ENTRY;
struct LGB_POP_RANGE_ENTRY;
namespace Sapphire
{
class Framework;
template< typename T >
class ObjectCache
{
using ObjectPtr = std::shared_ptr< T >;
using ObjectMap = std::unordered_map< uint32_t, ObjectPtr >;
using ZoneObjectCache = std::unordered_map< uint16_t, ObjectMap >;
ZoneObjectCache m_objectCache;
public:
ObjectPtr get( uint16_t zoneId, uint32_t id )
{
auto it = m_objectCache.find( zoneId );
if( it != m_objectCache.end() )
{
auto rangeIt = it->second.find( id );
if( rangeIt != it->second.end() )
{
return rangeIt->second;
}
}
return nullptr;
}
void insert( uint16_t zoneId, T& entry )
{
auto pShared = std::make_shared< T >( entry );
if( m_objectCache.find( zoneId ) == m_objectCache.end() )
{
ObjectMap cache;
cache[ entry.header.instanceId ] = pShared;
m_objectCache[ zoneId ] = cache;
}
else
{
auto it = m_objectCache.find( zoneId );
it->second[ entry.header.instanceId ] = pShared;
}
}
uint32_t size() const
{
return m_objectCache.size();
}
};
class InstanceObjectCache
{
public:
using MapRangePtr = std::shared_ptr< LGB_MAP_RANGE_ENTRY >;
using ExitRangePtr = std::shared_ptr< LGB_EXIT_RANGE_ENTRY >;
using PopRangePtr = std::shared_ptr< LGB_POP_RANGE_ENTRY >;
InstanceObjectCache( std::shared_ptr< Framework > pFramework );
~InstanceObjectCache() = default;
MapRangePtr getMapRange( uint16_t zoneId, uint32_t mapRangeId );
ExitRangePtr getExitRange( uint16_t zoneId, uint32_t exitRangeId );
PopRangePtr getPopRange( uint16_t zoneId, uint32_t popRangeId );
private:
ObjectCache< LGB_MAP_RANGE_ENTRY > m_mapRangeCache;
ObjectCache< LGB_EXIT_RANGE_ENTRY > m_exitRangeCache;
ObjectCache< LGB_POP_RANGE_ENTRY > m_popRangeCache;
std::shared_ptr< Framework > m_pFramework;
};
}
#endif //SAPPHIRE_INSTANCEOBJECTCACHE_H