mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 06:47:45 +00:00
parent
d3871ae6ce
commit
3ac70352d1
3 changed files with 84 additions and 14 deletions
|
@ -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 ) );
|
||||
|
||||
|
@ -311,7 +311,7 @@ void Core::Inventory::updateBagDb( InventoryType type )
|
|||
|
||||
bool Core::Inventory::isArmory( uint16_t containerId )
|
||||
{
|
||||
return
|
||||
return
|
||||
containerId == ArmoryBody ||
|
||||
containerId == ArmoryEar ||
|
||||
containerId == ArmoryFeet ||
|
||||
|
@ -468,12 +468,12 @@ bool Core::Inventory::isOneHandedWeapon( ItemUICategory weaponCategory )
|
|||
|
||||
bool Core::Inventory::isObtainable( uint32_t catalogId, uint8_t quantity )
|
||||
{
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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 >();
|
||||
|
@ -504,7 +504,9 @@ 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 );
|
||||
|
@ -609,7 +675,7 @@ void Core::Inventory::swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, ui
|
|||
|
||||
// An item is being moved from bag0-3 to equippment, meaning
|
||||
// the swapped out item will be placed in the matching armory.
|
||||
if( isEquipment( toInventoryId )
|
||||
if( isEquipment( toInventoryId )
|
||||
&& !isEquipment( fromInventoryId )
|
||||
&& !isArmory( fromInventoryId ) )
|
||||
{
|
||||
|
@ -655,7 +721,7 @@ Core::ItemPtr Core::Inventory::loadItem( uint64_t uId )
|
|||
{
|
||||
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
|
||||
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
|
||||
// load actual item
|
||||
// load actual item
|
||||
auto itemRes = pDb->query( "SELECT catalogId, stack, flags FROM charaglobalitem WHERE itemId = " + std::to_string( uId ) + ";" );
|
||||
if( !itemRes->next() )
|
||||
return nullptr;
|
||||
|
@ -664,10 +730,10 @@ Core::ItemPtr Core::Inventory::loadItem( uint64_t uId )
|
|||
{
|
||||
auto itemInfo = pExdData->get< Core::Data::Item >( itemRes->getUInt( 1 ) );
|
||||
bool isHq = itemRes->getUInt( 3 ) == 1 ? true : false;
|
||||
ItemPtr pItem( new Item( uId,
|
||||
ItemPtr pItem( new Item( uId,
|
||||
itemRes->getUInt( 1 ),
|
||||
itemInfo->modelMain,
|
||||
itemInfo->modelSub,
|
||||
itemInfo->modelSub,
|
||||
static_cast< ItemUICategory >( itemInfo->itemUICategory ),
|
||||
isHq ) );
|
||||
pItem->setStackSize( itemRes->getUInt( 2 ) );
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue