1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-01 16:37:45 +00:00

Add LootMessage packet to fix old ItemObtainIcon.

This commit is contained in:
collett 2020-05-12 02:30:21 +09:00
parent 37fbb35c0a
commit cc95097fbe
7 changed files with 112 additions and 31 deletions

View file

@ -1229,6 +1229,16 @@ namespace Sapphire::Common
} 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 >;
}

View file

@ -376,8 +376,8 @@ namespace Sapphire::Network::Packets
PerformNoteHandler = 0x029B, // updated 4.3
ShopMessage = 0x00C1, // updated 5.25
LootMessage = 0x00B1, // updated 5.25
};
////////////////////////////////////////////////////////////////////////////////

View file

@ -2018,6 +2018,19 @@ namespace Sapphire::Network::Packets::Server
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*/

View file

@ -360,7 +360,7 @@ namespace Sapphire::Entity
uint32_t getModelForSlot( Common::GearModelSlot slot );
/*! 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 */
void removeCurrency( Common::CurrencyType type, uint32_t amount );
@ -928,8 +928,8 @@ namespace Sapphire::Entity
InvSlotPair getFreeBagSlot();
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 );
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 silent = false, bool canMerge = true, bool sendLootMessage = false );
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 );
/*! 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 */
void removeCrystal( Common::CrystalType type, uint32_t amount );
@ -980,7 +980,7 @@ namespace Sapphire::Entity
void setActiveLand( uint8_t land, uint8_t ward );
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
//////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -298,7 +298,7 @@ void Sapphire::Entity::Player::unequipSoulCrystal( ItemPtr pItem )
}
// 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 currItem = m_storageMap[ Currency ]->getItem( slot );
@ -321,6 +321,22 @@ void Sapphire::Entity::Player::addCurrency( CurrencyType type, uint32_t amount )
Common::InventoryType::Currency,
*currItem );
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 )
@ -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 );
@ -371,7 +387,21 @@ void Sapphire::Entity::Player::addCrystal( Common::CrystalType type, uint32_t am
Common::InventoryType::Crystal,
*currItem );
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 )
@ -524,7 +554,7 @@ bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantit
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 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 );
writeItem( item );
auto slotUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slot, bag, *item );
queuePacket( slotUpdate );
if( !silent )
{
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
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() );
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 );
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;
}
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 );
item->setHq( isHq );
return addItem( item, silent, canMerge );
return addItem( item, silent, canMerge, sendLootMessage );
}
void
@ -929,7 +978,7 @@ uint32_t Sapphire::Entity::Player::getNextInventorySequence()
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 ];
@ -941,7 +990,7 @@ Sapphire::ItemPtr Sapphire::Entity::Player::dropInventoryItem( Sapphire::Common:
container->removeItem( slotId, false );
updateContainer( type, slotId, nullptr );
if( !slient )
if( !silent )
{
auto invUpdate = std::make_shared< UpdateInventorySlotPacket >( getId(), slotId, static_cast< uint16_t >( type ) );
queuePacket( invUpdate );

View file

@ -1065,7 +1065,7 @@ bool Sapphire::Entity::Player::giveQuestRewards( uint32_t questId, uint32_t opti
{
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 );
if( itemId == optionalChoice )
{
addItem( itemId, questInfo->itemCountReward1.at( i ) );
addItem( itemId, questInfo->itemCountReward1.at( i ), false, false, true, true );
break;
}
}
}
if( gilReward > 0 )
addCurrency( CurrencyType::Gil, gilReward );
addCurrency( CurrencyType::Gil, gilReward, true );
return true;
}

View file

@ -345,14 +345,23 @@ void Sapphire::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACK
player.sendUrgent( "Syntaxerror." );
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 ) )
player.sendUrgent( "Item #{0} could not be added to inventory.", param1 );
break;
if( !targetPlayer->addItem( isHq ? param1 - 1000000 : param1, quantity, isHq, false, true, true ) )
player.sendUrgent( "Item #{0} could not be added to inventory.", isHq ? param1 - 1000000 : param1 );
break;
}
}
case GmCommand::Gil:
{
targetPlayer->addCurrency( CurrencyType::Gil, param1 );
targetPlayer->addCurrency( CurrencyType::Gil, param1, true );
player.sendNotice( "Added {0} Gil for {1}", param1, targetPlayer->getName() );
break;
}