mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 06:27:45 +00:00
commit
d0c3a356a1
14 changed files with 162 additions and 68 deletions
|
@ -759,7 +759,16 @@ namespace Core::Common
|
|||
uint8_t color[ 8 ]; // 36
|
||||
};
|
||||
|
||||
struct HousePermissionSet
|
||||
enum LandPermissionSlot
|
||||
{
|
||||
FreeCompany,
|
||||
Private,
|
||||
Apartment,
|
||||
SharedHouse1,
|
||||
SharedHouse2
|
||||
};
|
||||
|
||||
struct LandPermissionSet
|
||||
{
|
||||
int16_t landSetId; //00
|
||||
int16_t wardNum; //02
|
||||
|
|
|
@ -2745,6 +2745,8 @@ Core::Data::HousingLandSet::HousingLandSet( uint32_t row_id, Core::Data::ExdData
|
|||
auto row = exdData->m_HousingLandSetDat.get_row( row_id );
|
||||
for ( int i = 0; i < 60; i++ )
|
||||
sizes.push_back( exdData->getField< uint8_t >( row, i ) );
|
||||
for ( int i = 60; i < 60 + 60; i++ )
|
||||
minPrices.push_back( exdData->getField< uint32_t >( row, i ) );
|
||||
for ( int i = 300; i < 300 + 60; i++ )
|
||||
prices.push_back( exdData->getField< uint32_t >( row, i ) );
|
||||
|
||||
|
|
|
@ -2853,6 +2853,7 @@ struct HousingPlacement
|
|||
struct HousingLandSet
|
||||
{
|
||||
std::vector< uint8_t > sizes;
|
||||
std::vector< uint32_t > minPrices;
|
||||
std::vector< uint32_t > prices;
|
||||
|
||||
HousingLandSet( uint32_t row_id, Core::Data::ExdDataGenerated* exdData );
|
||||
|
|
|
@ -212,6 +212,9 @@ enum ActorControlType :
|
|||
BeginReplayAck = 0x3A1,
|
||||
EndReplayAck = 0x3A2,
|
||||
|
||||
// Housing
|
||||
ShowHousingItemUI = 0x3F7,
|
||||
|
||||
// PvP Duel
|
||||
SetPvPState = 0x5E0, // param3 must be 6 to engage a duel (hardcoded in the client)
|
||||
EndDuelSession = 0x5E1, // because someone went oob?
|
||||
|
@ -287,6 +290,7 @@ enum ClientTriggerType
|
|||
AchievementList = 0x3E9,
|
||||
|
||||
RequestHousingSign = 0x451,
|
||||
RequestHousingItemUI = 0x463,
|
||||
RequestSharedEstateSettings = 0x46F,
|
||||
|
||||
CompanionAction = 0x6A4,
|
||||
|
|
|
@ -1578,21 +1578,21 @@ struct FFXIVIpcPerformNote : FFXIVIpcBasePacket< PerformNote >
|
|||
//IPCs
|
||||
struct FFXIVIpcLandPermission : FFXIVIpcBasePacket<LandPermission >
|
||||
{
|
||||
Common::HousePermissionSet freeCompanyHouse; // 00
|
||||
Common::LandPermissionSet freeCompanyHouse; // 00
|
||||
uint64_t unkown1;
|
||||
Common::HousePermissionSet privateHouse; // 24
|
||||
Common::LandPermissionSet privateHouse; // 24
|
||||
uint64_t unkown2;
|
||||
Common::HousePermissionSet apartment; // 48
|
||||
Common::LandPermissionSet apartment; // 48
|
||||
uint64_t unkown3;
|
||||
Common::HousePermissionSet sharedHouse[2]; //72
|
||||
Common::LandPermissionSet sharedHouse[2]; //72
|
||||
uint64_t unkown4;
|
||||
Common::HousePermissionSet unkownHouse;
|
||||
Common::LandPermissionSet unkownHouse;
|
||||
uint64_t unkown5;
|
||||
};
|
||||
|
||||
struct FFXIVIpcLandUpdate : FFXIVIpcBasePacket< LandUpdate >
|
||||
{
|
||||
uint16_t landSetId;
|
||||
uint16_t landId;
|
||||
uint16_t unknow0;
|
||||
uint16_t unknow1;
|
||||
uint16_t unknow2;
|
||||
|
|
|
@ -89,6 +89,12 @@ Core::Entity::Player::Player() :
|
|||
memset( m_classArray, 0, sizeof( m_classArray ) );
|
||||
memset( m_expArray, 0, sizeof( m_expArray ) );
|
||||
|
||||
for ( uint8_t i = 0; i < 5; i++ )
|
||||
{
|
||||
memset( &m_housePermission[i], 0xFF, 8 );
|
||||
memset( &m_housePermission[i].permissionMask, 0, 8 );
|
||||
}
|
||||
|
||||
m_objSpawnIndexAllocator.init( MAX_DISPLAYED_EOBJS );
|
||||
m_actorSpawnIndexAllocator.init( MAX_DISPLAYED_ACTORS, true );
|
||||
}
|
||||
|
@ -1568,48 +1574,7 @@ void Core::Entity::Player::sendZonePackets()
|
|||
sendItemLevel();
|
||||
}
|
||||
|
||||
struct HousePermissionSet
|
||||
{
|
||||
int16_t landSetId; //00
|
||||
int16_t wardNum; //02
|
||||
int16_t zoneId; //04
|
||||
int16_t worldId; //06
|
||||
uint32_t permissionMask; //08
|
||||
uint32_t unkown1; //12
|
||||
};
|
||||
|
||||
auto landPermissions = makeZonePacket< FFXIVIpcLandPermission >( getId() );
|
||||
landPermissions->data().freeCompanyHouse.landSetId = -1;
|
||||
landPermissions->data().freeCompanyHouse.wardNum = -1;
|
||||
landPermissions->data().freeCompanyHouse.zoneId = -1;
|
||||
landPermissions->data().freeCompanyHouse.worldId = -1;
|
||||
landPermissions->data().unkown1 = 0;
|
||||
landPermissions->data().privateHouse.landSetId = -1;
|
||||
landPermissions->data().privateHouse.wardNum = -1;
|
||||
landPermissions->data().privateHouse.zoneId = -1;
|
||||
landPermissions->data().privateHouse.worldId = -1;
|
||||
landPermissions->data().unkown2 = 0;
|
||||
landPermissions->data().apartment.landSetId = -1;
|
||||
landPermissions->data().apartment.wardNum = -1;
|
||||
landPermissions->data().apartment.zoneId = -1;
|
||||
landPermissions->data().apartment.worldId = -1;
|
||||
landPermissions->data().unkown3 = 0;
|
||||
landPermissions->data().sharedHouse[0].landSetId = -1;
|
||||
landPermissions->data().sharedHouse[0].wardNum = -1;
|
||||
landPermissions->data().sharedHouse[0].zoneId = -1;
|
||||
landPermissions->data().sharedHouse[0].worldId = -1;
|
||||
landPermissions->data().sharedHouse[1].landSetId = -1;
|
||||
landPermissions->data().sharedHouse[1].wardNum = -1;
|
||||
landPermissions->data().sharedHouse[1].zoneId = -1;
|
||||
landPermissions->data().sharedHouse[1].worldId = -1;
|
||||
landPermissions->data().unkown4 = 0;
|
||||
landPermissions->data().unkownHouse.landSetId = -1;
|
||||
landPermissions->data().unkownHouse.wardNum = -1;
|
||||
landPermissions->data().unkownHouse.zoneId = -1;
|
||||
landPermissions->data().unkownHouse.worldId = -1;
|
||||
landPermissions->data().unkown5 = 2;
|
||||
queuePacket( landPermissions );
|
||||
|
||||
sendLandPermissions();
|
||||
|
||||
auto initZonePacket = makeZonePacket< FFXIVIpcInitZone >( getId() );
|
||||
initZonePacket->data().zoneId = getCurrentZone()->getTerritoryTypeId();
|
||||
|
@ -1786,3 +1751,33 @@ bool Core::Entity::Player::isOnEnterEventDone() const
|
|||
{
|
||||
return m_onEnterEventDone;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landSetId, int16_t wardNum, int16_t zoneId )
|
||||
{
|
||||
m_housePermission[permissionSet].landSetId = landSetId;
|
||||
m_housePermission[permissionSet].permissionMask = permissionMask;
|
||||
m_housePermission[permissionSet].wardNum = wardNum;
|
||||
m_housePermission[permissionSet].worldId = 67;
|
||||
m_housePermission[permissionSet].unkown1 = 0;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::sendLandPermissions()
|
||||
{
|
||||
auto landPermissions = makeZonePacket< FFXIVIpcLandPermission >( getId() );
|
||||
|
||||
landPermissions->data().freeCompanyHouse = m_housePermission[Common::LandPermissionSlot::FreeCompany];
|
||||
landPermissions->data().privateHouse = m_housePermission[Common::LandPermissionSlot::Private];
|
||||
landPermissions->data().apartment = m_housePermission[Common::LandPermissionSlot::Apartment];
|
||||
landPermissions->data().sharedHouse[0] = m_housePermission[Common::LandPermissionSlot::SharedHouse1];
|
||||
landPermissions->data().sharedHouse[1] = m_housePermission[Common::LandPermissionSlot::SharedHouse2];
|
||||
memset( &landPermissions->data().unkownHouse, 0xFF, 8 );
|
||||
memset( &landPermissions->data().unkownHouse.permissionMask, 0, 8 );
|
||||
landPermissions->data().unkownHouse.permissionMask = 2;
|
||||
landPermissions->data().unkown1 = 0;
|
||||
landPermissions->data().unkown2 = 0;
|
||||
landPermissions->data().unkown3 = 0;
|
||||
landPermissions->data().unkown4 = 0;
|
||||
landPermissions->data().unkown5 = 0;
|
||||
|
||||
queuePacket( landPermissions );
|
||||
}
|
|
@ -761,6 +761,12 @@ namespace Core::Entity
|
|||
|
||||
void setDirectorInitialized( bool isInitialized );
|
||||
|
||||
// Housing Handling
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landSetId, int16_t wardNum, int16_t zoneId );
|
||||
|
||||
void sendLandPermissions();
|
||||
|
||||
// Player Battle Handling
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void initHateSlotQueue();
|
||||
|
@ -1013,6 +1019,9 @@ namespace Core::Entity
|
|||
uint8_t m_searchSelectRegion; // regions selected to show up in profile
|
||||
uint8_t m_searchSelectClass; // class selected to show up in profile
|
||||
|
||||
// housing info
|
||||
Common::LandPermissionSet m_housePermission[5];
|
||||
|
||||
// gc info
|
||||
uint8_t m_gc;
|
||||
uint8_t m_gcRank[3];
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Actor/BNpc.h"
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/HousingZone.h"
|
||||
#include "Zone/InstanceContent.h"
|
||||
#include "Zone/TerritoryMgr.h"
|
||||
#include "Event/EventDefs.h"
|
||||
|
@ -57,6 +58,7 @@ Core::DebugCommandHandler::DebugCommandHandler()
|
|||
registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 );
|
||||
registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 );
|
||||
registerCommand( "instance", &DebugCommandHandler::instance, "Instance utilities", 1 );
|
||||
registerCommand( "housing", &DebugCommandHandler::housing, "Housing utilities", 1 );
|
||||
}
|
||||
|
||||
// clear all loaded commands
|
||||
|
@ -981,3 +983,50 @@ Core::DebugCommandHandler::instance( char* data, Entity::Player& player, std::sh
|
|||
player.sendDebug( "Unknown sub command." );
|
||||
}
|
||||
}
|
||||
|
||||
void Core::DebugCommandHandler::housing( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command )
|
||||
{
|
||||
auto pTeriMgr = g_fw.get< TerritoryMgr >();
|
||||
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 == "permission" || subCommand == "perm" )
|
||||
{
|
||||
uint8_t permissionSet;
|
||||
sscanf( params.c_str(), "%hhu", &permissionSet );
|
||||
|
||||
if ( permissionSet < 5 )
|
||||
{
|
||||
auto pZone = player.getCurrentZone();
|
||||
if( pTeriMgr->isHousingTerritory( pZone->getTerritoryTypeId() ) )
|
||||
{
|
||||
auto pHousing = std::dynamic_pointer_cast< HousingZone >( pZone );
|
||||
if( pHousing )
|
||||
player.setLandPermissions( permissionSet, 8, pHousing->getLandSetId(), pHousing->getWardNum(), pHousing->getTerritoryTypeId() );
|
||||
else
|
||||
player.sendDebug( "You aren't in a housing Zone." );
|
||||
}
|
||||
}
|
||||
else
|
||||
player.sendDebug( "PermissionSet out of range." );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendDebug( "Unknown sub command." );
|
||||
}
|
||||
}
|
|
@ -53,6 +53,8 @@ namespace Core
|
|||
|
||||
void instance( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
|
||||
|
||||
void housing( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command) ;
|
||||
|
||||
void script( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
|
||||
|
||||
};
|
||||
|
|
|
@ -326,11 +326,23 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR
|
|||
|
||||
auto land = hZone->getLand( plot );
|
||||
plotPricePacket->data().price = land->getCurrentPrice();
|
||||
plotPricePacket->data().timeLeft = land->getDevaluationTime();
|
||||
|
||||
player.queuePacket( plotPricePacket );
|
||||
|
||||
break;
|
||||
}
|
||||
case ClientTriggerType::RequestHousingItemUI:
|
||||
{
|
||||
uint32_t plot = param2;
|
||||
auto pShowHousingItemUIPacket = makeActorControl142( player.getId(), ShowHousingItemUI, 0, plot );
|
||||
|
||||
player.queuePacket( pShowHousingItemUIPacket );
|
||||
|
||||
//TODO: show item housing container
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
|
|
|
@ -131,6 +131,20 @@ void Core::HousingZone::sendLandSet( Entity::Player& player )
|
|||
player.queuePacket( landsetInitializePacket );
|
||||
}
|
||||
|
||||
void Core::HousingZone::sendLandUpdate( uint8_t landId )
|
||||
{
|
||||
for( const auto& playerIt : m_playerMap )
|
||||
{
|
||||
auto pPlayer = playerIt.second;
|
||||
|
||||
auto landUpdatePacket = makeZonePacket< FFXIVIpcLandUpdate >( pPlayer->getId() );
|
||||
landUpdatePacket->data().landId = landId;
|
||||
landUpdatePacket->data().land = getLand( landId )->getLand();
|
||||
|
||||
pPlayer->queuePacket( landUpdatePacket );
|
||||
}
|
||||
}
|
||||
|
||||
bool Core::HousingZone::isPlayerSubInstance( Entity::Player& player )
|
||||
{
|
||||
return player.getPos().x < -15000.0f; //ToDo: get correct pos
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Core
|
|||
void onUpdate( uint32_t currTime ) override;
|
||||
|
||||
void sendLandSet( Entity::Player& player );
|
||||
void sendLandUpdate( uint8_t landId );
|
||||
bool isPlayerSubInstance( Entity::Player& player );
|
||||
|
||||
/* returns current ward number for this zone */
|
||||
|
|
|
@ -31,6 +31,7 @@ Core::Land::Land( uint16_t zoneId, uint8_t wardNum, uint8_t landId, uint32_t lan
|
|||
m_wardNum( wardNum ),
|
||||
m_landId( landId ),
|
||||
m_currentPrice( 0 ),
|
||||
m_minPrice( 0 ),
|
||||
m_nextDrop( 0 ),
|
||||
m_landSetId( landSetId ),
|
||||
m_landInfo( info )
|
||||
|
@ -46,7 +47,6 @@ Core::Land::~Land()
|
|||
|
||||
void Core::Land::load()
|
||||
{
|
||||
|
||||
m_land.houseState = HouseState::forSale;
|
||||
|
||||
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
|
||||
|
@ -54,14 +54,13 @@ void Core::Land::load()
|
|||
"AND landid = " + std::to_string( m_landId ) );
|
||||
if( !res->next() )
|
||||
{
|
||||
|
||||
|
||||
pDb->directExecute( "INSERT INTO land ( landsetid, landid, size, status, landprice ) "
|
||||
"VALUES ( " + std::to_string( m_landSetId ) + "," + std::to_string( m_landId ) + ","
|
||||
+ std::to_string( m_landInfo->sizes[ m_landId ] ) + ","
|
||||
+ " 1, " + std::to_string( m_landInfo->prices[ m_landId ] ) + " );" );
|
||||
|
||||
m_currentPrice = m_landInfo->prices[ m_landId ];
|
||||
m_minPrice = m_landInfo->minPrices[ m_landId ];
|
||||
m_land.houseSize = m_landInfo->sizes[ m_landId ];
|
||||
}
|
||||
else
|
||||
|
@ -237,6 +236,11 @@ uint32_t Core::Land::getMaxItems()
|
|||
return m_maxItems;
|
||||
}
|
||||
|
||||
uint32_t Core::Land::getDevaluationTime()
|
||||
{
|
||||
return m_nextDrop - Util::getTimeSeconds();
|
||||
}
|
||||
|
||||
void Core::Land::init()
|
||||
{
|
||||
|
||||
|
@ -269,22 +273,13 @@ void Core::Land::UpdateDatabase()
|
|||
|
||||
void Core::Land::Update( uint32_t currTime )
|
||||
{
|
||||
if( m_currentPrice == 0 && getState() == HouseState::forSale )
|
||||
if( getState() == HouseState::forSale )
|
||||
{
|
||||
m_currentPrice = m_initPrice;
|
||||
m_nextDrop = 0;
|
||||
if( m_nextDrop < currTime && m_minPrice < m_currentPrice )
|
||||
{
|
||||
m_nextDrop = currTime + 21600;
|
||||
m_currentPrice = ( m_currentPrice / 100 ) * 99.58;
|
||||
}
|
||||
UpdateDatabase();
|
||||
}
|
||||
if( m_nextDrop < currTime && getState() == HouseState::forSale )
|
||||
{
|
||||
m_currentPrice = ( m_currentPrice / 100 ) * 90;
|
||||
m_nextDrop = currTime + 86400;
|
||||
UpdateDatabase();
|
||||
}
|
||||
onUpdate();
|
||||
}
|
||||
|
||||
void Core::Land::onUpdate()
|
||||
{
|
||||
|
||||
}
|
|
@ -52,12 +52,12 @@ namespace Core
|
|||
void setPreset( uint32_t itemId );
|
||||
void UpdateDatabase();
|
||||
void Update( uint32_t currTime );
|
||||
void onUpdate();
|
||||
|
||||
const Common::LandStruct& getLand();
|
||||
uint32_t getMaxItems();
|
||||
|
||||
uint32_t getCurrentPrice() const;
|
||||
uint32_t getDevaluationTime();
|
||||
|
||||
private:
|
||||
uint16_t convertItemIdToHousingItemId( uint16_t itemId );
|
||||
|
@ -80,6 +80,7 @@ namespace Core
|
|||
uint32_t m_initPrice;
|
||||
uint32_t m_nextDrop;
|
||||
uint32_t m_currentPrice;
|
||||
uint32_t m_minPrice;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue