1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 14:37:44 +00:00

Merge pull request #420 from XeAri/housing

added housing item UI
This commit is contained in:
Mordred 2018-11-09 10:58:35 +01:00 committed by GitHub
commit d0c3a356a1
14 changed files with 162 additions and 68 deletions

View file

@ -759,7 +759,16 @@ namespace Core::Common
uint8_t color[ 8 ]; // 36 uint8_t color[ 8 ]; // 36
}; };
struct HousePermissionSet enum LandPermissionSlot
{
FreeCompany,
Private,
Apartment,
SharedHouse1,
SharedHouse2
};
struct LandPermissionSet
{ {
int16_t landSetId; //00 int16_t landSetId; //00
int16_t wardNum; //02 int16_t wardNum; //02

View file

@ -2745,6 +2745,8 @@ Core::Data::HousingLandSet::HousingLandSet( uint32_t row_id, Core::Data::ExdData
auto row = exdData->m_HousingLandSetDat.get_row( row_id ); auto row = exdData->m_HousingLandSetDat.get_row( row_id );
for ( int i = 0; i < 60; i++ ) for ( int i = 0; i < 60; i++ )
sizes.push_back( exdData->getField< uint8_t >( row, 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++ ) for ( int i = 300; i < 300 + 60; i++ )
prices.push_back( exdData->getField< uint32_t >( row, i ) ); prices.push_back( exdData->getField< uint32_t >( row, i ) );

View file

@ -2853,6 +2853,7 @@ struct HousingPlacement
struct HousingLandSet struct HousingLandSet
{ {
std::vector< uint8_t > sizes; std::vector< uint8_t > sizes;
std::vector< uint32_t > minPrices;
std::vector< uint32_t > prices; std::vector< uint32_t > prices;
HousingLandSet( uint32_t row_id, Core::Data::ExdDataGenerated* exdData ); HousingLandSet( uint32_t row_id, Core::Data::ExdDataGenerated* exdData );

View file

@ -212,6 +212,9 @@ enum ActorControlType :
BeginReplayAck = 0x3A1, BeginReplayAck = 0x3A1,
EndReplayAck = 0x3A2, EndReplayAck = 0x3A2,
// Housing
ShowHousingItemUI = 0x3F7,
// PvP Duel // PvP Duel
SetPvPState = 0x5E0, // param3 must be 6 to engage a duel (hardcoded in the client) SetPvPState = 0x5E0, // param3 must be 6 to engage a duel (hardcoded in the client)
EndDuelSession = 0x5E1, // because someone went oob? EndDuelSession = 0x5E1, // because someone went oob?
@ -287,6 +290,7 @@ enum ClientTriggerType
AchievementList = 0x3E9, AchievementList = 0x3E9,
RequestHousingSign = 0x451, RequestHousingSign = 0x451,
RequestHousingItemUI = 0x463,
RequestSharedEstateSettings = 0x46F, RequestSharedEstateSettings = 0x46F,
CompanionAction = 0x6A4, CompanionAction = 0x6A4,

View file

@ -1578,21 +1578,21 @@ struct FFXIVIpcPerformNote : FFXIVIpcBasePacket< PerformNote >
//IPCs //IPCs
struct FFXIVIpcLandPermission : FFXIVIpcBasePacket<LandPermission > struct FFXIVIpcLandPermission : FFXIVIpcBasePacket<LandPermission >
{ {
Common::HousePermissionSet freeCompanyHouse; // 00 Common::LandPermissionSet freeCompanyHouse; // 00
uint64_t unkown1; uint64_t unkown1;
Common::HousePermissionSet privateHouse; // 24 Common::LandPermissionSet privateHouse; // 24
uint64_t unkown2; uint64_t unkown2;
Common::HousePermissionSet apartment; // 48 Common::LandPermissionSet apartment; // 48
uint64_t unkown3; uint64_t unkown3;
Common::HousePermissionSet sharedHouse[2]; //72 Common::LandPermissionSet sharedHouse[2]; //72
uint64_t unkown4; uint64_t unkown4;
Common::HousePermissionSet unkownHouse; Common::LandPermissionSet unkownHouse;
uint64_t unkown5; uint64_t unkown5;
}; };
struct FFXIVIpcLandUpdate : FFXIVIpcBasePacket< LandUpdate > struct FFXIVIpcLandUpdate : FFXIVIpcBasePacket< LandUpdate >
{ {
uint16_t landSetId; uint16_t landId;
uint16_t unknow0; uint16_t unknow0;
uint16_t unknow1; uint16_t unknow1;
uint16_t unknow2; uint16_t unknow2;

View file

@ -89,6 +89,12 @@ Core::Entity::Player::Player() :
memset( m_classArray, 0, sizeof( m_classArray ) ); memset( m_classArray, 0, sizeof( m_classArray ) );
memset( m_expArray, 0, sizeof( m_expArray ) ); 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_objSpawnIndexAllocator.init( MAX_DISPLAYED_EOBJS );
m_actorSpawnIndexAllocator.init( MAX_DISPLAYED_ACTORS, true ); m_actorSpawnIndexAllocator.init( MAX_DISPLAYED_ACTORS, true );
} }
@ -1568,48 +1574,7 @@ void Core::Entity::Player::sendZonePackets()
sendItemLevel(); sendItemLevel();
} }
struct HousePermissionSet sendLandPermissions();
{
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 );
auto initZonePacket = makeZonePacket< FFXIVIpcInitZone >( getId() ); auto initZonePacket = makeZonePacket< FFXIVIpcInitZone >( getId() );
initZonePacket->data().zoneId = getCurrentZone()->getTerritoryTypeId(); initZonePacket->data().zoneId = getCurrentZone()->getTerritoryTypeId();
@ -1786,3 +1751,33 @@ bool Core::Entity::Player::isOnEnterEventDone() const
{ {
return m_onEnterEventDone; 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 );
}

View file

@ -761,6 +761,12 @@ namespace Core::Entity
void setDirectorInitialized( bool isInitialized ); 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 // Player Battle Handling
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
void initHateSlotQueue(); void initHateSlotQueue();
@ -1013,6 +1019,9 @@ namespace Core::Entity
uint8_t m_searchSelectRegion; // regions selected to show up in profile uint8_t m_searchSelectRegion; // regions selected to show up in profile
uint8_t m_searchSelectClass; // class 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 // gc info
uint8_t m_gc; uint8_t m_gc;
uint8_t m_gcRank[3]; uint8_t m_gcRank[3];

View file

@ -27,6 +27,7 @@
#include "Actor/BNpc.h" #include "Actor/BNpc.h"
#include "Zone/Zone.h" #include "Zone/Zone.h"
#include "Zone/HousingZone.h"
#include "Zone/InstanceContent.h" #include "Zone/InstanceContent.h"
#include "Zone/TerritoryMgr.h" #include "Zone/TerritoryMgr.h"
#include "Event/EventDefs.h" #include "Event/EventDefs.h"
@ -57,6 +58,7 @@ Core::DebugCommandHandler::DebugCommandHandler()
registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 ); registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 );
registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 ); registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 );
registerCommand( "instance", &DebugCommandHandler::instance, "Instance utilities", 1 ); registerCommand( "instance", &DebugCommandHandler::instance, "Instance utilities", 1 );
registerCommand( "housing", &DebugCommandHandler::housing, "Housing utilities", 1 );
} }
// clear all loaded commands // clear all loaded commands
@ -981,3 +983,50 @@ Core::DebugCommandHandler::instance( char* data, Entity::Player& player, std::sh
player.sendDebug( "Unknown sub command." ); 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." );
}
}

View file

@ -53,6 +53,8 @@ namespace Core
void instance( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command ); 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 ); void script( char* data, Entity::Player& player, std::shared_ptr< DebugCommand > command );
}; };

View file

@ -326,11 +326,23 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR
auto land = hZone->getLand( plot ); auto land = hZone->getLand( plot );
plotPricePacket->data().price = land->getCurrentPrice(); plotPricePacket->data().price = land->getCurrentPrice();
plotPricePacket->data().timeLeft = land->getDevaluationTime();
player.queuePacket( plotPricePacket ); player.queuePacket( plotPricePacket );
break; 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: default:
{ {

View file

@ -131,6 +131,20 @@ void Core::HousingZone::sendLandSet( Entity::Player& player )
player.queuePacket( landsetInitializePacket ); 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 ) bool Core::HousingZone::isPlayerSubInstance( Entity::Player& player )
{ {
return player.getPos().x < -15000.0f; //ToDo: get correct pos return player.getPos().x < -15000.0f; //ToDo: get correct pos

View file

@ -23,6 +23,7 @@ namespace Core
void onUpdate( uint32_t currTime ) override; void onUpdate( uint32_t currTime ) override;
void sendLandSet( Entity::Player& player ); void sendLandSet( Entity::Player& player );
void sendLandUpdate( uint8_t landId );
bool isPlayerSubInstance( Entity::Player& player ); bool isPlayerSubInstance( Entity::Player& player );
/* returns current ward number for this zone */ /* returns current ward number for this zone */

View file

@ -31,6 +31,7 @@ Core::Land::Land( uint16_t zoneId, uint8_t wardNum, uint8_t landId, uint32_t lan
m_wardNum( wardNum ), m_wardNum( wardNum ),
m_landId( landId ), m_landId( landId ),
m_currentPrice( 0 ), m_currentPrice( 0 ),
m_minPrice( 0 ),
m_nextDrop( 0 ), m_nextDrop( 0 ),
m_landSetId( landSetId ), m_landSetId( landSetId ),
m_landInfo( info ) m_landInfo( info )
@ -46,7 +47,6 @@ Core::Land::~Land()
void Core::Land::load() void Core::Land::load()
{ {
m_land.houseState = HouseState::forSale; m_land.houseState = HouseState::forSale;
auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); auto pDb = g_fw.get< Db::DbWorkerPool< Db::ZoneDbConnection > >();
@ -54,14 +54,13 @@ void Core::Land::load()
"AND landid = " + std::to_string( m_landId ) ); "AND landid = " + std::to_string( m_landId ) );
if( !res->next() ) if( !res->next() )
{ {
pDb->directExecute( "INSERT INTO land ( landsetid, landid, size, status, landprice ) " pDb->directExecute( "INSERT INTO land ( landsetid, landid, size, status, landprice ) "
"VALUES ( " + std::to_string( m_landSetId ) + "," + std::to_string( m_landId ) + "," "VALUES ( " + std::to_string( m_landSetId ) + "," + std::to_string( m_landId ) + ","
+ std::to_string( m_landInfo->sizes[ m_landId ] ) + "," + std::to_string( m_landInfo->sizes[ m_landId ] ) + ","
+ " 1, " + std::to_string( m_landInfo->prices[ m_landId ] ) + " );" ); + " 1, " + std::to_string( m_landInfo->prices[ m_landId ] ) + " );" );
m_currentPrice = 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 ]; m_land.houseSize = m_landInfo->sizes[ m_landId ];
} }
else else
@ -237,6 +236,11 @@ uint32_t Core::Land::getMaxItems()
return m_maxItems; return m_maxItems;
} }
uint32_t Core::Land::getDevaluationTime()
{
return m_nextDrop - Util::getTimeSeconds();
}
void Core::Land::init() void Core::Land::init()
{ {
@ -269,22 +273,13 @@ void Core::Land::UpdateDatabase()
void Core::Land::Update( uint32_t currTime ) void Core::Land::Update( uint32_t currTime )
{ {
if( m_currentPrice == 0 && getState() == HouseState::forSale ) if( getState() == HouseState::forSale )
{ {
m_currentPrice = m_initPrice; if( m_nextDrop < currTime && m_minPrice < m_currentPrice )
m_nextDrop = 0; {
m_nextDrop = currTime + 21600;
m_currentPrice = ( m_currentPrice / 100 ) * 99.58;
}
UpdateDatabase(); UpdateDatabase();
} }
if( m_nextDrop < currTime && getState() == HouseState::forSale )
{
m_currentPrice = ( m_currentPrice / 100 ) * 90;
m_nextDrop = currTime + 86400;
UpdateDatabase();
}
onUpdate();
}
void Core::Land::onUpdate()
{
} }

View file

@ -52,12 +52,12 @@ namespace Core
void setPreset( uint32_t itemId ); void setPreset( uint32_t itemId );
void UpdateDatabase(); void UpdateDatabase();
void Update( uint32_t currTime ); void Update( uint32_t currTime );
void onUpdate();
const Common::LandStruct& getLand(); const Common::LandStruct& getLand();
uint32_t getMaxItems(); uint32_t getMaxItems();
uint32_t getCurrentPrice() const; uint32_t getCurrentPrice() const;
uint32_t getDevaluationTime();
private: private:
uint16_t convertItemIdToHousingItemId( uint16_t itemId ); uint16_t convertItemIdToHousingItemId( uint16_t itemId );
@ -80,6 +80,7 @@ namespace Core
uint32_t m_initPrice; uint32_t m_initPrice;
uint32_t m_nextDrop; uint32_t m_nextDrop;
uint32_t m_currentPrice; uint32_t m_currentPrice;
uint32_t m_minPrice;
}; };
} }