1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 06:27:45 +00:00

addItem is way less retarded now, stacks are automagically filled first

This commit is contained in:
NotAdam 2018-08-25 00:15:26 +10:00
parent 3396645e3c
commit 1b7d11bb43
11 changed files with 83 additions and 65 deletions

View file

@ -2314,6 +2314,7 @@ Core::Data::Item::Item( uint32_t row_id, Core::Data::ExdDataGenerated* exdData )
isUnique = exdData->getField< bool >( row, 20 ); isUnique = exdData->getField< bool >( row, 20 );
isUntradable = exdData->getField< bool >( row, 21 ); isUntradable = exdData->getField< bool >( row, 21 );
isIndisposable = exdData->getField< bool >( row, 22 ); isIndisposable = exdData->getField< bool >( row, 22 );
isEquippable = exdData->getField< bool >( row, 23 );
priceMid = exdData->getField< uint32_t >( row, 24 ); priceMid = exdData->getField< uint32_t >( row, 24 );
priceLow = exdData->getField< uint32_t >( row, 25 ); priceLow = exdData->getField< uint32_t >( row, 25 );
canBeHq = exdData->getField< bool >( row, 26 ); canBeHq = exdData->getField< bool >( row, 26 );

View file

@ -2406,6 +2406,7 @@ struct Item
bool isUnique; bool isUnique;
bool isUntradable; bool isUntradable;
bool isIndisposable; bool isIndisposable;
bool isEquippable;
uint32_t priceMid; uint32_t priceMid;
uint32_t priceLow; uint32_t priceLow;
bool canBeHq; bool canBeHq;

View file

@ -42,7 +42,7 @@ private:
default: itemId = 4426; break; default: itemId = 4426; break;
} }
auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true ); auto item = player.addItem( itemId, 1, false, true );
if( item ) if( item )
player.equipItem( Common::EquipSlot::Ring2, item, true ); player.equipItem( Common::EquipSlot::Ring2, item, true );

View file

@ -57,7 +57,7 @@ private:
default: itemId = 4426; break; default: itemId = 4426; break;
} }
auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true ); auto item = player.addItem( itemId, 1, false, true );
if( item ) if( item )
player.equipItem( Common::EquipSlot::Ring2, item, true ); player.equipItem( Common::EquipSlot::Ring2, item, true );

View file

@ -43,7 +43,7 @@ private:
default: itemId = 4426; break; default: itemId = 4426; break;
} }
auto item = player.addItem( Common::InventoryType::ArmoryRing, -1, itemId, 1, false, true ); auto item = player.addItem( itemId, 1, false, true );
if( item ) if( item )
player.equipItem( Common::EquipSlot::Ring2, item, true ); player.equipItem( Common::EquipSlot::Ring2, item, true );

View file

@ -155,7 +155,7 @@ namespace Core {
return m_gmInvis; return m_gmInvis;
} }
bool setGmInvis( bool invis ) void setGmInvis( bool invis )
{ {
m_gmInvis = invis; m_gmInvis = invis;
} }

View file

@ -222,10 +222,6 @@ public:
// Inventory / Item / Currency // Inventory / Item / Currency
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
/*! add an item to the first free slot in one of the 4 main containers */
bool tryAddItem( uint16_t catalogId, uint32_t quantity );
/*! add an item to a given container */
// bool addItem( uint16_t containerId, uint16_t catalogId, uint32_t quantity );
/*! equip an item to a specified slot */ /*! equip an item to a specified slot */
void equipItem( Common::EquipSlot equipSlotId, ItemPtr pItem, bool sendModel ); void equipItem( Common::EquipSlot equipSlotId, ItemPtr pItem, bool sendModel );
/*! remove an item from an equipment slot */ /*! remove an item from an equipment slot */
@ -612,7 +608,7 @@ public:
bool loadInventory(); bool loadInventory();
InvSlotPairVec getSlotsOfItemsInInventory( uint32_t catalogId ); InvSlotPairVec getSlotsOfItemsInInventory( uint32_t catalogId );
InvSlotPair getFreeBagSlot(); InvSlotPair getFreeBagSlot();
Core::ItemPtr addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity = 1, bool isHq = false, bool slient = false ); Core::ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false );
void moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot ); 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 swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
void discardItem( uint16_t fromInventoryId, uint8_t fromSlotId ); void discardItem( uint16_t fromInventoryId, uint8_t fromSlotId );

View file

@ -320,17 +320,6 @@ void Core::Entity::Player::removeCrystal( Common::CrystalType type, uint32_t amo
queuePacket( invUpdate ); queuePacket( invUpdate );
} }
bool Core::Entity::Player::tryAddItem( uint16_t catalogId, uint32_t quantity )
{
for( uint16_t i = 0; i < 4; i++ )
{
if( addItem( i, -1, catalogId, quantity ) )
return true;
}
return false;
}
void Core::Entity::Player::sendInventory() void Core::Entity::Player::sendInventory()
{ {
InventoryMap::iterator it; InventoryMap::iterator it;
@ -495,7 +484,7 @@ bool Core::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity )
} }
Core::ItemPtr Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId, uint32_t catalogId, uint16_t quantity, bool isHq, bool silent ) Core::ItemPtr Core::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent )
{ {
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto pExdData = g_fw.get< Data::ExdDataGenerated >(); auto pExdData = g_fw.get< Data::ExdDataGenerated >();
@ -507,57 +496,87 @@ Core::ItemPtr Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId
return nullptr; return nullptr;
} }
int8_t rSlotId = -1; if( itemInfo->isEquippable )
quantity = 1;
//if( itemInfo->stack_size > 1 ) // used for item obtain notification
//{ uint32_t originalQuantity = quantity;
// auto itemList = this->getSlotsOfItemsInInventory( catalogId );
// // TODO: this is a stacked item so we need to see if the item is already in inventory and // todo: for now we're just going to add any items to main inv
// // check how much free space we have on existing stacks before looking for empty slots.
//} std::pair< uint8_t, uint8_t > freeBagSlot;
//else bool foundFreeSlot = false;
for( auto bag : { Bag0, Bag1, Bag2, Bag3 } )
{ {
auto freeSlot = getFreeBagSlot(); auto storage = m_storageMap[bag];
inventoryId = freeSlot.first;
rSlotId = freeSlot.second;
if( rSlotId == -1 ) for( uint8_t slot = 0; slot < storage->getMaxSize(); slot++ )
return nullptr; {
auto item = storage->getItem( slot );
// add any items that are stackable
if( item && !itemInfo->isEquippable && item->getId() == catalogId )
{
uint32_t count = item->getStackSize();
uint32_t maxStack = item->getMaxStackSize();
// if slot is full, skip it
if( count >= maxStack )
continue;
// update stack
uint32_t newStackSize = count + quantity;
uint32_t overflow = 0;
if( newStackSize > maxStack )
{
overflow = newStackSize - item->getMaxStackSize();
newStackSize = maxStack;
} }
auto item = createItem( catalogId, quantity ); item->setStackSize( newStackSize );
auto slotUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), slot, bag, *item );
queuePacket( slotUpdate );
quantity = overflow;
// return existing stack if we have no overflow - items fit into a preexisting stack
if( quantity == 0 )
return item;
}
else if( !item && !foundFreeSlot )
{
freeBagSlot = { bag, slot };
foundFreeSlot = true;
break;
}
}
}
// couldn't find a free slot and we still have some quantity of items left, shits fucked
if( !foundFreeSlot )
return nullptr;
auto item = createItem( catalogId, quantity );
item->setHq( isHq ); item->setHq( isHq );
if( rSlotId != -1 ) auto storage = m_storageMap[freeBagSlot.first];
{ storage->setItem( freeBagSlot.second, item );
auto storage = m_storageMap[inventoryId]; writeInventory( static_cast< InventoryType >( freeBagSlot.first ) );
storage->setItem( rSlotId, item );
pDb->execute( "UPDATE " + storage->getTableName() + " SET container_" +
std::to_string( rSlotId ) + " = " + std::to_string( item->getUId() ) +
" WHERE storageId = " + std::to_string( inventoryId ) +
" AND CharacterId = " + std::to_string( getId() ) );
if( !silent ) if( !silent )
{ {
auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, *item );
rSlotId,
inventoryId,
*item );
queuePacket( invUpdate ); queuePacket( invUpdate );
queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon, queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon, catalogId, originalQuantity ) );
catalogId, item->getStackSize() ) );
}
} }
return item; return item;
} }
void Core::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot ) void Core::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot )
@ -641,7 +660,7 @@ void Core::Entity::Player::splitItem( uint16_t fromInventoryId, uint8_t fromSlot
// todo: correct invalid move? again, not sure what retail does here // todo: correct invalid move? again, not sure what retail does here
return; return;
auto newItem = addItem( toInventoryId, toSlot, fromItem->getId(), itemCount, fromItem->isHq(), true ); auto newItem = addItem( fromItem->getId(), itemCount, fromItem->isHq(), true );
if( !newItem ) if( !newItem )
return; return;

View file

@ -1059,14 +1059,14 @@ bool Core::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t optional
{ {
for( uint32_t i = 0; i < questInfo->itemReward0.size(); i++ ) for( uint32_t i = 0; i < questInfo->itemReward0.size(); i++ )
{ {
addItem( -1, questInfo->itemReward0.at( i ), questInfo->itemCountReward0.at( i ) ); addItem( questInfo->itemCountReward0.at( i ) );
} }
} }
if( optionalItemCount > 0 ) if( optionalItemCount > 0 )
{ {
auto itemId = questInfo->itemReward1.at( optionalChoice ); auto itemId = questInfo->itemReward1.at( optionalChoice );
addItem( -1, itemId, questInfo->itemCountReward1.at( optionalChoice ) ); addItem( questInfo->itemCountReward1.at( optionalChoice ) );
} }
if( gilReward > 0 ) if( gilReward > 0 )

View file

@ -62,10 +62,11 @@ uint16_t Core::Items::Util::getArmoryToEquipSlot( uint8_t slotId )
case Common::Wrist: case Common::Wrist:
return Common::ArmoryWrist; return Common::ArmoryWrist;
}
default:
return 0; return 0;
} }
}

View file

@ -323,7 +323,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R
return; return;
} }
if( !targetPlayer->addItem( -1, param1, quantity ) ) if( !targetPlayer->addItem( param1, quantity ) )
player.sendUrgent( "Item " + std::to_string( param1 ) + " could not be added to inventory." ); player.sendUrgent( "Item " + std::to_string( param1 ) + " could not be added to inventory." );
break; break;
} }