mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-02 00:47:45 +00:00
Add LootMessage packet to fix old ItemObtainIcon.
This commit is contained in:
parent
37fbb35c0a
commit
cc95097fbe
7 changed files with 112 additions and 31 deletions
|
@ -1229,6 +1229,16 @@ namespace Sapphire::Common
|
||||||
} whm;
|
} whm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class LootMessageType : uint8_t
|
||||||
|
{
|
||||||
|
GetItem1 = 1, // p1: actorId, p4: itemId (HQ: itemId + 1,000,000 lol), p5: amount
|
||||||
|
GetItem2 = 3, // p1: actorId, p2: itemId, p3: amount, seems like same thing as GetItem1 but different param position.
|
||||||
|
FailedToGetLootNoFreeInventorySlot = 5, // p1: actorId
|
||||||
|
LootRolled = 7, // p1: actorId, p2: itemId, p3: amount
|
||||||
|
GetGil = 9, // p1: gil
|
||||||
|
EmptyCoffer = 11, // seems like no param
|
||||||
|
};
|
||||||
|
|
||||||
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,8 +376,8 @@ namespace Sapphire::Network::Packets
|
||||||
|
|
||||||
PerformNoteHandler = 0x029B, // updated 4.3
|
PerformNoteHandler = 0x029B, // updated 4.3
|
||||||
|
|
||||||
|
|
||||||
ShopMessage = 0x00C1, // updated 5.25
|
ShopMessage = 0x00C1, // updated 5.25
|
||||||
|
LootMessage = 0x00B1, // updated 5.25
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -2018,6 +2018,19 @@ namespace Sapphire::Network::Packets::Server
|
||||||
uint32_t unknown7;
|
uint32_t unknown7;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FFXIVIpcLootMessage : FFXIVIpcBasePacket< LootMessage >
|
||||||
|
{
|
||||||
|
Common::LootMessageType msgType;
|
||||||
|
uint8_t padding[3];
|
||||||
|
uint32_t param1;
|
||||||
|
uint32_t param2;
|
||||||
|
uint32_t param3;
|
||||||
|
uint32_t param4;
|
||||||
|
uint32_t param5;
|
||||||
|
uint32_t param6;
|
||||||
|
uint32_t param7;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/
|
#endif /*_CORE_NETWORK_PACKETS_SERVER_IPC_H*/
|
||||||
|
|
|
@ -360,7 +360,7 @@ namespace Sapphire::Entity
|
||||||
uint32_t getModelForSlot( Common::GearModelSlot slot );
|
uint32_t getModelForSlot( Common::GearModelSlot slot );
|
||||||
|
|
||||||
/*! add amount to the currency of type */
|
/*! add amount to the currency of type */
|
||||||
void addCurrency( Common::CurrencyType type, uint32_t amount );
|
void addCurrency( Common::CurrencyType type, uint32_t amount, bool sendLootMessage = false );
|
||||||
|
|
||||||
/*! remove amount from the currency of type */
|
/*! remove amount from the currency of type */
|
||||||
void removeCurrency( Common::CurrencyType type, uint32_t amount );
|
void removeCurrency( Common::CurrencyType type, uint32_t amount );
|
||||||
|
@ -928,8 +928,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
InvSlotPair getFreeBagSlot();
|
InvSlotPair getFreeBagSlot();
|
||||||
|
|
||||||
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 silent = false, bool canMerge = true, bool sendLootMessage = false );
|
||||||
ItemPtr addItem( ItemPtr itemToAdd, bool slient = false, bool canMerge = true );
|
ItemPtr addItem( ItemPtr itemToAdd, bool silent = false, bool canMerge = true, bool sendLootMessage = 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 );
|
||||||
|
|
||||||
|
@ -964,7 +964,7 @@ namespace Sapphire::Entity
|
||||||
uint32_t getCrystal( Common::CrystalType type );
|
uint32_t getCrystal( Common::CrystalType type );
|
||||||
|
|
||||||
/*! add amount to the crystal of type */
|
/*! add amount to the crystal of type */
|
||||||
void addCrystal( Common::CrystalType type, uint32_t amount );
|
void addCrystal( Common::CrystalType type, uint32_t amount, bool sendLootMessage = false );
|
||||||
|
|
||||||
/*! remove amount from the crystals of type */
|
/*! remove amount from the crystals of type */
|
||||||
void removeCrystal( Common::CrystalType type, uint32_t amount );
|
void removeCrystal( Common::CrystalType type, uint32_t amount );
|
||||||
|
@ -980,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, bool slient = false );
|
Sapphire::ItemPtr dropInventoryItem( Common::InventoryType type, uint16_t slotId, bool silent = false );
|
||||||
|
|
||||||
// Job UI
|
// Job UI
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -298,7 +298,7 @@ void Sapphire::Entity::Player::unequipSoulCrystal( ItemPtr pItem )
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: these next functions are so similar that they could likely be simplified
|
// TODO: these next functions are so similar that they could likely be simplified
|
||||||
void Sapphire::Entity::Player::addCurrency( CurrencyType type, uint32_t amount )
|
void Sapphire::Entity::Player::addCurrency( CurrencyType type, uint32_t amount, bool sendLootMessage )
|
||||||
{
|
{
|
||||||
auto slot = static_cast< uint8_t >( static_cast< uint8_t >( type ) - 1 );
|
auto slot = static_cast< uint8_t >( static_cast< uint8_t >( type ) - 1 );
|
||||||
auto currItem = m_storageMap[ Currency ]->getItem( slot );
|
auto currItem = m_storageMap[ Currency ]->getItem( slot );
|
||||||
|
@ -321,6 +321,22 @@ void Sapphire::Entity::Player::addCurrency( CurrencyType type, uint32_t amount )
|
||||||
Common::InventoryType::Currency,
|
Common::InventoryType::Currency,
|
||||||
*currItem );
|
*currItem );
|
||||||
queuePacket( invUpdate );
|
queuePacket( invUpdate );
|
||||||
|
|
||||||
|
|
||||||
|
if( sendLootMessage )
|
||||||
|
{
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case CurrencyType::Gil:
|
||||||
|
{
|
||||||
|
auto lootMsg = makeZonePacket< FFXIVIpcLootMessage >( getId() );
|
||||||
|
lootMsg->data().msgType = Common::LootMessageType::GetGil;
|
||||||
|
lootMsg->data().param1 = amount;
|
||||||
|
queuePacket( lootMsg );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Entity::Player::removeCurrency( Common::CurrencyType type, uint32_t amount )
|
void Sapphire::Entity::Player::removeCurrency( Common::CurrencyType type, uint32_t amount )
|
||||||
|
@ -346,7 +362,7 @@ void Sapphire::Entity::Player::removeCurrency( Common::CurrencyType type, uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Sapphire::Entity::Player::addCrystal( Common::CrystalType type, uint32_t amount )
|
void Sapphire::Entity::Player::addCrystal( Common::CrystalType type, uint32_t amount, bool sendLootMessage )
|
||||||
{
|
{
|
||||||
auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 );
|
auto currItem = m_storageMap[ Crystal ]->getItem( static_cast< uint8_t >( type ) - 1 );
|
||||||
|
|
||||||
|
@ -371,7 +387,21 @@ void Sapphire::Entity::Player::addCrystal( Common::CrystalType type, uint32_t am
|
||||||
Common::InventoryType::Crystal,
|
Common::InventoryType::Crystal,
|
||||||
*currItem );
|
*currItem );
|
||||||
queuePacket( invUpdate );
|
queuePacket( invUpdate );
|
||||||
queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, static_cast< uint8_t >( type ) + 1, amount ) );
|
|
||||||
|
if( sendLootMessage )
|
||||||
|
{
|
||||||
|
auto lootMsg = makeZonePacket< FFXIVIpcLootMessage >( getId() );
|
||||||
|
lootMsg->data().msgType = Common::LootMessageType::GetItem2;
|
||||||
|
lootMsg->data().param1 = getId();
|
||||||
|
lootMsg->data().param2 = currItem->getId();
|
||||||
|
lootMsg->data().param3 = amount;
|
||||||
|
queuePacket( lootMsg );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
|
||||||
|
soundEffectPacket->data().sequence = 0xFFFFFFFF;
|
||||||
|
soundEffectPacket->data().type = 6;
|
||||||
|
queuePacket( soundEffectPacket );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Entity::Player::removeCrystal( Common::CrystalType type, uint32_t amount )
|
void Sapphire::Entity::Player::removeCrystal( Common::CrystalType type, uint32_t amount )
|
||||||
|
@ -524,7 +554,7 @@ bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantit
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool silent, bool canMerge )
|
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool silent, bool canMerge, bool sendLootMessage )
|
||||||
{
|
{
|
||||||
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
auto& exdData = Common::Service< Data::ExdDataGenerated >::ref();
|
||||||
auto itemInfo = exdData.get< Sapphire::Data::Item >( itemToAdd->getId() );
|
auto itemInfo = exdData.get< Sapphire::Data::Item >( itemToAdd->getId() );
|
||||||
|
@ -591,13 +621,24 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool sil
|
||||||
item->setStackSize( newStackSize );
|
item->setStackSize( newStackSize );
|
||||||
writeItem( item );
|
writeItem( item );
|
||||||
|
|
||||||
auto slotUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slot, bag, *item );
|
if( !silent )
|
||||||
queuePacket( slotUpdate );
|
{
|
||||||
|
auto slotUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slot, bag, *item );
|
||||||
|
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( itemToAdd->getStackSize() == 0 )
|
if( itemToAdd->getStackSize() == 0 )
|
||||||
{
|
{
|
||||||
queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, itemToAdd->getId(), originalQuantity ) );
|
if( sendLootMessage )
|
||||||
|
{
|
||||||
|
auto lootMsg = makeZonePacket< FFXIVIpcLootMessage >( getId() );
|
||||||
|
lootMsg->data().msgType = Common::LootMessageType::GetItem2;
|
||||||
|
lootMsg->data().param1 = getId();
|
||||||
|
lootMsg->data().param2 = itemToAdd->isHq() ? itemToAdd->getId() + 1000000 : itemToAdd->getId();
|
||||||
|
lootMsg->data().param3 = originalQuantity;
|
||||||
|
queuePacket( lootMsg );
|
||||||
|
}
|
||||||
|
|
||||||
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
|
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
|
||||||
soundEffectPacket->data().sequence = 0xFFFFFFFF;
|
soundEffectPacket->data().sequence = 0xFFFFFFFF;
|
||||||
|
@ -629,24 +670,32 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( ItemPtr itemToAdd, bool sil
|
||||||
{
|
{
|
||||||
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, *itemToAdd );
|
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), freeBagSlot.second, freeBagSlot.first, *itemToAdd );
|
||||||
queuePacket( invUpdate );
|
queuePacket( invUpdate );
|
||||||
|
|
||||||
queuePacket( makeActorControlSelf( getId(), ItemObtainIcon, itemToAdd->getId(), originalQuantity ) );
|
|
||||||
|
|
||||||
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
|
|
||||||
soundEffectPacket->data().sequence = 0xFFFFFFFF;
|
|
||||||
soundEffectPacket->data().type = 6;
|
|
||||||
queuePacket( soundEffectPacket );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( sendLootMessage )
|
||||||
|
{
|
||||||
|
auto lootMsg = makeZonePacket< FFXIVIpcLootMessage >( getId() );
|
||||||
|
lootMsg->data().msgType = Common::LootMessageType::GetItem2;
|
||||||
|
lootMsg->data().param1 = getId();
|
||||||
|
lootMsg->data().param2 = itemToAdd->isHq() ? itemToAdd->getId() + 1000000 : itemToAdd->getId();
|
||||||
|
lootMsg->data().param3 = originalQuantity;
|
||||||
|
queuePacket( lootMsg );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto soundEffectPacket = makeZonePacket< FFXIVIpcInventoryActionAck >( getId() );
|
||||||
|
soundEffectPacket->data().sequence = 0xFFFFFFFF;
|
||||||
|
soundEffectPacket->data().type = 6;
|
||||||
|
queuePacket( soundEffectPacket );
|
||||||
|
|
||||||
return itemToAdd;
|
return itemToAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent, bool canMerge )
|
Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_t quantity, bool isHq, bool silent, bool canMerge, bool sendLootMessage )
|
||||||
{
|
{
|
||||||
auto item = createItem( catalogId, quantity );
|
auto item = createItem( catalogId, quantity );
|
||||||
item->setHq( isHq );
|
item->setHq( isHq );
|
||||||
return addItem( item, silent, canMerge );
|
return addItem( item, silent, canMerge, sendLootMessage );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -929,7 +978,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, bool slient )
|
Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common::InventoryType type, uint16_t slotId, bool silent )
|
||||||
{
|
{
|
||||||
auto& container = m_storageMap[ type ];
|
auto& container = m_storageMap[ type ];
|
||||||
|
|
||||||
|
@ -941,7 +990,7 @@ 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 )
|
if( !silent )
|
||||||
{
|
{
|
||||||
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slotId, static_cast< uint16_t >( type ) );
|
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slotId, static_cast< uint16_t >( type ) );
|
||||||
queuePacket( invUpdate );
|
queuePacket( invUpdate );
|
||||||
|
|
|
@ -1065,7 +1065,7 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti
|
||||||
{
|
{
|
||||||
for( uint32_t i = 0; i < rewardItemCount; i++ )
|
for( uint32_t i = 0; i < rewardItemCount; i++ )
|
||||||
{
|
{
|
||||||
addItem( questInfo->itemReward0.at( i ), questInfo->itemCountReward0.at( i ) );
|
addItem( questInfo->itemReward0.at( i ), questInfo->itemCountReward0.at( i ), false, false, true, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,14 +1076,14 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti
|
||||||
auto itemId = questInfo->itemReward1.at( i );
|
auto itemId = questInfo->itemReward1.at( i );
|
||||||
if( itemId == optionalChoice )
|
if( itemId == optionalChoice )
|
||||||
{
|
{
|
||||||
addItem( itemId, questInfo->itemCountReward1.at( i ) );
|
addItem( itemId, questInfo->itemCountReward1.at( i ), false, false, true, true );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( gilReward > 0 )
|
if( gilReward > 0 )
|
||||||
addCurrency( CurrencyType::Gil, gilReward );
|
addCurrency( CurrencyType::Gil, gilReward, true );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,14 +345,23 @@ void Sapphire::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACK
|
||||||
player.sendUrgent( "Syntaxerror." );
|
player.sendUrgent( "Syntaxerror." );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if( param1 <= 0x12 ) // crystal
|
||||||
|
{
|
||||||
|
targetPlayer->addCrystal( static_cast< Common::CrystalType >( param1 ), quantity, true );
|
||||||
|
}
|
||||||
|
else // item
|
||||||
|
{
|
||||||
|
// decode using the epic SE style HQ item id
|
||||||
|
bool isHq = param1 > 1000000;
|
||||||
|
|
||||||
if( !targetPlayer->addItem( param1, quantity ) )
|
if( !targetPlayer->addItem( isHq ? param1 - 1000000 : param1, quantity, isHq, false, true, true ) )
|
||||||
player.sendUrgent( "Item #{0} could not be added to inventory.", param1 );
|
player.sendUrgent( "Item #{0} could not be added to inventory.", isHq ? param1 - 1000000 : param1 );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case GmCommand::Gil:
|
case GmCommand::Gil:
|
||||||
{
|
{
|
||||||
targetPlayer->addCurrency( CurrencyType::Gil, param1 );
|
targetPlayer->addCurrency( CurrencyType::Gil, param1, true );
|
||||||
player.sendNotice( "Added {0} Gil for {1}", param1, targetPlayer->getName() );
|
player.sendNotice( "Added {0} Gil for {1}", param1, targetPlayer->getName() );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue