1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 06:27:45 +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
};
struct HousePermissionSet
enum LandPermissionSlot
{
FreeCompany,
Private,
Apartment,
SharedHouse1,
SharedHouse2
};
struct LandPermissionSet
{
int16_t landSetId; //00
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 );
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 ) );

View file

@ -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 );

View file

@ -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,

View file

@ -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;

View file

@ -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 );
}

View file

@ -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];

View file

@ -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." );
}
}

View file

@ -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 );
};

View file

@ -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:
{

View file

@ -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

View file

@ -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 */

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_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()
{
}

View file

@ -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;
};
}