1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-25 14:07:46 +00:00

WIP: Implement gearset handler

This commit is contained in:
Rushi 2022-02-18 02:24:18 +01:00
parent 4f90228105
commit c03968b194
9 changed files with 115 additions and 3 deletions

View file

@ -587,6 +587,13 @@ struct FFXIVIpcCatalogSearch : FFXIVIpcBasePacket< CatalogSearch >
char ItemName[121];
};
struct FFXIVIpcGearSetEquip : FFXIVIpcBasePacket< GearSetEquip >
{
uint32_t contextId;
uint16_t storageId[14];
int16_t containerIndex[14];
};
struct FFXIVIpcMarketBoardRequestItemListingInfo : FFXIVIpcBasePacket< MarketBoardRequestItemListingInfo >
{
/* 0000 */ uint32_t catalogId;

View file

@ -705,6 +705,8 @@ namespace Sapphire::Entity
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 );
void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );

View file

@ -472,6 +472,17 @@ Sapphire::Entity::Player::InvSlotPair Sapphire::Entity::Player::getFreeBagSlot()
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 )
{
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
// 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 );
@ -606,7 +617,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
auto item = storage->getItem( slot );
// 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 maxStack = item->getMaxStackSize();
@ -851,7 +862,9 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint16_t from
&& !World::Manager::ItemMgr::isArmory( fromInventoryId ) )
{
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() );
}

View file

@ -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_autoAttackDmg = static_cast< float >( m_weaponDmg * m_delayMs ) / 3000;
m_category = static_cast< Common::ItemUICategory >( itemInfo->data().UICategory );
m_slot = itemInfo->data().Slot;
m_itemLevel = itemInfo->data().EquipLevel;
m_maxStackSize = itemInfo->data().StackMax;
// EXD TODO: Not sure what this maps to
@ -76,6 +77,11 @@ uint16_t Sapphire::Item::getItemLevel() const
return m_itemLevel;
}
uint8_t Sapphire::Item::getSlot() const
{
return m_slot;
}
uint16_t Sapphire::Item::getWeaponDmg() const
{
return m_weaponDmg;

View file

@ -65,6 +65,8 @@ namespace Sapphire
uint16_t getItemLevel() const;
uint8_t getSlot() const;
uint32_t getMaxStackSize() const;
uint16_t getDurability() const;
@ -105,6 +107,7 @@ namespace Sapphire
uint16_t m_weaponDmg;
float m_autoAttackDmg;
uint16_t m_itemLevel;
uint8_t m_slot;
uint16_t m_durability;
uint16_t m_stain;
uint16_t m_spiritBond;

View file

@ -140,6 +140,9 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
setZoneHandler( ClientZoneIpcType::Config, "Config", &GameConnection::configHandler );
setZoneHandler( CatalogSearch, "CatalogSearch", &GameConnection::catalogSearch );
setZoneHandler( GearSetEquip, "GearSetEquip", &GameConnection::gearSetEquip );
setZoneHandler( MarketBoardRequestItemListingInfo, "MarketBoardRequestItemListingInfo", &GameConnection::marketBoardRequestItemInfo );
setZoneHandler( MarketBoardRequestItemListings, "MarketBoardRequestItemListings", &GameConnection::marketBoardRequestItemListings );

View file

@ -214,6 +214,8 @@ namespace Sapphire::Network
DECLARE_HANDLER( catalogSearch );
DECLARE_HANDLER( gearSetEquip );
DECLARE_HANDLER( marketBoardRequestItemInfo );
DECLARE_HANDLER( marketBoardRequestItemListings );

View file

@ -27,6 +27,8 @@
#include "Linkshell/Linkshell.h"
#include "Inventory/Item.h"
#include "Network/PacketWrappers/PlayerSetupPacket.h"
#include "Network/PacketWrappers/PingPacket.h"
#include "Network/PacketWrappers/MoveActorPacket.h"
@ -38,6 +40,7 @@
#include "Network/PacketWrappers/EventStartPacket.h"
#include "Network/PacketWrappers/EventFinishPacket.h"
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
#include "Network/PacketWrappers/UpdateInventorySlotPacket.h"
#include "Manager/DebugCommandMgr.h"
#include "Manager/EventMgr.h"
@ -51,6 +54,7 @@
#include "Manager/PartyMgr.h"
#include "Manager/PlayerMgr.h"
#include "Manager/WarpMgr.h"
#include "Manager/ItemMgr.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 )
{
const auto packet = ZoneChannelPacket< Client::FFXIVIpcMarketBoardRequestItemListingInfo >( inPacket );

View file

@ -21,6 +21,12 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
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:
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.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;
};
};
}