1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 14:57:44 +00:00

#31 & #314: Splitting and stacking items in inventory now works

This commit is contained in:
NotAdam 2018-06-12 12:46:05 +00:00
parent d3871ae6ce
commit 3ac70352d1
3 changed files with 84 additions and 14 deletions

View file

@ -128,7 +128,7 @@ Core::ItemPtr Core::Inventory::getItemAt( uint16_t containerId, uint8_t slotId )
return m_inventoryMap[containerId]->getItem( slotId );
}
Core::ItemPtr Core::Inventory::createItem( uint32_t catalogId, uint8_t quantity )
Core::ItemPtr Core::Inventory::createItem( uint32_t catalogId, uint16_t quantity )
{
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
@ -144,7 +144,7 @@ Core::ItemPtr Core::Inventory::createItem( uint32_t catalogId, uint8_t quantity
uint8_t flags = 0;
std::string itemName( itemInfo->name );
// std::string itemName( itemInfo->name );
ItemPtr pItem( new Item( catalogId ) );
@ -473,7 +473,7 @@ bool Core::Inventory::isObtainable( uint32_t catalogId, uint8_t quantity )
}
int16_t Core::Inventory::addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint8_t quantity )
int16_t Core::Inventory::addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity, bool isHq )
{
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
@ -505,6 +505,8 @@ int16_t Core::Inventory::addItem( uint16_t inventoryId, int8_t slotId, uint32_t
auto item = createItem( catalogId, quantity );
item->setHq( isHq );
if( rSlotId != -1 )
{
@ -598,6 +600,70 @@ bool Core::Inventory::updateContainer( uint16_t containerId, uint8_t slotId, Ite
return true;
}
void Core::Inventory::splitItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot, uint16_t itemCount )
{
auto fromItem = m_inventoryMap[fromInventoryId]->getItem( fromSlotId );
if( !fromItem )
return;
// check we have enough items in the origin slot
// nb: don't let the client 'split' a whole stack into another slot
if( fromItem->getStackSize() < itemCount )
// todo: correct the invalid item split? does retail do this or does it just ignore it?
return;
// make sure toInventoryId & toSlot are actually free so we don't orphan an item
if( m_inventoryMap[toInventoryId]->getItem( toSlot ) )
// todo: correct invalid move? again, not sure what retail does here
return;
auto newSlot = addItem( toInventoryId, toSlot, fromItem->getId(), itemCount, fromItem->isHq() );
if( newSlot == -1 )
return;
auto newItem = m_inventoryMap[toInventoryId]->getItem( static_cast< uint8_t >( newSlot ) );
fromItem->setStackSize( fromItem->getStackSize() - itemCount );
updateContainer( fromInventoryId, fromSlotId, fromItem );
updateContainer( toInventoryId, toSlot, newItem );
updateItemDb( fromItem );
}
void Core::Inventory::mergeItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot )
{
auto fromItem = m_inventoryMap[fromInventoryId]->getItem( fromSlotId );
auto toItem = m_inventoryMap[toInventoryId]->getItem( toSlot );
if( !fromItem || !toItem )
return;
if( fromItem->getId() != toItem->getId() )
return;
uint32_t stackSize = fromItem->getStackSize() + toItem->getStackSize();
uint32_t stackOverflow = stackSize - std::min< uint32_t >( m_maxSlotSize, stackSize );
// we can destroy the original stack if there's no overflow
if( stackOverflow == 0 )
{
m_inventoryMap[fromInventoryId]->removeItem( fromSlotId );
fromItem = nullptr;
}
else
fromItem->setStackSize( stackOverflow );
toItem->setStackSize( stackSize );
updateContainer( fromInventoryId, fromSlotId, fromItem );
updateContainer( toInventoryId, toSlot, toItem );
updateItemDb( toItem );
if( fromItem )
updateItemDb( fromItem );
}
void Core::Inventory::swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot )
{
auto fromItem = m_inventoryMap[fromInventoryId]->getItem( fromSlotId );

View file

@ -140,12 +140,14 @@ public:
InvSlotPairVec getSlotsOfItemsInInventory( uint32_t catalogId );
InvSlotPair getFreeBagSlot();
int16_t addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint8_t quantity = 1 );
int16_t addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity = 1, bool isHq = false );
void moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
void swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
void discardItem( uint16_t fromInventoryId, uint8_t fromSlotId );
void splitItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot, uint16_t splitCount );
void mergeItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
ItemPtr createItem( uint32_t catalogId, uint8_t quantity = 1 );
ItemPtr createItem( uint32_t catalogId, uint16_t quantity = 1 );
ItemPtr loadItem( uint64_t uId );
@ -197,6 +199,7 @@ public:
private:
Entity::Player* m_pOwner;
InventoryMap m_inventoryMap;
const uint32_t m_maxSlotSize = 999;
};
}

View file

@ -47,6 +47,7 @@ void Core::Network::GameConnection::inventoryModifyHandler( const Packets::GameP
uint8_t toSlot = inPacket.getValAt< uint8_t >( 0x44 );
uint16_t fromContainer = inPacket.getValAt< uint16_t >( 0x2C );
uint16_t toContainer = inPacket.getValAt< uint16_t >( 0x40 );
uint16_t splitCount = inPacket.getValAt< uint16_t >( 0x48 );
ZoneChannelPacket< FFXIVIpcInventoryActionAck > ackPacket( player.getId() );
ackPacket.data().sequence = seq;
@ -83,13 +84,13 @@ void Core::Network::GameConnection::inventoryModifyHandler( const Packets::GameP
case InventoryOperation::Merge: // merge stack action
{
player.getInventory()->mergeItem( fromContainer, fromSlot, toContainer, toSlot );
}
break;
case InventoryOperation::Split: // split stack action
{
player.getInventory()->splitItem( fromContainer, fromSlot, toContainer, toSlot, splitCount );
}
break;