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 );
isUntradable = exdData->getField< bool >( row, 21 );
isIndisposable = exdData->getField< bool >( row, 22 );
isEquippable = exdData->getField< bool >( row, 23 );
priceMid = exdData->getField< uint32_t >( row, 24 );
priceLow = exdData->getField< uint32_t >( row, 25 );
canBeHq = exdData->getField< bool >( row, 26 );

View file

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

View file

@ -42,7 +42,7 @@ private:
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 )
player.equipItem( Common::EquipSlot::Ring2, item, true );

View file

@ -57,7 +57,7 @@ private:
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 )
player.equipItem( Common::EquipSlot::Ring2, item, true );

View file

@ -43,7 +43,7 @@ private:
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 )
player.equipItem( Common::EquipSlot::Ring2, item, true );

View file

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

View file

@ -222,10 +222,6 @@ public:
// 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 */
void equipItem( Common::EquipSlot equipSlotId, ItemPtr pItem, bool sendModel );
/*! remove an item from an equipment slot */
@ -612,7 +608,7 @@ public:
bool loadInventory();
InvSlotPairVec getSlotsOfItemsInInventory( uint32_t catalogId );
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 swapItem( uint16_t fromInventoryId, uint8_t fromSlotId, uint16_t toInventoryId, uint8_t toSlot );
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 );
}
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()
{
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 pExdData = g_fw.get< Data::ExdDataGenerated >();
@ -507,57 +496,87 @@ Core::ItemPtr Core::Entity::Player::addItem( uint16_t inventoryId, int8_t slotId
return nullptr;
}
int8_t rSlotId = -1;
if( itemInfo->isEquippable )
quantity = 1;
//if( itemInfo->stack_size > 1 )
//{
// auto itemList = this->getSlotsOfItemsInInventory( catalogId );
// // TODO: this is a stacked item so we need to see if the item is already in inventory and
// // check how much free space we have on existing stacks before looking for empty slots.
//}
//else
// used for item obtain notification
uint32_t originalQuantity = quantity;
// todo: for now we're just going to add any items to main inv
std::pair< uint8_t, uint8_t > freeBagSlot;
bool foundFreeSlot = false;
for( auto bag : { Bag0, Bag1, Bag2, Bag3 } )
{
auto freeSlot = getFreeBagSlot();
inventoryId = freeSlot.first;
rSlotId = freeSlot.second;
auto storage = m_storageMap[bag];
if( rSlotId == -1 )
return nullptr;
for( uint8_t slot = 0; slot < storage->getMaxSize(); slot++ )
{
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;
}
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;
}
}
}
auto item = createItem( catalogId, quantity );
// 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 );
if( rSlotId != -1 )
auto storage = m_storageMap[freeBagSlot.first];
storage->setItem( freeBagSlot.second, item );
writeInventory( static_cast< InventoryType >( freeBagSlot.first ) );
if( !silent )
{
auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, *item );
queuePacket( invUpdate );
auto storage = m_storageMap[inventoryId];
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 )
{
auto invUpdate = boost::make_shared< UpdateInventorySlotPacket >( getId(),
rSlotId,
inventoryId,
*item );
queuePacket( invUpdate );
queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon,
catalogId, item->getStackSize() ) );
}
queuePacket( boost::make_shared< ActorControlPacket143 >( getId(), ItemObtainIcon, catalogId, originalQuantity ) );
}
return item;
}
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
return;
auto newItem = addItem( toInventoryId, toSlot, fromItem->getId(), itemCount, fromItem->isHq(), true );
auto newItem = addItem( fromItem->getId(), itemCount, fromItem->isHq(), true );
if( !newItem )
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++ )
{
addItem( -1, questInfo->itemReward0.at( i ), questInfo->itemCountReward0.at( i ) );
addItem( questInfo->itemCountReward0.at( i ) );
}
}
if( optionalItemCount > 0 )
{
auto itemId = questInfo->itemReward1.at( optionalChoice );
addItem( -1, itemId, questInfo->itemCountReward1.at( optionalChoice ) );
addItem( questInfo->itemCountReward1.at( optionalChoice ) );
}
if( gilReward > 0 )

View file

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

View file

@ -323,7 +323,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R
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." );
break;
}