mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 06:27:45 +00:00
WIP: Implement gearset handler
This commit is contained in:
parent
4f90228105
commit
c03968b194
9 changed files with 115 additions and 3 deletions
|
@ -587,6 +587,13 @@ struct FFXIVIpcCatalogSearch : FFXIVIpcBasePacket< CatalogSearch >
|
||||||
char ItemName[121];
|
char ItemName[121];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FFXIVIpcGearSetEquip : FFXIVIpcBasePacket< GearSetEquip >
|
||||||
|
{
|
||||||
|
uint32_t contextId;
|
||||||
|
uint16_t storageId[14];
|
||||||
|
int16_t containerIndex[14];
|
||||||
|
};
|
||||||
|
|
||||||
struct FFXIVIpcMarketBoardRequestItemListingInfo : FFXIVIpcBasePacket< MarketBoardRequestItemListingInfo >
|
struct FFXIVIpcMarketBoardRequestItemListingInfo : FFXIVIpcBasePacket< MarketBoardRequestItemListingInfo >
|
||||||
{
|
{
|
||||||
/* 0000 */ uint32_t catalogId;
|
/* 0000 */ uint32_t catalogId;
|
||||||
|
|
|
@ -705,6 +705,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
InvSlotPair getFreeBagSlot();
|
InvSlotPair getFreeBagSlot();
|
||||||
|
|
||||||
|
InvSlotPair getFreeContainerSlot( uint32_t containerId );
|
||||||
|
|
||||||
ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true );
|
ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true );
|
||||||
|
|
||||||
void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
|
void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
|
||||||
|
|
|
@ -472,6 +472,17 @@ Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeBagSlot()
|
||||||
return std::make_pair( 0, -1 );
|
return std::make_pair( 0, -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeContainerSlot( uint32_t containerId )
|
||||||
|
{
|
||||||
|
auto freeSlot = static_cast < int8_t >( m_storageMap[ containerId ]->getFreeSlot() );
|
||||||
|
|
||||||
|
if( freeSlot != -1 )
|
||||||
|
return std::make_pair( containerId, freeSlot );
|
||||||
|
|
||||||
|
// no room in inventory
|
||||||
|
return std::make_pair( 0, -1 );
|
||||||
|
}
|
||||||
|
|
||||||
Sapphire::ItemPtr Sapphire::Entity::Player::getItemAt( uint16_t containerId, uint16_t slotId )
|
Sapphire::ItemPtr Sapphire::Entity::Player::getItemAt( uint16_t containerId, uint16_t slotId )
|
||||||
{
|
{
|
||||||
return m_storageMap[ containerId ]->getItem( slotId );
|
return m_storageMap[ containerId ]->getItem( slotId );
|
||||||
|
@ -587,7 +598,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
|
||||||
|
|
||||||
// add the related armoury bag to the applicable bags and try and fill a free slot there before falling back to regular inventory
|
// add the related armoury bag to the applicable bags and try and fill a free slot there before falling back to regular inventory
|
||||||
// EXD TODO: wtf...
|
// EXD TODO: wtf...
|
||||||
if( /* No idea what it maps to itemInfo->data().isEquippable && */ getEquipDisplayFlags() & StoreNewItemsInArmouryChest )
|
if( itemInfo->data().Slot > 0 && getEquipDisplayFlags() & StoreNewItemsInArmouryChest )
|
||||||
{
|
{
|
||||||
auto bag = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( itemInfo->data().Slot );
|
auto bag = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( itemInfo->data().Slot );
|
||||||
|
|
||||||
|
@ -606,7 +617,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
|
||||||
auto item = storage->getItem( slot );
|
auto item = storage->getItem( slot );
|
||||||
|
|
||||||
// add any items that are stackable
|
// add any items that are stackable
|
||||||
if( canMerge && item && /*!itemInfo->isEquippable &&*/ item->getId() == catalogId )
|
if( canMerge && item && itemInfo->data().Slot > 0 && item->getId() == catalogId )
|
||||||
{
|
{
|
||||||
uint32_t count = item->getStackSize();
|
uint32_t count = item->getStackSize();
|
||||||
uint32_t maxStack = item->getMaxStackSize();
|
uint32_t maxStack = item->getMaxStackSize();
|
||||||
|
@ -851,7 +862,9 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint16_t from
|
||||||
&& !World::Manager::ItemMgr::isArmory( fromInventoryId ) )
|
&& !World::Manager::ItemMgr::isArmory( fromInventoryId ) )
|
||||||
{
|
{
|
||||||
updateContainer( fromInventoryId, fromSlotId, nullptr );
|
updateContainer( fromInventoryId, fromSlotId, nullptr );
|
||||||
fromInventoryId = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( toSlot );
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
||||||
|
auto itemInfo = exdData.getRow< Excel::Item >( toItem->getId() );
|
||||||
|
fromInventoryId = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( static_cast< Common::EquipSlotCategory >( itemInfo->data().Slot ) );
|
||||||
fromSlotId = static_cast < uint8_t >( m_storageMap[ fromInventoryId ]->getFreeSlot() );
|
fromSlotId = static_cast < uint8_t >( m_storageMap[ fromInventoryId ]->getFreeSlot() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ Sapphire::Item::Item( uint64_t uId, uint32_t catalogId, bool isHq ) :
|
||||||
m_weaponDmg = ( m_physicalDmg != 0 ) ? m_physicalDmg : m_magicalDmg;
|
m_weaponDmg = ( m_physicalDmg != 0 ) ? m_physicalDmg : m_magicalDmg;
|
||||||
m_autoAttackDmg = static_cast< float >( m_weaponDmg * m_delayMs ) / 3000;
|
m_autoAttackDmg = static_cast< float >( m_weaponDmg * m_delayMs ) / 3000;
|
||||||
m_category = static_cast< Common::ItemUICategory >( itemInfo->data().UICategory );
|
m_category = static_cast< Common::ItemUICategory >( itemInfo->data().UICategory );
|
||||||
|
m_slot = itemInfo->data().Slot;
|
||||||
m_itemLevel = itemInfo->data().EquipLevel;
|
m_itemLevel = itemInfo->data().EquipLevel;
|
||||||
m_maxStackSize = itemInfo->data().StackMax;
|
m_maxStackSize = itemInfo->data().StackMax;
|
||||||
// EXD TODO: Not sure what this maps to
|
// EXD TODO: Not sure what this maps to
|
||||||
|
@ -76,6 +77,11 @@ uint16_t Sapphire::Item::getItemLevel() const
|
||||||
return m_itemLevel;
|
return m_itemLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t Sapphire::Item::getSlot() const
|
||||||
|
{
|
||||||
|
return m_slot;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t Sapphire::Item::getWeaponDmg() const
|
uint16_t Sapphire::Item::getWeaponDmg() const
|
||||||
{
|
{
|
||||||
return m_weaponDmg;
|
return m_weaponDmg;
|
||||||
|
|
|
@ -65,6 +65,8 @@ namespace Sapphire
|
||||||
|
|
||||||
uint16_t getItemLevel() const;
|
uint16_t getItemLevel() const;
|
||||||
|
|
||||||
|
uint8_t getSlot() const;
|
||||||
|
|
||||||
uint32_t getMaxStackSize() const;
|
uint32_t getMaxStackSize() const;
|
||||||
|
|
||||||
uint16_t getDurability() const;
|
uint16_t getDurability() const;
|
||||||
|
@ -105,6 +107,7 @@ namespace Sapphire
|
||||||
uint16_t m_weaponDmg;
|
uint16_t m_weaponDmg;
|
||||||
float m_autoAttackDmg;
|
float m_autoAttackDmg;
|
||||||
uint16_t m_itemLevel;
|
uint16_t m_itemLevel;
|
||||||
|
uint8_t m_slot;
|
||||||
uint16_t m_durability;
|
uint16_t m_durability;
|
||||||
uint16_t m_stain;
|
uint16_t m_stain;
|
||||||
uint16_t m_spiritBond;
|
uint16_t m_spiritBond;
|
||||||
|
|
|
@ -140,6 +140,9 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
||||||
setZoneHandler( ClientZoneIpcType::Config, "Config", &GameConnection::configHandler );
|
setZoneHandler( ClientZoneIpcType::Config, "Config", &GameConnection::configHandler );
|
||||||
|
|
||||||
setZoneHandler( CatalogSearch, "CatalogSearch", &GameConnection::catalogSearch );
|
setZoneHandler( CatalogSearch, "CatalogSearch", &GameConnection::catalogSearch );
|
||||||
|
|
||||||
|
setZoneHandler( GearSetEquip, "GearSetEquip", &GameConnection::gearSetEquip );
|
||||||
|
|
||||||
setZoneHandler( MarketBoardRequestItemListingInfo, "MarketBoardRequestItemListingInfo", &GameConnection::marketBoardRequestItemInfo );
|
setZoneHandler( MarketBoardRequestItemListingInfo, "MarketBoardRequestItemListingInfo", &GameConnection::marketBoardRequestItemInfo );
|
||||||
setZoneHandler( MarketBoardRequestItemListings, "MarketBoardRequestItemListings", &GameConnection::marketBoardRequestItemListings );
|
setZoneHandler( MarketBoardRequestItemListings, "MarketBoardRequestItemListings", &GameConnection::marketBoardRequestItemListings );
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,8 @@ namespace Sapphire::Network
|
||||||
|
|
||||||
DECLARE_HANDLER( catalogSearch );
|
DECLARE_HANDLER( catalogSearch );
|
||||||
|
|
||||||
|
DECLARE_HANDLER( gearSetEquip );
|
||||||
|
|
||||||
DECLARE_HANDLER( marketBoardRequestItemInfo );
|
DECLARE_HANDLER( marketBoardRequestItemInfo );
|
||||||
|
|
||||||
DECLARE_HANDLER( marketBoardRequestItemListings );
|
DECLARE_HANDLER( marketBoardRequestItemListings );
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include "Linkshell/Linkshell.h"
|
#include "Linkshell/Linkshell.h"
|
||||||
|
|
||||||
|
#include "Inventory/Item.h"
|
||||||
|
|
||||||
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
||||||
#include "Network/PacketWrappers/PingPacket.h"
|
#include "Network/PacketWrappers/PingPacket.h"
|
||||||
#include "Network/PacketWrappers/MoveActorPacket.h"
|
#include "Network/PacketWrappers/MoveActorPacket.h"
|
||||||
|
@ -38,6 +40,7 @@
|
||||||
#include "Network/PacketWrappers/EventStartPacket.h"
|
#include "Network/PacketWrappers/EventStartPacket.h"
|
||||||
#include "Network/PacketWrappers/EventFinishPacket.h"
|
#include "Network/PacketWrappers/EventFinishPacket.h"
|
||||||
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
|
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
|
||||||
|
#include "Network/PacketWrappers/UpdateInventorySlotPacket.h"
|
||||||
|
|
||||||
#include "Manager/DebugCommandMgr.h"
|
#include "Manager/DebugCommandMgr.h"
|
||||||
#include "Manager/EventMgr.h"
|
#include "Manager/EventMgr.h"
|
||||||
|
@ -51,6 +54,7 @@
|
||||||
#include "Manager/PartyMgr.h"
|
#include "Manager/PartyMgr.h"
|
||||||
#include "Manager/PlayerMgr.h"
|
#include "Manager/PlayerMgr.h"
|
||||||
#include "Manager/WarpMgr.h"
|
#include "Manager/WarpMgr.h"
|
||||||
|
#include "Manager/ItemMgr.h"
|
||||||
|
|
||||||
#include "Action/Action.h"
|
#include "Action/Action.h"
|
||||||
|
|
||||||
|
@ -629,6 +633,63 @@ void Sapphire::Network::GameConnection::catalogSearch( const Packets::FFXIVARR_P
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also used for recommended gear
|
||||||
|
void Sapphire::Network::GameConnection::gearSetEquip( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
||||||
|
{
|
||||||
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcGearSetEquip >( inPacket );
|
||||||
|
|
||||||
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
|
|
||||||
|
// Loop over all slots
|
||||||
|
for (int slot = 0; slot < 14; slot++ )
|
||||||
|
{
|
||||||
|
const auto fromSlot = packet.data().containerIndex[ slot ];
|
||||||
|
const auto fromContainer = packet.data().storageId[ slot ];
|
||||||
|
|
||||||
|
if ( fromContainer == Common::GearSet0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto fromItem = fromSlot == -1 ? nullptr : player.getItemAt( fromContainer, fromSlot );
|
||||||
|
const auto equippedItem = player.getItemAt( Common::GearSet0, slot );
|
||||||
|
const auto operationType = ( fromItem && !equippedItem ) || ( !fromItem && equippedItem ) ?
|
||||||
|
ITEM_OPERATION_TYPE::ITEM_OPERATION_TYPE_MOVEITEM : ITEM_OPERATION_TYPE::ITEM_OPERATION_TYPE_SWAPITEM;
|
||||||
|
|
||||||
|
auto ackPacket = makeZonePacket< FFXIVIpcItemOperationBatch >( player.getId() );
|
||||||
|
ackPacket->data().contextId = packet.data().contextId;
|
||||||
|
ackPacket->data().operationType = operationType;
|
||||||
|
server.queueForPlayer( player.getCharacterId(), ackPacket );
|
||||||
|
|
||||||
|
if ( fromItem && equippedItem )
|
||||||
|
{
|
||||||
|
player.swapItem( fromContainer, fromSlot, Common::GearSet0, slot );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), fromSlot, fromContainer, *equippedItem, 0 ) );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, *fromItem, 0 ) );
|
||||||
|
}
|
||||||
|
else if ( fromItem && !equippedItem )
|
||||||
|
{
|
||||||
|
player.moveItem( fromContainer, fromSlot, Common::GearSet0, slot );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), fromSlot, fromContainer, 0 ) );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, *fromItem, 0 ) );
|
||||||
|
}
|
||||||
|
else if ( !fromItem && equippedItem )
|
||||||
|
{
|
||||||
|
auto containerId = World::Manager::ItemMgr::getCharaEquipSlotCategoryToArmoryId( static_cast< Common::EquipSlotCategory >( equippedItem->getSlot() ) );
|
||||||
|
auto freeSlot = player.getFreeContainerSlot( containerId ).second;
|
||||||
|
player.moveItem( Common::GearSet0, slot, containerId, freeSlot );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), freeSlot, containerId, *equippedItem, 0 ) );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< UpdateInventorySlotPacket >( player.getId(), slot, Common::GearSet0, 0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the inventory
|
||||||
|
//player.sendInventory();
|
||||||
|
|
||||||
|
if( packet.data().contextId < 0xFE )
|
||||||
|
{
|
||||||
|
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), Network::ActorControl::GearSetEquipMsg, packet.data().contextId ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Sapphire::Network::GameConnection::marketBoardRequestItemInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
void Sapphire::Network::GameConnection::marketBoardRequestItemInfo( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
|
||||||
{
|
{
|
||||||
const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemListingInfo >( inPacket );
|
const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemListingInfo >( inPacket );
|
||||||
|
|
|
@ -21,6 +21,12 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
initialize( slot, storageId, item, contextId );
|
initialize( slot, storageId, item, contextId );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UpdateInventorySlotPacket( uint32_t playerId, uint16_t slot, uint16_t storageId, uint32_t contextId ) :
|
||||||
|
ZoneChannelPacket< FFXIVIpcNormalItem >( playerId, playerId )
|
||||||
|
{
|
||||||
|
initialize( slot, storageId, contextId );
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialize( uint16_t slot, uint16_t storageId, const Item& item, uint32_t contextId )
|
void initialize( uint16_t slot, uint16_t storageId, const Item& item, uint32_t contextId )
|
||||||
{
|
{
|
||||||
|
@ -34,6 +40,15 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
m_data.item.stain = static_cast< uint8_t >( item.getStain() );
|
m_data.item.stain = static_cast< uint8_t >( item.getStain() );
|
||||||
m_data.item.signatureId = 0;
|
m_data.item.signatureId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void initialize( uint16_t slot, uint16_t storageId, uint32_t contextId )
|
||||||
|
{
|
||||||
|
m_data.contextId = contextId;
|
||||||
|
m_data.item.storageId = storageId;
|
||||||
|
m_data.item.containerIndex = slot;
|
||||||
|
m_data.item.stack = 0;
|
||||||
|
m_data.item.catalogId = 0;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue