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:
parent
4f90228105
commit
c03968b194
9 changed files with 115 additions and 3 deletions
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -214,6 +214,8 @@ namespace Sapphire::Network
|
|||
|
||||
DECLARE_HANDLER( catalogSearch );
|
||||
|
||||
DECLARE_HANDLER( gearSetEquip );
|
||||
|
||||
DECLARE_HANDLER( marketBoardRequestItemInfo );
|
||||
|
||||
DECLARE_HANDLER( marketBoardRequestItemListings );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue