mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
Merge remote-tracking branch 'origin/develop'
This commit is contained in:
commit
8afaa0a42d
82 changed files with 6056 additions and 2301 deletions
235
deps/datReader/Exd.cpp
vendored
235
deps/datReader/Exd.cpp
vendored
|
@ -1,8 +1,6 @@
|
|||
#include "Exd.h"
|
||||
|
||||
#include "bparse.h"
|
||||
#include "stream.h"
|
||||
#include <fstream>
|
||||
#include "Exh.h"
|
||||
|
||||
using xiv::utils::bparse::extract;
|
||||
|
@ -53,32 +51,24 @@ template<>
|
|||
|
||||
namespace xiv::exd
|
||||
{
|
||||
Exd::Exd( std::shared_ptr< Exh > i_exh, const std::vector< std::shared_ptr< dat::File>>& i_files )
|
||||
Exd::Exd( std::shared_ptr< Exh > exh, const std::vector< std::shared_ptr< dat::File > >& files )
|
||||
{
|
||||
_exh = i_exh;
|
||||
_files = i_files;
|
||||
_exh = exh;
|
||||
|
||||
|
||||
// Iterates over all the files
|
||||
const uint32_t member_count = _exh->get_members().size();
|
||||
for( auto& file_ptr : _files )
|
||||
for( auto& file : files )
|
||||
{
|
||||
// Get a stream
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||
std::vector< char > dataCpy = file->get_data_sections().front();
|
||||
|
||||
// Extract the header and skip to the record indices
|
||||
auto exd_header = extract< ExdHeader >( iss );
|
||||
iss.seekg( 0x20 );
|
||||
// Extract the header
|
||||
auto exdHeader = extract< ExdHeader >( dataCpy, 0 );
|
||||
|
||||
// Preallocate and extract the record_indices
|
||||
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
|
||||
std::vector< ExdRecordIndex > record_indices;
|
||||
record_indices.reserve( record_count );
|
||||
for( uint32_t i = 0; i < record_count; ++i )
|
||||
const uint32_t recordCount = exdHeader.index_size / sizeof( ExdRecordIndex );
|
||||
for( uint32_t i = 0; i < recordCount; ++i )
|
||||
{
|
||||
auto recordIndex = extract< ExdRecordIndex >( iss );
|
||||
_idCache[ recordIndex.id ] = ExdCacheEntry{ file_ptr, recordIndex.offset };
|
||||
auto recordIndex = extract< ExdRecordIndex >( dataCpy, 32 + ( i * sizeof( ExdRecordIndex ) ) );
|
||||
_idCache[ recordIndex.id ] = ExdCacheEntry{ file, recordIndex.offset + 6, extract< uint8_t >( dataCpy, recordIndex.offset + 5 ) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,40 +81,24 @@ namespace xiv::exd
|
|||
{
|
||||
|
||||
auto cacheEntryIt = _idCache.find( id );
|
||||
if( cacheEntryIt == _idCache.end() )
|
||||
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
||||
if( cacheEntryIt == _idCache.end() || subRow >= cacheEntryIt->second.subRows )
|
||||
throw std::runtime_error( "Id + SubId combination not found: " + std::to_string( id ) + "." + std::to_string( subRow ) );
|
||||
|
||||
// Iterates over all the files
|
||||
const uint32_t member_count = _exh->get_members().size();
|
||||
auto& file_ptr = cacheEntryIt->second.file;
|
||||
auto dataCpy = cacheEntryIt->second.file->get_data_sections().front();
|
||||
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||
std::vector< Field > fields;
|
||||
fields.reserve( _exh->get_members().size() );
|
||||
|
||||
// Get the vector fields for the given record and preallocate it
|
||||
auto fields = _data[ id ];
|
||||
fields.reserve( member_count );
|
||||
iss.seekg( cacheEntryIt->second.offset + 6 );
|
||||
uint32_t baseOffset = cacheEntryIt->second.offset + ( subRow * _exh->get_header().data_offset + 2 * ( subRow + 1 ) );
|
||||
|
||||
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
||||
|
||||
if( subRow >= subRows )
|
||||
throw std::runtime_error( "Out of bounds sub-row!" );
|
||||
|
||||
int offset = cacheEntryIt->second.offset + 6 + ( subRow * _exh->get_header().data_offset + 2 * ( subRow + 1 ) );
|
||||
|
||||
for( auto& member_entry : _exh->get_exh_members() )
|
||||
for( auto& memberEntry : _exh->get_exh_members() )
|
||||
{
|
||||
// Seek to the position of the member to extract.
|
||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||
iss.seekg( offset + member_entry.offset );
|
||||
|
||||
// Switch depending on the type to extract
|
||||
switch( member_entry.type )
|
||||
switch( memberEntry.type )
|
||||
{
|
||||
case DataType::string:
|
||||
// Extract the offset to the actual string
|
||||
// Seek to it then extract the actual string
|
||||
// Then extract the actual string from that offset
|
||||
{
|
||||
throw std::runtime_error( "String not implemented for variant 2!" );
|
||||
//auto string_offset = extract<uint32_t>( iss, "string_offset", false );
|
||||
|
@ -134,50 +108,46 @@ namespace xiv::exd
|
|||
break;
|
||||
|
||||
case DataType::boolean:
|
||||
fields.emplace_back( extract< bool >( iss, "bool" ) );
|
||||
fields.emplace_back( extract< bool >( dataCpy, baseOffset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::int8:
|
||||
fields.emplace_back( extract< int8_t >( iss, "int8_t" ) );
|
||||
fields.emplace_back( extract< int8_t >( dataCpy, baseOffset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::uint8:
|
||||
fields.emplace_back( extract< uint8_t >( iss, "uint8_t" ) );
|
||||
fields.emplace_back( extract< uint8_t >( dataCpy, baseOffset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::int16:
|
||||
fields.emplace_back( extract< int16_t >( iss, "int16_t", false ) );
|
||||
fields.emplace_back( extract< int16_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint16:
|
||||
fields.emplace_back( extract< uint16_t >( iss, "uint16_t", false ) );
|
||||
fields.emplace_back( extract< uint16_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::int32:
|
||||
fields.emplace_back( extract< int32_t >( iss, "int32_t", false ) );
|
||||
fields.emplace_back( extract< int32_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint32:
|
||||
fields.emplace_back( extract< uint32_t >( iss, "uint32_t", false ) );
|
||||
fields.emplace_back( extract< uint32_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::float32:
|
||||
fields.emplace_back( extract< float >( iss, "float", false ) );
|
||||
fields.emplace_back( extract< float >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint64:
|
||||
fields.emplace_back( extract< uint64_t >( iss, "uint64_t", false ) );
|
||||
fields.emplace_back( extract< uint64_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
auto type = static_cast< uint16_t >( member_entry.type );
|
||||
auto type = static_cast< uint16_t >( memberEntry.type );
|
||||
if( type < 0x19 || type > 0x20 )
|
||||
throw std::runtime_error( "Unknown DataType: " + std::to_string( type ) );
|
||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||
int32_t shift = type - 0x19;
|
||||
int32_t i = 1 << shift;
|
||||
val &= i;
|
||||
fields.emplace_back( ( val & i ) == i );
|
||||
fields.emplace_back( ( extract< uint8_t >( dataCpy, baseOffset + memberEntry.offset ) & ( 1 << ( type - 0x19 ) ) ) != 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -193,84 +163,68 @@ namespace xiv::exd
|
|||
if( cacheEntryIt == _idCache.end() )
|
||||
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
|
||||
|
||||
// Iterates over all the files
|
||||
const uint32_t member_count = _exh->get_members().size();
|
||||
auto& file_ptr = cacheEntryIt->second.file;
|
||||
auto dataCpy = cacheEntryIt->second.file->get_data_sections().front();
|
||||
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||
std::vector< Field > fields;
|
||||
fields.reserve( _exh->get_members().size() );
|
||||
|
||||
// Get the vector fields for the given record and preallocate it
|
||||
auto fields = _data[ id ];
|
||||
fields.reserve( member_count );
|
||||
iss.seekg( cacheEntryIt->second.offset + 6 );
|
||||
auto stringBaseOffset = cacheEntryIt->second.offset + _exh->get_header().data_offset;
|
||||
|
||||
uint8_t subRows = *reinterpret_cast< uint8_t* >( &dataCpy[ cacheEntryIt->second.offset + 5 ] );
|
||||
|
||||
for( auto& member_entry : _exh->get_exh_members() )
|
||||
for( auto& memberEntry : _exh->get_exh_members() )
|
||||
{
|
||||
// Seek to the position of the member to extract.
|
||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||
iss.seekg( cacheEntryIt->second.offset + 6 + member_entry.offset );
|
||||
|
||||
// Switch depending on the type to extract
|
||||
switch( member_entry.type )
|
||||
switch( memberEntry.type )
|
||||
{
|
||||
case DataType::string:
|
||||
// Extract the offset to the actual string
|
||||
// Seek to it then extract the actual string
|
||||
// Then extract the actual string from that offset
|
||||
{
|
||||
auto string_offset = extract< uint32_t >( iss, "string_offset", false );
|
||||
iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
|
||||
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
||||
auto stringOffset = extract< uint32_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false );
|
||||
fields.emplace_back( utils::bparse::extract_cstring( dataCpy, stringBaseOffset + stringOffset ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case DataType::boolean:
|
||||
fields.emplace_back( extract< bool >( iss, "bool" ) );
|
||||
fields.emplace_back( extract< bool >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::int8:
|
||||
fields.emplace_back( extract< int8_t >( iss, "int8_t" ) );
|
||||
fields.emplace_back( extract< int8_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::uint8:
|
||||
fields.emplace_back( extract< uint8_t >( iss, "uint8_t" ) );
|
||||
fields.emplace_back( extract< uint8_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::int16:
|
||||
fields.emplace_back( extract< int16_t >( iss, "int16_t", false ) );
|
||||
fields.emplace_back( extract< int16_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint16:
|
||||
fields.emplace_back( extract< uint16_t >( iss, "uint16_t", false ) );
|
||||
fields.emplace_back( extract< uint16_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::int32:
|
||||
fields.emplace_back( extract< int32_t >( iss, "int32_t", false ) );
|
||||
fields.emplace_back( extract< int32_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint32:
|
||||
fields.emplace_back( extract< uint32_t >( iss, "uint32_t", false ) );
|
||||
fields.emplace_back( extract< uint32_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::float32:
|
||||
fields.emplace_back( extract< float >( iss, "float", false ) );
|
||||
fields.emplace_back( extract< float >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint64:
|
||||
fields.emplace_back( extract< uint64_t >( iss, "uint64_t", false ) );
|
||||
fields.emplace_back( extract< uint64_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
auto type = static_cast< uint16_t >( member_entry.type );
|
||||
auto type = static_cast< uint16_t >( memberEntry.type );
|
||||
if( type < 0x19 || type > 0x20 )
|
||||
throw std::runtime_error( "Unknown DataType: " + std::to_string( type ) );
|
||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||
int32_t shift = type - 0x19;
|
||||
int32_t i = 1 << shift;
|
||||
val &= i;
|
||||
fields.emplace_back( ( val & i ) == i );
|
||||
fields.emplace_back( ( extract< uint8_t >( dataCpy, cacheEntryIt->second.offset + memberEntry.offset ) & ( 1 << ( type - 0x19 ) ) ) != 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -279,106 +233,99 @@ namespace xiv::exd
|
|||
}
|
||||
|
||||
// Get all rows
|
||||
const std::map< uint32_t, std::vector< Field>>& Exd::get_rows()
|
||||
const std::map< ExdRow, std::vector< Field >, exdRowSort > Exd::get_rows()
|
||||
{
|
||||
// Iterates over all the files
|
||||
const uint32_t member_count = _exh->get_members().size();
|
||||
for( auto& file_ptr : _files )
|
||||
std::map< ExdRow, std::vector< Field >, exdRowSort > data;
|
||||
|
||||
// Iterates over all the cached ids
|
||||
const uint32_t memberCount = _exh->get_members().size();
|
||||
for( auto& cacheEntry : _idCache )
|
||||
{
|
||||
// Get a stream
|
||||
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
|
||||
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
|
||||
std::vector< char > dataCpy = cacheEntry.second.file->get_data_sections().front();
|
||||
|
||||
// Extract the header and skip to the record indices
|
||||
auto exd_header = extract< ExdHeader >( iss );
|
||||
iss.seekg( 0x20 );
|
||||
auto baseOffset = cacheEntry.second.offset;
|
||||
auto stringBaseOffset = baseOffset + _exh->get_header().data_offset;
|
||||
|
||||
// Preallocate and extract the record_indices
|
||||
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
|
||||
std::vector< ExdRecordIndex > record_indices;
|
||||
record_indices.reserve( record_count );
|
||||
for( uint32_t i = 0; i < record_count; ++i )
|
||||
{
|
||||
record_indices.emplace_back( extract< ExdRecordIndex >( iss ) );
|
||||
}
|
||||
|
||||
for( auto& record_index : record_indices )
|
||||
for( int32_t i = 0; i < cacheEntry.second.subRows; i++ )
|
||||
{
|
||||
// Get the vector fields for the given record and preallocate it
|
||||
auto& fields = _data[ record_index.id ];
|
||||
fields.reserve( member_count );
|
||||
ExdRow row = { cacheEntry.first, i };
|
||||
auto& fields = data[ row ];
|
||||
fields.reserve( memberCount );
|
||||
|
||||
for( auto& member_entry : _exh->get_exh_members() )
|
||||
if( _exh->get_header().variant == 2 )
|
||||
baseOffset = cacheEntry.second.offset + ( i * _exh->get_header().data_offset + 2 * ( i + 1 ) );
|
||||
|
||||
for( auto& memberEntry : _exh->get_exh_members() )
|
||||
//for( auto& member_entry : _exh->get_members() )
|
||||
{
|
||||
// Seek to the position of the member to extract.
|
||||
// 6 is because we have uint32_t/uint16_t at the start of each record
|
||||
iss.seekg( record_index.offset + 6 + member_entry.offset );
|
||||
|
||||
// Switch depending on the type to extract
|
||||
switch( member_entry.type )
|
||||
switch( memberEntry.type )
|
||||
{
|
||||
case DataType::string:
|
||||
// Extract the offset to the actual string
|
||||
// Seek to it then extract the actual string
|
||||
// Then extract the actual string from that offset
|
||||
{
|
||||
auto string_offset = extract< uint32_t >( iss, "string_offset", false );
|
||||
iss.seekg( record_index.offset + 6 + _exh->get_header().data_offset + string_offset );
|
||||
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
|
||||
if( _exh->get_header().variant == 1 )
|
||||
{
|
||||
auto stringOffset = extract< uint32_t >( dataCpy, baseOffset + memberEntry.offset, false );
|
||||
fields.emplace_back( utils::bparse::extract_cstring( dataCpy, stringBaseOffset + stringOffset ) );
|
||||
}
|
||||
else if( _exh->get_header().variant == 2 )
|
||||
{
|
||||
throw std::runtime_error( "String not implemented for variant 2!" );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DataType::boolean:
|
||||
fields.emplace_back( extract< bool >( iss, "bool" ) );
|
||||
fields.emplace_back( extract< bool >( dataCpy, baseOffset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::int8:
|
||||
fields.emplace_back( extract< int8_t >( iss, "int8_t" ) );
|
||||
fields.emplace_back( extract< int8_t >( dataCpy, baseOffset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::uint8:
|
||||
fields.emplace_back( extract< uint8_t >( iss, "uint8_t" ) );
|
||||
fields.emplace_back( extract< uint8_t >( dataCpy, baseOffset + memberEntry.offset ) );
|
||||
break;
|
||||
|
||||
case DataType::int16:
|
||||
fields.emplace_back( extract< int16_t >( iss, "int16_t", false ) );
|
||||
fields.emplace_back( extract< int16_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint16:
|
||||
fields.emplace_back( extract< uint16_t >( iss, "uint16_t", false ) );
|
||||
fields.emplace_back( extract< uint16_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::int32:
|
||||
fields.emplace_back( extract< int32_t >( iss, "int32_t", false ) );
|
||||
fields.emplace_back( extract< int32_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint32:
|
||||
fields.emplace_back( extract< uint32_t >( iss, "uint32_t", false ) );
|
||||
fields.emplace_back( extract< uint32_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::float32:
|
||||
fields.emplace_back( extract< float >( iss, "float", false ) );
|
||||
fields.emplace_back( extract< float >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
case DataType::uint64:
|
||||
fields.emplace_back( extract< uint64_t >( iss, "uint64_t", false ) );
|
||||
fields.emplace_back( extract< uint64_t >( dataCpy, baseOffset + memberEntry.offset, false ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
auto type = static_cast< uint16_t >( member_entry.type );
|
||||
auto type = static_cast< uint16_t >( memberEntry.type );
|
||||
if( type < 0x19 || type > 0x20 )
|
||||
throw std::runtime_error( "Unknown DataType: " + std::to_string( type ) );
|
||||
uint64_t val = extract< uint64_t >( iss, "bool" );
|
||||
int32_t shift = type - 0x19;
|
||||
int32_t i = 1 << shift;
|
||||
val &= i;
|
||||
fields.emplace_back( ( val & i ) == i );
|
||||
fields.emplace_back( ( extract< uint8_t >( dataCpy, baseOffset + memberEntry.offset ) & ( 1 << ( type - 0x19 ) ) ) != 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _data;
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
31
deps/datReader/Exd.h
vendored
31
deps/datReader/Exd.h
vendored
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
|
||||
#include <variant>
|
||||
|
||||
|
@ -30,19 +32,37 @@ namespace xiv::exd
|
|||
{
|
||||
std::shared_ptr< dat::File > file;
|
||||
uint32_t offset;
|
||||
uint8_t subRows;
|
||||
};
|
||||
|
||||
struct ExdRow
|
||||
{
|
||||
uint32_t rowId;
|
||||
uint8_t subRowId;
|
||||
};
|
||||
|
||||
struct exdRowSort
|
||||
{
|
||||
constexpr bool operator()( const ExdRow& _Left, const ExdRow& _Right ) const
|
||||
{
|
||||
if( _Left.rowId == _Right.rowId )
|
||||
return _Left.subRowId < _Right.subRowId;
|
||||
|
||||
return _Left.rowId < _Right.rowId;
|
||||
}
|
||||
};
|
||||
|
||||
// Data for a given language
|
||||
class Exd
|
||||
{
|
||||
public:
|
||||
// i_exh: the header
|
||||
// i_files: the multiple exd files
|
||||
// exh: the header
|
||||
// files: the multiple exd files
|
||||
Exd()
|
||||
{
|
||||
}
|
||||
|
||||
Exd( std::shared_ptr< Exh > i_exh, const std::vector< std::shared_ptr< dat::File>>& i_files );
|
||||
Exd( std::shared_ptr< Exh > exh, const std::vector< std::shared_ptr< dat::File > >& files );
|
||||
|
||||
~Exd();
|
||||
|
||||
|
@ -53,12 +73,9 @@ namespace xiv::exd
|
|||
const std::vector< Field > get_row( uint32_t id, uint32_t subRow );
|
||||
|
||||
// Get all rows
|
||||
const std::map< uint32_t, std::vector< Field>>& get_rows();
|
||||
const std::map< ExdRow, std::vector< Field >, exdRowSort > get_rows();
|
||||
|
||||
protected:
|
||||
// Data indexed by the ID of the row, the vector is field with the same order as exh.members
|
||||
std::map< uint32_t, std::vector< Field>> _data;
|
||||
std::vector< std::shared_ptr< dat::File>> _files;
|
||||
std::shared_ptr< Exh > _exh;
|
||||
std::map< uint32_t, ExdCacheEntry > _idCache;
|
||||
};
|
||||
|
|
1
deps/datReader/ExdData.h
vendored
1
deps/datReader/ExdData.h
vendored
|
@ -6,6 +6,7 @@
|
|||
#include <mutex>
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace xiv
|
||||
{
|
||||
|
|
1
deps/datReader/GameData.h
vendored
1
deps/datReader/GameData.h
vendored
|
@ -6,6 +6,7 @@
|
|||
#include <mutex>
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace xiv::dat
|
||||
{
|
||||
|
|
7
deps/datReader/bparse.cpp
vendored
7
deps/datReader/bparse.cpp
vendored
|
@ -5,4 +5,9 @@ std::string xiv::utils::bparse::extract_cstring( std::istream& i_stream, const s
|
|||
std::string temp_str;
|
||||
std::getline( i_stream, temp_str, '\0' );
|
||||
return temp_str;
|
||||
}
|
||||
}
|
||||
|
||||
std::string xiv::utils::bparse::extract_cstring( std::vector< char >& data, uint32_t pos )
|
||||
{
|
||||
return &data[ pos ];
|
||||
}
|
||||
|
|
18
deps/datReader/bparse.h
vendored
18
deps/datReader/bparse.h
vendored
|
@ -93,9 +93,27 @@ namespace xiv::utils::bparse
|
|||
}
|
||||
}
|
||||
|
||||
template< typename StructType >
|
||||
StructType extract( std::vector< char >& data, uint32_t pos, bool isLe = true )
|
||||
{
|
||||
StructType tempStruct = *reinterpret_cast< StructType* >( &data[ pos ] );
|
||||
|
||||
if( std::is_class< StructType >::value )
|
||||
{
|
||||
reorder( tempStruct );
|
||||
}
|
||||
else if( !isLe )
|
||||
{
|
||||
tempStruct = byteswap( tempStruct );
|
||||
}
|
||||
return tempStruct;
|
||||
}
|
||||
|
||||
// For cstrings
|
||||
std::string extract_cstring( std::istream& i_stream, const std::string& i_name );
|
||||
|
||||
std::string extract_cstring( std::vector< char >& data, uint32_t pos );
|
||||
|
||||
}
|
||||
|
||||
#endif // XIV_UTILS_BPARSE_H
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "CommonGen.h"
|
||||
#include "Vector3.h"
|
||||
#include "Network/PacketDef/Ipcs.h"
|
||||
|
||||
// +---------------------------------------------------------------------------
|
||||
// The following enumerations are structures to require their type be included.
|
||||
|
@ -25,7 +26,7 @@ namespace Sapphire::Common
|
|||
const uint8_t CURRENT_EXPANSION_ID = 3;
|
||||
|
||||
const uint8_t CLASSJOB_TOTAL = 38;
|
||||
const uint8_t CLASSJOB_SLOTS = 28;
|
||||
const uint8_t CLASSJOB_SLOTS = 30;
|
||||
|
||||
const uint8_t TOWN_COUNT = 6;
|
||||
|
||||
|
@ -51,11 +52,11 @@ namespace Sapphire::Common
|
|||
|
||||
enum InventoryOperation : uint16_t
|
||||
{
|
||||
Discard = 0x013C,
|
||||
Move = 0x013D,
|
||||
Swap = 0x013E,
|
||||
Split = 0x013F,
|
||||
Merge = 0x0141,
|
||||
Discard = Network::Packets::ClientZoneIpcType::InventoryModifyHandler + 7,
|
||||
Move = Network::Packets::ClientZoneIpcType::InventoryModifyHandler + 8,
|
||||
Swap = Network::Packets::ClientZoneIpcType::InventoryModifyHandler + 9,
|
||||
Split = Network::Packets::ClientZoneIpcType::InventoryModifyHandler + 10,
|
||||
Merge = Network::Packets::ClientZoneIpcType::InventoryModifyHandler + 12
|
||||
};
|
||||
|
||||
enum ClientLanguage : uint8_t
|
||||
|
@ -161,44 +162,27 @@ namespace Sapphire::Common
|
|||
|
||||
enum class EquipSlotCategory : uint8_t
|
||||
{
|
||||
// main slots
|
||||
|
||||
CharaMainHand = 0,
|
||||
CharaOffHand = 1,
|
||||
CharaHead = 2,
|
||||
CharaBody = 3,
|
||||
CharaHands = 4,
|
||||
CharaWaist = 5,
|
||||
CharaLegs = 6,
|
||||
CharaFeet = 7,
|
||||
CharaEars = 8,
|
||||
CharaNeck = 9,
|
||||
CharaWrist = 10,
|
||||
CharaRing = 11,
|
||||
CharaSoulCrystal = 12,
|
||||
|
||||
/* following slots not seem to exist any more.
|
||||
when multi-slot gear is moved into equipment slot, normal slot listed above is used.
|
||||
client will move any incompatible gears into armory but no InventoryModifiyHandler is sent.
|
||||
server need to move those silently in order to sync with client.
|
||||
*/
|
||||
|
||||
/*! Cannot equip gear to offhand slot */
|
||||
//MainTwoHandedWeapon = 13,
|
||||
/*! Can be equipped in either main or offhand slot */
|
||||
//MainOrOffHand = 14, // unused
|
||||
/*! Cannot equip gear to head */
|
||||
//BodyDisallowHead = 15,
|
||||
/*! Cannot equip gear to hands, legs and feet slots */
|
||||
//BodyDisallowHandsLegsFeet = 16,
|
||||
/*! Cannot equip gear to feet slot */
|
||||
//LegsDisallowFeet = 18,
|
||||
/*! Cannot equp gear to head, hands, legs, feet slots */
|
||||
//BodyDisallowAll = 19,
|
||||
/*! Cannot equip gear to hands slot */
|
||||
//BodyDisallowHands = 20,
|
||||
/*! Cannot equip gear to legs & feet slots */
|
||||
//BodyDisallowLegsFeet = 21,
|
||||
MainHand = 1,
|
||||
OffHand = 2,
|
||||
Head = 3,
|
||||
Body = 4,
|
||||
Hands = 5,
|
||||
Waist = 6,
|
||||
Legs = 7,
|
||||
Feet = 8,
|
||||
Ears = 9,
|
||||
Neck = 10,
|
||||
Wrist = 11,
|
||||
Ring = 12,
|
||||
MainTwoHandedWeapon = 13,
|
||||
//MainOrOffHand = 14, // unused
|
||||
BodyDisallowHead = 15,
|
||||
BodyDisallowHandsLegsFeet = 16,
|
||||
SoulCrystal = 17,
|
||||
LegsDisallowFeet = 18,
|
||||
BodyDisallowAll = 19,
|
||||
BodyDisallowHands = 20,
|
||||
BodyDisallowLegsFeet = 21,
|
||||
};
|
||||
|
||||
enum InventoryType : uint16_t
|
||||
|
@ -773,6 +757,7 @@ namespace Sapphire::Common
|
|||
|
||||
BetweenAreas = 24,
|
||||
BoundByDuty = 28,
|
||||
Performing = 40,
|
||||
WatchingCutscene = 50, // this is actually just a dummy, this id is different
|
||||
|
||||
|
||||
|
@ -1263,9 +1248,6 @@ namespace Sapphire::Common
|
|||
GetGil = 9, // p1: gil
|
||||
EmptyCoffer = 11, // seems like no param
|
||||
};
|
||||
|
||||
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -257,6 +257,10 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
|
|||
"UPDATE house SET BuildTime = ?, Aetheryte = ?, Comment = ?, HouseName = ?, Endorsements = ? WHERE HouseId = ?;",
|
||||
CONNECTION_BOTH );
|
||||
|
||||
prepareStatement( HOUSING_HOUSE_DEL,
|
||||
"DELETE FROM house WHERE HouseId = ?;",
|
||||
CONNECTION_BOTH );
|
||||
|
||||
prepareStatement( LAND_INV_SEL_ALL,
|
||||
"SELECT houseiteminventory.*, charaglobalitem.catalogId, charaglobalitem.stain, charaglobalitem.CharacterId, "
|
||||
"landplaceditems.PosX, landplaceditems.PosY, landplaceditems.PosZ, landplaceditems.Rotation "
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -111,6 +111,8 @@ namespace Sapphire::Network::ActorControl
|
|||
|
||||
ScreenFadeOut = 0xAA,
|
||||
|
||||
CeremonyDecoration = 0xB9,
|
||||
|
||||
ZoneIn = 0xC8,
|
||||
ZoneInDefaultPos = 0xC9,
|
||||
|
||||
|
@ -213,7 +215,19 @@ namespace Sapphire::Network::ActorControl
|
|||
SetFavorite = 0x1FC,
|
||||
LearnTeleport = 0x1FD,
|
||||
|
||||
OpenRecommendationGuide = 0x200,
|
||||
/*!
|
||||
* param1 = event type bitmask
|
||||
* 1 = Quest
|
||||
* 2 = GuildLeveAssignment
|
||||
* 4 = GuildOrderGuide
|
||||
* 8 = TripleTriad
|
||||
* 16 = CustomTalk
|
||||
* 32 = PreHandler
|
||||
*/
|
||||
BeginMapUpdate = 0x1FF,
|
||||
FinishMapUpdate = 0x200,
|
||||
|
||||
//OpenRecommendationGuide = 0x200,
|
||||
ArmoryErrorMsg = 0x201,
|
||||
|
||||
AchievementPopup = 0x203,
|
||||
|
@ -364,6 +378,7 @@ namespace Sapphire::Network::ActorControl
|
|||
TitleList = 0x12F,
|
||||
|
||||
UpdatedSeenHowTos = 0x133,
|
||||
CutscenePlayed = 0x134, // param1 = cutscene id
|
||||
AllotAttribute = 0x135,
|
||||
|
||||
ClearFieldMarkers = 0x13A,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _CORE_NETWORK_PACKETS_IPCS_H
|
||||
#define _CORE_NETWORK_PACKETS_IPCS_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
namespace Sapphire::Network::Packets
|
||||
{
|
||||
|
||||
|
@ -43,67 +43,67 @@ namespace Sapphire::Network::Packets
|
|||
*/
|
||||
enum ServerZoneIpcType : uint16_t
|
||||
{
|
||||
Ping = 0x0219, // updated 5.35 hotfix
|
||||
Init = 0x0185, // updated 5.35 hotfix
|
||||
Ping = 0x02A8, // updated 5.58 hotfix
|
||||
Init = 0x013C, // updated 5.58 hotfix
|
||||
|
||||
ActorFreeSpawn = 0x0239, // updated 5.35 hotfix
|
||||
InitZone = 0x03CD, // updated 5.35 hotfix
|
||||
ActorFreeSpawn = 0x00B5, // updated 5.58 hotfix
|
||||
InitZone = 0x0320, // updated 5.58 hotfix
|
||||
|
||||
EffectResult = 0x01C2, // updated 5.35 hotfix
|
||||
ActorControl = 0x02A4, // updated 5.35 hotfix
|
||||
ActorControlSelf = 0x02C8, // updated 5.35 hotfix
|
||||
ActorControlTarget = 0x0209, // updated 5.35 hotfix
|
||||
EffectResult = 0x0387, // updated 5.58 hotfix
|
||||
ActorControl = 0x00B0, // updated 5.58 hotfix
|
||||
ActorControlSelf = 0x02B6, // updated 5.58 hotfix
|
||||
ActorControlTarget = 0x03C5, // updated 5.58 hotfix
|
||||
|
||||
/*!
|
||||
* @brief Used when resting
|
||||
*/
|
||||
UpdateHpMpTp = 0x0319, // updated 5.35 hotfix
|
||||
UpdateHpMpTp = 0x01A7, // updated 5.58 hotfix
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
ChatBanned = 0xF06B,
|
||||
Playtime = 0x03A4, // updated 5.35 hotfix
|
||||
Logout = 0x02AD, // updated 5.35 hotfix
|
||||
CFNotify = 0x02C4, // updated 5.35 hotfix
|
||||
Playtime = 0x0179, // updated 5.58 hotfix
|
||||
Logout = 0x0214, // updated 5.58 hotfix
|
||||
CFNotify = 0x0327, // updated 5.58 hotfix
|
||||
CFMemberStatus = 0x0079,
|
||||
CFDutyInfo = 0x0193, // updated 5.35 hotfix
|
||||
CFDutyInfo = 0x03AA, // updated 5.58 hotfix
|
||||
CFPlayerInNeed = 0xF07F,
|
||||
CFPreferredRole = 0x0196, // updated 5.35 hotfix
|
||||
CFCancel = 0x00EC, // updated 5.35 hotfix
|
||||
CFPreferredRole = 0x024B, // updated 5.58 hotfix
|
||||
CFCancel = 0x01AC, // updated 5.58 hotfix
|
||||
SocialRequestError = 0xF0AD,
|
||||
|
||||
CFRegistered = 0x010C, // updated 5.35 hotfix
|
||||
SocialRequestResponse = 0x01C7, // updated 5.35 hotfix
|
||||
SocialMessage = 0x0308, // updated 5.35 hotfix
|
||||
SocialMessage2 = 0x037C, // updated 5.35 hotfix
|
||||
CancelAllianceForming = 0x00C6, // updated 4.2
|
||||
CFRegistered = 0x029F, // updated 5.58 hotfix
|
||||
SocialRequestResponse = 0x0082, // updated 5.58 hotfix
|
||||
SocialMessage = 0x03CB, // updated 5.58 hotfix
|
||||
SocialMessage2 = 0x01D7, // updated 5.58 hotfix
|
||||
CancelAllianceForming = 0xF0C6, // updated 4.2
|
||||
|
||||
LogMessage = 0x00D0,
|
||||
LogMessage = 0x0118, // updated 5.58 hotfix
|
||||
|
||||
Chat = 0x0349, // updated 5.35 hotfix
|
||||
Chat = 0x00FE, // updated 5.58 hotfix
|
||||
PartyChat = 0x0065,
|
||||
|
||||
WorldVisitList = 0xF0FE, // added 4.5
|
||||
|
||||
SocialList = 0x0216, // updated 5.35 hotfix
|
||||
SocialList = 0x015F, // updated 5.58 hotfix
|
||||
|
||||
ExamineSearchInfo = 0x03C3, // updated 5.35 hotfix
|
||||
UpdateSearchInfo = 0x0121, // updated 5.35 hotfix
|
||||
InitSearchInfo = 0x036F, // updated 5.35 hotfix
|
||||
ExamineSearchComment = 0x0102, // updated 4.1
|
||||
ExamineSearchInfo = 0x0133, // updated 5.58 hotfix
|
||||
UpdateSearchInfo = 0x03E5, // updated 5.58 hotfix
|
||||
InitSearchInfo = 0x0321, // updated 5.58 hotfix
|
||||
ExamineSearchComment = 0x03AD, // updated 5.58 hotfix
|
||||
|
||||
ServerNoticeShort = 0x017A, // updated 5.35 hotfix
|
||||
ServerNotice = 0x02F8, // updated 5.35 hotfix
|
||||
SetOnlineStatus = 0x03D7, // updated 5.35 hotfix
|
||||
ServerNoticeShort = 0x0333, // updated 5.58 hotfix
|
||||
ServerNotice = 0x0171, // updated 5.58 hotfix
|
||||
SetOnlineStatus = 0x037B, // updated 5.58 hotfix
|
||||
|
||||
CountdownInitiate = 0x0237, // updated 5.25
|
||||
CountdownCancel = 0x00D9, // updated 5.18
|
||||
CountdownInitiate = 0x0111, // updated 5.58 hotfix
|
||||
CountdownCancel = 0x0231, // updated 5.58 hotfix
|
||||
|
||||
PlayerAddedToBlacklist = 0x033F, // updated 5.1
|
||||
PlayerRemovedFromBlacklist = 0x0385, // updated 5.1
|
||||
BlackList = 0x02DB, // updated 5.35 hotfix
|
||||
PlayerAddedToBlacklist = 0x024E, // updated 5.58 hotfix
|
||||
PlayerRemovedFromBlacklist = 0x011D, // updated 5.58 hotfix
|
||||
BlackList = 0x03C0, // updated 5.58 hotfix
|
||||
|
||||
LinkshellList = 0x01F0, // updated 5.35 hotfix
|
||||
LinkshellList = 0x02E2, // updated 5.58 hotfix
|
||||
|
||||
MailDeleteRequest = 0xF12B, // updated 5.0
|
||||
|
||||
|
@ -114,166 +114,181 @@ namespace Sapphire::Network::Packets
|
|||
|
||||
MarketTaxRates = 0x01F8, // updated 5.35 hotfix
|
||||
|
||||
MarketBoardSearchResult = 0x032C, // updated 5.35 hotfix
|
||||
MarketBoardItemListingCount = 0x038F, // updated 5.35 hotfix
|
||||
MarketBoardItemListingHistory = 0x0186, // updated 5.35 hotfix
|
||||
MarketBoardItemListing = 0x025F, // updated 5.35 hotfix
|
||||
|
||||
MarketBoardSearchResult = 0x01F1, // updated 5.58 hotfix
|
||||
MarketBoardItemListingCount = 0x0068, // updated 5.58 hotfix
|
||||
MarketBoardItemListingHistory = 0x01BA, // updated 5.58 hotfix
|
||||
MarketBoardItemListing = 0x0076, // updated 5.58 hotfix
|
||||
|
||||
CharaFreeCompanyTag = 0x013B, // updated 4.5
|
||||
FreeCompanyBoardMsg = 0x013C, // updated 4.5
|
||||
FreeCompanyInfo = 0xF13D, // updated 4.5
|
||||
ExamineFreeCompanyInfo = 0xF13E, // updated 4.5
|
||||
FreeCompanyBoardMsg = 0x03DB, // updated 5.58 hotfix
|
||||
FreeCompanyInfo = 0x01F7, // updated 5.58 hotfix
|
||||
ExamineFreeCompanyInfo = 0x0324, // updated 5.58 hotfix
|
||||
|
||||
FreeCompanyUpdateShortMessage = 0xF157, // added 5.0
|
||||
|
||||
StatusEffectList = 0x0382, // updated 5.35 hotfix
|
||||
StatusEffectList = 0x0074, // updated 5.58 hotfix
|
||||
EurekaStatusEffectList = 0x0167, // updated 5.18
|
||||
BossStatusEffectList = 0x0312, // added 5.1
|
||||
Effect = 0x0192, // updated 5.35 hotfix
|
||||
AoeEffect8 = 0x012C, // updated 5.35 hotfix
|
||||
AoeEffect16 = 0x01B9, // updated 5.35 hotfix
|
||||
AoeEffect24 = 0x02B4, // updated 5.35 hotfix
|
||||
AoeEffect32 = 0x00A4, // updated 5.35 hotfix
|
||||
PersistantEffect = 0x0317, // updated 5.35 hotfix
|
||||
Effect = 0x03CA, // updated 5.58 hotfix
|
||||
AoeEffect8 = 0x03C4, // updated 5.58 hotfix
|
||||
AoeEffect16 = 0x00FA, // updated 5.58 hotfix
|
||||
AoeEffect24 = 0x0339, // updated 5.58 hotfix
|
||||
AoeEffect32 = 0x023C, // updated 5.58 hotfix
|
||||
PersistantEffect = 0x025D, // updated 5.58 hotfix
|
||||
|
||||
GCAffiliation = 0x0105, // updated 5.35 hotfix
|
||||
GCAffiliation = 0x0094, // updated 5.58 hotfix
|
||||
|
||||
PlayerSpawn = 0x0179, // updated 5.35 hotfix
|
||||
NpcSpawn = 0x03A8, // updated 5.35 hotfix
|
||||
PlayerSpawn = 0x01D8, // updated 5.58 hotfix
|
||||
NpcSpawn = 0x00D2, // updated 5.58 hotfix
|
||||
NpcSpawn2 = 0x01CB, // ( Bigger statuseffectlist? ) updated 5.3
|
||||
ActorMove = 0x01BF, // updated 5.35 hotfix
|
||||
ActorMove = 0x00F8, // updated 5.58 hotfix
|
||||
|
||||
ActorSetPos = 0x03DF, // updated 5.35 hotfix
|
||||
ActorSetPos = 0x0299, // updated 5.58 hotfix
|
||||
|
||||
ActorCast = 0x0302, // updated 5.35 hotfix
|
||||
ActorCast = 0x015D, // updated 5.58 hotfix
|
||||
SomeCustomiseChangePacketProbably = 0x00CD, // added 5.18
|
||||
|
||||
PartyList = 0x02B2, // updated 5.35 hotfix
|
||||
PartyMessage = 0x00AE, // updated 5.35 hotfix
|
||||
HateRank = 0x02CC, // updated 5.35 hotfix
|
||||
HateList = 0x0198, // updated 5.35 hotfix
|
||||
ObjectSpawn = 0x02B8, // updated 5.35 hotfix
|
||||
ObjectDespawn = 0x00C0, // updated 5.35 hotfix
|
||||
UpdateClassInfo = 0x0235, // updated 5.35 hotfix
|
||||
SilentSetClassJob = 0x018E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything
|
||||
PlayerSetup = 0x0290, // updated 5.35 hotfix
|
||||
PlayerStats = 0x023B, // updated 5.35 hotfix
|
||||
ActorOwner = 0x00E8, // updated 5.35 hotfix
|
||||
PlayerStateFlags = 0x00F8, // updated 5.35 hotfix
|
||||
PlayerClassInfo = 0x02C3, // updated 5.35 hotfix
|
||||
CharaVisualEffect = 0x02E2, // updated 5.35 hotfix
|
||||
PartyList = 0x0349, // updated 5.58 hotfix
|
||||
PartyMessage = 0x00A4, // updated 5.58 hotfix
|
||||
HateRank = 0x0150, // updated 5.58 hotfix
|
||||
HateList = 0x0243, // updated 5.58 hotfix
|
||||
ObjectSpawn = 0x0125, // updated 5.58 hotfix
|
||||
ObjectDespawn = 0x0148, // updated 5.58 hotfix
|
||||
UpdateClassInfo = 0x0084, // updated 5.58 hotfix
|
||||
SilentSetClassJob = 0xF18E, // updated 5.0 - seems to be the case, not sure if it's actually used for anything
|
||||
PlayerSetup = 0x01D5, // updated 5.58 hotfix
|
||||
PlayerStats = 0x0295, // updated 5.58 hotfix
|
||||
ActorOwner = 0x0260, // updated 5.58 hotfix
|
||||
PlayerStateFlags = 0x03BF, // updated 5.58 hotfix
|
||||
PlayerClassInfo = 0x0131, // updated 5.58 hotfix
|
||||
CharaVisualEffect = 0x0292, // updated 5.58 hotfix
|
||||
|
||||
ModelEquip = 0x0277, // updated 5.35 hotfix
|
||||
Examine = 0x00BC, // updated 5.35 hotfix
|
||||
CharaNameReq = 0x008E, // updated 5.35 hotfix
|
||||
ModelEquip = 0x03A2, // updated 5.58 hotfix
|
||||
Examine = 0x0365, // updated 5.58 hotfix
|
||||
CharaNameReq = 0x01F0, // updated 5.58 hotfix
|
||||
|
||||
// nb: see #565 on github
|
||||
UpdateRetainerItemSalePrice = 0xF19F, // updated 5.0
|
||||
RetainerSaleHistory = 0x020E, // updated 5.21 hotfix
|
||||
RetainerInformation = 0x01F9, // updated 5.35 hotfix
|
||||
RetainerSaleHistory = 0x03CE, // updated 5.58 hotfix
|
||||
RetainerInformation = 0x022F, // updated 5.58 hotfix
|
||||
|
||||
SetLevelSync = 0x1186, // not updated for 4.4, not sure what it is anymore
|
||||
|
||||
ItemInfo = 0x0214, // updated 5.35 hotfix
|
||||
ContainerInfo = 0x00C5, // updated 5.35 hotfix
|
||||
InventoryTransactionFinish = 0x02F0, // updated 5.35 hotfix
|
||||
InventoryTransaction = 0x01FD, // updated 5.35 hotfix
|
||||
CurrencyCrystalInfo = 0x0379, // updated 5.35 hotfix
|
||||
ItemInfo = 0x01CC, // updated 5.58 hotfix
|
||||
ContainerInfo = 0x025C, // updated 5.58 hotfix
|
||||
InventoryTransactionFinish = 0x0176, // updated 5.58 hotfix
|
||||
InventoryTransaction = 0x027F, // updated 5.58 hotfix
|
||||
CurrencyCrystalInfo = 0x0345, // updated 5.58 hotfix
|
||||
|
||||
InventoryActionAck = 0x03E4, // updated 5.35 hotfix
|
||||
UpdateInventorySlot = 0x036A, // updated 5.35 hotfix
|
||||
InventoryActionAck = 0x03B8, // updated 5.58 hotfix
|
||||
UpdateInventorySlot = 0x02F7, // updated 5.58 hotfix
|
||||
|
||||
HuntingLogEntry = 0x0146, // updated 5.35 hotfix
|
||||
HuntingLogEntry = 0x01D9, // updated 5.58 hotfix
|
||||
|
||||
EventPlay = 0x00F3, // updated 5.35 hotfix
|
||||
EventPlay4 = 0x00AC, // updated 5.35 hotfix
|
||||
EventPlay8 = 0x023F, // updated 5.35 hotfix
|
||||
EventPlay16 = 0x025B, // updated 5.35 hotfix
|
||||
EventPlay32 = 0x029A, // updated 5.35 hotfix
|
||||
EventPlay64 = 0x02C1, // updated 5.35 hotfix
|
||||
EventPlay128 = 0x038A, // updated 5.35 hotfix
|
||||
EventPlay255 = 0x034B, // updated 5.35 hotfix
|
||||
EventPlay = 0x016B, // updated 5.58 hotfix
|
||||
EventPlay4 = 0x010A, // updated 5.58 hotfix
|
||||
EventPlay8 = 0x0337, // updated 5.58 hotfix
|
||||
EventPlay16 = 0x0269, // updated 5.58 hotfix
|
||||
EventPlay32 = 0x023E, // updated 5.58 hotfix
|
||||
EventPlay64 = 0x00DE, // updated 5.58 hotfix
|
||||
EventPlay128 = 0x02D0, // updated 5.58 hotfix
|
||||
EventPlay255 = 0x0362, // updated 5.58 hotfix
|
||||
|
||||
EventStart = 0x009A, // updated 5.35 hotfix
|
||||
EventFinish = 0x007E, // updated 5.35 hotfix
|
||||
EventContinue = 0x00B6, // updated 5.58 hotfix
|
||||
|
||||
EventStart = 0x02DA, // updated 5.58 hotfix
|
||||
EventFinish = 0x0235, // updated 5.58 hotfix
|
||||
|
||||
EventLinkshell = 0x1169,
|
||||
|
||||
QuestActiveList = 0x0117, // updated 5.35 hotfix
|
||||
QuestUpdate = 0x0073, // updated 5.35 hotfix
|
||||
QuestCompleteList = 0x0240, // updated 5.35 hotfix
|
||||
QuestActiveList = 0x0097, // updated 5.58 hotfix
|
||||
QuestUpdate = 0x01B2, // updated 5.58 hotfix
|
||||
QuestCompleteList = 0x006D, // updated 5.58 hotfix
|
||||
|
||||
QuestFinish = 0x00E9, // updated 5.35 hotfix
|
||||
MSQTrackerComplete = 0xF1D6, // updated 5.0
|
||||
QuestFinish = 0x021B, // updated 5.58 hotfix
|
||||
MSQTrackerComplete = 0x0348, // updated 5.58 hotfix
|
||||
MSQTrackerProgress = 0xF1CD, // updated 4.5 ? this actually looks like the two opcodes have been combined, see #474
|
||||
|
||||
QuestMessage = 0x0381, // updated 5.35 hotfix
|
||||
QuestMessage = 0x0220, // updated 5.58 hotfix
|
||||
|
||||
QuestTracker = 0x018B, // updated 5.35 hotfix
|
||||
QuestTracker = 0x00D8, // updated 5.58 hotfix
|
||||
|
||||
Mount = 0x01B5, // updated 5.35 hotfix
|
||||
Mount = 0x01E1, // updated 5.58 hotfix
|
||||
|
||||
DirectorVars = 0x011D, // updated 5.35 hotfix
|
||||
DirectorVars = 0x0154, // updated 5.58 hotfix
|
||||
SomeDirectorUnk1 = 0x0084, // updated 5.18
|
||||
SomeDirectorUnk2 = 0xF0C1, // updated 5.18
|
||||
SomeDirectorUnk4 = 0x0202, // updated 5.35 hotfix
|
||||
SomeDirectorUnk4 = 0x03DD, // updated 5.58 hotfix
|
||||
SomeDirectorUnk8 = 0x028A, // updated 5.18
|
||||
SomeDirectorUnk16 = 0x028C, // updated 5.18
|
||||
DirectorPopUp = 0xF162, // updated 5.18 - display dialogue pop-ups in duties and FATEs, for example, Teraflare's countdown
|
||||
DirectorPopUp4 = 0x0214, // updated 5.18
|
||||
DirectorPopUp8 = 0x00F8, // updated 5.18
|
||||
DirectorPopUp = 0x03DF, // updated 5.58 hotfix
|
||||
DirectorPopUp4 = 0x019B, // updated 5.58 hotfix
|
||||
DirectorPopUp8 = 0x0271, // updated 5.58 hotfix
|
||||
|
||||
CFAvailableContents = 0xF1FD, // updated 4.2
|
||||
|
||||
WeatherChange = 0x027B, // updated 5.35 hotfix
|
||||
PlayerTitleList = 0x0251, // updated 5.35 hotfix
|
||||
Discovery = 0x031B, // updated 5.35 hotfix
|
||||
WeatherChange = 0x0323, // updated 5.58 hotfix
|
||||
PlayerTitleList = 0x014E, // updated 5.58 hotfix
|
||||
Discovery = 0x01C2, // updated 5.58 hotfix
|
||||
|
||||
EorzeaTimeOffset = 0x01D4, // updated 5.35 hotfix
|
||||
EorzeaTimeOffset = 0x0070, // updated 5.58 hotfix
|
||||
|
||||
EquipDisplayFlags = 0x00BE, // updated 5.35 hotfix
|
||||
EquipDisplayFlags = 0x02C6, // updated 5.58 hotfix
|
||||
|
||||
MiniCactpotInit = 0x0286, // added 5.31
|
||||
ShopMessage = 0x0197, // updated 5.35 hotfix
|
||||
LootMessage = 0x01B7, // updated 5.35 hotfix
|
||||
ShopMessage = 0x0287, // updated 5.58 hotfix
|
||||
LootMessage = 0x0383, // updated 5.58 hotfix
|
||||
ResultDialog = 0x0273, // updated 5.58 hotfix
|
||||
DesynthResult = 0x0238, // updated 5.58 hotfix
|
||||
|
||||
/// Housing //////////////////////////////////////
|
||||
|
||||
LandSetInitialize = 0x0095, // updated 5.35 hotfix
|
||||
LandUpdate = 0x00BF, // updated 5.35 hotfix
|
||||
YardObjectSpawn = 0x01CA, // updated 5.35 hotfix
|
||||
HousingIndoorInitialize = 0x01FF, // updated 5.35 hotfix
|
||||
LandPriceUpdate = 0x0380, // updated 5.35 hotfix
|
||||
LandInfoSign = 0x023D, // updated 5.35 hotfix
|
||||
LandRename = 0x0140, // updated 5.35 hotfix
|
||||
HousingEstateGreeting = 0x00C7, // updated 5.35 hotfix
|
||||
HousingUpdateLandFlagsSlot = 0x027E, // updated 5.35 hotfix
|
||||
HousingLandFlags = 0x022F, // updated 5.35 hotfix
|
||||
HousingShowEstateGuestAccess = 0x03B5, // updated 5.35 hotfix
|
||||
LandSetInitialize = 0x0159, // updated 5.58 hotfix
|
||||
LandUpdate = 0x0228, // updated 5.58 hotfix
|
||||
YardObjectSpawn = 0x023D, // updated 5.58 hotfix
|
||||
HousingIndoorInitialize = 0x0210, // updated 5.58 hotfix
|
||||
LandPriceUpdate = 0x0300, // updated 5.58 hotfix
|
||||
LandInfoSign = 0x03E7, // updated 5.58 hotfix
|
||||
LandRename = 0x01BF, // updated 5.58 hotfix
|
||||
HousingEstateGreeting = 0x0126, // updated 5.58 hotfix
|
||||
HousingUpdateLandFlagsSlot = 0x0157, // updated 5.58 hotfix
|
||||
HousingLandFlags = 0x03B1, // updated 5.58 hotfix
|
||||
HousingShowEstateGuestAccess = 0x00CC, // updated 5.58 hotfix
|
||||
|
||||
HousingObjectInitialize = 0x01AA, // updated 5.35 hotfix
|
||||
HousingInternalObjectSpawn = 0x0234, // updated 5.35 hotfix
|
||||
HousingObjectInitialize = 0x0112, // updated 5.58 hotfix
|
||||
HousingInternalObjectSpawn = 0x02C8, // updated 5.58 hotfix
|
||||
|
||||
HousingWardInfo = 0x02FD, // updated 5.35 hotfix
|
||||
HousingObjectMove = 0x022C, // updated 5.35 hotfix
|
||||
HousingWardInfo = 0x012A, // updated 5.58 hotfix
|
||||
HousingObjectMove = 0x0265, // updated 5.58 hotfix
|
||||
|
||||
SharedEstateSettingsResponse = 0x006A, // updated 5.35 hotfix
|
||||
SharedEstateSettingsResponse = 0x030E, // updated 5.58 hotfix
|
||||
|
||||
LandUpdateHouseName = 0x00B1, // updated 5.35 hotfix
|
||||
LandUpdateHouseName = 0x017C, // updated 5.58 hotfix
|
||||
|
||||
LandSetMap = 0x0149, // updated 5.35 hotfix
|
||||
LandSetMap = 0x02E5, // updated 5.58 hotfix
|
||||
|
||||
CeremonySetActorAppearance = 0x02ED, // updated 5.58 hotfix
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui
|
||||
PerformNote = 0x0286, // updated 4.3
|
||||
PerformNote = 0x0127, // updated 5.58 hotfix
|
||||
|
||||
PrepareZoning = 0x026C, // updated 5.35 hotfix
|
||||
ActorGauge = 0x0112, // updated 5.35 hotfix
|
||||
PrepareZoning = 0x02AB, // updated 5.58 hotfix
|
||||
ActorGauge = 0x01C1, // updated 5.58 hotfix
|
||||
DutyGauge = 0x02E5, // updated 5.58 hotfix
|
||||
|
||||
// daily quest info -> without them sent, login will take longer...
|
||||
DailyQuests = 0x0139, // updated 5.35 hotfix
|
||||
DailyQuestRepeatFlags = 0x024C, // updated 5.35 hotfix
|
||||
DailyQuests = 0x02D6, // updated 5.58 hotfix
|
||||
DailyQuestRepeatFlags = 0x01AB, // updated 5.58 hotfix
|
||||
|
||||
MapUpdate = 0x0394, // updated 5.58 hotfix
|
||||
MapUpdate4 = 0x036F, // updated 5.58 hotfix
|
||||
MapUpdate8 = 0x0311, // updated 5.58 hotfix
|
||||
MapUpdate16 = 0x0108, // updated 5.58 hotfix
|
||||
MapUpdate32 = 0x007A, // updated 5.58 hotfix
|
||||
MapUpdate64 = 0x02A0, // updated 5.58 hotfix
|
||||
MapUpdate128 = 0x0303, // updated 5.58 hotfix
|
||||
|
||||
/// Doman Mahjong //////////////////////////////////////
|
||||
MahjongOpenGui = 0x02A4, // only available in mahjong instance
|
||||
|
@ -282,10 +297,20 @@ namespace Sapphire::Network::Packets
|
|||
MahjongEndRoundTsumo = 0x02BF, // called tsumo
|
||||
MahjongEndRoundRon = 0x2C0, // called ron or double ron (waiting for action must be flagged from discard packet to call)
|
||||
MahjongTileDiscard = 0x02C1, // giri (discarding a tile.) chi(1)/pon(2)/kan(4)/ron(8) flags etc..
|
||||
MahjongPlayersInfo = 0x02C2, // actor id, name, rating and stuff..
|
||||
MahjongPlayersInfo = 0xF2C2, // actor id, name, rating and stuff..
|
||||
// 2C3 and 2C4 are currently unknown
|
||||
MahjongEndRoundDraw = 0x02C5, // self explanatory
|
||||
MahjongEndGame = 0x02C6, // finished oorasu(all-last) round; shows a result screen.
|
||||
|
||||
/// Airship & Submarine //////////////////////////////////////
|
||||
AirshipExplorationResult = 0x0203, // updated 5.58 hotfix
|
||||
AirshipStatus = 0x030C, // updated 5.58 hotfix
|
||||
AirshipStatusList = 0x02FE, // updated 5.58 hotfix
|
||||
AirshipTimers = 0x0166, // updated 5.58 hotfix
|
||||
SubmarineExplorationResult = 0x00AA, // updated 5.58 hotfix
|
||||
SubmarineProgressionStatus = 0x0357, // updated 5.58 hotfix
|
||||
SubmarineStatusList = 0x01EF, // updated 5.58 hotfix
|
||||
SubmarineTimers = 0x0247, // updated 5.58 hotfix
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -293,109 +318,111 @@ namespace Sapphire::Network::Packets
|
|||
*/
|
||||
enum ClientZoneIpcType : uint16_t
|
||||
{
|
||||
PingHandler = 0x0219, // updated 5.35 hotfix
|
||||
InitHandler = 0x0185, // updated 5.35 hotfix
|
||||
PingHandler = 0x0288, // updated 5.58 hotfix
|
||||
InitHandler = 0x02EB, // updated 5.58 hotfix
|
||||
|
||||
FinishLoadingHandler = 0x01BE, // updated 5.35 hotfix
|
||||
FinishLoadingHandler = 0x013C, // updated 5.58 hotfix
|
||||
|
||||
CFCommenceHandler = 0x0118, // updated 5.35 hotfix
|
||||
CFCommenceHandler = 0x0381, // updated 5.58 hotfix
|
||||
|
||||
CFCancelHandler = 0x0332, // updated 5.35 hotfix
|
||||
CFRegisterDuty = 0x0289, // updated 5.35 hotfix
|
||||
CFRegisterRoulette = 0x0088, // updated 5.35 hotfix
|
||||
PlayTimeHandler = 0x02A8, // updated 5.35 hotfix
|
||||
LogoutHandler = 0x00EC, // updated 5.35 hotfix
|
||||
CancelLogout = 0x03DB, // updated 5.35 hotfix
|
||||
CFCancelHandler = 0x02B2, // updated 5.58 hotfix
|
||||
CFRegisterDuty = 0x01BD, // updated 5.58 hotfix
|
||||
CFRegisterRoulette = 0x037A, // updated 5.58 hotfix
|
||||
PlayTimeHandler = 0x02B7, // updated 5.58 hotfix
|
||||
LogoutHandler = 0x00A0, // updated 5.58 hotfix
|
||||
CancelLogout = 0x01AC, // updated 5.58 hotfix
|
||||
CFDutyInfoHandler = 0xF078, // updated 4.2
|
||||
|
||||
CFDutyInfoHandler = 0x0078, // updated 4.2
|
||||
SocialReqSendHandler = 0x00D7, // updated 5.58 hotfix
|
||||
SocialResponseHandler = 0x023B, // updated 5.58 hotfix
|
||||
CreateCrossWorldLS = 0x035D, // updated 5.58 hotfix
|
||||
|
||||
SocialReqSendHandler = 0x0387, // updated 5.35 hotfix
|
||||
SocialResponseHandler = 0x028D, // updated 5.35 hotfix
|
||||
CreateCrossWorldLS = 0x00AF, // updated 4.3
|
||||
|
||||
ChatHandler = 0x0131, // updated 5.35 hotfix
|
||||
ChatHandler = 0x03B0, // updated 5.58 hotfix
|
||||
PartyChatHandler = 0x0065,
|
||||
PartySetLeaderHandler = 0x0208, // updated 5.35 hotfix
|
||||
LeavePartyHandler = 0x0337, // updated 5.35 hotfix
|
||||
KickPartyMemberHandler = 0x014C, // updated 5.35 hotfix
|
||||
DisbandPartyHandler = 0x0205, // updated 5.35 hotfix
|
||||
PartySetLeaderHandler = 0x036C, // updated 5.58 hotfix
|
||||
LeavePartyHandler = 0x019D, // updated 5.58 hotfix
|
||||
KickPartyMemberHandler = 0x0262, // updated 5.58 hotfix
|
||||
DisbandPartyHandler = 0x0276, // updated 5.58 hotfix
|
||||
|
||||
SocialListHandler = 0x0340, // updated 5.35 hotfix
|
||||
SetSearchInfoHandler = 0x0314, // updated 5.35 hotfix
|
||||
ReqSearchInfoHandler = 0x01E9, // updated 5.35 hotfix
|
||||
SocialListHandler = 0x01CA, // updated 5.58 hotfix
|
||||
SetSearchInfoHandler = 0x01D4, // updated 5.58 hotfix
|
||||
ReqSearchInfoHandler = 0x014F, // updated 5.58 hotfix
|
||||
ReqExamineSearchCommentHandler = 0x00E7, // updated 5.0
|
||||
|
||||
ReqRemovePlayerFromBlacklist = 0x00F1, // updated 5.0
|
||||
BlackListHandler = 0x0079, // updated 5.35 hotfix
|
||||
PlayerSearchHandler = 0x00F4, // updated 5.0
|
||||
ReqRemovePlayerFromBlacklist = 0x00B4, // updated 5.58 hotfix
|
||||
BlackListHandler = 0x00F2, // updated 5.58 hotfix
|
||||
PlayerSearchHandler = 0x037D, // updated 5.58 hotfix
|
||||
|
||||
LinkshellListHandler = 0x024B, // updated 5.35 hotfix
|
||||
LinkshellListHandler = 0x03B6, // updated 5.58 hotfix
|
||||
|
||||
MarketBoardRequestItemListingInfo = 0x0102, // updated 4.5
|
||||
MarketBoardRequestItemListings = 0x0103, // updated 4.5
|
||||
MarketBoardSearch = 0x0107, // updated 4.5
|
||||
MarketBoardRequestItemListingInfo = 0x00F4, // updated 5.58 hotfix
|
||||
MarketBoardRequestItemListings = 0x0122, // updated 5.58 hotfix
|
||||
MarketBoardSearch = 0x0082, // updated 5.58 hotfix
|
||||
|
||||
ReqExamineFcInfo = 0x0113, // updated 4.1
|
||||
ReqExamineFcInfo = 0x037B, // updated 5.58 hotfix
|
||||
|
||||
FcInfoReqHandler = 0x011A, // updated 4.2
|
||||
FcInfoReqHandler = 0x03D4, // updated 5.58 hotfix
|
||||
|
||||
FreeCompanyUpdateShortMessageHandler = 0x0123, // added 5.0
|
||||
|
||||
ReqMarketWishList = 0x012C, // updated 4.3
|
||||
ReqMarketWishList = 0x00C3, // updated 5.58 hotfix
|
||||
|
||||
ReqJoinNoviceNetwork = 0x0129, // updated 4.2
|
||||
|
||||
ReqCountdownInitiate = 0x025F, // updated 5.35 hotfix
|
||||
ReqCountdownCancel = 0x0244, // updated 5.25
|
||||
ReqCountdownInitiate = 0x02EC, // updated 5.58 hotfix
|
||||
ReqCountdownCancel = 0x0068, // updated 5.58 hotfix
|
||||
|
||||
ZoneLineHandler = 0x0279, // updated 5.35 hotfix
|
||||
ClientTrigger = 0x03D3, // updated 5.35 hotfix
|
||||
DiscoveryHandler = 0x00E3, // updated 5.35 hotfix
|
||||
ZoneLineHandler = 0x008D, // updated 5.58 hotfix
|
||||
ClientTrigger = 0x03DB, // updated 5.58 hotfix
|
||||
DiscoveryHandler = 0x038B, // updated 5.58 hotfix
|
||||
|
||||
PlaceFieldMarkerPreset = 0x023F, // updated 5.25
|
||||
PlaceFieldMarker = 0x01BA, // updated 5.25
|
||||
SkillHandler = 0x01CD, // updated 5.35 hotfix
|
||||
GMCommand1 = 0x02AC, // updated 5.35 hotfix
|
||||
GMCommand2 = 0x029F, // updated 5.35 hotfix
|
||||
AoESkillHandler = 0x030C, // updated 5.35 hotfix
|
||||
PlaceFieldMarkerPreset = 0x026D, // updated 5.58 hotfix
|
||||
PlaceFieldMarker = 0x0371, // updated 5.58 hotfix
|
||||
SkillHandler = 0x02DC, // updated 5.58 hotfix
|
||||
GMCommand1 = 0x0272, // updated 5.58 hotfix
|
||||
GMCommand2 = 0x00E9, // updated 5.58 hotfix
|
||||
AoESkillHandler = 0x0152, // updated 5.58 hotfix
|
||||
|
||||
UpdatePositionHandler = 0x0236, // updated 5.35 hotfix
|
||||
UpdatePositionHandler = 0x01AF, // updated 5.58 hotfix
|
||||
|
||||
InventoryModifyHandler = 0x0135, // updated 5.35 hotfix
|
||||
|
||||
InventoryEquipRecommendedItems = 0x0116, // updated 5.35 hotfix
|
||||
InventoryModifyHandler = 0x029E, // updated 5.58 hotfix
|
||||
|
||||
ReqPlaceHousingItem = 0x02AE, // updated 5.35 hotfix
|
||||
BuildPresetHandler = 0x01C2, // updated 5.35 hotfix
|
||||
InventoryEquipRecommendedItems = 0x01C9, // updated 5.58 hotfix
|
||||
|
||||
TalkEventHandler = 0x02A4, // updated 5.35 hotfix
|
||||
EmoteEventHandler = 0x02C8, // updated 5.35 hotfix
|
||||
WithinRangeEventHandler = 0x0209, // updated 5.35 hotfix
|
||||
OutOfRangeEventHandler = 0x0319, // updated 5.35 hotfix
|
||||
EnterTeriEventHandler = 0x0192, // updated 5.35 hotfix
|
||||
ShopEventHandler = 0x01F6, // updated 5.35 hotfix
|
||||
ReqPlaceHousingItem = 0x02D4, // updated 5.58 hotfix
|
||||
BuildPresetHandler = 0x0223, // updated 5.58 hotfix
|
||||
|
||||
ReturnEventHandler = 0x02B4, // updated 5.35 hotfix
|
||||
TradeReturnEventHandler = 0x00A4, // updated 5.35 hotfix
|
||||
TradeMultipleReturnEventHander = 0x035C, // updated 5.35 hotfix
|
||||
TalkEventHandler = 0x0387, // updated 5.58 hotfix
|
||||
EmoteEventHandler = 0x00B0, // updated 5.58 hotfix
|
||||
WithinRangeEventHandler = 0x02B6, // updated 5.58 hotfix
|
||||
OutOfRangeEventHandler = 0x03C5, // updated 5.58 hotfix
|
||||
EnterTeriEventHandler = 0x01A7, // updated 5.58 hotfix
|
||||
ShopEventHandler = 0x0384, // updated 5.58 hotfix
|
||||
ReturnEventHandler = 0x00FA, // updated 5.58 hotfix
|
||||
TradeReturnEventHandler = 0x0339, // updated 5.58 hotfix
|
||||
TradeReturnEventHandler2 = 0x023C, // updated 5.58 hotfix
|
||||
EventYield2Handler = 0x021D, // updated 5.58 hotfix
|
||||
EventYield16Handler = 0x0207, // updated 5.58 hotfix
|
||||
|
||||
LinkshellEventHandler = 0x016B, // updated 4.5
|
||||
LinkshellEventHandler1 = 0x016C, // updated 4.5
|
||||
|
||||
ReqEquipDisplayFlagsChange = 0x02F6, // updated 5.35 hotfix
|
||||
ReqEquipDisplayFlagsChange = 0x02A5, // updated 5.58 hotfix
|
||||
|
||||
LandRenameHandler = 0x0155, // updated 5.35 hotfix
|
||||
HousingUpdateHouseGreeting = 0x02EA, // updated 5.35 hotfix
|
||||
HousingUpdateObjectPosition = 0x00D5, // updated 5.35 hotfix
|
||||
LandRenameHandler = 0x028E, // updated 5.58 hotfix
|
||||
HousingUpdateHouseGreeting = 0x0343, // updated 5.58 hotfix
|
||||
HousingUpdateObjectPosition = 0x012C, // updated 5.58 hotfix
|
||||
HousingEditExterior = 0x027B, // updated 5.58 hotfix
|
||||
HousingEditInterior = 0x02E3, // updated 5.58 hotfix
|
||||
|
||||
SetSharedEstateSettings = 0x017B, // updated 5.0
|
||||
SetSharedEstateSettings = 0x00D2, // updated 5.58 hotfix
|
||||
|
||||
UpdatePositionInstance = 0x0345, // updated 5.35 hotfix
|
||||
UpdatePositionInstance = 0x00F8, // updated 5.58 hotfix
|
||||
|
||||
PerformNoteHandler = 0x029B, // updated 4.3
|
||||
PerformNoteHandler = 0x0243, // updated 5.58 hotfix
|
||||
|
||||
WorldInteractionHandler = 0x00A9, // updated 5.35 hotfix
|
||||
Dive = 0x02CC, // updated 5.35 hotfix
|
||||
WorldInteractionHandler = 0x0274, // updated 5.58 hotfix
|
||||
Dive = 0x0320, // updated 5.58 hotfix
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -423,5 +450,5 @@ namespace Sapphire::Network::Packets
|
|||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /*_CORE_NETWORK_PACKETS_IPCS_H*/
|
||||
|
|
|
@ -426,6 +426,51 @@ struct FFXIVIpcDive :
|
|||
uint32_t padding;
|
||||
};
|
||||
|
||||
struct FFXIVIpcHousingEditExterior :
|
||||
FFXIVIpcBasePacket< HousingEditExterior >
|
||||
{
|
||||
uint16_t landId;
|
||||
uint8_t unknown[6];
|
||||
uint8_t removeFlag;
|
||||
uint8_t unknown2;
|
||||
uint16_t container[9];
|
||||
uint16_t slot[9];
|
||||
uint16_t padding;
|
||||
};
|
||||
|
||||
struct FFXIVIpcHousingEditInterior :
|
||||
FFXIVIpcBasePacket< HousingEditInterior >
|
||||
{
|
||||
uint64_t unknown;
|
||||
uint16_t container[10];
|
||||
uint16_t slot[10];
|
||||
};
|
||||
|
||||
struct FFXIVIpcEventYieldHandler :
|
||||
FFXIVIpcBasePacket< EventYield2Handler >
|
||||
{
|
||||
uint32_t eventId;
|
||||
uint16_t scene;
|
||||
uint16_t padding;
|
||||
uint64_t unknown;
|
||||
};
|
||||
|
||||
struct FFXIVIpcEventYield16Handler :
|
||||
FFXIVIpcBasePacket< EventYield16Handler >
|
||||
{
|
||||
uint32_t eventId;
|
||||
uint16_t scene;
|
||||
uint16_t padding;
|
||||
uint32_t params[16];
|
||||
};
|
||||
|
||||
struct FFXIVIpcCFCommenceHandler :
|
||||
FFXIVIpcBasePacket< CFCommenceHandler >
|
||||
{
|
||||
uint8_t param;
|
||||
uint8_t dummy[7];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //_CORE_NETWORK_PACKETS_ZONE_CLIENT_IPC_H
|
||||
|
|
|
@ -680,6 +680,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint16_t unk; // == 0
|
||||
uint16_t modelChara;
|
||||
uint16_t rotation;
|
||||
uint16_t currentMount;
|
||||
uint16_t activeMinion;
|
||||
uint8_t spawnIndex;
|
||||
uint8_t state;
|
||||
|
@ -693,24 +694,20 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint8_t classJob;
|
||||
uint8_t u26d;
|
||||
uint16_t u27a;
|
||||
uint8_t currentMount;
|
||||
uint8_t mountHead;
|
||||
uint8_t mountBody;
|
||||
uint8_t mountFeet;
|
||||
uint8_t mountColor;
|
||||
uint8_t scale;
|
||||
|
||||
//uint32_t elementalLevel; one of these two field changed to 16bit
|
||||
//uint32_t element;
|
||||
uint8_t elementData[6];
|
||||
|
||||
uint8_t unknown5_5[3];
|
||||
Common::StatusEffect effect[30];
|
||||
Common::FFXIVARR_POSITION3 pos;
|
||||
uint32_t models[10];
|
||||
char name[32];
|
||||
uint8_t look[26];
|
||||
char fcTag[6];
|
||||
uint32_t unk30;
|
||||
uint32_t unk30[2];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -753,9 +750,10 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint32_t displayFlags;
|
||||
uint16_t fateID;
|
||||
uint16_t mPCurr;
|
||||
uint16_t unknown1; // 0
|
||||
uint16_t unknown2; // 0 or pretty big numbers > 30000
|
||||
uint16_t unknown1;
|
||||
uint16_t unknown2;
|
||||
uint16_t modelChara;
|
||||
uint16_t currentMount;
|
||||
uint16_t rotation;
|
||||
uint16_t activeMinion;
|
||||
uint8_t spawnIndex;
|
||||
|
@ -770,14 +768,13 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint8_t classJob;
|
||||
uint8_t u26d;
|
||||
uint16_t u27a;
|
||||
uint8_t currentMount;
|
||||
uint8_t mountHead;
|
||||
uint8_t mountBody;
|
||||
uint8_t mountFeet;
|
||||
uint8_t mountColor;
|
||||
uint8_t scale;
|
||||
uint16_t elementalLevel; // Eureka
|
||||
uint16_t element; // Eureka
|
||||
uint8_t elemental[6];
|
||||
uint8_t unknown5_5[3];
|
||||
Common::StatusEffect effect[30];
|
||||
Common::FFXIVARR_POSITION3 pos;
|
||||
uint32_t models[10];
|
||||
|
@ -789,7 +786,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint8_t bNPCPartSlot;
|
||||
uint8_t unk32;
|
||||
uint16_t unk33;
|
||||
uint32_t unk34;
|
||||
uint32_t unk34[2];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -930,13 +927,13 @@ namespace Sapphire::Network::Packets::Server
|
|||
//Current instance can be confirmed at any time using the /instance text command." ( 7B F8 69 )
|
||||
|
||||
uint8_t unknown5;
|
||||
uint32_t unknown7;
|
||||
uint32_t unknown8;
|
||||
uint16_t festivalId;
|
||||
uint16_t additionalFestivalId;
|
||||
uint32_t unknown9;
|
||||
uint32_t unknown10;
|
||||
uint32_t unknown11;
|
||||
uint32_t unknown12[4];
|
||||
uint32_t festivalId;
|
||||
uint32_t unknown12[3];
|
||||
uint32_t additionalFestivalId;
|
||||
uint32_t unknown13[3];
|
||||
Common::FFXIVARR_POSITION3 pos;
|
||||
uint32_t unknown14[3];
|
||||
|
@ -1041,13 +1038,12 @@ namespace Sapphire::Network::Packets::Server
|
|||
unsigned char mountGuideMask[22];
|
||||
unsigned char u19_2;
|
||||
*/
|
||||
unsigned char unknown5_3a[176];
|
||||
unsigned char unknown5_55a[178];
|
||||
unsigned char companionName[21];
|
||||
unsigned char companionDefRank;
|
||||
unsigned char companionAttRank;
|
||||
unsigned char companionHealRank;
|
||||
unsigned char mountGuideMask[23];
|
||||
unsigned char maybeReservedMountSlots;
|
||||
unsigned char mountGuideMask[29];
|
||||
//==
|
||||
char name[32];
|
||||
unsigned char unknownOword[16];
|
||||
|
@ -1056,10 +1052,10 @@ namespace Sapphire::Network::Packets::Server
|
|||
unsigned char aetheryte[21];
|
||||
unsigned char discovery[445];
|
||||
unsigned char howto[34];
|
||||
unsigned char minions[51];
|
||||
unsigned char minions[55];
|
||||
unsigned char chocoboTaxiMask[10];
|
||||
unsigned char watchedCutscenes[131];
|
||||
unsigned char companionBardingMask[10];
|
||||
unsigned char watchedCutscenes[137];
|
||||
unsigned char companionBardingMask[11];
|
||||
unsigned char companionEquippedHead;
|
||||
unsigned char companionEquippedBody;
|
||||
unsigned char companionEquippedLegs;
|
||||
|
@ -1074,7 +1070,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
unsigned char unknownPvp5AB[11];
|
||||
unsigned char unknown5B9[5];
|
||||
*/
|
||||
unsigned char unknown5_3c[234];
|
||||
unsigned char unknown5_45b[236];
|
||||
//==
|
||||
unsigned char pose;
|
||||
/*
|
||||
|
@ -1092,28 +1088,32 @@ namespace Sapphire::Network::Packets::Server
|
|||
unsigned char aetherCurrentMask[22];
|
||||
unsigned char u10[3];
|
||||
*/
|
||||
unsigned char unknown5_3d[292];
|
||||
unsigned char unknown5_55b[295];
|
||||
//==
|
||||
unsigned char orchestrionMask[40];
|
||||
unsigned char orchestrionMask[40]; // this field may already be extended, if it is, the beginning bytes are at the end of unknown5_55b
|
||||
unsigned char hallOfNoviceCompletion[3];
|
||||
unsigned char animaCompletion[11];
|
||||
unsigned char unknown5_3e[33];
|
||||
unsigned char unknown5_55c[35];
|
||||
unsigned char unlockedRaids[28];
|
||||
unsigned char unlockedDungeons[18];
|
||||
unsigned char unlockedGuildhests[10];
|
||||
unsigned char unlockedTrials[9]; // 5.35 trial:pvp either 9:5 or 8:6 not confirmed
|
||||
unsigned char unlockedPvp[5];
|
||||
/*
|
||||
at least 8 bytes at most 10 bytes in unlockedTrials not confirmed, adjust unlockedPvp so they share a total of 15 bytes and sync with clearedTrials/clearedPvp.
|
||||
*/
|
||||
unsigned char unlockedTrials[9];
|
||||
unsigned char unlockedPvp[6];
|
||||
//==
|
||||
unsigned char clearedRaids[28];
|
||||
unsigned char clearedDungeons[18];
|
||||
unsigned char clearedGuildhests[10];
|
||||
unsigned char clearedTrials[9];
|
||||
unsigned char clearedPvp[5];
|
||||
unsigned char clearedPvp[6];
|
||||
/*
|
||||
unsigned short fishingRecordsFishWeight[26];
|
||||
unsigned int exploratoryMissionNextTimestamp;
|
||||
unsigned char pvpLevel;
|
||||
*/
|
||||
unsigned char padding2[8];
|
||||
unsigned char unknown5_55d[9];
|
||||
//==
|
||||
};
|
||||
|
||||
|
@ -1439,6 +1439,20 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint8_t unknown[8];
|
||||
};
|
||||
|
||||
struct FFXIVIpcEventPlay16 : FFXIVIpcBasePacket< EventPlay16 >
|
||||
{
|
||||
uint64_t actorId;
|
||||
uint32_t eventId;
|
||||
uint16_t scene;
|
||||
uint16_t padding;
|
||||
uint32_t flags;
|
||||
uint32_t param3;
|
||||
uint8_t paramSize;
|
||||
uint8_t padding1[3];
|
||||
uint32_t param[16];
|
||||
uint32_t padding2;
|
||||
};
|
||||
|
||||
template< int ArgCount >
|
||||
struct FFXIVIpcEventPlayN
|
||||
{
|
||||
|
@ -1835,7 +1849,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint32_t bNPCName;
|
||||
uint32_t textId;
|
||||
uint32_t popupTimeMs;
|
||||
uint32_t pad3[4];
|
||||
uint32_t param[6];
|
||||
};
|
||||
|
||||
|
||||
|
@ -1847,7 +1861,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
|
||||
struct FFXIVIpcPerformNote : FFXIVIpcBasePacket< PerformNote >
|
||||
{
|
||||
uint8_t data[32];
|
||||
uint8_t data[16];
|
||||
};
|
||||
|
||||
struct FFXIVIpcHousingUpdateLandFlagsSlot : FFXIVIpcBasePacket< HousingUpdateLandFlagsSlot >
|
||||
|
@ -2238,6 +2252,97 @@ namespace Sapphire::Network::Packets::Server
|
|||
char memberName[32];
|
||||
uint8_t padding[3];
|
||||
};
|
||||
|
||||
struct FFXIVIpcEventContinue : FFXIVIpcBasePacket< EventContinue >
|
||||
{
|
||||
uint32_t eventId;
|
||||
uint16_t scene;
|
||||
uint16_t unknown;
|
||||
uint64_t unknown2;
|
||||
};
|
||||
|
||||
struct FFXIVDirectorUnk4 : FFXIVIpcBasePacket< SomeDirectorUnk4 >
|
||||
{
|
||||
uint32_t param[4];
|
||||
uint64_t unknown;
|
||||
};
|
||||
|
||||
struct FFXIVCeremonySetActorAppearance : FFXIVIpcBasePacket< CeremonySetActorAppearance >
|
||||
{
|
||||
uint8_t u1;
|
||||
uint8_t questBL;
|
||||
uint16_t padding1;
|
||||
uint32_t u3;
|
||||
struct
|
||||
{
|
||||
uint64_t mainWeaponModel;
|
||||
uint64_t secWeaponModel;
|
||||
uint64_t craftToolModel;
|
||||
uint32_t c_u6;
|
||||
uint32_t c_u7;
|
||||
uint32_t charId;
|
||||
uint16_t u4;
|
||||
uint16_t guardianDeity;
|
||||
uint32_t u5;
|
||||
uint32_t models[10];
|
||||
uint8_t look[26];
|
||||
uint16_t padding3;
|
||||
} actors[2];
|
||||
};
|
||||
|
||||
//For quests this is only used for pre-accepted ones. Accepted quests are getting handled by the client.
|
||||
template< int ArgCount >
|
||||
struct FFXIVIpcMapUpdateN
|
||||
{
|
||||
uint8_t entryCount;
|
||||
uint8_t padding[ 3 ];
|
||||
uint32_t iconIds[ ArgCount ];
|
||||
uint32_t levelIds[ ArgCount ];
|
||||
uint32_t eventIds[ ArgCount ]; // possible event ids for this: Quest, GuildLeveAssignment, GuildOrderGuide, TripleTriad, CustomTalk, PreHandler
|
||||
uint8_t additionalData[ ArgCount ]; // use unknown
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate :
|
||||
FFXIVIpcBasePacket< MapUpdate >,
|
||||
FFXIVIpcMapUpdateN< 2 >
|
||||
{
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate4 :
|
||||
FFXIVIpcBasePacket< MapUpdate4 >,
|
||||
FFXIVIpcMapUpdateN< 4 >
|
||||
{
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate8 :
|
||||
FFXIVIpcBasePacket< MapUpdate8 >,
|
||||
FFXIVIpcMapUpdateN< 8 >
|
||||
{
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate16 :
|
||||
FFXIVIpcBasePacket< MapUpdate16 >,
|
||||
FFXIVIpcMapUpdateN< 16 >
|
||||
{
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate32 :
|
||||
FFXIVIpcBasePacket< MapUpdate32 >,
|
||||
FFXIVIpcMapUpdateN< 32 >
|
||||
{
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate64 :
|
||||
FFXIVIpcBasePacket< MapUpdate64 >,
|
||||
FFXIVIpcMapUpdateN< 64 >
|
||||
{
|
||||
};
|
||||
|
||||
struct FFXIVIpcMapUpdate128 :
|
||||
FFXIVIpcBasePacket< MapUpdate128 >,
|
||||
FFXIVIpcMapUpdateN< 128 >
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/
|
||||
|
|
|
@ -129,7 +129,7 @@ uint32_t Util::getTimeSeconds()
|
|||
|
||||
uint64_t Util::getEorzeanTimeStamp()
|
||||
{
|
||||
return static_cast< uint64_t >( getTimeSeconds() * 20.571428571428573f );
|
||||
return static_cast< uint64_t >( getTimeSeconds() * 20.571428571428573 );
|
||||
}
|
||||
|
||||
void Util::valueToFlagByteIndexValue( uint32_t inVal, uint8_t& outVal, uint16_t& outIndex )
|
||||
|
|
|
@ -76,4 +76,9 @@ uint16_t Util::floatToUInt16Rot( float val )
|
|||
uint8_t Util::floatToUInt8Rot( float val )
|
||||
{
|
||||
return static_cast< uint8_t >( 0x80 * ( ( val + PI ) ) / PI );
|
||||
}
|
||||
|
||||
float Util::floatFromUInt16Rot( uint16_t rot )
|
||||
{
|
||||
return rot / 32768.0f * PI - PI;
|
||||
}
|
|
@ -25,6 +25,8 @@ namespace Sapphire::Common::Util
|
|||
|
||||
uint16_t floatToUInt16Rot( float val );
|
||||
|
||||
float floatFromUInt16Rot( uint16_t rot );
|
||||
|
||||
uint8_t floatToUInt8Rot( float val );
|
||||
|
||||
template < typename T >
|
||||
|
|
|
@ -452,8 +452,8 @@ void Lobby::GameConnection::generateEncryptionKey( uint32_t key, const std::stri
|
|||
m_baseKey[ 2 ] = 0x34;
|
||||
m_baseKey[ 3 ] = 0x12;
|
||||
memcpy( m_baseKey + 0x04, &key, 4 );
|
||||
m_baseKey[ 8 ] = 0x88;
|
||||
m_baseKey[ 9 ] = 0x13;
|
||||
m_baseKey[ 8 ] = 0x18;
|
||||
m_baseKey[ 9 ] = 0x15;
|
||||
memcpy( ( char* ) m_baseKey + 0x0C, keyPhrase.c_str(), keyPhrase.size() );
|
||||
Common::Util::md5( m_baseKey, m_encKey, 0x2C );
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
// todo: this is fucked
|
||||
};
|
||||
|
||||
player.playScene( getId(), 1, 0xFB2EC8F8, 0, 1, returnScene, callback );
|
||||
player.playScene( getId(), 1, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, 0, 1, returnScene, callback );
|
||||
}
|
||||
|
||||
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
player.setInstance( internalZone, pos );
|
||||
player.setInstance( internalZone, pos, player.getRot() );
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -132,7 +132,7 @@ private:
|
|||
{
|
||||
if( result.param2 == 1 )
|
||||
{
|
||||
if( player.giveQuestRewards( getId(), 0 ) )
|
||||
if( player.giveQuestRewards( getId(), result.param3 ) )
|
||||
{
|
||||
player.setQuestUI8BH( getId(), 0 );
|
||||
player.finishQuest( getId() );
|
||||
|
|
|
@ -162,12 +162,12 @@ std::string zoneNameToPath( const std::string& name )
|
|||
auto teriPath = std::get< std::string >(
|
||||
fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Path ) ) );
|
||||
ZoneInfo info;
|
||||
info.id = row.first;
|
||||
info.id = row.first.rowId;
|
||||
info.path = teriPath;
|
||||
info.name = teriName;
|
||||
info.mapId = std::get< uint16_t >(
|
||||
fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Map ) ) );
|
||||
zoneInfoMap[ row.first ] = info;
|
||||
zoneInfoMap[ row.first.rowId ] = info;
|
||||
|
||||
if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) )
|
||||
{
|
||||
|
@ -212,7 +212,7 @@ void loadEobjNames()
|
|||
static auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::en ) );
|
||||
for( auto& row : exd.get_rows() )
|
||||
{
|
||||
auto id = row.first;
|
||||
auto id = row.first.rowId;
|
||||
auto& fields = row.second;
|
||||
auto name = std::get< std::string >( fields.at( 0 ) );
|
||||
eobjNameMap[ id ] = name;
|
||||
|
|
|
@ -42,7 +42,7 @@ std::string generateEnum( const std::string& exd, int8_t nameIndex, const std::s
|
|||
for( auto row : rows )
|
||||
{
|
||||
auto& fields = row.second;
|
||||
uint32_t id = row.first;
|
||||
uint32_t id = row.first.rowId;
|
||||
|
||||
std::string value;
|
||||
try
|
||||
|
|
|
@ -23,7 +23,7 @@ void Sapphire::Data::ExdDataGenerated::loadIdList( xiv::exd::Exd& data, std::set
|
|||
|
||||
for( auto row : pDataRows )
|
||||
{
|
||||
uint32_t id = row.first;
|
||||
uint32_t id = row.first.rowId;
|
||||
outIdList.insert( id );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ std::string getEobjSgbPath( uint32_t eobjId )
|
|||
|
||||
for( auto& row : exportedSgExd.get_rows() )
|
||||
{
|
||||
auto id = row.first;
|
||||
auto id = row.first.rowId;
|
||||
auto& fields = row.second;
|
||||
|
||||
auto path = std::get< std::string >( fields.at( 0 ) );
|
||||
|
@ -100,7 +100,7 @@ std::string getEobjSgbPath( uint32_t eobjId )
|
|||
|
||||
for( auto& row : eObjExd.get_rows() )
|
||||
{
|
||||
auto id = row.first;
|
||||
auto id = row.first.rowId;
|
||||
auto& fields = row.second;
|
||||
|
||||
eobjSgbPaths[id] = std::get< uint16_t >( fields.at( 11 ) );
|
||||
|
@ -127,9 +127,9 @@ std::string zoneNameToPath( const std::string& name )
|
|||
{
|
||||
path = teriPath;
|
||||
found = true;
|
||||
zoneId = row.first;
|
||||
zoneId = row.first.rowId;
|
||||
}
|
||||
zoneNameMap[ row.first ] = teriName;
|
||||
zoneNameMap[ row.first.rowId ] = teriName;
|
||||
}
|
||||
|
||||
if( found )
|
||||
|
|
|
@ -91,7 +91,7 @@ std::string getEobjSgbPath( uint32_t eobjId )
|
|||
|
||||
for( auto& row : exportedSgExd.get_rows() )
|
||||
{
|
||||
auto id = row.first;
|
||||
auto id = row.first.rowId;
|
||||
auto& fields = row.second;
|
||||
|
||||
auto path = std::get< std::string >( fields.at( 0 ) );
|
||||
|
@ -102,7 +102,7 @@ std::string getEobjSgbPath( uint32_t eobjId )
|
|||
|
||||
for( auto& row : eObjExd.get_rows() )
|
||||
{
|
||||
auto id = row.first;
|
||||
auto id = row.first.rowId;
|
||||
auto& fields = row.second;
|
||||
|
||||
eobjSgbPaths[id] = std::get< uint16_t >( fields.at( 11 ) );
|
||||
|
@ -129,9 +129,9 @@ std::string zoneNameToPath( const std::string& name )
|
|||
{
|
||||
path = teriPath;
|
||||
found = true;
|
||||
zoneId = row.first;
|
||||
zoneId = row.first.rowId;
|
||||
}
|
||||
zoneNameMap[ row.first ] = teriName;
|
||||
zoneNameMap[ row.first.rowId ] = teriName;
|
||||
}
|
||||
|
||||
if( found )
|
||||
|
|
|
@ -351,7 +351,7 @@ Sapphire::InstanceContentPtr Sapphire::Entity::Actor::getCurrentInstance() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*! \return QuestBattlePtr to the current instance, nullptr if not an instance or not set */
|
||||
/*! \return QuestBattlePtr to the current instance, nullptr if not a quest battle or not set */
|
||||
Sapphire::QuestBattlePtr Sapphire::Entity::Actor::getCurrentQuestBattle() const
|
||||
{
|
||||
if( m_pCurrentTerritory )
|
||||
|
@ -360,6 +360,15 @@ Sapphire::QuestBattlePtr Sapphire::Entity::Actor::getCurrentQuestBattle() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*! \return PublicContentPtr to the current instance, nullptr if not a public content or not set */
|
||||
Sapphire::PublicContentPtr Sapphire::Entity::Actor::getCurrentPublicContent() const
|
||||
{
|
||||
if( m_pCurrentTerritory )
|
||||
return m_pCurrentTerritory->getAsPublicContent();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Get the current cell of a region the actor is in
|
||||
|
||||
|
|
|
@ -130,6 +130,8 @@ namespace Sapphire::Entity
|
|||
|
||||
QuestBattlePtr getCurrentQuestBattle() const;
|
||||
|
||||
PublicContentPtr getCurrentPublicContent() const;
|
||||
|
||||
// get the current cell of a region the actor is in
|
||||
Cell* getCellPtr();
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Sapphire::Entity
|
|||
Common::FFXIVARR_POSITION3 pos, float rotation, const std::string& givenName = "none" );
|
||||
|
||||
using OnTalkEventHandler = std::function< void( Entity::Player&, Entity::EventObjectPtr,
|
||||
TerritoryPtr, uint64_t ) >;
|
||||
TerritoryPtr, uint32_t, uint64_t ) >;
|
||||
|
||||
uint32_t getGimmickId() const;
|
||||
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
#include "Manager/HousingMgr.h"
|
||||
#include "Manager/TerritoryMgr.h"
|
||||
#include "Manager/RNGMgr.h"
|
||||
#include "Manager/MapMgr.h"
|
||||
|
||||
#include "Territory/Territory.h"
|
||||
#include "Territory/ZonePosition.h"
|
||||
#include "Territory/InstanceContent.h"
|
||||
#include "Territory/QuestBattle.h"
|
||||
#include "Territory/PublicContent.h"
|
||||
#include "Territory/InstanceObjectCache.h"
|
||||
#include "Territory/Land.h"
|
||||
|
||||
|
@ -81,7 +84,8 @@ Sapphire::Entity::Player::Player() :
|
|||
m_directorInitialized( false ),
|
||||
m_onEnterEventDone( false ),
|
||||
m_falling( false ),
|
||||
m_pQueuedAction( nullptr )
|
||||
m_pQueuedAction( nullptr ),
|
||||
m_cfNotifiedContent( 0 )
|
||||
{
|
||||
m_id = 0;
|
||||
m_currentStance = Stance::Passive;
|
||||
|
@ -239,13 +243,16 @@ uint64_t Sapphire::Entity::Player::getOnlineStatusMask() const
|
|||
return m_onlineStatus;
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime, uint16_t animation )
|
||||
void Sapphire::Entity::Player::prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime, uint16_t animation, uint8_t param4, uint8_t param7, uint8_t unknown )
|
||||
{
|
||||
auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( getId() );
|
||||
preparePacket->data().targetZone = targetZone;
|
||||
preparePacket->data().fadeOutTime = fadeOutTime;
|
||||
preparePacket->data().animation = animation;
|
||||
preparePacket->data().fadeOut = static_cast< uint8_t >( fadeOut ? 1 : 0 );
|
||||
preparePacket->data().param4 = param4;
|
||||
preparePacket->data().param7 = param7;
|
||||
preparePacket->data().unknown = unknown;
|
||||
queuePacket( preparePacket );
|
||||
}
|
||||
|
||||
|
@ -468,7 +475,7 @@ bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance )
|
|||
return teriMgr.movePlayer( instance, getAsPlayer() );
|
||||
}
|
||||
|
||||
bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance, Common::FFXIVARR_POSITION3 pos )
|
||||
bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance, Common::FFXIVARR_POSITION3 pos, float rot )
|
||||
{
|
||||
m_onEnterEventDone = false;
|
||||
if( !instance )
|
||||
|
@ -486,11 +493,17 @@ bool Sapphire::Entity::Player::setInstance( TerritoryPtr instance, Common::FFXIV
|
|||
m_prevTerritoryId = getTerritoryId();
|
||||
}
|
||||
|
||||
m_pos = pos;
|
||||
m_rot = rot;
|
||||
if( teriMgr.movePlayer( instance, getAsPlayer() ) )
|
||||
{
|
||||
m_pos = pos;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pos = m_prevPos;
|
||||
m_rot= m_prevRot;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -499,8 +512,18 @@ bool Sapphire::Entity::Player::exitInstance()
|
|||
{
|
||||
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
||||
|
||||
auto pZone = getCurrentTerritory();
|
||||
auto pInstance = pZone->getAsInstanceContent();
|
||||
auto d = getCurrentTerritory()->getAsDirector();
|
||||
if( d && d->getContentFinderConditionId() > 0 )
|
||||
{
|
||||
auto p = makeZonePacket< FFXIVDirectorUnk4 >( getId() );
|
||||
p->data().param[0] = d->getDirectorId();
|
||||
p->data().param[1] = 1534;
|
||||
p->data().param[2] = 1;
|
||||
p->data().param[3] = d->getContentFinderConditionId();
|
||||
queuePacket( p );
|
||||
|
||||
prepareZoning( 0, 1, 1, 0, 0, 1, 9 );
|
||||
}
|
||||
|
||||
resetHp();
|
||||
resetMp();
|
||||
|
@ -708,7 +731,7 @@ void Sapphire::Entity::Player::learnSong( uint8_t songId, uint32_t itemId )
|
|||
queuePacket( makeActorControlSelf( getId(), ToggleOrchestrionUnlock, songId, 1, itemId ) );
|
||||
}
|
||||
|
||||
bool Sapphire::Entity::Player::isActionLearned( uint8_t actionId ) const
|
||||
bool Sapphire::Entity::Player::isActionLearned( uint32_t actionId ) const
|
||||
{
|
||||
uint16_t index;
|
||||
uint8_t value;
|
||||
|
@ -1264,6 +1287,17 @@ const uint8_t* Sapphire::Entity::Player::getMountGuideBitmask() const
|
|||
return m_mountGuide;
|
||||
}
|
||||
|
||||
const bool Sapphire::Entity::Player::hasMount( uint32_t mountId ) const
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto mount = exdData.get< Data::Mount >( mountId );
|
||||
|
||||
if( mount->order == -1 || mount->modelChara == 0 )
|
||||
return false;
|
||||
|
||||
return m_mountGuide[ mount->order / 8 ] & ( 1 << ( mount->order % 8 ) );
|
||||
}
|
||||
|
||||
uint64_t Sapphire::Entity::Player::getContentId() const
|
||||
{
|
||||
return m_contentId;
|
||||
|
@ -1591,7 +1625,7 @@ uint16_t Sapphire::Entity::Player::getCurrentCompanion() const
|
|||
return m_companionId;
|
||||
}
|
||||
|
||||
uint8_t Sapphire::Entity::Player::getCurrentMount() const
|
||||
uint16_t Sapphire::Entity::Player::getCurrentMount() const
|
||||
{
|
||||
return m_mount;
|
||||
}
|
||||
|
@ -1751,14 +1785,14 @@ void Sapphire::Entity::Player::sendZonePackets()
|
|||
//setStateFlag( PlayerStateFlag::BetweenAreas );
|
||||
//setStateFlag( PlayerStateFlag::BetweenAreas1 );
|
||||
|
||||
if( isActionLearned( static_cast< uint8_t >( Common::UnlockEntry::HuntingLog ) ) )
|
||||
sendHuntingLog();
|
||||
|
||||
sendStats();
|
||||
|
||||
// only initialize the UI if the player in fact just logged in.
|
||||
if( isLogin() )
|
||||
{
|
||||
if( isActionLearned( static_cast< uint8_t >( Common::UnlockEntry::HuntingLog ) ) )
|
||||
sendHuntingLog();
|
||||
|
||||
auto contentFinderList = makeZonePacket< FFXIVIpcCFAvailableContents >( getId() );
|
||||
|
||||
for( auto i = 0; i < sizeof( contentFinderList->data().contents ); i++ )
|
||||
|
@ -1808,6 +1842,12 @@ void Sapphire::Entity::Player::sendZonePackets()
|
|||
initZonePacket->data().pos.x = getPos().x;
|
||||
initZonePacket->data().pos.y = getPos().y;
|
||||
initZonePacket->data().pos.z = getPos().z;
|
||||
if( auto d = getCurrentTerritory()->getAsDirector() )
|
||||
{
|
||||
initZonePacket->data().contentfinderConditionId = d->getContentFinderConditionId();
|
||||
initZonePacket->data().bitmask = 0xFF;
|
||||
initZonePacket->data().bitmask1 = 0x2A;
|
||||
}
|
||||
queuePacket( initZonePacket );
|
||||
|
||||
getCurrentTerritory()->onPlayerZoneIn( *this );
|
||||
|
@ -1862,6 +1902,8 @@ Sapphire::Entity::Player::sendZoneInPackets( uint32_t param1, uint32_t param2 =
|
|||
|
||||
setZoningType( Common::ZoneingType::None );
|
||||
unsetStateFlag( PlayerStateFlag::BetweenAreas );
|
||||
|
||||
Common::Service< MapMgr >::ref().updateAll( *this );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::finishZoning()
|
||||
|
|
|
@ -111,6 +111,8 @@ namespace Sapphire::Entity
|
|||
void playSceneChain( uint32_t eventId, uint32_t scene, uint32_t flags,
|
||||
Event::EventHandler::SceneChainCallback sceneChainCallback );
|
||||
|
||||
void playScene16( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t param3, std::vector< uint32_t > paramList, Event::EventHandler::SceneReturnCallback eventReturnCallback );
|
||||
|
||||
/*! setup the event and return a ptr to it */
|
||||
Event::EventHandlerPtr bootstrapSceneEvent( uint32_t eventId, uint32_t flags );
|
||||
|
||||
|
@ -192,6 +194,8 @@ namespace Sapphire::Entity
|
|||
/*! remove a given quest */
|
||||
void removeQuest( uint16_t questId );
|
||||
|
||||
bool isQuestCompleted( uint16_t questId );
|
||||
|
||||
/*! add a quest to the completed quests mask */
|
||||
void updateQuestsCompleted( uint32_t questId );
|
||||
|
||||
|
@ -490,7 +494,7 @@ namespace Sapphire::Entity
|
|||
bool setInstance( TerritoryPtr instance );
|
||||
|
||||
/*! sets the players instance & initiates zoning process */
|
||||
bool setInstance( Sapphire::TerritoryPtr instance, Sapphire::Common::FFXIVARR_POSITION3 pos );
|
||||
bool setInstance( Sapphire::TerritoryPtr instance, Sapphire::Common::FFXIVARR_POSITION3 pos, float rot );
|
||||
|
||||
/*! returns the player to their position before zoning into an instance */
|
||||
bool exitInstance();
|
||||
|
@ -547,7 +551,7 @@ namespace Sapphire::Entity
|
|||
void dyeItemFromDyeingInfo();
|
||||
|
||||
/*! prepares zoning / fades out the screen */
|
||||
void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime = 0, uint16_t animation = 0 );
|
||||
void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime = 0, uint16_t animation = 0, uint8_t param4 = 0, uint8_t param7 = 0, uint8_t unknown = 0 );
|
||||
|
||||
/*! get player's title list (available titles) */
|
||||
uint8_t* getTitleList();
|
||||
|
@ -584,7 +588,7 @@ namespace Sapphire::Entity
|
|||
uint16_t getCurrentCompanion() const;
|
||||
|
||||
/*! get the current mount */
|
||||
uint8_t getCurrentMount() const;
|
||||
uint16_t getCurrentMount() const;
|
||||
|
||||
/*! set current persistent emote */
|
||||
void setPersistentEmote( uint32_t emoteId );
|
||||
|
@ -642,7 +646,7 @@ namespace Sapphire::Entity
|
|||
void learnSong( uint8_t songId, uint32_t itemId );
|
||||
|
||||
/*! check if an action is already unlocked in the bitmask. */
|
||||
bool isActionLearned( uint8_t actionId ) const;
|
||||
bool isActionLearned( uint32_t actionId ) const;
|
||||
|
||||
/*! return a const pointer to the unlock bitmask array */
|
||||
const uint8_t* getUnlockBitmask() const;
|
||||
|
@ -653,6 +657,8 @@ namespace Sapphire::Entity
|
|||
/*! return a const pointer to the mount guide bitmask array */
|
||||
const uint8_t* getMountGuideBitmask() const;
|
||||
|
||||
const bool hasMount( uint32_t mountId ) const;
|
||||
|
||||
bool checkAction() override;
|
||||
|
||||
bool hasQueuedAction() const;
|
||||
|
@ -942,12 +948,13 @@ namespace Sapphire::Entity
|
|||
|
||||
ItemPtr getItemAt( uint16_t containerId, uint8_t slotId );
|
||||
|
||||
bool updateContainer( uint16_t storageId, uint8_t slotId, ItemPtr pItem );
|
||||
bool updateContainer( uint16_t storageId, uint8_t slotId, ItemPtr pItem, bool writeToDb = true );
|
||||
|
||||
/*! calculate and return player ilvl based off equipped gear */
|
||||
uint16_t calculateEquippedGearItemLevel();
|
||||
|
||||
ItemPtr getEquippedWeapon();
|
||||
ItemPtr getEquippedSecondaryWeapon();
|
||||
|
||||
/*! return the current amount of currency of type */
|
||||
uint32_t getCurrency( Common::CurrencyType type );
|
||||
|
@ -992,6 +999,8 @@ namespace Sapphire::Entity
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setPosAndNotifyClient( float x, float y, float z, float rot );
|
||||
|
||||
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );
|
||||
|
||||
void sendHuntingLog();
|
||||
|
@ -1005,6 +1014,7 @@ namespace Sapphire::Entity
|
|||
uint64_t m_lastMoveTime;
|
||||
uint8_t m_lastMoveflag;
|
||||
bool m_falling;
|
||||
uint16_t m_cfNotifiedContent;
|
||||
|
||||
std::vector< ShopBuyBackEntry >& getBuyBackListForShop( uint32_t shopId );
|
||||
void addBuyBackItemForShop( uint32_t shopId, const ShopBuyBackEntry& entry );
|
||||
|
@ -1067,8 +1077,8 @@ namespace Sapphire::Entity
|
|||
uint16_t m_activeTitle;
|
||||
uint8_t m_titleList[48];
|
||||
uint8_t m_howTo[34];
|
||||
uint8_t m_minions[40];
|
||||
uint8_t m_mountGuide[22];
|
||||
uint8_t m_minions[55];
|
||||
uint8_t m_mountGuide[29];
|
||||
uint8_t m_homePoint;
|
||||
uint8_t m_startTown;
|
||||
uint16_t m_townWarpFstFlags;
|
||||
|
@ -1076,8 +1086,8 @@ namespace Sapphire::Entity
|
|||
uint8_t m_discovery[445];
|
||||
uint32_t m_playTime;
|
||||
|
||||
uint16_t m_classArray[28];
|
||||
uint32_t m_expArray[28];
|
||||
uint16_t m_classArray[ Common::CLASSJOB_SLOTS ];
|
||||
uint32_t m_expArray[ Common::CLASSJOB_SLOTS ];
|
||||
uint8_t m_aetheryte[21];
|
||||
uint8_t m_unlocks[64];
|
||||
uint8_t m_orchestrion[40];
|
||||
|
|
|
@ -323,6 +323,33 @@ void Sapphire::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlaye
|
|||
unsetStateFlag( PlayerStateFlag::InNpcEvent );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::playScene16( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t param3, std::vector< uint32_t > paramList, Event::EventHandler::SceneReturnCallback eventReturnCallback )
|
||||
{
|
||||
auto pEvent = bootstrapSceneEvent( eventId, flags );
|
||||
if( !pEvent )
|
||||
return;
|
||||
|
||||
pEvent->setPlayedScene( true );
|
||||
pEvent->setEventReturnCallback( eventReturnCallback );
|
||||
pEvent->setSceneChainCallback( nullptr );
|
||||
auto eventPlay16 = makeZonePacket< FFXIVIpcEventPlay16 >( getId() );
|
||||
eventPlay16->data().actorId = pEvent->getActorId();
|
||||
eventPlay16->data().eventId = pEvent->getId();
|
||||
eventPlay16->data().scene = scene;
|
||||
eventPlay16->data().flags = flags;
|
||||
eventPlay16->data().param3 = param3;
|
||||
eventPlay16->data().paramSize = paramList.size();
|
||||
int i = 0;
|
||||
for( auto p : paramList )
|
||||
{
|
||||
assert( i < 16 );
|
||||
eventPlay16->data().param[ i ] = paramList.at( i );
|
||||
i++;
|
||||
}
|
||||
|
||||
queuePacket( eventPlay16 );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::eventActionStart( uint32_t eventId,
|
||||
uint32_t action,
|
||||
World::Action::ActionCallback finishCallback,
|
||||
|
|
|
@ -580,9 +580,9 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool sil
|
|||
bool foundFreeSlot = false;
|
||||
|
||||
std::vector< uint16_t > bags = { Bag0, Bag1, Bag2, Bag3 };
|
||||
|
||||
sendDebug( "adding item: {}, equipSlotCategory: {}, stackSize: {}", itemToAdd->getId(), itemInfo->equipSlotCategory, itemInfo->stackSize );
|
||||
// add the related armoury bag to the applicable bags and try and fill a free slot there before falling back to regular inventory
|
||||
if( itemInfo->isEquippable && getEquipDisplayFlags() & StoreNewItemsInArmouryChest )
|
||||
if( itemInfo->equipSlotCategory > 0 && getEquipDisplayFlags() & StoreNewItemsInArmouryChest )
|
||||
{
|
||||
auto bag = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( static_cast< Common::EquipSlotCategory >( itemInfo->equipSlotCategory ) );
|
||||
|
||||
|
@ -601,7 +601,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool sil
|
|||
auto item = storage->getItem( slot );
|
||||
|
||||
// add any items that are stackable
|
||||
if( canMerge && item && !itemInfo->isEquippable && item->getId() == itemToAdd->getId() )
|
||||
if( canMerge && item && item->getMaxStackSize() > 1 && item->getId() == itemToAdd->getId() )
|
||||
{
|
||||
uint32_t count = item->getStackSize();
|
||||
uint32_t maxStack = item->getMaxStackSize();
|
||||
|
@ -739,7 +739,7 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId
|
|||
sendStatusEffectUpdate(); // send if any equip is changed
|
||||
}
|
||||
|
||||
bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint8_t slotId, ItemPtr pItem )
|
||||
bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint8_t slotId, ItemPtr pItem, bool writeToDb )
|
||||
{
|
||||
auto containerType = World::Manager::ItemMgr::getContainerType( storageId );
|
||||
|
||||
|
@ -752,7 +752,8 @@ bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint8_t slot
|
|||
case Bag:
|
||||
case CurrencyCrystal:
|
||||
{
|
||||
writeInventory( static_cast< InventoryType >( storageId ) );
|
||||
if( writeToDb )
|
||||
writeInventory( static_cast< InventoryType >( storageId ) );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -767,7 +768,8 @@ bool Sapphire::Entity::Player::updateContainer( uint16_t storageId, uint8_t slot
|
|||
else
|
||||
unequipItem( static_cast< GearSetSlot >( slotId ), pItem, true );
|
||||
|
||||
writeInventory( static_cast< InventoryType >( storageId ) );
|
||||
if( writeToDb )
|
||||
writeInventory( static_cast< InventoryType >( storageId ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -804,7 +806,7 @@ void Sapphire::Entity::Player::splitItem( uint16_t fromInventoryId, uint8_t from
|
|||
|
||||
fromItem->setStackSize( fromItem->getStackSize() - itemCount );
|
||||
|
||||
updateContainer( fromInventoryId, fromSlotId, fromItem );
|
||||
updateContainer( fromInventoryId, fromSlotId, fromItem, fromInventoryId != toInventoryId );
|
||||
updateContainer( toInventoryId, toSlot, newItem );
|
||||
|
||||
updateItemDb( fromItem );
|
||||
|
@ -835,7 +837,7 @@ void Sapphire::Entity::Player::mergeItem( uint16_t fromInventoryId, uint8_t from
|
|||
{
|
||||
fromItem->setStackSize( stackOverflow );
|
||||
updateItemDb( fromItem );
|
||||
updateContainer( fromInventoryId, fromSlotId, fromItem );
|
||||
updateContainer( fromInventoryId, fromSlotId, fromItem, fromInventoryId != toInventoryId );
|
||||
}
|
||||
|
||||
|
||||
|
@ -862,14 +864,16 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS
|
|||
&& !World::Manager::ItemMgr::isArmory( fromInventoryId ) )
|
||||
{
|
||||
updateContainer( fromInventoryId, fromSlotId, nullptr );
|
||||
fromInventoryId = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( static_cast< Common::EquipSlotCategory >( toSlot ) );
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto itemInfo = exdData.get< Sapphire::Data::Item >( toItem->getId() );
|
||||
fromInventoryId = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( static_cast< Common::EquipSlotCategory >( itemInfo->equipSlotCategory ) );
|
||||
fromSlotId = static_cast < uint8_t >( m_storageMap[ fromInventoryId ]->getFreeSlot() );
|
||||
}
|
||||
|
||||
auto containerTypeFrom = World::Manager::ItemMgr::getContainerType( fromInventoryId );
|
||||
auto containerTypeTo = World::Manager::ItemMgr::getContainerType( toInventoryId );
|
||||
|
||||
updateContainer( toInventoryId, toSlot, fromItem );
|
||||
updateContainer( toInventoryId, toSlot, fromItem, fromInventoryId != toInventoryId );
|
||||
updateContainer( fromInventoryId, fromSlotId, toItem );
|
||||
|
||||
if( static_cast< InventoryType >( toInventoryId ) == GearSet0 ||
|
||||
|
@ -939,6 +943,11 @@ Sapphire::ItemPtr Sapphire::Entity::Player::getEquippedWeapon()
|
|||
return m_storageMap[ GearSet0 ]->getItem( GearSetSlot::MainHand );
|
||||
}
|
||||
|
||||
Sapphire::ItemPtr Sapphire::Entity::Player::getEquippedSecondaryWeapon()
|
||||
{
|
||||
return m_storageMap[ InventoryType::GearSet0 ]->getItem( GearSetSlot::OffHand );
|
||||
}
|
||||
|
||||
uint8_t Sapphire::Entity::Player::getFreeSlotsInBags()
|
||||
{
|
||||
uint8_t slots = 0;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "Network/GameConnection.h"
|
||||
#include "Network/PacketWrappers/QuestMessagePacket.h"
|
||||
|
||||
#include "Manager/MapMgr.h"
|
||||
|
||||
#include "Session.h"
|
||||
|
||||
using namespace Sapphire::Common;
|
||||
|
@ -17,8 +19,6 @@ void Sapphire::Entity::Player::finishQuest( uint16_t questId )
|
|||
{
|
||||
int8_t idx = getQuestIndex( questId );
|
||||
|
||||
removeQuest( questId );
|
||||
|
||||
auto questFinishPacket = makeZonePacket< FFXIVIpcQuestFinish >( getId() );
|
||||
questFinishPacket->data().questId = questId;
|
||||
questFinishPacket->data().flag1 = 1;
|
||||
|
@ -26,6 +26,7 @@ void Sapphire::Entity::Player::finishQuest( uint16_t questId )
|
|||
queuePacket( questFinishPacket );
|
||||
|
||||
updateQuestsCompleted( questId );
|
||||
removeQuest( questId );
|
||||
|
||||
//sendQuestTracker(); already sent in removeQuest()
|
||||
}
|
||||
|
@ -33,7 +34,12 @@ void Sapphire::Entity::Player::finishQuest( uint16_t questId )
|
|||
void Sapphire::Entity::Player::unfinishQuest( uint16_t questId )
|
||||
{
|
||||
removeQuestsCompleted( questId );
|
||||
sendQuestInfo();
|
||||
|
||||
auto questFinishPacket = makeZonePacket< FFXIVIpcQuestFinish >( getId() );
|
||||
questFinishPacket->data().questId = questId;
|
||||
questFinishPacket->data().flag1 = 0;
|
||||
questFinishPacket->data().flag2 = 1;
|
||||
queuePacket( questFinishPacket );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::removeQuest( uint16_t questId )
|
||||
|
@ -42,6 +48,11 @@ void Sapphire::Entity::Player::removeQuest( uint16_t questId )
|
|||
|
||||
if( ( idx != -1 ) && ( m_activeQuests[ idx ] != nullptr ) )
|
||||
{
|
||||
std::shared_ptr< QuestActive > pQuest = m_activeQuests[ idx ];
|
||||
m_activeQuests[ idx ].reset();
|
||||
|
||||
Common::Service< World::Manager::MapMgr >::ref().updateQuests( *this );
|
||||
|
||||
auto questUpdatePacket = makeZonePacket< FFXIVIpcQuestUpdate >( getId() );
|
||||
questUpdatePacket->data().slot = static_cast< uint8_t >( idx );
|
||||
questUpdatePacket->data().questInfo.c.questId = 0;
|
||||
|
@ -54,9 +65,6 @@ void Sapphire::Entity::Player::removeQuest( uint16_t questId )
|
|||
m_questTracking[ ii ] = -1;
|
||||
}
|
||||
|
||||
std::shared_ptr< QuestActive > pQuest = m_activeQuests[ idx ];
|
||||
m_activeQuests[ idx ].reset();
|
||||
|
||||
m_questIdToQuestIdx.erase( questId );
|
||||
m_questIdxToQuestId.erase( idx );
|
||||
|
||||
|
@ -916,6 +924,8 @@ void Sapphire::Entity::Player::updateQuest( uint16_t questId, uint8_t sequence )
|
|||
m_questIdToQuestIdx[ questId ] = idx;
|
||||
m_questIdxToQuestId[ idx ] = questId;
|
||||
|
||||
Common::Service< World::Manager::MapMgr >::ref().updateQuests( *this );
|
||||
|
||||
auto questUpdatePacket = makeZonePacket< FFXIVIpcQuestUpdate >( getId() );
|
||||
questUpdatePacket->data().slot = idx;
|
||||
questUpdatePacket->data().questInfo = *pNewQuest;
|
||||
|
@ -1013,6 +1023,11 @@ Sapphire::Entity::Player::sendQuestMessage( uint32_t questId, int8_t msgId, uint
|
|||
}
|
||||
|
||||
|
||||
bool Sapphire::Entity::Player::isQuestCompleted( uint16_t questId )
|
||||
{
|
||||
return ( m_questCompleteFlags[ questId / 8 ] & ( 0x80 >> ( questId % 8 ) ) );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::updateQuestsCompleted( uint32_t questId )
|
||||
{
|
||||
uint16_t index = questId / 8;
|
||||
|
@ -1030,7 +1045,10 @@ void Sapphire::Entity::Player::removeQuestsCompleted( uint32_t questId )
|
|||
|
||||
uint8_t value = 0x80 >> bitIndex;
|
||||
|
||||
m_questCompleteFlags[ index ] ^= value;
|
||||
if( m_questCompleteFlags[ index ] & value )
|
||||
m_questCompleteFlags[ index ] ^= value;
|
||||
|
||||
Common::Service< World::Manager::MapMgr >::ref().updateQuests( *this );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -186,6 +186,9 @@ bool Sapphire::Entity::Player::load( uint32_t charId, World::SessionPtr pSession
|
|||
auto titleList = res->getBlobVector( "TitleList" );
|
||||
memcpy( reinterpret_cast< char* >( m_titleList ), titleList.data(), titleList.size() );
|
||||
|
||||
auto minions = res->getBlobVector( "Minions" );
|
||||
memcpy( reinterpret_cast< char* >( m_minions ), minions.data(), minions.size() );
|
||||
|
||||
auto mountGuide = res->getBlobVector( "Mounts" );
|
||||
memcpy( reinterpret_cast< char* >( m_mountGuide ), mountGuide.data(), mountGuide.size() );
|
||||
|
||||
|
|
|
@ -16,9 +16,10 @@ using namespace Sapphire::Network::Packets;
|
|||
using namespace Sapphire::Network::Packets::Server;
|
||||
using namespace Sapphire::Network::ActorControl;
|
||||
|
||||
Sapphire::Event::Director::Director( Sapphire::Event::Director::DirectorType type, uint16_t contentId ) :
|
||||
Sapphire::Event::Director::Director( Sapphire::Event::Director::DirectorType type, uint16_t contentId, uint16_t contentFinderConditionId ) :
|
||||
m_contentId( contentId ),
|
||||
m_type( type ),
|
||||
m_contentFinderConditionId( contentFinderConditionId ),
|
||||
m_directorId( ( static_cast< uint32_t >( type ) << 16 ) | contentId ),
|
||||
m_sequence( 1 ),
|
||||
m_branch( 0 ),
|
||||
|
@ -37,6 +38,11 @@ uint16_t Sapphire::Event::Director::getContentId() const
|
|||
return m_contentId;
|
||||
}
|
||||
|
||||
uint16_t Sapphire::Event::Director::getContentFinderConditionId() const
|
||||
{
|
||||
return m_contentFinderConditionId;
|
||||
}
|
||||
|
||||
uint8_t Sapphire::Event::Director::getSequence() const
|
||||
{
|
||||
return m_sequence;
|
||||
|
@ -52,14 +58,18 @@ void Sapphire::Event::Director::sendDirectorVars( Sapphire::Entity::Player& play
|
|||
auto varPacket = makeZonePacket< FFXIVIpcDirectorVars >( player.getId() );
|
||||
varPacket->data().m_directorId = getDirectorId();
|
||||
varPacket->data().m_sequence = getSequence();
|
||||
varPacket->data().m_branch = 0;
|
||||
varPacket->data().m_branch = getBranch();
|
||||
memcpy( varPacket->data().m_unionData, m_unionData.arrData, sizeof( varPacket->data().m_unionData ) );
|
||||
player.queuePacket( varPacket );
|
||||
player.sendDebug( "DirectorVar#{}: {:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X} seq{}, b{}", getDirectorId(),
|
||||
m_unionData.ui8.UI8A, m_unionData.ui8.UI8B, m_unionData.ui8.UI8C, m_unionData.ui8.UI8D, m_unionData.ui8.UI8E,
|
||||
m_unionData.ui8.UI8F, m_unionData.ui8.UI8G, m_unionData.ui8.UI8H, m_unionData.ui8.UI8I, m_unionData.ui8.UI8J,
|
||||
getSequence(), getBranch() );
|
||||
}
|
||||
|
||||
void Sapphire::Event::Director::sendDirectorInit( Sapphire::Entity::Player& player ) const
|
||||
{
|
||||
Logger::debug( "DirectorID#{}, QuestBattleID#{}", m_directorId, m_contentId );
|
||||
Logger::debug( "DirectorID#{}, ContentId#{}, ContentFinderConditionId#{}", m_directorId, m_contentId, m_contentFinderConditionId );
|
||||
player.queuePacket( makeActorControlSelf( player.getId(), DirectorInit, m_directorId, m_contentId ) );
|
||||
}
|
||||
|
||||
|
@ -183,12 +193,12 @@ void Sapphire::Event::Director::setDirectorSequence( uint8_t value )
|
|||
m_sequence = value;
|
||||
}
|
||||
|
||||
void Sapphire::Event::Director::setCustomVar( uint32_t varId, uint32_t value )
|
||||
void Sapphire::Event::Director::setCustomVar( uint32_t varId, uint64_t value )
|
||||
{
|
||||
m_customVarMap[ varId ] = value;
|
||||
}
|
||||
|
||||
uint32_t Sapphire::Event::Director::getCustomVar( uint32_t varId )
|
||||
uint64_t Sapphire::Event::Director::getCustomVar( uint32_t varId )
|
||||
{
|
||||
auto it = m_customVarMap.find( varId );
|
||||
if( it != m_customVarMap.end() )
|
||||
|
|
|
@ -42,12 +42,14 @@ namespace Sapphire::Event
|
|||
DutyFailed
|
||||
};
|
||||
|
||||
Director( DirectorType type, uint16_t contentId );
|
||||
Director( DirectorType type, uint16_t contentId, uint16_t contentFinderConditionId = 0 );
|
||||
|
||||
uint32_t getDirectorId() const;
|
||||
|
||||
uint16_t getContentId() const;
|
||||
|
||||
uint16_t getContentFinderConditionId() const;
|
||||
|
||||
DirectorType getType() const;
|
||||
|
||||
uint8_t getSequence() const;
|
||||
|
@ -104,8 +106,8 @@ namespace Sapphire::Event
|
|||
|
||||
void setDirectorBranch( uint8_t value );
|
||||
|
||||
void setCustomVar( uint32_t varId, uint32_t value );
|
||||
uint32_t getCustomVar( uint32_t varId );
|
||||
void setCustomVar( uint32_t varId, uint64_t value );
|
||||
uint64_t getCustomVar( uint32_t varId );
|
||||
|
||||
private:
|
||||
/*! Id of the content of the director */
|
||||
|
@ -114,6 +116,8 @@ namespace Sapphire::Event
|
|||
/*! DirectorType | ContentId */
|
||||
uint32_t m_directorId;
|
||||
|
||||
uint16_t m_contentFinderConditionId;
|
||||
|
||||
/*! currect sequence */
|
||||
uint8_t m_sequence;
|
||||
|
||||
|
@ -183,7 +187,7 @@ namespace Sapphire::Event
|
|||
|
||||
uint32_t m_elapsedTime;
|
||||
|
||||
std::unordered_map< uint32_t, uint32_t > m_customVarMap;
|
||||
std::unordered_map< uint32_t, uint64_t > m_customVarMap;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -78,10 +78,20 @@ namespace Sapphire::Event
|
|||
FcTalk = 0x001F,
|
||||
Adventure = 0x0021,
|
||||
DailyQuestSupply = 0x0022,
|
||||
TripleTriad = 0x0023,
|
||||
PreHandler = 0x0036,
|
||||
ICDirector = 0x8003,
|
||||
PublicContentDirector = 0x8004,
|
||||
QuestBattleDirector = 0x8006,
|
||||
};
|
||||
|
||||
enum class QuestAvailability : uint8_t
|
||||
{
|
||||
Invisible,
|
||||
Available,
|
||||
Locked
|
||||
};
|
||||
|
||||
using SceneReturnCallback = std::function< void( Entity::Player&, const SceneResult& ) >;
|
||||
using SceneChainCallback = std::function< void( Entity::Player& ) >;
|
||||
using EventFinishCallback = std::function< void( Entity::Player&, uint64_t ) >;
|
||||
|
|
|
@ -24,6 +24,7 @@ TYPE_FORWARD( HousingZone );
|
|||
TYPE_FORWARD( House );
|
||||
TYPE_FORWARD( InstanceContent );
|
||||
TYPE_FORWARD( QuestBattle );
|
||||
TYPE_FORWARD( PublicContent );
|
||||
TYPE_FORWARD( Item );
|
||||
TYPE_FORWARD( ItemContainer );
|
||||
TYPE_FORWARD( ZonePosition );
|
||||
|
|
|
@ -85,6 +85,9 @@ Sapphire::ItemPtr Sapphire::ItemContainer::getItem( uint8_t slotId )
|
|||
Logger::error( "Slot out of range {0}", slotId );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if( m_itemMap.find( slotId ) == m_itemMap.end() )
|
||||
return nullptr;
|
||||
|
||||
return m_itemMap[ slotId ];
|
||||
}
|
||||
|
@ -92,7 +95,10 @@ Sapphire::ItemPtr Sapphire::ItemContainer::getItem( uint8_t slotId )
|
|||
void Sapphire::ItemContainer::setItem( uint8_t slotId, ItemPtr pItem )
|
||||
{
|
||||
if( slotId > m_size )
|
||||
{
|
||||
Logger::error( "Slot out of range {0}", slotId );
|
||||
return;
|
||||
}
|
||||
|
||||
m_itemMap[ slotId ] = pItem;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Territory/HousingZone.h"
|
||||
#include "Territory/InstanceContent.h"
|
||||
#include "Territory/QuestBattle.h"
|
||||
#include "Territory/PublicContent.h"
|
||||
#include "Manager/TerritoryMgr.h"
|
||||
#include "Event/EventDefs.h"
|
||||
|
||||
|
@ -60,6 +61,8 @@ Sapphire::World::Manager::DebugCommandMgr::DebugCommandMgr()
|
|||
registerCommand( "script", &DebugCommandMgr::script, "Server script utilities.", 1 );
|
||||
registerCommand( "instance", &DebugCommandMgr::instance, "Instance utilities", 1 );
|
||||
registerCommand( "questbattle", &DebugCommandMgr::questBattle, "Quest battle utilities", 1 );
|
||||
registerCommand( "pc", &DebugCommandMgr::pc, "Public content utilities", 1 );
|
||||
registerCommand( "publiccontent", &DebugCommandMgr::pc, "Public content utilities", 1 );
|
||||
registerCommand( "qb", &DebugCommandMgr::questBattle, "Quest battle utilities", 1 );
|
||||
registerCommand( "housing", &DebugCommandMgr::housing, "Housing utilities", 1 );
|
||||
}
|
||||
|
@ -226,22 +229,14 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player&
|
|||
if( player.getLevelForClass( static_cast< Common::ClassJob > ( id ) ) == 0 )
|
||||
{
|
||||
player.setLevelForClass( 1, static_cast< Common::ClassJob > ( id ) );
|
||||
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
|
||||
player.sendModel();
|
||||
player.sendItemLevel();
|
||||
player.calculateStats();
|
||||
player.sendStats();
|
||||
player.sendStatusEffectUpdate();
|
||||
player.sendStatusUpdate();
|
||||
}
|
||||
else
|
||||
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
|
||||
player.sendModel();
|
||||
player.sendItemLevel();
|
||||
player.calculateStats();
|
||||
player.sendStats();
|
||||
player.sendStatusEffectUpdate();
|
||||
player.sendStatusUpdate();
|
||||
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
|
||||
player.sendModel();
|
||||
player.sendItemLevel();
|
||||
player.calculateStats();
|
||||
player.sendStats();
|
||||
player.sendStatusEffectUpdate();
|
||||
player.sendStatusUpdate();
|
||||
}
|
||||
else if( subCommand == "cfpenalty" )
|
||||
{
|
||||
|
@ -591,9 +586,23 @@ void Sapphire::World::Manager::DebugCommandMgr::get( char* data, Entity::Player&
|
|||
|
||||
int16_t map_id = exdData.get< Sapphire::Data::TerritoryType >( player.getCurrentTerritory()->getTerritoryTypeId() )->map;
|
||||
|
||||
player.sendNotice( "Pos:\n {0}\n {1}\n {2}\n {3}\n MapId: {4}\n ZoneId:{5}",
|
||||
player.sendNotice( "Pos: x: {0}, y: {1}, z: {2}, r: {3}\n MapId: {4}, ZoneId:{5}, Weather:{6}, Festival:{7}, {8}",
|
||||
player.getPos().x, player.getPos().y, player.getPos().z,
|
||||
player.getRot(), map_id, player.getCurrentTerritory()->getTerritoryTypeId() );
|
||||
player.getRot(), map_id, player.getCurrentTerritory()->getTerritoryTypeId(),
|
||||
static_cast< uint8_t >( player.getCurrentTerritory()->getCurrentWeather() ), player.getCurrentTerritory()->getCurrentFestival().first,
|
||||
player.getCurrentTerritory()->getCurrentFestival().second );
|
||||
if( auto instance = player.getCurrentInstance() )
|
||||
{
|
||||
player.sendNotice( "Instance info:\nContentId: {}, DirectorId: {}\nSequence: {}, Branch: {}, BGM: {}",
|
||||
instance->getInstanceContentId(), instance->getDirectorId(), instance->getSequence(),
|
||||
instance->getBranch(), instance->getCurrentBGM() );
|
||||
}
|
||||
else if( auto instance = player.getCurrentPublicContent() )
|
||||
{
|
||||
player.sendNotice( "Public content info:\nContentId: {}, DirectorId: {}\nSequence: {}, Branch: {}",
|
||||
instance->getContentId(), instance->getDirectorId(), instance->getSequence(),
|
||||
instance->getBranch() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1290,3 +1299,137 @@ void Sapphire::World::Manager::DebugCommandMgr::housing( char* data, Entity::Pla
|
|||
player.sendDebug( "Unknown sub command." );
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::DebugCommandMgr::pc( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command )
|
||||
{
|
||||
auto& terriMgr = Common::Service< TerritoryMgr >::ref();
|
||||
std::string cmd( data ), params, subCommand;
|
||||
auto cmdPos = cmd.find_first_of( ' ' );
|
||||
|
||||
if( cmdPos != std::string::npos )
|
||||
{
|
||||
params = cmd.substr( cmdPos + 1 );
|
||||
|
||||
auto p = params.find_first_of( ' ' );
|
||||
|
||||
if( p != std::string::npos )
|
||||
{
|
||||
subCommand = params.substr( 0, p );
|
||||
params = params.substr( subCommand.length() + 1 );
|
||||
}
|
||||
else
|
||||
subCommand = params;
|
||||
}
|
||||
|
||||
if( subCommand == "create" || subCommand == "cr" )
|
||||
{
|
||||
uint32_t contentFinderConditionId;
|
||||
sscanf( params.c_str(), "%d", &contentFinderConditionId );
|
||||
|
||||
auto instance = terriMgr.createPublicContent( contentFinderConditionId );
|
||||
if( instance )
|
||||
player.sendDebug( "Created instance with id#{0} -> {1}", instance->getGuId(), instance->getName() );
|
||||
else
|
||||
player.sendDebug( "Failed to create instance with id#{0}", contentFinderConditionId );
|
||||
}
|
||||
else if ( subCommand == "create2" || subCommand == "cr2" )
|
||||
{
|
||||
uint16_t contentId, terriId;
|
||||
sscanf( params.c_str(), "%hu %hu", &contentId, &terriId );
|
||||
|
||||
auto instance = terriMgr.createPublicContent( contentId, terriId );
|
||||
if( instance )
|
||||
player.sendDebug( "Created instance with id#{0} -> {1}", instance->getGuId(), instance->getName() );
|
||||
else
|
||||
player.sendDebug( "Failed to create instance with id#{0}, territory#{1}. Server console output may contain additional info.", contentId, terriId );
|
||||
}
|
||||
else if( subCommand == "remove" || subCommand == "rm" )
|
||||
{
|
||||
uint32_t terriId;
|
||||
sscanf( params.c_str(), "%d", &terriId );
|
||||
|
||||
if( terriMgr.removeTerritoryInstance( terriId ) )
|
||||
player.sendDebug( "Removed instance with id#{0}", terriId );
|
||||
else
|
||||
player.sendDebug( "Failed to remove instance with id#{0}", terriId );
|
||||
}
|
||||
else if( subCommand == "return" || subCommand == "ret" )
|
||||
{
|
||||
player.exitInstance();
|
||||
}
|
||||
else if( subCommand == "set" )
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t value;
|
||||
sscanf( params.c_str(), "%d %d", &index, &value );
|
||||
|
||||
|
||||
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
instance->setVar( static_cast< uint8_t >( index ), static_cast< uint8_t >( value ) );
|
||||
}
|
||||
else if( subCommand == "seq" )
|
||||
{
|
||||
uint8_t seq;
|
||||
|
||||
sscanf( params.c_str(), "%hhu", &seq );
|
||||
|
||||
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
instance->setSequence( seq );
|
||||
}
|
||||
else if( subCommand == "branch" )
|
||||
{
|
||||
uint8_t branch;
|
||||
|
||||
sscanf( params.c_str(), "%hhu", &branch );
|
||||
|
||||
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
instance->setBranch( branch );
|
||||
}
|
||||
else if( subCommand == "objstate" )
|
||||
{
|
||||
char objName[128];
|
||||
uint8_t state;
|
||||
|
||||
sscanf( params.c_str(), "%s %hhu", objName, &state );
|
||||
|
||||
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
auto obj = instance->getEObjByName( objName );
|
||||
if( !obj )
|
||||
return;
|
||||
|
||||
obj->setState( state );
|
||||
}
|
||||
else if( subCommand == "objflag" )
|
||||
{
|
||||
char objName[256];
|
||||
uint32_t state1;
|
||||
uint32_t state2;
|
||||
|
||||
sscanf( params.c_str(), "%s %i %i", objName, &state1, &state2 );
|
||||
|
||||
auto instance = std::dynamic_pointer_cast< PublicContent >( player.getCurrentTerritory() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
auto obj = instance->getEObjByName( objName );
|
||||
if( !obj )
|
||||
{
|
||||
player.sendDebug( "No eobj found." );
|
||||
return;
|
||||
}
|
||||
|
||||
obj->setAnimationFlag( state1, state2 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace Sapphire::World::Manager
|
|||
|
||||
void instance( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
|
||||
void questBattle( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
|
||||
void pc( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
|
||||
|
||||
void housing( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command) ;
|
||||
|
||||
|
|
|
@ -74,6 +74,13 @@ std::string Sapphire::World::Manager::EventMgr::getEventName( uint32_t eventId )
|
|||
name[ 0 ] = toupper( name[ 0 ] );
|
||||
return name;
|
||||
}
|
||||
case Event::EventHandler::EventHandlerType::PublicContentDirector:
|
||||
{
|
||||
auto pcInfo = exdData.get< Sapphire::Data::PublicContent >( eventId & 0x0000FFFF );
|
||||
if( !pcInfo )
|
||||
return "unknown";
|
||||
return pcInfo->name;
|
||||
}
|
||||
|
||||
|
||||
case Event::EventHandler::EventHandlerType::Warp:
|
||||
|
|
|
@ -662,6 +662,14 @@ void Sapphire::World::Manager::HousingMgr::createHouse( Sapphire::HousePtr house
|
|||
db.execute( stmt );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::HousingMgr::deleteHouse( Sapphire::HousePtr house ) const
|
||||
{
|
||||
auto& db = Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
|
||||
auto stmt = db.getPreparedStatement( Db::HOUSING_HOUSE_DEL );
|
||||
stmt->setUInt( 1, house->getId() );
|
||||
db.execute( stmt );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::HousingMgr::buildPresetEstate( Entity::Player& player, uint8_t plotNum, uint32_t presetCatalogId )
|
||||
{
|
||||
auto hZone = std::dynamic_pointer_cast< HousingZone >( player.getCurrentTerritory() );
|
||||
|
@ -903,6 +911,8 @@ void Sapphire::World::Manager::HousingMgr::updateHouseModels( Sapphire::HousePtr
|
|||
{
|
||||
assert( house );
|
||||
|
||||
house->clearModelCache();
|
||||
|
||||
auto& containers = getEstateInventory( house->getLandIdent() );
|
||||
|
||||
auto extContainer = containers.find( static_cast< uint16_t >( InventoryType::HousingExteriorAppearance ) );
|
||||
|
@ -1627,3 +1637,122 @@ Sapphire::Inventory::HousingItemPtr Sapphire::World::Manager::HousingMgr::getHou
|
|||
|
||||
return Inventory::make_HousingItem( tmpItem->getUId(), tmpItem->getId() );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::HousingMgr::editAppearance( bool isInterior, Sapphire::Entity::Player& player, const Common::LandIdent landIdent, std::vector< uint16_t > containerList, std::vector< uint8_t> slotList, uint8_t removeFlag )
|
||||
{
|
||||
auto landSetId = toLandSetId( static_cast< uint16_t >( landIdent.territoryTypeId ), static_cast< uint8_t >( landIdent.wardNum ) );
|
||||
auto terri = getHousingZoneByLandSetId( landSetId );
|
||||
|
||||
auto land = terri->getLand( static_cast< uint8_t >( landIdent.landId ) );
|
||||
if( !land )
|
||||
return;
|
||||
|
||||
if( !hasPermission( player, *land, 0 ) )
|
||||
return;
|
||||
|
||||
auto& housingContainer = getEstateInventory( landIdent )[ isInterior ? InventoryType::HousingInteriorAppearance : InventoryType::HousingExteriorAppearance ];
|
||||
|
||||
auto& invMgr = Service< InventoryMgr >::ref();
|
||||
|
||||
for( int i = 0; i < ( isInterior ? 10 : 9 ); i++ )
|
||||
{
|
||||
auto container = containerList.at( i );
|
||||
auto slot = slotList.at( i );
|
||||
if( container == 0x270F || slot == 0xFF )
|
||||
{
|
||||
if( i >= 5 )
|
||||
{
|
||||
auto removed = ( ( removeFlag >> ( i - 5 ) ) & 1 ) > 0;
|
||||
if( removed )
|
||||
{
|
||||
auto oldItem = housingContainer->getItem( i );
|
||||
if( oldItem )
|
||||
{
|
||||
housingContainer->removeItem( i );
|
||||
invMgr.removeItemFromHousingContainer( landIdent, housingContainer->getId(), i );
|
||||
player.addItem( oldItem, false, false, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
auto item = getHousingItemFromPlayer( player, static_cast< Sapphire::Common::InventoryType >( container ), slot );
|
||||
if( item )
|
||||
{
|
||||
auto oldItem = housingContainer->getItem( i );
|
||||
housingContainer->setItem( i, item );
|
||||
if( oldItem )
|
||||
{
|
||||
player.insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( container ), slot, oldItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
invMgr.sendInventoryContainer( player, housingContainer );
|
||||
invMgr.saveHousingContainer( landIdent, housingContainer );
|
||||
updateHouseModels( land->getHouse() );
|
||||
if( !isInterior )
|
||||
{
|
||||
terri->sendLandUpdate( landIdent.landId );
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::HousingMgr::removeHouse( Entity::Player& player, uint16_t plot )
|
||||
{
|
||||
auto terri = std::dynamic_pointer_cast< HousingZone >( player.getCurrentTerritory() );
|
||||
if( !terri )
|
||||
return;
|
||||
|
||||
auto land = terri->getLand( static_cast< uint8_t >( plot ) );
|
||||
if( !land || !land->getHouse() )
|
||||
return;
|
||||
|
||||
if( !hasPermission( player, *land, 0 ) )
|
||||
return;
|
||||
|
||||
auto& interiorContainer = getEstateInventory( land->getLandIdent() )[ InventoryType::HousingInteriorAppearance ];
|
||||
auto& invMgr = Service< InventoryMgr >::ref();
|
||||
|
||||
std::unordered_map< InventoryType, ItemContainerPtr > changedContainerSet = {};
|
||||
|
||||
for( int i = 0; i < interiorContainer->getMaxSize(); i++ )
|
||||
{
|
||||
auto item = interiorContainer->getItem( i );
|
||||
if( !item )
|
||||
continue;
|
||||
|
||||
Inventory::InventoryContainerPair freeSlotPair;
|
||||
auto freeContainer = getFreeEstateInventorySlot( land->getLandIdent(), freeSlotPair, m_internalStoreroomContainers );
|
||||
if ( !freeContainer )
|
||||
{
|
||||
// not sure what to do
|
||||
interiorContainer->removeItem( i, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
interiorContainer->removeItem( i, false );
|
||||
freeContainer->setItem( freeSlotPair.second , item );
|
||||
changedContainerSet[ freeSlotPair.first ] = freeContainer;
|
||||
}
|
||||
}
|
||||
|
||||
invMgr.sendInventoryContainer( player, interiorContainer );
|
||||
invMgr.saveHousingContainer( land->getLandIdent(), interiorContainer );
|
||||
for( auto entry : changedContainerSet )
|
||||
{
|
||||
invMgr.sendInventoryContainer( player, entry.second );
|
||||
invMgr.saveHousingContainer( land->getLandIdent(), entry.second );
|
||||
}
|
||||
|
||||
deleteHouse( land->getHouse() );
|
||||
land->setHouse( nullptr );
|
||||
|
||||
land->setStatus( HouseStatus::Sold );
|
||||
land->updateLandDb();
|
||||
terri->sendLandUpdate( plot );
|
||||
|
||||
player.setLandFlags( LandFlagsSlot::Private, 0, land->getLandIdent() );
|
||||
|
||||
terri->removeEstateEntranceEObj( plot );
|
||||
|
||||
// missing reply for ClientTrigger RequestEstateHallRemoval
|
||||
}
|
|
@ -181,6 +181,10 @@ namespace Sapphire::World::Manager
|
|||
|
||||
bool hasPermission( Entity::Player& player, Land& land, uint32_t permission );
|
||||
|
||||
void editAppearance( bool isInterior, Sapphire::Entity::Player& player, const Common::LandIdent landIdent, std::vector< uint16_t > containerList, std::vector< uint8_t > slotList, uint8_t removeFlag );
|
||||
|
||||
void removeHouse( Entity::Player& player, uint16_t plot );
|
||||
|
||||
private:
|
||||
|
||||
Inventory::HousingItemPtr getHousingItemFromPlayer( Entity::Player& player, Common::InventoryType type, uint8_t slot );
|
||||
|
@ -272,6 +276,8 @@ namespace Sapphire::World::Manager
|
|||
*/
|
||||
void createHouse( HousePtr house ) const;
|
||||
|
||||
void deleteHouse( HousePtr house ) const;
|
||||
|
||||
/*!
|
||||
* @brief Gets the next available house id
|
||||
* @return The next available house id
|
||||
|
|
|
@ -89,6 +89,9 @@ void Sapphire::World::Manager::InventoryMgr::saveHousingContainer( Common::LandI
|
|||
|
||||
for( auto& item : container->getItemMap() )
|
||||
{
|
||||
if( !item.second )
|
||||
continue;
|
||||
|
||||
saveHousingContainerItem( u64ident, container->getId(), item.first, item.second->getUId() );
|
||||
}
|
||||
}
|
||||
|
@ -143,15 +146,15 @@ void Sapphire::World::Manager::InventoryMgr::updateHousingItemPosition( Sapphire
|
|||
|
||||
stmt->setUInt64( 1, item->getUId() );
|
||||
|
||||
stmt->setUInt( 2, pos.x );
|
||||
stmt->setUInt( 3, pos.y );
|
||||
stmt->setUInt( 4, pos.z );
|
||||
stmt->setInt( 5, rot );
|
||||
stmt->setDouble( 2, static_cast< double >( pos.x ) );
|
||||
stmt->setDouble( 3, static_cast< double >( pos.y ) );
|
||||
stmt->setDouble( 4, static_cast< double >( pos.z ) );
|
||||
stmt->setDouble( 5, static_cast< double >( rot ) );
|
||||
|
||||
stmt->setUInt( 6, pos.x );
|
||||
stmt->setUInt( 7, pos.y );
|
||||
stmt->setUInt( 8, pos.z );
|
||||
stmt->setInt( 9, rot );
|
||||
stmt->setDouble( 6, static_cast< double >( pos.x ) );
|
||||
stmt->setDouble( 7, static_cast< double >( pos.y ) );
|
||||
stmt->setDouble( 8, static_cast< double >( pos.z ) );
|
||||
stmt->setDouble( 9, static_cast< double >( rot ) );
|
||||
|
||||
db.execute( stmt );
|
||||
}
|
||||
|
|
|
@ -32,51 +32,51 @@ uint16_t Sapphire::World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId(
|
|||
|
||||
switch( slot )
|
||||
{
|
||||
case Common::EquipSlotCategory::CharaHead:
|
||||
case Common::EquipSlotCategory::Head:
|
||||
return Common::ArmoryHead;
|
||||
|
||||
case Common::EquipSlotCategory::CharaBody:
|
||||
//case Common::EquipSlotCategory::BodyDisallowHead:
|
||||
//case Common::EquipSlotCategory::BodyDisallowHandsLegsFeet:
|
||||
//case Common::EquipSlotCategory::BodyDisallowAll:
|
||||
//case Common::EquipSlotCategory::BodyDisallowHands:
|
||||
//case Common::EquipSlotCategory::BodyDisallowLegsFeet:
|
||||
case Common::EquipSlotCategory::Body:
|
||||
case Common::EquipSlotCategory::BodyDisallowHead:
|
||||
case Common::EquipSlotCategory::BodyDisallowHandsLegsFeet:
|
||||
case Common::EquipSlotCategory::BodyDisallowAll:
|
||||
case Common::EquipSlotCategory::BodyDisallowHands:
|
||||
case Common::EquipSlotCategory::BodyDisallowLegsFeet:
|
||||
return Common::ArmoryBody;
|
||||
|
||||
case Common::EquipSlotCategory::CharaEars:
|
||||
case Common::EquipSlotCategory::Ears:
|
||||
return Common::ArmoryEar;
|
||||
|
||||
case Common::EquipSlotCategory::CharaFeet:
|
||||
case Common::EquipSlotCategory::Feet:
|
||||
return Common::ArmoryFeet;
|
||||
|
||||
case Common::EquipSlotCategory::CharaHands:
|
||||
case Common::EquipSlotCategory::Hands:
|
||||
return Common::ArmoryHand;
|
||||
|
||||
case Common::EquipSlotCategory::CharaLegs:
|
||||
//case Common::EquipSlotCategory::LegsDisallowFeet:
|
||||
case Common::EquipSlotCategory::Legs:
|
||||
case Common::EquipSlotCategory::LegsDisallowFeet:
|
||||
return Common::ArmoryLegs;
|
||||
|
||||
case Common::EquipSlotCategory::CharaMainHand:
|
||||
//case Common::EquipSlotCategory::MainTwoHandedWeapon:
|
||||
case Common::EquipSlotCategory::MainHand:
|
||||
case Common::EquipSlotCategory::MainTwoHandedWeapon:
|
||||
//case Common::EquipSlotCategory::MainOrOffHand:
|
||||
return Common::ArmoryMain;
|
||||
|
||||
case Common::EquipSlotCategory::CharaOffHand:
|
||||
case Common::EquipSlotCategory::OffHand:
|
||||
return Common::ArmoryOff;
|
||||
|
||||
case Common::EquipSlotCategory::CharaRing:
|
||||
case Common::EquipSlotCategory::Ring:
|
||||
return Common::ArmoryRing;
|
||||
|
||||
case Common::EquipSlotCategory::CharaWaist:
|
||||
case Common::EquipSlotCategory::Waist:
|
||||
return Common::ArmoryWaist;
|
||||
|
||||
case Common::EquipSlotCategory::CharaWrist:
|
||||
case Common::EquipSlotCategory::Wrist:
|
||||
return Common::ArmoryWrist;
|
||||
|
||||
case Common::EquipSlotCategory::CharaNeck:
|
||||
case Common::EquipSlotCategory::Neck:
|
||||
return Common::ArmoryNeck;
|
||||
|
||||
case Common::EquipSlotCategory::CharaSoulCrystal:
|
||||
case Common::EquipSlotCategory::SoulCrystal:
|
||||
return Common::ArmorySoulCrystal;
|
||||
|
||||
default:
|
||||
|
|
685
src/world/Manager/MapMgr.cpp
Normal file
685
src/world/Manager/MapMgr.cpp
Normal file
|
@ -0,0 +1,685 @@
|
|||
#include <Common.h>
|
||||
#include <Service.h>
|
||||
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
|
||||
#include <Event/EventHandler.h>
|
||||
|
||||
#include <Network/CommonActorControl.h>
|
||||
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
||||
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
||||
|
||||
#include <Util/Util.cpp>
|
||||
|
||||
#include <Actor/Player.h>
|
||||
|
||||
#include <Script/ScriptMgr.h>
|
||||
#include <Script/NativeScriptMgr.h>
|
||||
|
||||
#include <Territory/InstanceObjectCache.h>
|
||||
#include <datReader/DatCategories/bg/lgb.h>
|
||||
|
||||
#include "MapMgr.h"
|
||||
#include "TerritoryMgr.h"
|
||||
|
||||
using namespace Sapphire::Event;
|
||||
using namespace Sapphire::Network::Packets;
|
||||
using namespace Sapphire::Network::Packets::Server;
|
||||
|
||||
Sapphire::World::Manager::MapMgr::MapMgr()
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
|
||||
for( uint32_t questId = 65536; auto curQuest = exdData.get< Data::Quest >( questId ); questId++ )
|
||||
m_quests.emplace( questId, curQuest );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MapMgr::updateAll( Entity::Player& player )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto& objectCache = Common::Service< Sapphire::InstanceObjectCache >::ref();
|
||||
|
||||
EventSet mapData;
|
||||
|
||||
auto eventNpcs = objectCache.getAllEventNpc( player.getZoneId() );
|
||||
if( eventNpcs )
|
||||
{
|
||||
for( const auto& eventNpc : *eventNpcs )
|
||||
{
|
||||
auto eNpc = exdData.get< Data::ENpcBase >( eventNpc.second->data.enpcId );
|
||||
if( eNpc )
|
||||
{
|
||||
auto eNpcData = eNpc->eNpcData;
|
||||
for( auto npcData : eNpcData )
|
||||
{
|
||||
if( npcData == 0 )
|
||||
continue; // Some npcs have data gaps, so we have to iterate through the entire array
|
||||
|
||||
EventData eventData;
|
||||
eventData.eventId = npcData;
|
||||
eventData.levelId = eventNpc.first;
|
||||
|
||||
auto eventHandlerType = static_cast< EventHandler::EventHandlerType >( npcData >> 16 );
|
||||
|
||||
switch( eventHandlerType )
|
||||
{
|
||||
case EventHandler::EventHandlerType::Quest:
|
||||
{
|
||||
auto quest = m_quests[ npcData ];
|
||||
|
||||
if( quest->issuerLocation == eventNpc.first )
|
||||
{
|
||||
insertQuest( player, npcData, mapData );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EventHandler::EventHandlerType::GuildLeveAssignment:
|
||||
{
|
||||
if( player.isActionLearned( 5 ) )
|
||||
{
|
||||
auto guildLeve = exdData.get< Data::GuildleveAssignment >( npcData );
|
||||
|
||||
eventData.iconId = exdData.get< Data::EventIconType >( 5 )->mapIconAvailable + 1;
|
||||
|
||||
if( player.isQuestCompleted( guildLeve->quest[ 0 ] ) ||
|
||||
( ( guildLeve->typeId == 2 || npcData == 393217 || npcData == 393223 || npcData == 393225 ) && // Leve npc locations: Bentbranch / Horizon / Swiftperch
|
||||
( player.isQuestCompleted( 220 ) || player.isQuestCompleted( 687 ) || player.isQuestCompleted( 693 ) ) ) )
|
||||
{
|
||||
if( guildLeve->typeId == 2 )
|
||||
{
|
||||
if( player.getGc() != 0 )
|
||||
{
|
||||
for( int8_t i = 0; i < 3; i++ )
|
||||
{
|
||||
if( player.getGcRankArray()[ i ] >= guildLeve->grandCompanyRank )
|
||||
{
|
||||
mapData.insert( eventData );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapData.insert( eventData );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EventHandler::EventHandlerType::CustomTalk:
|
||||
{
|
||||
// Include only the beginner arena icon yet. There a few other ones, that aren't referenced in the game files (Some examples are: The Triple Triad Tournament npc which has multiple icons and the ocean fishing icon)
|
||||
if( npcData == 721223 )
|
||||
{
|
||||
auto customTalk = exdData.get< Data::CustomTalk >( npcData );
|
||||
|
||||
eventData.iconId = customTalk->iconMap;
|
||||
|
||||
mapData.insert( eventData );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EventHandler::EventHandlerType::GuildOrderGuide:
|
||||
{
|
||||
if( player.isActionLearned( 7 ) )
|
||||
{
|
||||
eventData.iconId = exdData.get< Data::EventIconType >( 6 )->mapIconAvailable + 1;
|
||||
|
||||
mapData.insert( eventData );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EventHandler::EventHandlerType::TripleTriad:
|
||||
{
|
||||
if( npcData == 2293771 ) // Triple Triad Master npc for now only
|
||||
{
|
||||
eventData.iconId = exdData.get< Data::EventIconType >( 7 )->mapIconAvailable + 1;
|
||||
|
||||
mapData.insert( eventData );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EventHandler::EventHandlerType::PreHandler:
|
||||
{
|
||||
//I think this is used in Bozja and Zadnor, need evidence
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto eventObjs = objectCache.getAllEventObj( player.getZoneId() );
|
||||
if( eventObjs )
|
||||
{
|
||||
for( const auto& eventObj : *eventObjs )
|
||||
{
|
||||
auto eObj = exdData.get< Data::EObj >( eventObj.second->data.eobjId );
|
||||
if( eObj )
|
||||
{
|
||||
auto eObjData = eObj->data;
|
||||
if( eObjData )
|
||||
{
|
||||
EventData eventData;
|
||||
eventData.eventId = eObjData;
|
||||
eventData.levelId = eventObj.first;
|
||||
|
||||
auto eventHandlerType = static_cast< EventHandler::EventHandlerType >( eObjData >> 16 );
|
||||
|
||||
if( eventHandlerType == EventHandler::EventHandlerType::Quest )
|
||||
{
|
||||
auto quest = m_quests[ eObjData ];
|
||||
|
||||
if( quest->issuerLocation == eventObj.first )
|
||||
{
|
||||
insertQuest( player, eObjData, mapData );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sendPackets( player, mapData, All );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MapMgr::updateQuests( Entity::Player& player )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto& objectCache = Common::Service< Sapphire::InstanceObjectCache >::ref();
|
||||
|
||||
EventSet mapData;
|
||||
|
||||
auto eventNpcs = objectCache.getAllEventNpc( player.getZoneId() );
|
||||
if( eventNpcs )
|
||||
{
|
||||
for( const auto& eventNpc : *eventNpcs )
|
||||
{
|
||||
auto eNpcData = exdData.get< Data::ENpcBase >( eventNpc.second->data.enpcId )->eNpcData;
|
||||
|
||||
for( auto npcData : eNpcData )
|
||||
{
|
||||
if( npcData == 0 )
|
||||
continue; // Some npcs have data gaps, so we have to iterate through the entire array
|
||||
|
||||
EventData eventData;
|
||||
eventData.eventId = npcData;
|
||||
eventData.levelId = eventNpc.first;
|
||||
|
||||
auto eventHandlerType = static_cast< EventHandler::EventHandlerType >( npcData >> 16 );
|
||||
|
||||
if( eventHandlerType == EventHandler::EventHandlerType::Quest )
|
||||
{
|
||||
auto quest = m_quests[ npcData ];
|
||||
|
||||
if( quest->issuerLocation == eventNpc.first )
|
||||
{
|
||||
insertQuest( player, npcData, mapData );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto eventObjs = objectCache.getAllEventObj( player.getZoneId() );
|
||||
if( eventObjs )
|
||||
{
|
||||
for( const auto& eventObj : *eventObjs )
|
||||
{
|
||||
auto eObj = exdData.get< Data::EObj >( eventObj.second->data.eobjId );
|
||||
if( eObj )
|
||||
{
|
||||
auto eObjData = eObj->data;
|
||||
if( eObjData )
|
||||
{
|
||||
EventData eventData;
|
||||
eventData.eventId = eObjData;
|
||||
eventData.levelId = eventObj.first;
|
||||
|
||||
auto eventHandlerType = static_cast< EventHandler::EventHandlerType >( eObjData >> 16 );
|
||||
|
||||
if( eventHandlerType == EventHandler::EventHandlerType::Quest )
|
||||
{
|
||||
auto quest = m_quests[ eObjData ];
|
||||
|
||||
if( quest->issuerLocation == eventObj.first )
|
||||
{
|
||||
insertQuest( player, eObjData, mapData );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendPackets( player, mapData, Quest );
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MapMgr::insertQuest( Entity::Player& player, uint32_t questId, EventSet& mapData )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
|
||||
auto quest = m_quests[ questId ];
|
||||
|
||||
if( isQuestVisible( player, questId, quest ) )
|
||||
{
|
||||
auto script = scriptMgr.getNativeScriptHandler().getScript< Sapphire::ScriptAPI::EventScript >( questId );
|
||||
|
||||
// Just don't show quests on map, that aren't implemented yet
|
||||
if( script )
|
||||
{
|
||||
EventData eventData;
|
||||
eventData.eventId = questId;
|
||||
|
||||
auto eventState = script->getQuestAvailability( player, questId );
|
||||
|
||||
if( eventState == Event::EventHandler::QuestAvailability::Available || eventState == Event::EventHandler::QuestAvailability::Locked )
|
||||
{
|
||||
if( eventState == Event::EventHandler::QuestAvailability::Available && isQuestAvailable( player, questId, quest ) )
|
||||
{
|
||||
eventData.iconId = exdData.get< Data::EventIconType >( quest->eventIconType )->mapIconAvailable + 1 + quest->isRepeatable;
|
||||
eventData.levelId = quest->issuerLocation;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventData.iconId = exdData.get< Data::EventIconType >( quest->eventIconType )->mapIconInvalid + 1 + quest->isRepeatable;
|
||||
eventData.levelId = quest->issuerLocation;
|
||||
}
|
||||
|
||||
mapData.insert( eventData );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Sapphire::World::Manager::MapMgr::isQuestAvailable( Entity::Player& player, uint32_t questId, Data::ExdDataGenerated::QuestPtr questPtr )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
|
||||
if( questPtr->grandCompany || questPtr->grandCompanyRank )
|
||||
{
|
||||
if( questPtr->grandCompany != player.getGc() )
|
||||
{
|
||||
if( questPtr->grandCompanyRank > player.getGcRankArray()[ player.getGc() - 1 ] )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( questPtr->instanceContentJoin == 1 )
|
||||
{
|
||||
for( int32_t i = 0; i < 3; i++ )
|
||||
{
|
||||
if( questPtr->instanceContent[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if( questPtr->instanceContentJoin == 2 )
|
||||
{
|
||||
for( int32_t i = 0; i < 3; i++ )
|
||||
{
|
||||
if( questPtr->instanceContent[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( questPtr->bellStart || questPtr->bellEnd )
|
||||
{
|
||||
uint64_t curEorzeaTime = Util::getEorzeanTimeStamp();
|
||||
uint32_t convTime = 100 * ( curEorzeaTime / 3600 % 24 ) + curEorzeaTime / 60 % 60;
|
||||
|
||||
if( questPtr->bellStart <= questPtr->bellEnd )
|
||||
{
|
||||
if( convTime < questPtr->bellStart || convTime >= questPtr->bellEnd )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( convTime < questPtr->bellStart && convTime >= questPtr->bellEnd )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto classJobCategory = &exdData.get< Data::ClassJobCategory >( questPtr->classJobCategory0 )->aDV;
|
||||
if( !classJobCategory[ static_cast< uint8_t >( player.getClass() ) ] )
|
||||
return false;
|
||||
|
||||
if( questPtr->classJobCategory1 > 1 )
|
||||
{
|
||||
classJobCategory = &exdData.get< Data::ClassJobCategory >( questPtr->classJobCategory1 )->aDV;
|
||||
if( !classJobCategory[ static_cast< uint8_t >( player.getClass() ) ] )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sapphire::World::Manager::MapMgr::isQuestVisible( Entity::Player& player, uint32_t questId, Data::ExdDataGenerated::QuestPtr questPtr )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
|
||||
if( ( player.isQuestCompleted( questId ) && ( !questPtr->isRepeatable && questId != 67114 ) ) || player.hasQuest( questId ) )
|
||||
return false;
|
||||
|
||||
if( questPtr->classJobUnlock )
|
||||
{
|
||||
if( questPtr->classJobUnlockFlag == 3 )
|
||||
if( static_cast< uint8_t >( player.getClass() ) != questPtr->classJobUnlock )
|
||||
return false;
|
||||
else if( questPtr->classJobUnlockFlag == 4 )
|
||||
if ( static_cast< uint8_t >( player.getClass() ) == questPtr->classJobUnlock )
|
||||
return false;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Was this really ever used?
|
||||
if( questPtr->startTown )
|
||||
{
|
||||
if( questPtr->startTown != player.getStartTown() )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( Common::CURRENT_EXPANSION_ID < questPtr->expansion )
|
||||
return false;
|
||||
|
||||
if( questPtr->mountRequired )
|
||||
{
|
||||
if( !player.hasMount( questPtr->mountRequired ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( questPtr->grandCompany )
|
||||
{
|
||||
if( questPtr->grandCompany != player.getGc() )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( questPtr->header != 0 )
|
||||
{
|
||||
if ( !player.isActionLearned( questPtr->header ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( questPtr->previousQuestJoin == 1 )
|
||||
{
|
||||
for( int32_t i = 0; i < 3; i++ )
|
||||
{
|
||||
if( questPtr->previousQuest[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
if( !player.isQuestCompleted( questPtr->previousQuest[ i ] ) )
|
||||
{
|
||||
if( i == 0 && questPtr->previousQuest0Sequence != 0 )
|
||||
{
|
||||
if( player.getQuestSeq( questPtr->previousQuest[ i ] ) < questPtr->previousQuest0Sequence )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( questPtr->previousQuestJoin == 2 )
|
||||
{
|
||||
for( int32_t i = 0; i <= 3; i++ )
|
||||
{
|
||||
if( i == 3 )
|
||||
return false;
|
||||
|
||||
if( questPtr->previousQuest[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
if( player.isQuestCompleted( questPtr->previousQuest[ i ] ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( questPtr->questLockJoin == 1 )
|
||||
{
|
||||
for( int32_t i = 0; i <= 2; i++ )
|
||||
{
|
||||
if( i == 2 )
|
||||
return false;
|
||||
|
||||
if( questPtr->questLock[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
if( !player.isQuestCompleted( questPtr->questLock[ i ] ) && !player.hasQuest( questPtr->questLock[ i ] ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( questPtr->questLockJoin == 2 )
|
||||
{
|
||||
for( int32_t i = 0; i < 2; i++ )
|
||||
{
|
||||
if( questPtr->questLock[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
if( player.isQuestCompleted( questPtr->questLock[ i ] ) || player.hasQuest( questPtr->questLock[ i ] ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( questPtr->festival )
|
||||
{
|
||||
auto& territoryMgr = Common::Service< Manager::TerritoryMgr >::ref();
|
||||
auto& festival = territoryMgr.getCurrentFestival();
|
||||
|
||||
if( questPtr->festival != festival.first && questPtr->festival != festival.second )
|
||||
return false;
|
||||
|
||||
// Don't show festivals with begin state other than 0 yet
|
||||
if( questPtr->festivalBegin != 0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ( questPtr->type & 1 ) == 0 )
|
||||
{
|
||||
auto classJobCategory = &exdData.get< Data::ClassJobCategory >( questPtr->classJobCategory0 )->aDV;
|
||||
|
||||
for( int32_t i = 1; i <= Common::CLASSJOB_TOTAL; i++ )
|
||||
{
|
||||
if( classJobCategory[ i ] )
|
||||
{
|
||||
if( player.getLevelForClass( static_cast< Common::ClassJob >( i ) ) >= questPtr->classJobLevel0 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( i == Common::CLASSJOB_TOTAL )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( player.getLevel() < questPtr->classJobLevel0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int32_t i = 0; i <= Common::CLASSJOB_TOTAL; i++ )
|
||||
{
|
||||
auto classJob = exdData.get< Data::ClassJob >( i );
|
||||
|
||||
if( classJob->relicQuest == questId )
|
||||
{
|
||||
for( int32_t j = 0; i <= Common::CLASSJOB_TOTAL; i++ )
|
||||
{
|
||||
classJob = exdData.get< Data::ClassJob >( i );
|
||||
|
||||
if( player.hasQuest( classJob->relicQuest ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( questPtr->beastTribe )
|
||||
return false;
|
||||
|
||||
if( questPtr->satisfactionNpc )
|
||||
return false;
|
||||
|
||||
if( questPtr->isHouseRequired )
|
||||
return false;
|
||||
|
||||
if( questPtr->deliveryQuest )
|
||||
return false;
|
||||
|
||||
if( player.getQuestSeq( questId ) == 0 )
|
||||
{
|
||||
auto questAccept = exdData.get< Data::QuestAcceptAdditionCondition >( questId );
|
||||
|
||||
if( questAccept )
|
||||
{
|
||||
for( int32_t i = 0; i < 2; i++ )
|
||||
{
|
||||
if( ( &questAccept->requirement0 )[ i ] >= 65536 )
|
||||
{
|
||||
if( !player.isActionLearned( 245 ) && !player.isQuestCompleted( ( &questAccept->requirement0 )[ i ] ) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !player.isActionLearned( ( &questAccept->requirement0 )[ i ] ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sapphire::World::Manager::MapMgr::isTripleTriadAvailable( Entity::Player& player, uint32_t tripleTriadId )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto tripleTriad = exdData.get< Data::TripleTriad >( tripleTriadId );
|
||||
|
||||
if( tripleTriad->previousQuestJoin == 1 )
|
||||
{
|
||||
for( int32_t i = 0; i < 3; i++ )
|
||||
{
|
||||
if( tripleTriad->previousQuest[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
if( !player.isQuestCompleted( tripleTriad->previousQuest[ i ] ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( tripleTriad->previousQuestJoin == 2 )
|
||||
{
|
||||
for( int32_t i = 0; i < 3; i++ )
|
||||
{
|
||||
if( tripleTriad->previousQuest[ i ] == 0 )
|
||||
continue;
|
||||
|
||||
if( player.isQuestCompleted( tripleTriad->previousQuest[ i ] ) )
|
||||
break;
|
||||
|
||||
if( i == 2 )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MapMgr::fillPacket( EventSet& mapData, uint32_t* iconIds, uint32_t* levelIds, uint32_t* eventIds )
|
||||
{
|
||||
int32_t i = 0;
|
||||
for( auto& eventData : mapData )
|
||||
{
|
||||
iconIds[ i ] = eventData.iconId;
|
||||
levelIds[ i ] = eventData.levelId;
|
||||
eventIds[ i ] = eventData.eventId;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::World::Manager::MapMgr::sendPackets( Entity::Player& player, EventSet& mapData, UpdateMode updateMode )
|
||||
{
|
||||
player.queuePacket( makeActorControlSelf( player.getId(), Network::ActorControl::BeginMapUpdate, updateMode ) );
|
||||
|
||||
if( mapData.size() <= 2 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
else if( mapData.size() <= 4 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate4 >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
else if( mapData.size() <= 8 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate8 >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
else if( mapData.size() <= 16 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate16 >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
else if( mapData.size() <= 32 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate32 >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
else if( mapData.size() <= 64 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate64 >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
else if( mapData.size() <= 128 )
|
||||
{
|
||||
auto mapUpdatePacket = makeZonePacket< FFXIVIpcMapUpdate128 >( player.getId() );
|
||||
mapUpdatePacket->data().entryCount = mapData.size();
|
||||
|
||||
fillPacket( mapData, mapUpdatePacket->data().iconIds, mapUpdatePacket->data().levelIds, mapUpdatePacket->data().eventIds );
|
||||
|
||||
player.queuePacket( mapUpdatePacket );
|
||||
}
|
||||
|
||||
player.queuePacket( makeActorControlSelf( player.getId(), Network::ActorControl::FinishMapUpdate ) );
|
||||
}
|
77
src/world/Manager/MapMgr.h
Normal file
77
src/world/Manager/MapMgr.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef SAPPHIRE_MAPMGR_H
|
||||
#define SAPPHIRE_MAPMGR_H
|
||||
|
||||
#include "ForwardsZone.h"
|
||||
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Sapphire::World::Manager
|
||||
{
|
||||
|
||||
using QuestMap = std::unordered_map< uint32_t, Data::ExdDataGenerated::QuestPtr >;
|
||||
|
||||
class MapMgr
|
||||
{
|
||||
public:
|
||||
enum UpdateMode : uint8_t
|
||||
{
|
||||
Quest = 1,
|
||||
GuildLeveAssignment = 2,
|
||||
GuildOrderGuide = 4,
|
||||
TripleTriad = 8,
|
||||
CustomTalk = 16,
|
||||
PreHandler = 32,
|
||||
|
||||
All = 0x3F
|
||||
};
|
||||
|
||||
MapMgr();
|
||||
|
||||
void updateAll( Entity::Player& player );
|
||||
void updateQuests( Entity::Player& player );
|
||||
|
||||
private:
|
||||
struct EventData
|
||||
{
|
||||
uint32_t iconId;
|
||||
uint32_t levelId;
|
||||
uint32_t eventId;
|
||||
};
|
||||
|
||||
struct less
|
||||
{
|
||||
constexpr bool operator()( const EventData& _Left, const EventData& _Right ) const
|
||||
{
|
||||
const uint16_t left = _Left.eventId;
|
||||
const uint16_t right = _Right.eventId;
|
||||
|
||||
if( left == right )
|
||||
{
|
||||
const uint16_t typeLeft = _Left.eventId >> 16;
|
||||
const uint16_t typeRight = _Right.eventId >> 16;
|
||||
|
||||
return typeLeft < typeRight;
|
||||
}
|
||||
|
||||
return left < right;
|
||||
}
|
||||
};
|
||||
|
||||
using EventSet = std::multiset< EventData, less >;
|
||||
|
||||
QuestMap m_quests;
|
||||
|
||||
void insertQuest( Entity::Player& player, uint32_t questId, EventSet& mapData );
|
||||
|
||||
bool isQuestVisible( Entity::Player& player, uint32_t questId, Data::ExdDataGenerated::QuestPtr questPtr );
|
||||
bool isQuestAvailable( Entity::Player& player, uint32_t questId, Data::ExdDataGenerated::QuestPtr questPtr );
|
||||
bool isTripleTriadAvailable( Entity::Player& player, uint32_t tripleTriadId );
|
||||
|
||||
void fillPacket( EventSet& mapData, uint32_t* iconIds, uint32_t* levelIds, uint32_t* eventIds );
|
||||
void sendPackets( Entity::Player& player, EventSet& mapData, UpdateMode updateMode );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SAPPHIRE_MAPMGR_H
|
|
@ -13,6 +13,7 @@
|
|||
#include "Territory/ZonePosition.h"
|
||||
#include "Territory/InstanceContent.h"
|
||||
#include "Territory/QuestBattle.h"
|
||||
#include "Territory/PublicContent.h"
|
||||
#include "TerritoryMgr.h"
|
||||
#include "HousingMgr.h"
|
||||
|
||||
|
@ -301,7 +302,28 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createQuestBattle
|
|||
if( !pQuestBattleInfo )
|
||||
return nullptr;
|
||||
|
||||
auto pQuestInfo = exdData.get< Sapphire::Data::Quest >( pQuestBattleInfo->quest );
|
||||
auto eventId = pQuestBattleInfo->quest;
|
||||
auto eventType = static_cast< Event::EventHandler::EventHandlerType >( eventId >> 16 );
|
||||
switch( eventType )
|
||||
{
|
||||
case Event::EventHandler::EventHandlerType::Array:
|
||||
{
|
||||
auto eventArray = exdData.get< Sapphire::Data::ArrayEventHandler >( eventId );
|
||||
if( eventArray )
|
||||
{
|
||||
for( int i = 0; i < eventArray->data.size(); i++ )
|
||||
{
|
||||
auto nextId = eventArray->data[ i ];
|
||||
if( nextId == 0 )
|
||||
break;
|
||||
eventId = nextId;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto pQuestInfo = exdData.get< Sapphire::Data::Quest >( eventId );
|
||||
if( !pQuestInfo )
|
||||
return nullptr;
|
||||
|
||||
|
@ -316,7 +338,7 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createQuestBattle
|
|||
Logger::debug( "Starting instance for QuestBattle id: {0} ({1})", questBattleId, pQuestInfo->name );
|
||||
|
||||
auto pZone = make_QuestBattle( pQuestBattleInfo, pContentFinderCondition->territoryType, getNextInstanceId(),
|
||||
pTeri->name, pQuestInfo->name, questBattleId );
|
||||
pTeri->name, pQuestInfo->name, questBattleId, contentFinderConditionId );
|
||||
pZone->init();
|
||||
|
||||
m_questBattleIdToInstanceMap[ questBattleId ][ pZone->getGuId() ] = pZone;
|
||||
|
@ -350,7 +372,7 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createInstanceCon
|
|||
Logger::debug( "Starting instance for InstanceContent id: {0} ({1})", instanceContentId, pContentFinderCondition->name );
|
||||
|
||||
auto pZone = make_InstanceContent( pInstanceContent, pContentFinderCondition->territoryType, getNextInstanceId(),
|
||||
pTeri->name, pContentFinderCondition->name, instanceContentId );
|
||||
pTeri->name, pContentFinderCondition->name, instanceContentId, contentFinderConditionId );
|
||||
pZone->init();
|
||||
|
||||
m_instanceContentIdToInstanceMap[ instanceContentId ][ pZone->getGuId() ] = pZone;
|
||||
|
@ -360,6 +382,68 @@ Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createInstanceCon
|
|||
return pZone;
|
||||
}
|
||||
|
||||
Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createPublicContent( uint32_t contentFinderConditionId )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
|
||||
auto pContentFinderCondition = exdData.get< Sapphire::Data::ContentFinderCondition >( contentFinderConditionId );
|
||||
if( !pContentFinderCondition )
|
||||
return nullptr;
|
||||
auto contentId = pContentFinderCondition->content;
|
||||
|
||||
auto pPublicContent = exdData.get< Sapphire::Data::PublicContent >( contentId );
|
||||
if( !pPublicContent )
|
||||
return nullptr;
|
||||
|
||||
auto pTeri = getTerritoryDetail( pContentFinderCondition->territoryType );
|
||||
|
||||
if( !pTeri || pContentFinderCondition->name.empty() )
|
||||
return nullptr;
|
||||
|
||||
Logger::debug( "Starting instance for PublicContent id: {0} ({1})", contentId, pContentFinderCondition->name );
|
||||
|
||||
auto pZone = make_PublicContent( pPublicContent, pContentFinderCondition->territoryType, getNextInstanceId(),
|
||||
pTeri->name, pContentFinderCondition->name, contentId, contentFinderConditionId );
|
||||
pZone->init();
|
||||
|
||||
m_publicContentIdToInstanceMap[ contentId ][ pZone->getGuId() ] = pZone;
|
||||
m_guIdToTerritoryPtrMap[ pZone->getGuId() ] = pZone;
|
||||
m_instanceZoneSet.insert( pZone );
|
||||
|
||||
return pZone;
|
||||
}
|
||||
|
||||
Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::createPublicContent( uint16_t contentId, uint16_t territoryId )
|
||||
{
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
|
||||
auto pPublicContent = exdData.get< Sapphire::Data::PublicContent >( contentId );
|
||||
if( !pPublicContent )
|
||||
return nullptr;
|
||||
|
||||
if( pPublicContent->contentFinderCondition > 0 )
|
||||
{
|
||||
Logger::warn( "the public content {} has a ContentFinderCondition value of {}, create the instance using it instead.", contentId, pPublicContent->contentFinderCondition );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pTeri = getTerritoryDetail( territoryId );
|
||||
|
||||
if( !pTeri )
|
||||
return nullptr;
|
||||
|
||||
Logger::debug( "Starting instance for PublicContent id: {0} ({1})", contentId, pPublicContent->name );
|
||||
|
||||
auto pZone = make_PublicContent( pPublicContent, territoryId, getNextInstanceId(), pTeri->name, pPublicContent->name, contentId, 0 );
|
||||
pZone->init();
|
||||
|
||||
m_publicContentIdToInstanceMap[ contentId ][ pZone->getGuId() ] = pZone;
|
||||
m_guIdToTerritoryPtrMap[ pZone->getGuId() ] = pZone;
|
||||
m_instanceZoneSet.insert( pZone );
|
||||
|
||||
return pZone;
|
||||
}
|
||||
|
||||
Sapphire::TerritoryPtr Sapphire::World::Manager::TerritoryMgr::findOrCreateHousingInterior( const Common::LandIdent landIdent )
|
||||
{
|
||||
// check if zone already spawned first
|
||||
|
@ -444,11 +528,21 @@ bool Sapphire::World::Manager::TerritoryMgr::removeTerritoryInstance( uint32_t g
|
|||
m_instanceZoneSet.erase( pZone );
|
||||
m_territorySet.erase( pZone );
|
||||
|
||||
if( isInstanceContentTerritory( pZone->getTerritoryTypeId() ) )
|
||||
if( pZone->getAsInstanceContent() )
|
||||
{
|
||||
auto instance = std::dynamic_pointer_cast< InstanceContent >( pZone );
|
||||
m_instanceContentIdToInstanceMap[ instance->getInstanceContentId() ].erase( pZone->getGuId() );
|
||||
}
|
||||
else if( pZone->getAsPublicContent() )
|
||||
{
|
||||
auto instance = std::dynamic_pointer_cast< PublicContent >( pZone );
|
||||
m_publicContentIdToInstanceMap[ instance->getContentId() ].erase( pZone->getGuId() );
|
||||
}
|
||||
else if( pZone->getAsQuestBattle() )
|
||||
{
|
||||
auto instance = std::dynamic_pointer_cast< QuestBattle >( pZone );
|
||||
m_questBattleIdToInstanceMap[ instance->getQuestBattleId() ].erase( pZone->getGuId() );
|
||||
}
|
||||
else
|
||||
m_territoryTypeIdToInstanceGuidMap[ pZone->getTerritoryTypeId() ].erase( pZone->getGuId() );
|
||||
|
||||
|
@ -540,6 +634,7 @@ void Sapphire::World::Manager::TerritoryMgr::updateTerritoryInstances( uint64_t
|
|||
|
||||
// remove zone from maps
|
||||
m_territorySet.erase( zone );
|
||||
m_guIdToTerritoryPtrMap.erase( zone->getGuId() );
|
||||
it = m_landIdentToTerritoryPtrMap.erase( it );
|
||||
}
|
||||
else
|
||||
|
@ -615,7 +710,7 @@ bool Sapphire::World::Manager::TerritoryMgr::movePlayer( TerritoryPtr pZone, Sap
|
|||
if( pHousing )
|
||||
pPlayer->setTerritoryId( pHousing->getLandSetId() );
|
||||
}
|
||||
else if( isInstanceContentTerritory( pZone->getTerritoryTypeId() ) )
|
||||
else if( pZone->getAsInstanceContent() || pZone->getAsQuestBattle() || pZone->getAsPublicContent() )
|
||||
{
|
||||
pPlayer->setTerritoryId( pZone->getGuId() );
|
||||
}
|
||||
|
@ -627,14 +722,27 @@ bool Sapphire::World::Manager::TerritoryMgr::movePlayer( TerritoryPtr pZone, Sap
|
|||
// mark character as zoning in progress
|
||||
pPlayer->setLoadingComplete( false );
|
||||
|
||||
bool zoneChanged = true;
|
||||
if( pPlayer->getLastPing() != 0 && pPlayer->getCurrentTerritory() )
|
||||
pPlayer->getCurrentTerritory()->removeActor( pPlayer );
|
||||
{
|
||||
zoneChanged = pPlayer->getCurrentTerritory()->getGuId() != pZone->getGuId();
|
||||
if( zoneChanged )
|
||||
pPlayer->getCurrentTerritory()->removeActor( pPlayer );
|
||||
}
|
||||
|
||||
pPlayer->setCurrentZone( pZone );
|
||||
pZone->pushActor( pPlayer );
|
||||
if( zoneChanged )
|
||||
{
|
||||
pPlayer->setCurrentZone( pZone );
|
||||
pZone->pushActor( pPlayer );
|
||||
|
||||
// map player to instanceId so it can be tracked.
|
||||
m_playerIdToInstanceMap[ pPlayer->getId() ] = pZone->getGuId();
|
||||
// map player to instanceId so it can be tracked.
|
||||
m_playerIdToInstanceMap[ pPlayer->getId() ] = pZone->getGuId();
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer->removeFromInRange();
|
||||
pPlayer->clearInRangeSet();
|
||||
}
|
||||
|
||||
pPlayer->sendZonePackets();
|
||||
|
||||
|
|
|
@ -118,6 +118,9 @@ namespace Sapphire::World::Manager
|
|||
|
||||
TerritoryPtr createQuestBattle( uint32_t contentFinderConditionId );
|
||||
|
||||
TerritoryPtr createPublicContent( uint32_t contentFinderConditionId );
|
||||
TerritoryPtr createPublicContent( uint16_t contentId, uint16_t territoryId );
|
||||
|
||||
void createAndJoinQuestBattle( Entity::Player& player, uint16_t contentFinderConditionId );
|
||||
|
||||
TerritoryPtr findOrCreateHousingInterior( const Common::LandIdent landIdent );
|
||||
|
@ -179,6 +182,7 @@ namespace Sapphire::World::Manager
|
|||
using InstanceContentIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >;
|
||||
using QuestBattleIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >;
|
||||
using QuestBattleIdToContentFinderCondMap = std::unordered_map< uint16_t, uint16_t >;
|
||||
using PublicContentIdToInstanceMap = std::unordered_map< uint16_t, InstanceIdToTerritoryPtrMap >;
|
||||
using PlayerIdToInstanceIdMap = std::unordered_map< uint32_t, uint32_t >;
|
||||
using PositionMap = std::unordered_map< int32_t, ZonePositionPtr >;
|
||||
using InstanceIdList = std::vector< uint32_t >;
|
||||
|
@ -196,9 +200,12 @@ namespace Sapphire::World::Manager
|
|||
/*! map holding actual instances of InstanceContent */
|
||||
InstanceContentIdToInstanceMap m_instanceContentIdToInstanceMap;
|
||||
|
||||
/*! map holding actual instances of InstanceContent */
|
||||
/*! map holding actual instances of QuestBattle */
|
||||
QuestBattleIdToInstanceMap m_questBattleIdToInstanceMap;
|
||||
|
||||
/*! map holding actual instances of PublicContent */
|
||||
PublicContentIdToInstanceMap m_publicContentIdToInstanceMap;
|
||||
|
||||
/*! flat map for easier lookup of instances by guid */
|
||||
InstanceIdToTerritoryPtrMap m_guIdToTerritoryPtrMap;
|
||||
|
||||
|
|
|
@ -90,6 +90,8 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
|||
setZoneHandler( ClientZoneIpcType::ReqPlaceHousingItem, "ReqPlaceHousingItem", &GameConnection::reqPlaceHousingItem );
|
||||
setZoneHandler( ClientZoneIpcType::HousingUpdateObjectPosition, "HousingUpdateObjectPosition",
|
||||
&GameConnection::reqMoveHousingItem );
|
||||
setZoneHandler( ClientZoneIpcType::HousingEditExterior, "HousingEditExterior", &GameConnection::housingEditExterior );
|
||||
setZoneHandler( ClientZoneIpcType::HousingEditInterior, "HousingEditInterior", &GameConnection::housingEditInterior );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk );
|
||||
setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote );
|
||||
|
@ -100,10 +102,12 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
|||
setZoneHandler( ClientZoneIpcType::EnterTeriEventHandler, "EventHandlerEnterTeri",
|
||||
&GameConnection::eventHandlerEnterTerritory );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "EventHandlerReturn", &GameConnection::eventHandlerReturn );
|
||||
setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "EventHandlerReturn",
|
||||
setZoneHandler( ClientZoneIpcType::ReturnEventHandler, "ReturnEventHandler", &GameConnection::eventHandlerReturn );
|
||||
setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler, "TradeReturnEventHandler",
|
||||
&GameConnection::eventHandlerReturn );
|
||||
setZoneHandler( ClientZoneIpcType::TradeMultipleReturnEventHander, "EventHandlerReturn", &GameConnection::eventHandlerReturn );
|
||||
setZoneHandler( ClientZoneIpcType::TradeReturnEventHandler2, "TradeReturnEventHandler2", &GameConnection::eventHandlerReturn );
|
||||
setZoneHandler( ClientZoneIpcType::EventYield2Handler, "EventYield2Handler", &GameConnection::eventYieldHandler );
|
||||
setZoneHandler( ClientZoneIpcType::EventYield16Handler, "EventYield16Handler", &GameConnection::eventYieldHandler );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::ShopEventHandler, "ShopEventHandler",
|
||||
&GameConnection::eventHandlerShop );
|
||||
|
@ -118,7 +122,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
|||
setZoneHandler( ClientZoneIpcType::CFRegisterDuty, "CFRegisterDuty", &GameConnection::cfRegisterDuty );
|
||||
setZoneHandler( ClientZoneIpcType::CFRegisterRoulette, "CFRegisterRoulette", &GameConnection::cfRegisterRoulette );
|
||||
setZoneHandler( ClientZoneIpcType::CFCommenceHandler, "CFDutyAccepted", &GameConnection::cfDutyAccepted );
|
||||
setZoneHandler( ClientZoneIpcType::CFCancelHandler, "CFCancel", &GameConnection::cfCancel );
|
||||
//setZoneHandler( ClientZoneIpcType::CFCancelHandler, "CFCancel", &GameConnection::cfCancel );
|
||||
|
||||
setZoneHandler( ClientZoneIpcType::ReqEquipDisplayFlagsChange, "ReqEquipDisplayFlagsChange",
|
||||
&GameConnection::reqEquipDisplayFlagsHandler );
|
||||
|
|
|
@ -181,6 +181,10 @@ namespace Sapphire::Network
|
|||
|
||||
DECLARE_HANDLER( reqMoveHousingItem );
|
||||
|
||||
DECLARE_HANDLER( housingEditExterior );
|
||||
|
||||
DECLARE_HANDLER( housingEditInterior );
|
||||
|
||||
DECLARE_HANDLER( marketBoardSearch );
|
||||
|
||||
DECLARE_HANDLER( marketBoardRequestItemInfo );
|
||||
|
@ -190,6 +194,8 @@ namespace Sapphire::Network
|
|||
DECLARE_HANDLER( worldInteractionhandler );
|
||||
|
||||
DECLARE_HANDLER( diveHandler );
|
||||
|
||||
DECLARE_HANDLER( eventYieldHandler );
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Network/GameConnection.h"
|
||||
#include "Network/PacketWrappers/ServerNoticePacket.h"
|
||||
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
|
||||
#include "Network/PacketDef/Zone/ClientZoneDef.h"
|
||||
|
||||
#include "Session.h"
|
||||
|
||||
|
@ -43,9 +44,6 @@ void Sapphire::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_
|
|||
Entity::Player& player )
|
||||
{
|
||||
Packets::FFXIVARR_PACKET_RAW copy = inPacket;
|
||||
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
|
||||
std::vector< uint16_t > selectedContent;
|
||||
|
||||
for( uint32_t offset = 0x1E; offset <= 0x26; offset += 0x2 )
|
||||
|
@ -54,70 +52,75 @@ void Sapphire::Network::GameConnection::cfRegisterDuty( const Packets::FFXIVARR_
|
|||
if( id == 0 )
|
||||
break;
|
||||
|
||||
player.sendDebug( "got contentId#{0}", id );
|
||||
player.sendDebug( "got contentFinderConditionId#{0}", id );
|
||||
|
||||
selectedContent.push_back( id );
|
||||
}
|
||||
|
||||
// todo: rand bias problem, will do for now tho
|
||||
auto index = static_cast< uint32_t >( std::rand() ) % selectedContent.size();
|
||||
auto contentId = selectedContent.at( index );
|
||||
auto contentFinderConditionId = selectedContent.at( index );
|
||||
|
||||
player.sendDebug( "Duty register request for contentid#{0}", contentId );
|
||||
|
||||
// let's cancel it because otherwise you can't register it again
|
||||
/*
|
||||
auto cfCancelPacket = makeZonePacket< FFXIVIpcCFNotify >( player.getId() );
|
||||
cfCancelPacket->data().state1 = 3;
|
||||
cfCancelPacket->data().state2 = 1; // Your registration is withdrawn.
|
||||
queueOutPacket( cfCancelPacket );
|
||||
*/
|
||||
auto packet = makeZonePacket< FFXIVIpcCFCancel >( player.getId() );
|
||||
packet->data().cancelReason = 890;
|
||||
queueOutPacket( packet );
|
||||
|
||||
auto cfCondition = exdData.get< Sapphire::Data::ContentFinderCondition >( contentId );
|
||||
if( !cfCondition )
|
||||
return;
|
||||
|
||||
auto instance = teriMgr.createInstanceContent( cfCondition->content );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
auto pInstance = instance->getAsInstanceContent();
|
||||
pInstance->bindPlayer( player.getId() );
|
||||
|
||||
player.sendDebug( "Created instance with id#", instance->getGuId() );
|
||||
|
||||
player.setInstance( instance );
|
||||
player.sendDebug( "Duty register request for contentFinderConditionId#{0}", contentFinderConditionId );
|
||||
player.m_cfNotifiedContent = contentFinderConditionId;
|
||||
auto notify = makeZonePacket< FFXIVIpcCFNotify >( player.getId() );
|
||||
notify->data().state1 = 8195;
|
||||
notify->data().param3 = 1;
|
||||
notify->data().param4 = contentFinderConditionId;
|
||||
player.queuePacket( notify );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::cfRegisterRoulette( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
/*
|
||||
auto cfCancelPacket = makeZonePacket< FFXIVIpcCFNotify >( player.getId() );
|
||||
cfCancelPacket->data().state1 = 3;
|
||||
cfCancelPacket->data().state2 = 1; // Your registration is withdrawn.
|
||||
queueOutPacket( cfCancelPacket );
|
||||
*/
|
||||
auto packet = makeZonePacket< FFXIVIpcCFCancel >( player.getId() );
|
||||
packet->data().cancelReason = 890;
|
||||
queueOutPacket( packet );
|
||||
|
||||
player.sendDebug( "Roulette register" );
|
||||
player.sendDebug( "Roulette register not implemented." );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::cfDutyAccepted( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
player.sendDebug( "TODO: Duty accept" );
|
||||
}
|
||||
const auto packetIn = ZoneChannelPacket< Client::FFXIVIpcCFCommenceHandler >( inPacket );
|
||||
if( packetIn.data().param == 0 )
|
||||
{
|
||||
// accept
|
||||
if( player.m_cfNotifiedContent > 0 )
|
||||
{
|
||||
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
||||
|
||||
auto instance = teriMgr.createInstanceContent( player.m_cfNotifiedContent );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
player.m_cfNotifiedContent = 0;
|
||||
auto pInstance = instance->getAsInstanceContent();
|
||||
pInstance->bindPlayer( player.getId() );
|
||||
|
||||
player.sendDebug( "Created instance with id#{}", instance->getGuId() );
|
||||
|
||||
player.prepareZoning( pInstance->getTerritoryTypeId(), true, 1, 0, 0, 1, 9 );
|
||||
|
||||
player.setInstance( instance );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// cancel
|
||||
player.m_cfNotifiedContent = 0;
|
||||
auto packet = makeZonePacket< FFXIVIpcCFCancel >( player.getId() );
|
||||
packet->data().cancelReason = 890;
|
||||
queueOutPacket( packet );
|
||||
}
|
||||
}
|
||||
/*
|
||||
void Sapphire::Network::GameConnection::cfCancel( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
auto packet = makeZonePacket< FFXIVIpcCFCancel >( player.getId() );
|
||||
packet->data().cancelReason = 890;
|
||||
queueOutPacket( packet );
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -475,6 +475,14 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::RequestEstateHallRemoval:
|
||||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
|
||||
housingMgr.removeHouse( player, static_cast< uint16_t >( param11 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::UpdateEstateGuestAccess:
|
||||
{
|
||||
auto canTeleport = ( param2 & 0xFF ) == 1;
|
||||
|
@ -494,7 +502,27 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX
|
|||
player.sendDebug( "event battle p1: {0}, p11: {1}, p12: {2}, p2: {3}, p3: {4}, p4: {5}, p5: {6}", param1, param11, param12, param2, param3, param4, param5 );
|
||||
break;
|
||||
}
|
||||
|
||||
case ClientTriggerType::CutscenePlayed:
|
||||
{
|
||||
player.sendDebug( "cutscene: {}", param1 );
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::OpenPerformInstrumentUI:
|
||||
{
|
||||
//param11 = instrument, 0 = end
|
||||
player.sendDebug( "perform: {}", param11 );
|
||||
if( param11 == 0 )
|
||||
{
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 1, 0, 0, 0 ), true );
|
||||
player.unsetStateFlag( PlayerStateFlag::Performing );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControl::SetStatus, 16, param11, 0, 0 ), true );
|
||||
player.setStateFlag( PlayerStateFlag::Performing );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Logger::debug( "[{0}] Unhandled action: {1:04X}", m_pSession->getId(), commandId );
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "Territory/InstanceContent.h"
|
||||
#include "Territory/QuestBattle.h"
|
||||
#include "Territory/PublicContent.h"
|
||||
|
||||
#include "Session.h"
|
||||
|
||||
|
@ -59,6 +60,14 @@ void Sapphire::Network::GameConnection::eventHandlerTalk( const Packets::FFXIVAR
|
|||
{
|
||||
instance->onTalk( player, eventId, actorId );
|
||||
}
|
||||
else if( auto instance = player.getCurrentQuestBattle() )
|
||||
{
|
||||
instance->onTalk( player, eventId, actorId );
|
||||
}
|
||||
else if( auto instance = player.getCurrentPublicContent() )
|
||||
{
|
||||
instance->onTalk( player, eventId, actorId );
|
||||
}
|
||||
else if( !scriptMgr.onTalk( player, actorId, eventId ) &&
|
||||
eventType == Event::EventHandler::EventHandlerType::Quest )
|
||||
{
|
||||
|
@ -180,6 +189,11 @@ void Sapphire::Network::GameConnection::eventHandlerEnterTerritory( const Packet
|
|||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 1, player.getZoneId() );
|
||||
instance->onEnterTerritory( player, eventId, param1, param2 );
|
||||
}
|
||||
else if( auto instance = player.getCurrentPublicContent() )
|
||||
{
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 1, player.getZoneId() );
|
||||
instance->onEnterTerritory( player, eventId, param1, param2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() );
|
||||
|
@ -273,5 +287,39 @@ void Sapphire::Network::GameConnection::eventHandlerShop( const Packets::FFXIVAR
|
|||
scriptMgr.onTalk( player, player.getId(), eventId );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::eventYieldHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
||||
{
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
auto& eventMgr = Common::Service< World::Manager::EventMgr >::ref();
|
||||
|
||||
auto opcode = *reinterpret_cast< const uint16_t* >( &inPacket.data[ 2 ] );
|
||||
auto eventId = *reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 + 0 ] );
|
||||
auto scene = *reinterpret_cast< const uint16_t* >( &inPacket.data[ 0x10 + 4 ] );
|
||||
auto pParam = reinterpret_cast< const uint32_t* >( &inPacket.data[ 0x10 + 8 ] );
|
||||
|
||||
std::vector< uint32_t > param;
|
||||
|
||||
switch( opcode )
|
||||
{
|
||||
case EventYield16Handler:
|
||||
{
|
||||
for( int i = 0; i < 16; i++ )
|
||||
{
|
||||
param.push_back( pParam[ i ] );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string eventName = "onEventYield";
|
||||
std::string objName = eventMgr.getEventName( eventId );
|
||||
player.sendDebug( "Calling: {0}.{1} - {2} scene: {3}", objName, eventName, eventId, scene );
|
||||
|
||||
scriptMgr.onEventYield( player, eventId, scene, param );
|
||||
|
||||
auto response = makeZonePacket< FFXIVIpcEventContinue >( player.getId() );
|
||||
response->data().eventId = eventId;
|
||||
response->data().scene = scene;
|
||||
player.queuePacket( response );
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "Territory/Territory.h"
|
||||
#include "Territory/HousingZone.h"
|
||||
#include "Territory/Housing/HousingInteriorTerritory.h"
|
||||
#include "Territory/Land.h"
|
||||
#include "Territory/ZonePosition.h"
|
||||
#include "Territory/House.h"
|
||||
|
@ -386,15 +387,18 @@ void Sapphire::Network::GameConnection::pingHandler( const Packets::FFXIVARR_PAC
|
|||
void Sapphire::Network::GameConnection::finishLoadingHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
player.sendQuestInfo();
|
||||
if( player.isLogin() )
|
||||
{
|
||||
player.sendQuestInfo();
|
||||
|
||||
// TODO: load and save this data instead of hardcoding
|
||||
auto gcPacket = makeZonePacket< FFXIVGCAffiliation >( player.getId() );
|
||||
gcPacket->data().gcId = player.getGc();
|
||||
gcPacket->data().gcRank[ 0 ] = player.getGcRankArray()[ 0 ];
|
||||
gcPacket->data().gcRank[ 1 ] = player.getGcRankArray()[ 1 ];
|
||||
gcPacket->data().gcRank[ 2 ] = player.getGcRankArray()[ 2 ];
|
||||
player.queuePacket( gcPacket );
|
||||
// TODO: load and save this data instead of hardcoding
|
||||
auto gcPacket = makeZonePacket< FFXIVGCAffiliation >( player.getId() );
|
||||
gcPacket->data().gcId = player.getGc();
|
||||
gcPacket->data().gcRank[ 0 ] = player.getGcRankArray()[ 0 ];
|
||||
gcPacket->data().gcRank[ 1 ] = player.getGcRankArray()[ 1 ];
|
||||
gcPacket->data().gcRank[ 2 ] = player.getGcRankArray()[ 2 ];
|
||||
player.queuePacket( gcPacket );
|
||||
}
|
||||
|
||||
player.getCurrentTerritory()->onFinishLoading( player );
|
||||
|
||||
|
@ -607,7 +611,7 @@ void Sapphire::Network::GameConnection::performNoteHandler( const Packets::FFXIV
|
|||
Entity::Player& player )
|
||||
{
|
||||
auto performPacket = makeZonePacket< FFXIVIpcPerformNote >( player.getId() );
|
||||
memcpy( &performPacket->data().data[ 0 ], &inPacket.data[ 0x10 ], 32 );
|
||||
memcpy( &performPacket->data().data[ 0 ], &inPacket.data[ 0x10 ], 16 );
|
||||
player.sendToInRangeSet( performPacket );
|
||||
}
|
||||
|
||||
|
@ -691,6 +695,46 @@ void Sapphire::Network::GameConnection::reqMoveHousingItem( const Packets::FFXIV
|
|||
housingMgr.reqMoveHousingItem( player, data.ident, data.slot, data.pos, data.rotation );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::housingEditExterior( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
||||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcHousingEditExterior >( inPacket );
|
||||
auto terri = std::dynamic_pointer_cast< HousingZone >( player.getCurrentTerritory() );
|
||||
if( !terri )
|
||||
return;
|
||||
|
||||
std::vector< uint16_t > containerList;
|
||||
std::vector< uint8_t > slotList;
|
||||
for( int i = 0; i < 9; i++ )
|
||||
{
|
||||
auto container = packet.data().container[i];
|
||||
containerList.push_back( container );
|
||||
slotList.push_back( container != 0x270F ? static_cast< uint8_t >( packet.data().slot[i] ) : 0xFF );
|
||||
}
|
||||
|
||||
housingMgr.editAppearance( false, player, terri->getLand( packet.data().landId )->getLandIdent(), containerList, slotList, packet.data().removeFlag );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::housingEditInterior( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
||||
{
|
||||
auto& housingMgr = Common::Service< HousingMgr >::ref();
|
||||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcHousingEditInterior >( inPacket );
|
||||
auto terri = std::dynamic_pointer_cast< World::Territory::Housing::HousingInteriorTerritory >( player.getCurrentTerritory() );
|
||||
if( !terri )
|
||||
return;
|
||||
|
||||
std::vector< uint16_t > containerList;
|
||||
std::vector< uint8_t > slotList;
|
||||
for( int i = 0; i < 10; i++ )
|
||||
{
|
||||
auto container = packet.data().container[i];
|
||||
containerList.push_back( container );
|
||||
slotList.push_back( container != 0x270F ? static_cast< uint8_t >( packet.data().slot[i] ) : 0xFF );
|
||||
}
|
||||
|
||||
housingMgr.editAppearance( true, player, terri->getLandIdent(), containerList, slotList, 0 );
|
||||
}
|
||||
|
||||
void Sapphire::Network::GameConnection::marketBoardSearch( const Packets::FFXIVARR_PACKET_RAW& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
|
@ -746,12 +790,12 @@ void Sapphire::Network::GameConnection::worldInteractionhandler( const Packets::
|
|||
break;
|
||||
|
||||
player.setPos( packet.data().position );
|
||||
player.setRot( Util::floatFromUInt16Rot( param4 ) );
|
||||
if( emote == 0x32 && player.hasInRangeActor() )
|
||||
{
|
||||
auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setpos->data().r16 = param4;
|
||||
setpos->data().waitForLoad = 18;
|
||||
setpos->data().unknown1 = 1;
|
||||
setpos->data().x = packet.data().position.x;
|
||||
setpos->data().y = packet.data().position.y;
|
||||
setpos->data().z = packet.data().position.z;
|
||||
|
@ -781,7 +825,6 @@ void Sapphire::Network::GameConnection::worldInteractionhandler( const Packets::
|
|||
auto setpos = makeZonePacket< FFXIVIpcActorSetPos >( player.getId() );
|
||||
setpos->data().r16 = param2;
|
||||
setpos->data().waitForLoad = 18;
|
||||
setpos->data().unknown1 = 2;
|
||||
setpos->data().x = packet.data().position.x;
|
||||
setpos->data().y = packet.data().position.y;
|
||||
setpos->data().z = packet.data().position.z;
|
||||
|
|
|
@ -22,15 +22,15 @@ namespace Sapphire::Network::Packets::Server
|
|||
uint32_t param3 = 0,
|
||||
uint32_t param4 = 0,
|
||||
uint32_t param5 = 0,
|
||||
uint32_t padding1 = 0 ) :
|
||||
uint32_t param6 = 0 ) :
|
||||
ZoneChannelPacket< FFXIVIpcActorControlSelf >( actorId, actorId )
|
||||
{
|
||||
initialize( category, param1, param2, param3, param4, param5 );
|
||||
initialize( category, param1, param2, param3, param4, param5, param6 );
|
||||
};
|
||||
|
||||
private:
|
||||
void initialize( uint16_t category, uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
|
||||
uint32_t param5 )
|
||||
uint32_t param5, uint32_t param6 )
|
||||
{
|
||||
m_data.padding = 0;
|
||||
m_data.category = category;
|
||||
|
@ -39,6 +39,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
m_data.param3 = param3;
|
||||
m_data.param4 = param4;
|
||||
m_data.param5 = param5;
|
||||
m_data.param6 = param6;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Sapphire::Network::Packets::Server
|
|||
memcpy( m_data.aetheryte, player.getAetheryteArray(), sizeof( m_data.aetheryte ) );
|
||||
|
||||
// Set the class levels and exp.
|
||||
for( uint8_t i = 0; i < 25; i++ )
|
||||
for( uint8_t i = 0; i < Common::CLASSJOB_SLOTS; i++ )
|
||||
{
|
||||
m_data.levels[ i ] = player.getClassArray()[ i ];
|
||||
m_data.exp[ i ] = player.getExpArray()[ i ];
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "Forwards.h"
|
||||
#include "Inventory/Item.h"
|
||||
#include "StatusEffect/StatusEffect.h"
|
||||
#include "Territory/Territory.h"
|
||||
#include "Event/Director.h"
|
||||
|
||||
namespace Sapphire::Network::Packets::Server
|
||||
{
|
||||
|
@ -143,6 +145,10 @@ namespace Sapphire::Network::Packets::Server
|
|||
m_data.effect[ effect.first ].param = effect.second->getParam();
|
||||
}
|
||||
|
||||
if( auto d = player.getCurrentTerritory()->getAsDirector() )
|
||||
{
|
||||
m_data.directorId = d->getDirectorId();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
#include <Event/EventHandler.h>
|
||||
#include "NativeScriptApi.h"
|
||||
#include <cassert>
|
||||
|
||||
|
@ -134,6 +133,15 @@ namespace Sapphire::ScriptAPI
|
|||
{
|
||||
}
|
||||
|
||||
void EventScript::onEventYield( Sapphire::Entity::Player& player, uint16_t scene, std::vector< uint32_t > param )
|
||||
{
|
||||
}
|
||||
|
||||
Event::EventHandler::QuestAvailability EventScript::getQuestAvailability( Sapphire::Entity::Player& player, uint32_t eventId )
|
||||
{
|
||||
return Event::EventHandler::QuestAvailability::Available;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
EventObjectScript::EventObjectScript( uint32_t eobjId ) :
|
||||
|
@ -216,5 +224,31 @@ namespace Sapphire::ScriptAPI
|
|||
{
|
||||
}
|
||||
|
||||
PublicContentScript::PublicContentScript( uint32_t contentId ) :
|
||||
ScriptObject( uint32_t{ 0x8004 } << 16 | contentId, typeid( PublicContentScript ).hash_code() )
|
||||
{
|
||||
}
|
||||
|
||||
void PublicContentScript::onInit( PublicContent& instance )
|
||||
{
|
||||
}
|
||||
|
||||
void PublicContentScript::onUpdate( PublicContent& instance, uint64_t tickCount )
|
||||
{
|
||||
}
|
||||
|
||||
void PublicContentScript::onPlayerZoneIn( PublicContent& instance, Entity::Player& player )
|
||||
{
|
||||
}
|
||||
|
||||
void PublicContentScript::onLeaveTerritory( PublicContent& instance, Entity::Player& player )
|
||||
{
|
||||
}
|
||||
|
||||
void PublicContentScript::onEnterTerritory( PublicContent& instance, Entity::Player& player, uint32_t eventId,
|
||||
uint16_t param1, uint16_t param2 )
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define NATIVE_SCRIPT_API
|
||||
|
||||
#include <string>
|
||||
#include <Event/EventHandler.h>
|
||||
#include "ForwardsZone.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -166,6 +167,10 @@ namespace Sapphire::ScriptAPI
|
|||
uint32_t catalogId );
|
||||
|
||||
virtual void onEObjHit( Sapphire::Entity::Player& player, uint64_t actorId, uint32_t actionId );
|
||||
|
||||
virtual void onEventYield( Sapphire::Entity::Player& player, uint16_t scene, std::vector< uint32_t > param );
|
||||
|
||||
virtual Event::EventHandler::QuestAvailability getQuestAvailability( Sapphire::Entity::Player& player, uint32_t eventId );
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -237,6 +242,23 @@ namespace Sapphire::ScriptAPI
|
|||
uint16_t param1, uint16_t param2 );
|
||||
};
|
||||
|
||||
class PublicContentScript : public ScriptObject
|
||||
{
|
||||
public:
|
||||
explicit PublicContentScript( uint32_t contentId );
|
||||
|
||||
virtual void onInit( Sapphire::PublicContent& instance );
|
||||
|
||||
virtual void onUpdate( Sapphire::PublicContent& instance, uint64_t tickCount );
|
||||
|
||||
virtual void onPlayerZoneIn( Sapphire::PublicContent& instance, Sapphire::Entity::Player& player );
|
||||
|
||||
virtual void onLeaveTerritory( Sapphire::PublicContent& instance, Sapphire::Entity::Player& player );
|
||||
|
||||
virtual void onEnterTerritory( Sapphire::PublicContent& instance, Sapphire::Entity::Player& player, uint32_t eventId,
|
||||
uint16_t param1, uint16_t param2 );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Territory/Territory.h"
|
||||
#include "Territory/InstanceContent.h"
|
||||
#include "Territory/QuestBattle.h"
|
||||
#include "Territory/PublicContent.h"
|
||||
#include "Actor/Player.h"
|
||||
#include "Actor/EventObject.h"
|
||||
#include "ServerMgr.h"
|
||||
|
@ -530,8 +531,7 @@ Sapphire::Scripting::NativeScriptMgr& Sapphire::Scripting::ScriptMgr::getNativeS
|
|||
return *m_nativeScriptMgr;
|
||||
}
|
||||
|
||||
bool
|
||||
Sapphire::Scripting::ScriptMgr::onDutyComplete( Sapphire::QuestBattlePtr instance, Sapphire::Entity::Player& player )
|
||||
bool Sapphire::Scripting::ScriptMgr::onDutyComplete( Sapphire::QuestBattlePtr instance, Sapphire::Entity::Player& player )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::QuestBattleScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
|
@ -542,3 +542,77 @@ Sapphire::Scripting::ScriptMgr::onDutyComplete( Sapphire::QuestBattlePtr instanc
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sapphire::Scripting::ScriptMgr::onEventYield( Sapphire::Entity::Player& player, uint32_t eventId, uint16_t scene, std::vector< uint32_t > param )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( eventId );
|
||||
if( script )
|
||||
{
|
||||
script->onEventYield( player, scene, param );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sapphire::Scripting::ScriptMgr::onPublicContentInit( PublicContentPtr instance )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
{
|
||||
script->onInit( *instance );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sapphire::Scripting::ScriptMgr::onPublicContentUpdate( PublicContentPtr instance, uint64_t tickCount )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
|
||||
|
||||
if( script )
|
||||
{
|
||||
script->onUpdate( *instance, tickCount );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sapphire::Scripting::ScriptMgr::onPublicContentPlayerZoneIn( PublicContentPtr instance, Entity::Player& player )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
{
|
||||
script->onPlayerZoneIn( *instance, player );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sapphire::Scripting::ScriptMgr::onPublicContentLeaveTerritory( PublicContentPtr instance, Entity::Player& player )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
{
|
||||
script->onLeaveTerritory( *instance, player );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sapphire::Scripting::ScriptMgr::onPublicContentEnterTerritory( PublicContentPtr instance, Entity::Player& player,
|
||||
uint32_t eventId, uint16_t param1, uint16_t param2 )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::PublicContentScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
{
|
||||
script->onEnterTerritory( *instance, player, eventId, param1, param2 );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -112,6 +112,18 @@ namespace Sapphire::Scripting
|
|||
|
||||
bool onDutyComplete( QuestBattlePtr instance, Entity::Player& player );
|
||||
|
||||
bool onEventYield( Entity::Player& player, uint32_t eventId, uint16_t scene, std::vector< uint32_t > param );
|
||||
|
||||
bool onPublicContentInit( PublicContentPtr instance );
|
||||
|
||||
bool onPublicContentUpdate( PublicContentPtr instance, uint64_t tickCount );
|
||||
|
||||
bool onPublicContentPlayerZoneIn( PublicContentPtr instance, Entity::Player& player );
|
||||
|
||||
bool onPublicContentLeaveTerritory( PublicContentPtr instance, Entity::Player& player );
|
||||
|
||||
bool onPublicContentEnterTerritory( PublicContentPtr instance, Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 );
|
||||
|
||||
bool loadDir( const std::string& dirname, std::set< std::string >& files, const std::string& ext );
|
||||
|
||||
NativeScriptMgr& getNativeScriptHandler();
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "Manager/RNGMgr.h"
|
||||
#include "Manager/NaviMgr.h"
|
||||
#include "Manager/ActionMgr.h"
|
||||
#include "Manager/MapMgr.h"
|
||||
|
||||
#include "Territory/InstanceObjectCache.h"
|
||||
|
||||
|
@ -173,6 +174,10 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] )
|
|||
auto pInstanceObjCache = std::make_shared< Sapphire::InstanceObjectCache >();
|
||||
Common::Service< Sapphire::InstanceObjectCache >::set( pInstanceObjCache );
|
||||
|
||||
Logger::info( "MapMgr: Caching quests" );
|
||||
auto pMapMgr = std::make_shared< Manager::MapMgr >();
|
||||
Common::Service< Manager::MapMgr >::set( pMapMgr );
|
||||
|
||||
auto pActionMgr = std::make_shared< Manager::ActionMgr >();
|
||||
Common::Service< Manager::ActionMgr >::set( pActionMgr );
|
||||
|
||||
|
|
|
@ -64,6 +64,11 @@ Sapphire::House::ExteriorModelsArray const& Sapphire::House::getHouseModels() co
|
|||
return m_exteriorModelCache;
|
||||
}
|
||||
|
||||
void Sapphire::House::clearModelCache()
|
||||
{
|
||||
m_exteriorModelCache.fill( std::make_pair( 0, 0 ) );
|
||||
}
|
||||
|
||||
const std::string& Sapphire::House::getHouseName() const
|
||||
{
|
||||
return m_estateName;
|
||||
|
|
|
@ -41,6 +41,8 @@ namespace Sapphire
|
|||
|
||||
ExteriorModelsArray const& getHouseModels() const;
|
||||
|
||||
void clearModelCache();
|
||||
|
||||
void updateHouseDb();
|
||||
|
||||
void setHasAetheryte( bool hasAetheryte );
|
||||
|
|
|
@ -321,6 +321,23 @@ Sapphire::Entity::EventObjectPtr Sapphire::HousingZone::registerEstateEntranceEO
|
|||
return eObj;
|
||||
}
|
||||
|
||||
void Sapphire::HousingZone::removeEstateEntranceEObj( uint8_t landId )
|
||||
{
|
||||
auto land = getLand( landId );
|
||||
assert( land );
|
||||
|
||||
for( auto entry : m_eventObjects )
|
||||
{
|
||||
auto eObj = entry.second;
|
||||
if( eObj->getHousingLink() == landId << 8 )
|
||||
{
|
||||
removeActor( eObj );
|
||||
m_eventObjects.erase( entry.first );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::HousingZone::updateYardObjects( Sapphire::Common::LandIdent ident )
|
||||
{
|
||||
auto& housingMgr = Common::Service< World::Manager::HousingMgr >::ref();
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace Sapphire
|
|||
Sapphire::LandPtr getLand( uint8_t id );
|
||||
|
||||
Entity::EventObjectPtr registerEstateEntranceEObj( uint8_t landId );
|
||||
void removeEstateEntranceEObj( uint8_t landId );
|
||||
|
||||
void updateYardObjects( Common::LandIdent ident );
|
||||
void spawnYardObject( uint8_t landId, uint16_t slotId, Sapphire::Inventory::HousingItem& item );
|
||||
|
|
|
@ -32,9 +32,9 @@ Sapphire::InstanceContent::InstanceContent( std::shared_ptr< Sapphire::Data::Ins
|
|||
uint32_t guId,
|
||||
const std::string& internalName,
|
||||
const std::string& contentName,
|
||||
uint32_t instanceContentId ) :
|
||||
uint32_t instanceContentId, uint16_t contentFinderConditionId ) :
|
||||
Territory( static_cast< uint16_t >( territoryType ), guId, internalName, contentName ),
|
||||
Director( Event::Director::InstanceContent, instanceContentId ),
|
||||
Director( Event::Director::InstanceContent, instanceContentId, contentFinderConditionId ),
|
||||
m_instanceConfiguration( pInstanceConfiguration ),
|
||||
m_instanceContentId( instanceContentId ),
|
||||
m_state( Created ),
|
||||
|
@ -80,11 +80,7 @@ void Sapphire::InstanceContent::onPlayerZoneIn( Entity::Player& player )
|
|||
// mark player as "bound by duty"
|
||||
player.setStateFlag( PlayerStateFlag::BoundByDuty );
|
||||
|
||||
// if the instance was not started yet, director init is sent on enter event.
|
||||
// else it will be sent on finish loading.
|
||||
if( m_state == Created )
|
||||
sendDirectorInit( player );
|
||||
|
||||
sendDirectorInit( player );
|
||||
}
|
||||
|
||||
void Sapphire::InstanceContent::onLeaveTerritory( Entity::Player& player )
|
||||
|
@ -164,7 +160,6 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount )
|
|||
|
||||
void Sapphire::InstanceContent::onFinishLoading( Entity::Player& player )
|
||||
{
|
||||
sendDirectorInit( player );
|
||||
}
|
||||
|
||||
void Sapphire::InstanceContent::onInitDirector( Entity::Player& player )
|
||||
|
@ -310,6 +305,8 @@ void Sapphire::InstanceContent::onRegisterEObj( Entity::EventObjectPtr object )
|
|||
m_eventObjectMap[ object->getName() ] = object;
|
||||
if( object->getObjectId() == 2000182 ) // start
|
||||
m_pEntranceEObj = object;
|
||||
if( m_pEntranceEObj == nullptr && object->getName() == "Entrance" )
|
||||
m_pEntranceEObj = object;
|
||||
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto objData = exdData.get< Sapphire::Data::EObj >( object->getObjectId() );
|
||||
|
@ -375,7 +372,7 @@ void Sapphire::InstanceContent::onTalk( Sapphire::Entity::Player& player, uint32
|
|||
return;
|
||||
|
||||
if( auto onTalk = it->second->getOnTalkHandler() )
|
||||
onTalk( player, it->second, getAsInstanceContent(), actorId );
|
||||
onTalk( player, it->second, getAsInstanceContent(), eventId, actorId );
|
||||
else
|
||||
player.sendDebug( "No onTalk handler found for interactable eobj with EObjID#{0}, eventId#{1} ",
|
||||
it->second->getObjectId(), eventId );
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Sapphire
|
|||
uint32_t guId,
|
||||
const std::string& internalName,
|
||||
const std::string& contentName,
|
||||
uint32_t instanceContentId );
|
||||
uint32_t instanceContentId, uint16_t contentFinderConditionId = 0 );
|
||||
|
||||
virtual ~InstanceContent();
|
||||
|
||||
|
|
|
@ -41,16 +41,23 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
// 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::string planeventLgbPath( path + "/level/planevent.lgb" );
|
||||
std::string plannerLgbPath( path + "/level/planner.lgb" );
|
||||
std::vector< char > bgSection;
|
||||
std::vector< char > planmapSection;
|
||||
std::vector< char > planeventSection;
|
||||
std::vector< char > plannerSection;
|
||||
|
||||
std::unique_ptr< xiv::dat::File > bgFile;
|
||||
std::unique_ptr< xiv::dat::File > planmap_file;
|
||||
std::unique_ptr< xiv::dat::File > planevent_file;
|
||||
std::unique_ptr< xiv::dat::File > planner_file;
|
||||
|
||||
try
|
||||
{
|
||||
bgFile = exdData.getGameData()->getFile( bgLgbPath );
|
||||
planmap_file = exdData.getGameData()->getFile( planmapLgbPath );
|
||||
planevent_file = exdData.getGameData()->getFile( planeventLgbPath );
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
{
|
||||
|
@ -60,6 +67,7 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
|
||||
bgSection = bgFile->access_data_sections().at( 0 );
|
||||
planmapSection = planmap_file->access_data_sections().at( 0 );
|
||||
planeventSection = planevent_file->access_data_sections().at( 0 );
|
||||
|
||||
std::vector< std::string > stringList;
|
||||
|
||||
|
@ -67,8 +75,23 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
|
||||
LGB_FILE bgLgb( &bgSection[ 0 ], "bg" );
|
||||
LGB_FILE planmapLgb( &planmapSection[ 0 ], "planmap" );
|
||||
LGB_FILE planeventLgb( &planeventSection[ 0 ], "planevent" );
|
||||
|
||||
std::vector< LGB_FILE > lgbList;
|
||||
|
||||
try
|
||||
{
|
||||
planner_file = exdData.getGameData()->getFile( plannerLgbPath );
|
||||
plannerSection = planner_file->access_data_sections().at( 0 );
|
||||
LGB_FILE plannerLgb( &plannerSection[ 0 ], "planner" );
|
||||
|
||||
lgbList = { bgLgb, planmapLgb, planeventLgb, plannerLgb };
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
{
|
||||
lgbList = { bgLgb, planmapLgb, planeventLgb };
|
||||
}
|
||||
|
||||
std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb };
|
||||
uint32_t max_index = 0;
|
||||
|
||||
for( const auto& lgb : lgbList )
|
||||
|
@ -92,6 +115,16 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
auto pPopRange = std::reinterpret_pointer_cast< LGB_POP_RANGE_ENTRY >( pEntry );
|
||||
m_popRangeCache.insert( id, pPopRange );
|
||||
}
|
||||
else if( pEntry->getType() == LgbEntryType::EventNpc )
|
||||
{
|
||||
auto pEventNpc = std::reinterpret_pointer_cast< LGB_ENPC_ENTRY >( pEntry );
|
||||
m_eventNpcCache.insert( id, pEventNpc );
|
||||
}
|
||||
else if( pEntry->getType() == LgbEntryType::EventObject )
|
||||
{
|
||||
auto pEventObj = std::reinterpret_pointer_cast< LGB_EOBJ_ENTRY >( pEntry );
|
||||
m_eventObjCache.insert( id, pEventObj );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,8 +132,8 @@ Sapphire::InstanceObjectCache::InstanceObjectCache()
|
|||
std::cout << "\n";
|
||||
|
||||
Logger::debug(
|
||||
"InstanceObjectCache Cached: MapRange: {} ExitRange: {} PopRange: {}",
|
||||
m_mapRangeCache.size(), m_exitRangeCache.size(), m_popRangeCache.size()
|
||||
"InstanceObjectCache Cached: MapRange: {} ExitRange: {} PopRange: {} ENpc: {} Eobj: {}",
|
||||
m_mapRangeCache.size(), m_exitRangeCache.size(), m_popRangeCache.size(), m_eventNpcCache.size(), m_eventObjCache.size()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -121,4 +154,28 @@ Sapphire::InstanceObjectCache::PopRangePtr
|
|||
Sapphire::InstanceObjectCache::getPopRange( uint16_t zoneId, uint32_t popRangeId )
|
||||
{
|
||||
return m_popRangeCache.get( zoneId, popRangeId );
|
||||
}
|
||||
|
||||
Sapphire::InstanceObjectCache::EventNpcPtr
|
||||
Sapphire::InstanceObjectCache::getEventNpc( uint16_t zoneId, uint32_t eventNpcId )
|
||||
{
|
||||
return m_eventNpcCache.get( zoneId, eventNpcId );
|
||||
}
|
||||
|
||||
Sapphire::InstanceObjectCache::EventObjPtr
|
||||
Sapphire::InstanceObjectCache::getEventObj( uint16_t zoneId, uint32_t eventObjId )
|
||||
{
|
||||
return m_eventObjCache.get( zoneId, eventObjId );
|
||||
}
|
||||
|
||||
Sapphire::InstanceObjectCache::EventNpcMapPtr
|
||||
Sapphire::InstanceObjectCache::getAllEventNpc( uint16_t zoneId )
|
||||
{
|
||||
return m_eventNpcCache.getAll( zoneId );
|
||||
}
|
||||
|
||||
Sapphire::InstanceObjectCache::EventObjMapPtr
|
||||
Sapphire::InstanceObjectCache::getAllEventObj( uint16_t zoneId )
|
||||
{
|
||||
return m_eventObjCache.getAll( zoneId );
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
struct LGB_MAP_RANGE_ENTRY;
|
||||
struct LGB_EXIT_RANGE_ENTRY;
|
||||
struct LGB_POP_RANGE_ENTRY;
|
||||
struct LGB_ENPC_ENTRY;
|
||||
struct LGB_EOBJ_ENTRY;
|
||||
|
||||
|
||||
namespace Sapphire
|
||||
|
@ -37,6 +39,16 @@ namespace Sapphire
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ObjectMap* getAll( uint16_t zoneId )
|
||||
{
|
||||
auto it = m_objectCache.find( zoneId );
|
||||
if( it != m_objectCache.end() )
|
||||
{
|
||||
return &it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void insert( uint16_t zoneId, std::shared_ptr< T > entry )
|
||||
{
|
||||
|
@ -65,6 +77,11 @@ namespace Sapphire
|
|||
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 >;
|
||||
using EventNpcPtr = std::shared_ptr< LGB_ENPC_ENTRY >;
|
||||
using EventObjPtr = std::shared_ptr< LGB_EOBJ_ENTRY >;
|
||||
|
||||
using EventNpcMapPtr = std::unordered_map< uint32_t, EventNpcPtr >*;
|
||||
using EventObjMapPtr = std::unordered_map< uint32_t, EventObjPtr >*;
|
||||
|
||||
InstanceObjectCache();
|
||||
~InstanceObjectCache() = default;
|
||||
|
@ -72,11 +89,18 @@ namespace Sapphire
|
|||
MapRangePtr getMapRange( uint16_t zoneId, uint32_t mapRangeId );
|
||||
ExitRangePtr getExitRange( uint16_t zoneId, uint32_t exitRangeId );
|
||||
PopRangePtr getPopRange( uint16_t zoneId, uint32_t popRangeId );
|
||||
EventNpcPtr getEventNpc( uint16_t zoneId, uint32_t eventNpcId );
|
||||
EventObjPtr getEventObj( uint16_t zoneId, uint32_t eventObjId );
|
||||
|
||||
EventNpcMapPtr getAllEventNpc( uint16_t zoneId );
|
||||
EventObjMapPtr getAllEventObj( uint16_t zoneId );
|
||||
|
||||
private:
|
||||
ObjectCache< LGB_MAP_RANGE_ENTRY > m_mapRangeCache;
|
||||
ObjectCache< LGB_EXIT_RANGE_ENTRY > m_exitRangeCache;
|
||||
ObjectCache< LGB_POP_RANGE_ENTRY > m_popRangeCache;
|
||||
ObjectCache< LGB_ENPC_ENTRY > m_eventNpcCache;
|
||||
ObjectCache< LGB_EOBJ_ENTRY > m_eventObjCache;
|
||||
std::shared_ptr< Framework > m_pFramework;
|
||||
|
||||
};
|
||||
|
|
|
@ -240,5 +240,20 @@ void Sapphire::Land::update( uint64_t tickCount )
|
|||
|
||||
Sapphire::Land::InvMaxItemsPair Sapphire::Land::getInventoryItemMax() const
|
||||
{
|
||||
return std::make_pair( m_maxPlacedExternalItems, m_maxPlacedInternalItems );
|
||||
switch( m_size )
|
||||
{
|
||||
case HouseSize::Cottage:
|
||||
{
|
||||
return std::make_pair( 20, 200 );
|
||||
}
|
||||
case HouseSize::House:
|
||||
{
|
||||
return std::make_pair( 30, 300 );
|
||||
}
|
||||
case HouseSize::Mansion:
|
||||
{
|
||||
return std::make_pair( 40, 400 );
|
||||
}
|
||||
}
|
||||
assert( false );
|
||||
}
|
||||
|
|
|
@ -86,10 +86,6 @@ namespace Sapphire
|
|||
|
||||
Sapphire::HousePtr m_pHouse;
|
||||
|
||||
//item storage
|
||||
uint16_t m_maxPlacedExternalItems;
|
||||
uint16_t m_maxPlacedInternalItems;
|
||||
|
||||
//price
|
||||
uint32_t m_initPrice;
|
||||
uint32_t m_nextDrop;
|
||||
|
|
270
src/world/Territory/PublicContent.cpp
Normal file
270
src/world/Territory/PublicContent.cpp
Normal file
|
@ -0,0 +1,270 @@
|
|||
#include <Common.h>
|
||||
#include <Logging/Logger.h>
|
||||
#include <Util/Util.h>
|
||||
#include <Util/UtilMath.h>
|
||||
#include <Exd/ExdDataGenerated.h>
|
||||
#include <Network/CommonActorControl.h>
|
||||
#include <Service.h>
|
||||
|
||||
#include "Actor/Player.h"
|
||||
#include "Actor/EventObject.h"
|
||||
#include "Event/Director.h"
|
||||
#include "Event/EventDefs.h"
|
||||
#include "Event/EventHandler.h"
|
||||
#include "Script/ScriptMgr.h"
|
||||
|
||||
#include "Network/PacketWrappers/ActorControlPacket.h"
|
||||
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
||||
|
||||
#include "PublicContent.h"
|
||||
|
||||
using namespace Sapphire::Common;
|
||||
using namespace Sapphire::Network::Packets;
|
||||
using namespace Sapphire::Network::Packets::Server;
|
||||
using namespace Sapphire::Network::ActorControl;
|
||||
|
||||
Sapphire::PublicContent::PublicContent( std::shared_ptr< Sapphire::Data::PublicContent > pConfiguration,
|
||||
uint16_t territoryType,
|
||||
uint32_t guId,
|
||||
const std::string& internalName,
|
||||
const std::string& contentName,
|
||||
uint32_t contentId, uint16_t contentFinderConditionId ) :
|
||||
Territory( static_cast< uint16_t >( territoryType ), guId, internalName, contentName ),
|
||||
Director( Event::Director::PublicContent, contentId, contentFinderConditionId ),
|
||||
m_Configuration( pConfiguration ),
|
||||
m_ContentId( contentId )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Sapphire::PublicContent::init()
|
||||
{
|
||||
if( !Territory::init() )
|
||||
return false;
|
||||
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
scriptMgr.onPublicContentInit( getAsPublicContent() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Sapphire::PublicContent::~PublicContent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t Sapphire::PublicContent::getContentId() const
|
||||
{
|
||||
return m_ContentId;
|
||||
}
|
||||
|
||||
Sapphire::Data::ExdDataGenerated::PublicContentPtr Sapphire::PublicContent::getConfiguration() const
|
||||
{
|
||||
return m_Configuration;
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onPlayerZoneIn( Entity::Player& player )
|
||||
{
|
||||
Logger::debug( "PublicContent::onPlayerZoneIn: Territory#{0}|{1}, Entity#{2}", getGuId(), getTerritoryTypeId(), player.getId() );
|
||||
sendDirectorInit( player );
|
||||
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
scriptMgr.onPublicContentPlayerZoneIn( getAsPublicContent(), player );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onLeaveTerritory( Entity::Player& player )
|
||||
{
|
||||
Logger::debug( "PublicContent::onLeaveTerritory: Territory#{0}|{1}, Entity#{2}", getGuId(), getTerritoryTypeId(), player.getId() );
|
||||
clearDirector( player );
|
||||
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
scriptMgr.onPublicContentLeaveTerritory( getAsPublicContent(), player );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onUpdate( uint64_t tickCount )
|
||||
{
|
||||
updateBNpcs( tickCount );
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
scriptMgr.onPublicContentUpdate( getAsPublicContent(), tickCount );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onFinishLoading( Entity::Player& player )
|
||||
{
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onInitDirector( Entity::Player& player )
|
||||
{
|
||||
sendDirectorVars( player );
|
||||
player.setDirectorInitialized( true );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onDirectorSync( Entity::Player& player )
|
||||
{
|
||||
player.queuePacket( makeActorControlSelf( player.getId(), DirectorUpdate, 0x00110001, 0x80000000, 1 ) );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onBeforePlayerZoneIn( Sapphire::Entity::Player& player )
|
||||
{
|
||||
/*if( m_pEntranceEObj != nullptr )
|
||||
{
|
||||
player.setRot( PI );
|
||||
player.setPos( m_pEntranceEObj->getPos() );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.setRot( PI );
|
||||
player.setPos( { 0.f, 0.f, 0.f } );
|
||||
}*/
|
||||
player.resetObjSpawnIndex();
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 )
|
||||
{
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
scriptMgr.onPublicContentEnterTerritory( getAsPublicContent(), player, eventId, param1, param2 );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onRegisterEObj( Entity::EventObjectPtr object )
|
||||
{
|
||||
if( object->getName() != "none" )
|
||||
m_eventObjectMap[ object->getName() ] = object;
|
||||
if( object->getObjectId() == 2000182 ) // start
|
||||
m_pEntranceEObj = object;
|
||||
if( m_pEntranceEObj == nullptr && object->getName() == "Entrance" )
|
||||
m_pEntranceEObj = object;
|
||||
|
||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||
auto objData = exdData.get< Sapphire::Data::EObj >( object->getObjectId() );
|
||||
if( objData )
|
||||
m_eventIdToObjectMap[ objData->data ] = object;
|
||||
else
|
||||
Logger::error( "PublicContent::onRegisterEObj Territory " +
|
||||
m_internalName + ": No EObj data found for EObj with ID: " +
|
||||
std::to_string( object->getObjectId() ) );
|
||||
}
|
||||
|
||||
Sapphire::Entity::EventObjectPtr Sapphire::PublicContent::getEObjByName( const std::string& name )
|
||||
{
|
||||
auto it = m_eventObjectMap.find( name );
|
||||
if( it == m_eventObjectMap.end() )
|
||||
return nullptr;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::clearDirector( Entity::Player& player )
|
||||
{
|
||||
sendDirectorClear( player );
|
||||
player.setDirectorInitialized( false );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::onTalk( Sapphire::Entity::Player& player, uint32_t eventId, uint64_t actorId )
|
||||
{
|
||||
auto it = m_eventIdToObjectMap.find( eventId );
|
||||
if( it == m_eventIdToObjectMap.end() )
|
||||
return;
|
||||
|
||||
if( auto onTalk = it->second->getOnTalkHandler() )
|
||||
onTalk( player, it->second, getAsPublicContent(), eventId, actorId );
|
||||
else
|
||||
player.sendDebug( "No onTalk handler found for interactable eobj with EObjID#{0}, eventId#{1} ",
|
||||
it->second->getObjectId(), eventId );
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::setVar( uint8_t index, uint8_t value )
|
||||
{
|
||||
if( index > 19 )
|
||||
return;
|
||||
|
||||
switch( index )
|
||||
{
|
||||
case 0:
|
||||
setDirectorUI8AL( value );
|
||||
break;
|
||||
case 1:
|
||||
setDirectorUI8AH( value );
|
||||
break;
|
||||
case 2:
|
||||
setDirectorUI8BL( value );
|
||||
break;
|
||||
case 3:
|
||||
setDirectorUI8BH( value );
|
||||
break;
|
||||
case 4:
|
||||
setDirectorUI8CL( value );
|
||||
break;
|
||||
case 5:
|
||||
setDirectorUI8CH( value );
|
||||
break;
|
||||
case 6:
|
||||
setDirectorUI8DL( value );
|
||||
break;
|
||||
case 7:
|
||||
setDirectorUI8DH( value );
|
||||
break;
|
||||
case 8:
|
||||
setDirectorUI8EL( value );
|
||||
break;
|
||||
case 9:
|
||||
setDirectorUI8EH( value );
|
||||
break;
|
||||
case 10:
|
||||
setDirectorUI8FL( value );
|
||||
break;
|
||||
case 11:
|
||||
setDirectorUI8FH( value );
|
||||
break;
|
||||
case 12:
|
||||
setDirectorUI8GL( value );
|
||||
break;
|
||||
case 13:
|
||||
setDirectorUI8GH( value );
|
||||
break;
|
||||
case 14:
|
||||
setDirectorUI8HL( value );
|
||||
break;
|
||||
case 15:
|
||||
setDirectorUI8HH( value );
|
||||
break;
|
||||
case 16:
|
||||
setDirectorUI8IL( value );
|
||||
break;
|
||||
case 17:
|
||||
setDirectorUI8IH( value );
|
||||
break;
|
||||
case 18:
|
||||
setDirectorUI8JL( value );
|
||||
break;
|
||||
case 19:
|
||||
setDirectorUI8JH( value );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// todo: genericise this?
|
||||
for( const auto& playerIt : m_playerMap )
|
||||
{
|
||||
sendDirectorVars( *playerIt.second );
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::setSequence( uint8_t value )
|
||||
{
|
||||
setDirectorSequence( value );
|
||||
|
||||
for( const auto& playerIt : m_playerMap )
|
||||
{
|
||||
sendDirectorVars( *playerIt.second );
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::PublicContent::setBranch( uint8_t value )
|
||||
{
|
||||
setDirectorBranch( value );
|
||||
|
||||
for( const auto& playerIt : m_playerMap )
|
||||
{
|
||||
sendDirectorVars( *playerIt.second );
|
||||
}
|
||||
}
|
72
src/world/Territory/PublicContent.h
Normal file
72
src/world/Territory/PublicContent.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
#ifndef SAPPHIRE_PUBLICCONTENT_H
|
||||
#define SAPPHIRE_PUBLICCONTENT_H
|
||||
|
||||
#include "Territory.h"
|
||||
#include "Event/Director.h"
|
||||
#include "Forwards.h"
|
||||
|
||||
namespace Sapphire::Data
|
||||
{
|
||||
struct PublicContent;
|
||||
}
|
||||
|
||||
namespace Sapphire
|
||||
{
|
||||
class PublicContent : public Event::Director, public Territory
|
||||
{
|
||||
public:
|
||||
PublicContent( std::shared_ptr< Sapphire::Data::PublicContent > pConfiguration,
|
||||
uint16_t territoryType,
|
||||
uint32_t guId,
|
||||
const std::string& internalName,
|
||||
const std::string& contentName,
|
||||
uint32_t contentId, uint16_t contentFinderConditionId = 0 );
|
||||
|
||||
virtual ~PublicContent();
|
||||
|
||||
bool init() override;
|
||||
|
||||
void onBeforePlayerZoneIn( Entity::Player& player ) override;
|
||||
|
||||
void onPlayerZoneIn( Entity::Player& player ) override;
|
||||
|
||||
void onLeaveTerritory( Entity::Player& player ) override;
|
||||
|
||||
void onUpdate( uint64_t tickCount ) override;
|
||||
|
||||
void onFinishLoading( Entity::Player& player ) override;
|
||||
|
||||
void onInitDirector( Entity::Player& player ) override;
|
||||
|
||||
void onDirectorSync( Entity::Player& player ) override;
|
||||
|
||||
void onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override;
|
||||
|
||||
void onRegisterEObj( Entity::EventObjectPtr object ) override;
|
||||
|
||||
std::shared_ptr< Sapphire::Data::PublicContent > getConfiguration() const;
|
||||
|
||||
uint32_t getContentId() const;
|
||||
|
||||
Entity::EventObjectPtr getEObjByName( const std::string& name );
|
||||
|
||||
void clearDirector( Entity::Player& player );
|
||||
|
||||
void onTalk( Entity::Player& player, uint32_t eventId, uint64_t actorId );
|
||||
|
||||
void setSequence( uint8_t value );
|
||||
|
||||
void setBranch( uint8_t value );
|
||||
|
||||
void setVar( uint8_t index, uint8_t value );
|
||||
|
||||
private:
|
||||
std::shared_ptr< Sapphire::Data::PublicContent > m_Configuration;
|
||||
uint32_t m_ContentId;
|
||||
Entity::EventObjectPtr m_pEntranceEObj;
|
||||
std::map< std::string, Entity::EventObjectPtr > m_eventObjectMap;
|
||||
std::unordered_map< uint32_t, Entity::EventObjectPtr > m_eventIdToObjectMap;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //SAPPHIRE_PUBLICCONTENT_H
|
|
@ -34,9 +34,9 @@ Sapphire::QuestBattle::QuestBattle( std::shared_ptr< Sapphire::Data::QuestBattle
|
|||
uint32_t guId,
|
||||
const std::string& internalName,
|
||||
const std::string& contentName,
|
||||
uint32_t questBattleId ) :
|
||||
uint32_t questBattleId, uint16_t contentFinderConditionId ) :
|
||||
Territory( static_cast< uint16_t >( territoryType ), guId, internalName, contentName ),
|
||||
Director( Event::Director::QuestBattle, questBattleId ),
|
||||
Director( Event::Director::QuestBattle, questBattleId, contentFinderConditionId ),
|
||||
m_pBattleDetails( pBattleDetails ),
|
||||
m_questBattleId( questBattleId ),
|
||||
m_state( Created ),
|
||||
|
@ -330,7 +330,7 @@ void Sapphire::QuestBattle::onTalk( Sapphire::Entity::Player& player, uint32_t e
|
|||
return;
|
||||
|
||||
if( auto onTalkHandler = it->second->getOnTalkHandler() )
|
||||
onTalkHandler( player, it->second, getAsQuestBattle(), actorId );
|
||||
onTalkHandler( player, it->second, getAsQuestBattle(), eventId, actorId );
|
||||
else
|
||||
player.sendDebug( "No onTalk handler found for interactable eobj with EObjID#{0}, eventId#{1} ",
|
||||
it->second->getObjectId(), eventId );
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Sapphire
|
|||
uint32_t guId,
|
||||
const std::string& internalName,
|
||||
const std::string& contentName,
|
||||
uint32_t questBattleId );
|
||||
uint32_t questBattleId, uint16_t contentFinderConditionId = 0 );
|
||||
|
||||
virtual ~QuestBattle() = default;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Territory.h"
|
||||
#include "InstanceContent.h"
|
||||
#include "QuestBattle.h"
|
||||
#include "PublicContent.h"
|
||||
#include "Manager/TerritoryMgr.h"
|
||||
#include "Navi/NaviProvider.h"
|
||||
|
||||
|
@ -268,12 +269,7 @@ void Sapphire::Territory::pushActor( Entity::ActorPtr pActor )
|
|||
|
||||
void Sapphire::Territory::removeActor( Entity::ActorPtr pActor )
|
||||
{
|
||||
float mx = pActor->getPos().x;
|
||||
float my = pActor->getPos().z;
|
||||
uint32_t cx = getPosX( mx );
|
||||
uint32_t cy = getPosY( my );
|
||||
|
||||
Cell* pCell = getCellPtr( cx, cy );
|
||||
Cell* pCell = pActor->getCellPtr();
|
||||
if( pCell && pCell->hasActor( pActor ) )
|
||||
pCell->removeActorFromCell( pActor );
|
||||
|
||||
|
@ -780,6 +776,11 @@ Sapphire::Entity::EventObjectPtr Sapphire::Territory::getEObj( uint32_t objId )
|
|||
return obj->second;
|
||||
}
|
||||
|
||||
Sapphire::Event::DirectorPtr Sapphire::Territory::getAsDirector()
|
||||
{
|
||||
return std::dynamic_pointer_cast< Event::Director, Territory >( shared_from_this() );
|
||||
}
|
||||
|
||||
Sapphire::InstanceContentPtr Sapphire::Territory::getAsInstanceContent()
|
||||
{
|
||||
return std::dynamic_pointer_cast< InstanceContent, Territory >( shared_from_this() );
|
||||
|
@ -790,6 +791,11 @@ Sapphire::QuestBattlePtr Sapphire::Territory::getAsQuestBattle()
|
|||
return std::dynamic_pointer_cast< QuestBattle, Territory >( shared_from_this() );
|
||||
}
|
||||
|
||||
Sapphire::PublicContentPtr Sapphire::Territory::getAsPublicContent()
|
||||
{
|
||||
return std::dynamic_pointer_cast< PublicContent, Territory >( shared_from_this() );
|
||||
}
|
||||
|
||||
uint32_t Sapphire::Territory::getNextEObjId()
|
||||
{
|
||||
return ++m_nextEObjId;
|
||||
|
@ -1043,4 +1049,19 @@ void Sapphire::Territory::processEffectResults( uint64_t tickCount )
|
|||
|
||||
it = m_effectResults.erase( it );
|
||||
}
|
||||
}
|
||||
|
||||
Sapphire::Entity::PlayerPtr Sapphire::Territory::getPlayer( uint32_t charId )
|
||||
{
|
||||
return m_playerMap[ charId ];
|
||||
}
|
||||
|
||||
void Sapphire::Territory::foreachPlayer( std::function< void( Sapphire::Entity::PlayerPtr player ) > callback )
|
||||
{
|
||||
if( !callback )
|
||||
return;
|
||||
for( auto entry : m_playerMap )
|
||||
{
|
||||
callback( entry.second );
|
||||
}
|
||||
}
|
|
@ -166,10 +166,14 @@ namespace Sapphire
|
|||
|
||||
Entity::EventObjectPtr getEObj( uint32_t objId );
|
||||
|
||||
Event::DirectorPtr getAsDirector();
|
||||
|
||||
InstanceContentPtr getAsInstanceContent();
|
||||
|
||||
QuestBattlePtr getAsQuestBattle();
|
||||
|
||||
PublicContentPtr getAsPublicContent();
|
||||
|
||||
void updateSpawnPoints();
|
||||
|
||||
uint32_t getNextEffectSequence();
|
||||
|
@ -179,6 +183,10 @@ namespace Sapphire
|
|||
void addEffectResult( World::Action::EffectResultPtr result );
|
||||
|
||||
void processEffectResults( uint64_t tickCount );
|
||||
|
||||
Entity::PlayerPtr getPlayer( uint32_t charId );
|
||||
|
||||
void foreachPlayer( std::function< void( Entity::PlayerPtr player ) > callback );
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue