diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index deaea6a2..d8010c37 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -169,6 +169,10 @@ namespace Packets { EquipDisplayFlags = 0x0210, // updated 4.3 + WardInfo = 0x0224, // updated 4.3 + WardHousingPermission = 0x022D, // updated 4.3 + WardYardInfo = 0x022F, // updated 4.3 + DuelChallenge = 0x0277, // 4.2; this is responsible for opening the ui PerformNote = 0x0286, // updated 4.3 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 7dc55ed3..bc707e46 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1306,6 +1306,58 @@ struct FFXIVIpcPerformNote : FFXIVIpcBasePacket uint8_t data[32]; }; +struct FFXIVIpcWardInfo : FFXIVIpcBasePacket +{ + uint16_t pad0; + uint16_t wardNum; // set 1 for "Mist, Ward 2" + uint16_t zoneId; + uint16_t worldId; + uint8_t pad1; + uint8_t SubInstance; // (default : 1/2) + uint8_t pad3; + uint8_t pad4; + uint8_t pad5; + uint8_t pad6; + uint8_t pad7; + uint8_t pad8; + struct { + uint8_t HouseSize; //1 = small, 2 = middle, 3 = big; 1 + uint8_t HouseState; //1 = for sell, 2 = sold, 3 = hasOwner, 0x0A = House sharing; 2 + uint8_t iconColor; //HouseState has to be 3; 1 = Private, 2 = FC House; 4 + uint8_t iconIconAdd; //Heart Icon = 2; 6 + uint32_t pad9; //can be 0 (default) maybe fcId; 8 + uint32_t fcIcon; //can be 0 (default); 12 + uint32_t fcIconColor; //can be 0 (default); 16 + uint16_t houseRoofId; //18 + uint16_t houseFacadeId;//20 + uint16_t houseWindowId;//22 + uint16_t houseDoorId;//24 + uint8_t gardenData[4];//28 + uint16_t gardenSignId; //For fcIcon; 30 + uint16_t gardenFenceId; //32 + uint8_t color[8]; //40 + } landSet[30]; +}; + +struct FFXIVIpcWardYardInfo : FFXIVIpcBasePacket +{ + /* consistency check? */ + uint32_t pad1; //always 0xFFFFFFFF + uint32_t pad2; //always 0xFFFFFFFF + uint8_t pad3; //always 0xFF + /* --- */ + uint8_t packetNum; + uint16_t packetTotal; + struct + { + uint32_t itemId; + uint16_t itemRotation; + uint16_t pos_1; + uint16_t pos_2; + uint16_t pos_3; + } object[100]; +}; + struct FFXIVIpcMSQTrackerProgress : FFXIVIpcBasePacket { uint32_t id; diff --git a/src/servers/sapphire_zone/Forwards.h b/src/servers/sapphire_zone/Forwards.h index 6335aeb7..b81d6dee 100644 --- a/src/servers/sapphire_zone/Forwards.h +++ b/src/servers/sapphire_zone/Forwards.h @@ -20,6 +20,7 @@ namespace Core { TYPE_FORWARD( Cell ); TYPE_FORWARD( Zone ); + TYPE_FORWARD( HousingZone ); TYPE_FORWARD( InstanceContent ); TYPE_FORWARD( Item ); TYPE_FORWARD( ItemContainer ); diff --git a/src/servers/sapphire_zone/Zone/HousingZone.cpp b/src/servers/sapphire_zone/Zone/HousingZone.cpp new file mode 100644 index 00000000..72dbd57e --- /dev/null +++ b/src/servers/sapphire_zone/Zone/HousingZone.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +#include +#include + +#include "Actor/Player.h" + +#include "Forwards.h" +#include "HousingZone.h" +#include "Framework.h" + +extern Core::Framework g_fw; + +using namespace Core::Common; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +Core::HousingZone::HousingZone(uint8_t wardNum, + uint16_t territoryId, + uint32_t guId, + const std::string& internalName, + const std::string& contentName) + : Zone(territoryId, guId, internalName, contentName), + m_wardNum( wardNum ) +{ + +} + +bool Core::HousingZone::init() +{ + uint32_t LandSetId; + + for ( LandSetId = 0; LandSetId < 60; LandSetId++ ) + { + //TODO: load house information here + } + + return true; +} + +Core::HousingZone::~HousingZone() +{ + +} + +void Core::HousingZone::onPlayerZoneIn(Entity::Player& player) +{ + auto pLog = g_fw.get< Logger >(); + pLog->debug( "HousingZone::onPlayerZoneIn: Zone#" + std::to_string(getGuId()) + "|" + + + ", Entity#" + std::to_string( player.getId() ) ); + + uint32_t landSetId; + uint32_t yardPacketNum; + + auto wardInfoPackage = makeZonePacket< FFXIVIpcWardInfo >( player.getId() ); + auto wardYardInfoPackage = makeZonePacket< FFXIVIpcWardYardInfo >(player.getId()); + + wardInfoPackage->data().wardNum = m_wardNum; + wardInfoPackage->data().zoneId = player.getZoneId(); + //TODO: get current WorldId + wardInfoPackage->data().worldId = 67; + //TODO: handle Subdivision + wardInfoPackage->data().SubInstance = 1; + + for (landSetId = 0; landSetId < 30 ; landSetId++) + { + wardInfoPackage->data().landSet[landSetId].HouseSize = 1; + wardInfoPackage->data().landSet[landSetId].HouseState = 1; + } + + wardYardInfoPackage->data().pad1 = 0xFFFFFFFF; + wardYardInfoPackage->data().pad2 = 0xFFFFFFFF; + wardYardInfoPackage->data().pad3 = 0xFF; + wardYardInfoPackage->data().packetTotal = 8; + + player.queuePacket( wardInfoPackage ); + + for (yardPacketNum = 0; yardPacketNum < wardYardInfoPackage->data().packetTotal; yardPacketNum++) + { + //Add Objects here + wardYardInfoPackage->data().packetNum = yardPacketNum; + + player.queuePacket( wardYardInfoPackage ); + } + +} + +uint8_t Core::HousingZone::getWardNum() const +{ + return m_wardNum; +} diff --git a/src/servers/sapphire_zone/Zone/HousingZone.h b/src/servers/sapphire_zone/Zone/HousingZone.h new file mode 100644 index 00000000..feae3534 --- /dev/null +++ b/src/servers/sapphire_zone/Zone/HousingZone.h @@ -0,0 +1,30 @@ +#ifndef SAPPHIRE_HOUSINGZONE_H +#define SAPPHIRE_HOUSINGZONE_H + +#include "Zone.h" +#include "Forwards.h" + +namespace Core +{ + class HousingZone : public Zone + { + public: + HousingZone( uint8_t wardNum, + uint16_t territoryId, + uint32_t guId, + const std::string& internalName, + const std::string& contentName ); + virtual ~HousingZone(); + + bool init() override; + void onPlayerZoneIn(Entity::Player& player) override; + + /* returns current ward number for this zone */ + uint8_t getWardNum() const; + private: + uint8_t m_wardNum; + + }; + +} +#endif //SAPPHIRE_HOUSINGZONE_H diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp index 6ec35837..4b767fb1 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -7,6 +7,7 @@ #include "Actor/Player.h" #include "Zone.h" +#include "HousingZone.h" #include "ZonePosition.h" #include "InstanceContent.h" #include "TerritoryMgr.h" @@ -45,6 +46,7 @@ bool Core::TerritoryMgr::init() loadTerritoryPositionMap(); createDefaultTerritories(); + createHosuingTerritories(); return true; } @@ -140,6 +142,52 @@ bool Core::TerritoryMgr::createDefaultTerritories() return true; } +bool Core::TerritoryMgr::createHosuingTerritories() +{ + //separate housing zones from default + auto pExdData = g_fw.get< Data::ExdDataGenerated >(); + auto pLog = g_fw.get< Logger >(); + for ( const auto& territory : m_territoryTypeDetailCacheMap ) + { + auto territoryId = territory.first; + auto territoryInfo = territory.second; + uint32_t wardNum; + + if ( territoryInfo->name.empty() ) + continue; + + auto pPlaceName = pExdData->get< Core::Data::PlaceName >( territoryInfo->placeName ); + + if (!pPlaceName || pPlaceName->name.empty() || !isHousingTerritory( territoryId ) ) + continue; + + for ( wardNum = 0; wardNum < 18; wardNum++ ) + { + + uint32_t guid = getNextInstanceId(); + pLog->info(std::to_string( territoryId ) + + "\t" + std::to_string( guid ) + + "\t" + std::to_string( territoryInfo->territoryIntendedUse ) + + "\t" + ( territoryInfo->name.length() <= 4 ? territoryInfo->name + "\t" : territoryInfo->name ) + + "\t" + "HOUSING" + + "\t" + pPlaceName->name + + "#" + std::to_string( wardNum ) ); + + auto pHousingZone = make_HousingZone( wardNum, territoryId, guid, territoryInfo->name, pPlaceName->name ); + pHousingZone->init(); + + InstanceIdToZonePtrMap instanceMap; + instanceMap[guid] = pHousingZone; + m_instanceIdToZonePtrMap[guid] = pHousingZone; + m_territoryIdToInstanceGuidMap[territoryId][guid] = pHousingZone; + m_zoneSet.insert( { pHousingZone } ); + } + + } + + return true; +} + Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTypeId ) { if( !isValidTerritory( territoryTypeId ) ) @@ -264,6 +312,16 @@ bool Core::TerritoryMgr::isDefaultTerritory( uint32_t territoryTypeId ) const } +bool Core::TerritoryMgr::isHousingTerritory(uint32_t territoryTypeId) const +{ + auto pTeri = getTerritoryDetail( territoryTypeId ); + + if (!pTeri) + return false; + + return pTeri->territoryIntendedUse == TerritoryIntendedUse::HousingArea; +} + Core::ZonePositionPtr Core::TerritoryMgr::getTerritoryPosition( uint32_t territoryPositionId ) const { auto it = m_territoryPositionMap.find( territoryPositionId ); diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.h b/src/servers/sapphire_zone/Zone/TerritoryMgr.h index 32d5532d..228b3517 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.h +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.h @@ -66,6 +66,8 @@ namespace Core bool createDefaultTerritories(); + bool createHosuingTerritories(); + /*! caches TerritoryType details into m_territoryTypeMap */ void loadTerritoryTypeDetailCache(); @@ -88,6 +90,9 @@ namespace Core /*! returns true if the territoryType is a default non-instanced zone */ bool isDefaultTerritory( uint32_t territoryTypeId ) const; + /*! returns true if the territoryType is a housing zone */ + bool isHousingTerritory(uint32_t territoryTypeId) const; + /*! creates a new instance for a given territoryTypeId */ ZonePtr createTerritoryInstance( uint32_t territoryTypeId );