1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-06 10:47:45 +00:00

Selling items and buying back from shop, show corresponding messages in chat.

This commit is contained in:
collett 2020-05-11 06:25:25 +09:00
parent 2823923a88
commit b70435413e
11 changed files with 232 additions and 40 deletions

View file

@ -209,7 +209,7 @@ namespace Sapphire::Network::Packets
DirectorVars = 0x00E6, // updated 5.18 DirectorVars = 0x00E6, // updated 5.18
SomeDirectorUnk1 = 0x0084, // updated 5.18 SomeDirectorUnk1 = 0x0084, // updated 5.18
SomeDirectorUnk2 = 0x00C1, // updated 5.18 SomeDirectorUnk2 = 0xF0C1, // updated 5.18
SomeDirectorUnk4 = 0x01F3, // updated 5.21 hotfix SomeDirectorUnk4 = 0x01F3, // updated 5.21 hotfix
SomeDirectorUnk8 = 0x028A, // updated 5.18 SomeDirectorUnk8 = 0x028A, // updated 5.18
SomeDirectorUnk16 = 0x028C, // updated 5.18 SomeDirectorUnk16 = 0x028C, // updated 5.18
@ -376,6 +376,8 @@ namespace Sapphire::Network::Packets
PerformNoteHandler = 0x029B, // updated 4.3 PerformNoteHandler = 0x029B, // updated 4.3
ShopMessage = 0x00C1, // updated 5.25
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -1411,7 +1411,8 @@ namespace Sapphire::Network::Packets::Server
uint16_t scene; uint16_t scene;
uint16_t padding; uint16_t padding;
uint32_t sceneFlags; uint32_t sceneFlags;
uint8_t paramCount; uint32_t unknown;
uint8_t paramSize;
uint8_t padding2[3]; uint8_t padding2[3];
uint32_t params[ArgCount]; uint32_t params[ArgCount];
}; };
@ -2005,6 +2006,18 @@ namespace Sapphire::Network::Packets::Server
uint32_t unknown2; uint32_t unknown2;
}; };
struct FFXIVIpcShopMessage : FFXIVIpcBasePacket< ShopMessage >
{
uint32_t shopId;
uint32_t msgType;
uint32_t unknown2;
uint32_t itemId;
uint32_t amount;
uint32_t price;
uint32_t unknown6;
uint32_t unknown7;
};
} }
#endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/ #endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/

View file

@ -25,23 +25,27 @@ public:
private: private:
void shopInteractionCallback( Entity::Player& player, const Event::SceneResult& result ) void shopInteractionCallback( Entity::Player& player, const Event::SceneResult& result )
{ {
// item purchase // buy, sell, buy back
if( result.param1 == 768 ) if( result.param1 == 768 || result.param1 == 512 )
{ {
// buy // buy
if( result.param2 == 1 ) if( result.param2 == 1 )
{ {
auto& shopMgr = Common::Service< Sapphire::World::Manager::ShopMgr >::ref(); auto& shopMgr = Common::Service< Sapphire::World::Manager::ShopMgr >::ref();
shopMgr.purchaseGilShopItem( player, result.eventId, result.param3, result.param4 ); shopMgr.purchaseGilShopItem( player, result.eventId, result.param3, result.param4 );
} }
// sell // sell
// can't sell if the vendor is yourself (eg, housing permit shop) // can't sell if the vendor is yourself (eg, housing permit shop)
else if( result.param2 == 2 && result.actorId != player.getId() ) else if( result.param2 == 2 && result.actorId != player.getId() )
{ {
auto& shopMgr = Common::Service< Sapphire::World::Manager::ShopMgr >::ref();
shopMgr.shopSellItem( player, result.eventId, result.param3, result.param4 );
}
//buy back
else if( result.param2 == 3 && result.actorId != player.getId() )
{
auto& shopMgr = Common::Service< Sapphire::World::Manager::ShopMgr >::ref();
shopMgr.shopBuyBack( player, result.eventId, result.param3 );
} }
player.playGilShop( result.eventId, SCENE_FLAGS, result.param2, std::bind( &GilShop::shopInteractionCallback, this, std::placeholders::_1, std::placeholders::_2 ) ); player.playGilShop( result.eventId, SCENE_FLAGS, result.param2, std::bind( &GilShop::shopInteractionCallback, this, std::placeholders::_1, std::placeholders::_2 ) );

View file

@ -1330,6 +1330,7 @@ void Sapphire::Entity::Player::performZoning( uint16_t zoneId, const Common::FFX
m_bMarkedForZoning = true; m_bMarkedForZoning = true;
setRot( rotation ); setRot( rotation );
setZone( zoneId ); setZone( zoneId );
clearBuyBackMap();
} }
bool Sapphire::Entity::Player::isMarkedForZoning() const bool Sapphire::Entity::Player::isMarkedForZoning() const
@ -2245,6 +2246,22 @@ bool Sapphire::Entity::Player::checkAction()
return true; return true;
} }
std::vector< Sapphire::Entity::ShopBuyBackEntry >& Sapphire::Entity::Player::getBuyBackListForShop( uint32_t shopId )
{
return m_shopBuyBackMap[ shopId ];
}
void Sapphire::Entity::Player::addBuyBackItemForShop( uint32_t shopId, const Sapphire::Entity::ShopBuyBackEntry& entry )
{
auto& list = m_shopBuyBackMap[ shopId ];
list.insert( list.begin(), entry );
}
void Sapphire::Entity::Player::clearBuyBackMap()
{
m_shopBuyBackMap.clear();
}
void Sapphire::Entity::Player::gaugeClear() void Sapphire::Entity::Player::gaugeClear()
{ {
std::memset( &m_gauge, 0, sizeof( m_gauge ) ); std::memset( &m_gauge, 0, sizeof( m_gauge ) );

View file

@ -33,6 +33,13 @@ namespace Sapphire::Entity
} }
}; };
struct ShopBuyBackEntry
{
ItemPtr item;
uint32_t amount;
uint32_t value;
};
/** Class representing the Player /** Class representing the Player
* Inheriting from Actor * Inheriting from Actor
* *
@ -921,7 +928,8 @@ namespace Sapphire::Entity
InvSlotPair getFreeBagSlot(); InvSlotPair getFreeBagSlot();
Sapphire::ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true ); ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true );
ItemPtr addItem( ItemPtr itemToAdd, bool slient = false, bool canMerge = true );
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 );
@ -972,7 +980,7 @@ namespace Sapphire::Entity
void setActiveLand( uint8_t land, uint8_t ward ); void setActiveLand( uint8_t land, uint8_t ward );
Common::ActiveLand getActiveLand() const; Common::ActiveLand getActiveLand() const;
Sapphire::ItemPtr dropInventoryItem( Common::InventoryType type, uint16_t slotId ); Sapphire::ItemPtr dropInventoryItem( Common::InventoryType type, uint16_t slotId, bool slient = false );
// Job UI // Job UI
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
@ -996,6 +1004,10 @@ namespace Sapphire::Entity
uint8_t m_lastMoveflag; uint8_t m_lastMoveflag;
bool m_falling; bool m_falling;
std::vector< ShopBuyBackEntry >& getBuyBackListForShop( uint32_t shopId );
void addBuyBackItemForShop( uint32_t shopId, const ShopBuyBackEntry& entry );
void clearBuyBackMap();
private: private:
uint32_t m_lastWrite; uint32_t m_lastWrite;
uint32_t m_lastPing; uint32_t m_lastPing;
@ -1137,7 +1149,7 @@ namespace Sapphire::Entity
Common::Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; Common::Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator;
std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries; std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries;
std::unordered_map< uint32_t, std::vector< ShopBuyBackEntry > > m_shopBuyBackMap;
}; };
} }

View file

@ -12,6 +12,7 @@
#include "Network/PacketWrappers/EventFinishPacket.h" #include "Network/PacketWrappers/EventFinishPacket.h"
#include "Network/PacketWrappers/DirectorPlayScenePacket.h" #include "Network/PacketWrappers/DirectorPlayScenePacket.h"
#include "Inventory/Item.h"
#include "Territory/Territory.h" #include "Territory/Territory.h"
#include "ServerMgr.h" #include "ServerMgr.h"
@ -147,19 +148,49 @@ void Sapphire::Entity::Player::playGilShop( uint32_t eventId, uint32_t flags, ui
openGilShopPacket->data().actorId = getId(); openGilShopPacket->data().actorId = getId();
switch( param1 ) switch( param1 )
{ {
case 0:
{
openGilShopPacket->data().paramSize = 0xA1;
break;
}
case 1: case 1:
{ {
openGilShopPacket->data().params[ 0 ] = 0x02; openGilShopPacket->data().paramSize = 0x02;
openGilShopPacket->data().params[ 1 ] = 1; openGilShopPacket->data().params[ 0 ] = 1;
openGilShopPacket->data().params[ 2 ] = 0x64; openGilShopPacket->data().params[ 1 ] = 0x64;
break; break;
} }
case 2: case 2:
{ {
openGilShopPacket->data().params[ 0 ] = 0xA2; openGilShopPacket->data().paramSize = 0xA2;
openGilShopPacket->data().params[ 1 ] = 2; openGilShopPacket->data().params[ 0 ] = 2;
break; break;
} }
case 3:
{
openGilShopPacket->data().paramSize = 0xA2;
openGilShopPacket->data().params[ 0 ] = 3;
openGilShopPacket->data().params[ 1 ] = 0x64;
break;
}
}
auto& buyBackList = getBuyBackListForShop( eventId );
int index = param1 == 0 ? 1 : 2;
for( auto& entry : buyBackList )
{
if( index >= openGilShopPacket->data().paramSize )
break;
openGilShopPacket->data().params[ index++ ] = entry.item->getId();
openGilShopPacket->data().params[ index++ ] = entry.amount;
openGilShopPacket->data().params[ index++ ] = entry.value;
index += 2;
openGilShopPacket->data().params[ index++ ] = eventId;
index += 2;
openGilShopPacket->data().params[ index++ ] = ( ( entry.item->getDurability() << 16 ) + static_cast< uint16_t >( entry.item->isHq() ? 1 : 0 ) );
openGilShopPacket->data().params[ index++ ] = ( ( entry.item->getStain() << 16 ) + entry.item->getSpiritbond() );
openGilShopPacket->data().params[ index++ ] = 0; // glamour
index += 5;
} }
openGilShopPacket->data().scene = 10; openGilShopPacket->data().scene = 10;

View file

@ -521,15 +521,13 @@ void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const
bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity ) bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity )
{ {
return true; return true;
} }
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool silent, bool canMerge )
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent, bool canMerge )
{ {
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref(); auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto itemInfo = exdData.get< Sapphire::Data::Item >( catalogId ); auto itemInfo = exdData.get< Sapphire::Data::Item >( itemToAdd->getId() );
// if item data doesn't exist or it's a blank field // if item data doesn't exist or it's a blank field
if( !itemInfo || itemInfo->levelItem == 0 ) if( !itemInfo || itemInfo->levelItem == 0 )
@ -537,10 +535,10 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
return nullptr; return nullptr;
} }
quantity = std::min< uint32_t >( quantity, itemInfo->stackSize ); itemToAdd->setStackSize( std::min< uint32_t >( itemToAdd->getStackSize(), itemInfo->stackSize ) );
// used for item obtain notification // used for item obtain notification
uint32_t originalQuantity = quantity; uint32_t originalQuantity = itemToAdd->getStackSize();
std::pair< uint16_t, uint8_t > freeBagSlot; std::pair< uint16_t, uint8_t > freeBagSlot;
bool foundFreeSlot = false; bool foundFreeSlot = false;
@ -567,7 +565,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
auto item = storage->getItem( slot ); auto item = storage->getItem( slot );
// add any items that are stackable // add any items that are stackable
if( canMerge && item && !itemInfo->isEquippable && item->getId() == catalogId ) if( canMerge && item && !itemInfo->isEquippable && item->getId() == itemToAdd->getId() )
{ {
uint32_t count = item->getStackSize(); uint32_t count = item->getStackSize();
uint32_t maxStack = item->getMaxStackSize(); uint32_t maxStack = item->getMaxStackSize();
@ -577,18 +575,18 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
continue; continue;
// check slot is same quality // check slot is same quality
if( item->isHq() != isHq ) if( item->isHq() != itemToAdd->isHq() )
continue; continue;
// update stack // update stack
uint32_t newStackSize = count + quantity; uint32_t newStackSize = count + itemToAdd->getStackSize();
if( newStackSize > maxStack ) if( newStackSize > maxStack )
{ {
quantity = newStackSize - maxStack; itemToAdd->setStackSize( newStackSize - maxStack );
newStackSize = maxStack; newStackSize = maxStack;
} }
else else
quantity = 0; itemToAdd->setStackSize( 0 );
item->setStackSize( newStackSize ); item->setStackSize( newStackSize );
writeItem( item ); writeItem( item );
@ -597,9 +595,9 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
queuePacket( slotUpdate ); queuePacket( slotUpdate );
// return existing stack if we have no overflow - items fit into a preexisting stack // return existing stack if we have no overflow - items fit into a preexisting stack
if( quantity == 0 ) if( itemToAdd->getStackSize() == 0 )
{ {
queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, catalogId, originalQuantity ) ); queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, itemToAdd->getId(), originalQuantity ) );
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() ); auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
soundEffectPacket->data().sequence = 0xFFFFFFFF; soundEffectPacket->data().sequence = 0xFFFFFFFF;
@ -622,21 +620,17 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
if( !foundFreeSlot ) if( !foundFreeSlot )
return nullptr; return nullptr;
auto item = createItem( catalogId, quantity );
item->setHq( isHq );
auto storage = m_storageMap[ freeBagSlot.first ]; auto storage = m_storageMap[ freeBagSlot.first ];
storage->setItem( freeBagSlot.second, item ); storage->setItem( freeBagSlot.second, itemToAdd );
writeInventory( static_cast< InventoryType >( freeBagSlot.first ) ); writeInventory( static_cast< InventoryType >( freeBagSlot.first ) );
if( !silent ) if( !silent )
{ {
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, *itemToAdd );
*item );
queuePacket( invUpdate ); queuePacket( invUpdate );
queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, catalogId, originalQuantity ) ); queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, itemToAdd->getId(), originalQuantity ) );
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() ); auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
soundEffectPacket->data().sequence = 0xFFFFFFFF; soundEffectPacket->data().sequence = 0xFFFFFFFF;
@ -644,7 +638,15 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
queuePacket( soundEffectPacket ); queuePacket( soundEffectPacket );
} }
return item; return itemToAdd;
}
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent, bool canMerge )
{
auto item = createItem( catalogId, quantity );
item->setHq( isHq );
return addItem( item, silent, canMerge );
} }
void void
@ -927,7 +929,7 @@ uint32_t Sapphire::Entity::Player::getNextInventorySequence()
return m_inventorySequence++; return m_inventorySequence++;
} }
Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common::InventoryType type, uint16_t slotId ) Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common::InventoryType type, uint16_t slotId, bool slient )
{ {
auto& container = m_storageMap[ type ]; auto& container = m_storageMap[ type ];
@ -939,6 +941,12 @@ Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common:
container->removeItem( slotId, false ); container->removeItem( slotId, false );
updateContainer( type, slotId, nullptr ); updateContainer( type, slotId, nullptr );
if( !slient )
{
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slotId, static_cast< uint16_t >( type ) );
queuePacket( invUpdate );
}
auto seq = getNextInventorySequence(); auto seq = getNextInventorySequence();
// send inv update // send inv update

View file

@ -4,8 +4,15 @@
#include <Actor/Player.h> #include <Actor/Player.h>
#include <Common.h> #include <Common.h>
#include <Service.h> #include <Service.h>
#include <Network/GamePacket.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h>
#include "Inventory/Item.h"
#include "Inventory/ItemContainer.h"
using namespace Sapphire; using namespace Sapphire;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
bool Sapphire::World::Manager::ShopMgr::purchaseGilShopItem( Entity::Player& player, uint32_t shopId, uint16_t itemId, uint32_t quantity ) bool Sapphire::World::Manager::ShopMgr::purchaseGilShopItem( Entity::Player& player, uint32_t shopId, uint16_t itemId, uint32_t quantity )
{ {
@ -29,5 +36,86 @@ bool Sapphire::World::Manager::ShopMgr::purchaseGilShopItem( Entity::Player& pla
player.removeCurrency( Common::CurrencyType::Gil, price ); player.removeCurrency( Common::CurrencyType::Gil, price );
auto packet = makeZonePacket< FFXIVIpcShopMessage >( player.getId() );
packet->data().shopId = shopId;
packet->data().msgType = 1687;
packet->data().unknown2 = 3;
packet->data().itemId = gilShopItem->item;
packet->data().amount = quantity;
packet->data().price = price;
packet->data().unknown6 = 0;
packet->data().unknown7 = 0;
player.queuePacket( packet );
return true; return true;
} }
bool Sapphire::World::Manager::ShopMgr::shopSellItem( Sapphire::Entity::Player& player, uint32_t shopId, uint16_t containerId, uint16_t slotId )
{
auto item = player.getItemAt( containerId, slotId );
if( item )
{
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
auto itemData = exdData.get< Data::Item >( item->getId() );
if( itemData && !itemData->isIndisposable )
{
auto value = itemData->priceLow * item->getStackSize();
player.dropInventoryItem( static_cast< Common::InventoryType >( containerId ), slotId );
player.addCurrency( Common::CurrencyType::Gil, value );
Entity::ShopBuyBackEntry entry =
{
item,
item->getStackSize(),
itemData->priceLow
};
player.addBuyBackItemForShop( shopId, entry );
auto packet = makeZonePacket< FFXIVIpcShopMessage >( player.getId() );
packet->data().shopId = shopId;
packet->data().msgType = 1688;
packet->data().unknown2 = 3;
packet->data().itemId = item->getId();
packet->data().amount = item->getStackSize();
packet->data().price = value;
packet->data().unknown6 = 0;
packet->data().unknown7 = 0;
player.queuePacket( packet );
return true;
}
}
return false;
}
bool Sapphire::World::Manager::ShopMgr::shopBuyBack( Sapphire::Entity::Player& player, uint32_t shopId, uint16_t index )
{
auto& buyBackList = player.getBuyBackListForShop( shopId );
if( buyBackList.size() > index )
{
auto& entry = buyBackList[ index ];
if( player.getCurrency( Common::CurrencyType::Gil ) < entry.value )
return false;
auto originalStack = entry.item->getStackSize();
if( !player.addItem( entry.item ) )
return false;
player.removeCurrency( Common::CurrencyType::Gil, entry.value );
buyBackList.erase( buyBackList.begin() + index );
auto packet = makeZonePacket< FFXIVIpcShopMessage >( player.getId() );
packet->data().shopId = shopId;
packet->data().msgType = 1689;
packet->data().unknown2 = 3;
packet->data().itemId = entry.item->getId();
packet->data().amount = originalStack;
packet->data().price = entry.value * originalStack;
packet->data().unknown6 = 0;
packet->data().unknown7 = 0;
player.queuePacket( packet );
return true;
}
return false;
}

View file

@ -7,5 +7,7 @@ namespace Sapphire::World::Manager
public: public:
ShopMgr() = default; ShopMgr() = default;
bool purchaseGilShopItem( Sapphire::Entity::Player& player, uint32_t shopId, uint16_t itemId, uint32_t quantity ); bool purchaseGilShopItem( Sapphire::Entity::Player& player, uint32_t shopId, uint16_t itemId, uint32_t quantity );
bool shopSellItem( Sapphire::Entity::Player& player, uint32_t shopId, uint16_t containerId, uint16_t slotId );
bool shopBuyBack( Sapphire::Entity::Player& player, uint32_t shopId, uint16_t index );
}; };
} }

View file

@ -204,8 +204,8 @@ void Sapphire::Network::GameConnection::eventHandlerReturn( const Packets::FFXIV
std::string eventName = eventMgr.getEventName( eventId ); std::string eventName = eventMgr.getEventName( eventId );
player.sendDebug( "eventId: {0} ({0:08X}) scene: {1}, p1: {2}, p2: {3}, p3: {4}", player.sendDebug( "eventId: {0} ({0:08X}) scene: {1}, p1: {2}, p2: {3}, p3: {4}, p4: {5}",
eventId, scene, param1, param2, param3 ); eventId, scene, param1, param2, param3, param4 );
auto pEvent = player.getEvent( eventId ); auto pEvent = player.getEvent( eventId );
if( pEvent ) if( pEvent )

View file

@ -21,6 +21,12 @@ namespace Sapphire::Network::Packets::Server
initialize( slot, storageId, item ); initialize( slot, storageId, item );
}; };
UpdateInventorySlotPacket( uint32_t playerId, uint8_t slot, uint16_t storageId ) :
ZoneChannelPacket< FFXIVIpcUpdateInventorySlot >( playerId, playerId )
{
initialize( slot, storageId );
};
private: private:
void initialize( uint8_t slot, uint16_t storageId, const Item& item ) void initialize( uint8_t slot, uint16_t storageId, const Item& item )
{ {
@ -47,6 +53,15 @@ namespace Sapphire::Network::Packets::Server
//uint8_t buffer4; //uint8_t buffer4;
//uint8_t buffer5; //uint8_t buffer5;
}; };
void initialize( uint8_t slot, uint16_t storageId )
{
m_data.sequence = 0;
m_data.containerId = storageId;
m_data.slot = slot;
m_data.quantity = 0;
m_data.catalogId = 0;
};
}; };
} }