mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-07 05:13:44 +00:00
feat(loot): rewards, purchases, mail and trades say where items came from
The other item sources live marked in AddItemToInventoryClientSync's extra info, with the keys and values live sent: - mission and achievement rewards: _Metric_Mission_ID_Int and source LOT 1, the player (225 of 225 live rewards) - activity rewards: _Metric_Activity_ID_Int and the activity object's LOT - vendor purchases: the vendor's LOT and _Metric_Currency_Delta_Int, the coins paid as a negative number (left out when the item costs no coins) - mail attachments: _Metric_Mail_ID_Int64 - traded items: _Metric_Transaction_ID_Int64, the trade's ID Loot::GiveLoot gains overloads that pass them on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -189,7 +189,8 @@ void Trade::Complete() {
|
||||
recordCoins(m_CoinsA, characterA->GetID(), characterB->GetID());
|
||||
recordCoins(m_CoinsB, characterB->GetID(), characterA->GetID());
|
||||
|
||||
const auto giveItems = [zone](const std::vector<TradeItem>& items, InventoryComponent* from, MissionComponent* fromMissions,
|
||||
const auto tradeId = m_TradeId;
|
||||
const auto giveItems = [zone, tradeId](const std::vector<TradeItem>& items, InventoryComponent* from, MissionComponent* fromMissions,
|
||||
InventoryComponent* to, const LWOOBJID fromCharacter, const LWOOBJID toCharacter) {
|
||||
for (const auto& tradeItem : items) {
|
||||
auto* itemToRemove = from->FindItemById(tradeItem.itemId);
|
||||
@@ -204,9 +205,12 @@ void Trade::Complete() {
|
||||
const auto bound = itemToRemove->GetBound();
|
||||
itemToRemove->SetCount(itemToRemove->GetCount() - tradeItem.itemCount);
|
||||
fromMissions->Progress(eMissionTaskType::GATHER, tradeItem.itemLot, LWOOBJID_EMPTY, "", -static_cast<int32_t>(tradeItem.itemCount));
|
||||
// Live sent the trade's ID with the traded items
|
||||
ReceiveItemOptions options{};
|
||||
options.metrics.transactionId = tradeId;
|
||||
const auto received = whole
|
||||
? to->ReceiveItem(LWOOBJID_EMPTY, tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::TRADE, config, subKey, bound)
|
||||
: to->ReceiveItem(LWOOBJID_EMPTY, tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::TRADE);
|
||||
? to->ReceiveItem(LWOOBJID_EMPTY, tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::TRADE, config, subKey, bound, options)
|
||||
: to->ReceiveItem(LWOOBJID_EMPTY, tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::TRADE, {}, LWOOBJID_EMPTY, false, options);
|
||||
|
||||
EconomyLedger::RecordTransfer({ .method = IEconomyLedger::eTransferMethod::TRADE, .itemId = tradeItem.itemId, .newItemId = received.id,
|
||||
.lot = tradeItem.itemLot, .count = tradeItem.itemCount, .fromCharacter = fromCharacter, .toCharacter = toCharacter, .zone = zone,
|
||||
|
||||
@@ -208,7 +208,11 @@ void VendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
|
||||
}
|
||||
|
||||
character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR, CoinSource::Object(*m_Parent));
|
||||
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
|
||||
// Live sent the vendor's LOT, and the coins paid when there were any, with the bought items
|
||||
LootMetrics metrics{};
|
||||
metrics.sourceLot = m_Parent->GetLOT();
|
||||
if (coinCost > 0) metrics.currencyDelta = -static_cast<int32_t>(coinCost);
|
||||
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR, eInventoryType::INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, eInventoryType::INVALID, 0, false, -1, metrics);
|
||||
SendTransactionResult(buyer->GetObjectID(), buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
@@ -510,6 +510,11 @@ void Mission::YieldRewards() {
|
||||
}
|
||||
}
|
||||
|
||||
// Live sent the mission's ID and the player's LOT with each reward item (225 of 225 live mission and achievement rewards)
|
||||
LootMetrics rewardMetrics{};
|
||||
rewardMetrics.sourceLot = entity->GetLOT();
|
||||
rewardMetrics.missionId = static_cast<int32_t>(info.id);
|
||||
|
||||
if (m_Completions > 0) {
|
||||
std::vector<std::pair<LOT, uint32_t>> items;
|
||||
|
||||
@@ -528,7 +533,7 @@ void Mission::YieldRewards() {
|
||||
// If a mission rewards zero of an item, make it reward 1.
|
||||
auto count = pair.second > 0 ? pair.second : 1;
|
||||
LOG("Player %llu is receiving %i of item %i from repeatable mission %i", entity->GetObjectID(), count, pair.first, info.id);
|
||||
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT);
|
||||
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT, eInventoryType::INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, eInventoryType::INVALID, 0, false, -1, rewardMetrics);
|
||||
}
|
||||
|
||||
if (info.reward_currency_repeatable > 0 || coinsToSend > 0) {
|
||||
@@ -556,7 +561,7 @@ void Mission::YieldRewards() {
|
||||
// If a mission rewards zero of an item, make it reward 1.
|
||||
auto count = pair.second > 0 ? pair.second : 1;
|
||||
LOG("Player %llu is receiving %i of item %i from mission %i", entity->GetObjectID(), count, pair.first, info.id);
|
||||
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT);
|
||||
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT, eInventoryType::INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, eInventoryType::INVALID, 0, false, -1, rewardMetrics);
|
||||
}
|
||||
|
||||
if (info.reward_currency > 0 || coinsToSend > 0) {
|
||||
|
||||
@@ -523,14 +523,22 @@ Loot::Return Loot::RollLootMatrix(Entity* player, uint32_t matrixIndex) {
|
||||
}
|
||||
|
||||
void Loot::GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType) {
|
||||
GiveLoot(player, matrixIndex, lootSourceType, LootMetrics{});
|
||||
}
|
||||
|
||||
void Loot::GiveLoot(Entity* player, const Loot::Return& result, eLootSourceType lootSourceType) {
|
||||
GiveLoot(player, result, lootSourceType, LootMetrics{});
|
||||
}
|
||||
|
||||
void Loot::GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType, const LootMetrics& metrics) {
|
||||
player = player->GetOwner(); // If the owner is overwritten, we collect that here
|
||||
|
||||
const auto result = RollLootMatrix(player, matrixIndex);
|
||||
|
||||
GiveLoot(player, result, lootSourceType);
|
||||
GiveLoot(player, result, lootSourceType, metrics);
|
||||
}
|
||||
|
||||
void Loot::GiveLoot(Entity* player, const Loot::Return& result, eLootSourceType lootSourceType) {
|
||||
void Loot::GiveLoot(Entity* player, const Loot::Return& result, eLootSourceType lootSourceType, const LootMetrics& metrics) {
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
@@ -539,7 +547,7 @@ void Loot::GiveLoot(Entity* player, const Loot::Return& result, eLootSourceType
|
||||
return;
|
||||
|
||||
for (const auto& pair : result) {
|
||||
inventoryComponent->AddItem(pair.first, pair.second, lootSourceType);
|
||||
inventoryComponent->AddItem(pair.first, pair.second, lootSourceType, eInventoryType::INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, eInventoryType::INVALID, 0, false, -1, metrics);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,7 +585,11 @@ void Loot::GiveActivityLoot(Entity* player, const LWOOBJID source, uint32_t acti
|
||||
|
||||
const auto [minCoins, maxCoins] = GetActivityCoinRange(*selectedReward);
|
||||
|
||||
GiveLoot(player, selectedReward->LootMatrixIndex, eLootSourceType::ACTIVITY);
|
||||
// Live sent the activity's ID and the activity object's LOT with each reward item
|
||||
LootMetrics metrics{};
|
||||
metrics.activityId = static_cast<int32_t>(activityID);
|
||||
if (const auto* const sourceEntity = Game::entityManager->GetEntity(source)) metrics.sourceLot = sourceEntity->GetLOT();
|
||||
GiveLoot(player, selectedReward->LootMatrixIndex, eLootSourceType::ACTIVITY, metrics);
|
||||
|
||||
uint32_t coins = static_cast<uint32_t>(minCoins + GeneralUtils::GenerateRandomNumber<float>(0, 1) * (maxCoins - minCoins));
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
class Entity;
|
||||
struct LootMetrics;
|
||||
struct CDActivityRewards;
|
||||
struct CDCurrencyTable;
|
||||
|
||||
@@ -31,6 +32,9 @@ namespace Loot {
|
||||
void CacheMatrix(const uint32_t matrixIndex);
|
||||
void GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType = eLootSourceType::NONE);
|
||||
void GiveLoot(Entity* player, const Loot::Return& result, eLootSourceType lootSourceType = eLootSourceType::NONE);
|
||||
// As above, telling the client where the items came from (LootMetrics)
|
||||
void GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType, const LootMetrics& metrics);
|
||||
void GiveLoot(Entity* player, const Loot::Return& result, eLootSourceType lootSourceType, const LootMetrics& metrics);
|
||||
void GiveActivityLoot(Entity* player, const LWOOBJID source, uint32_t activityID, int32_t rating = 0);
|
||||
void DropLoot(Entity* player, const LWOOBJID source, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropItem(Entity& player, GameMessages::DropClientLoot& lootMsg, bool useTeam = false, bool forceFfa = false);
|
||||
|
||||
@@ -239,7 +239,10 @@ namespace Mail {
|
||||
|
||||
LwoNameValue config;
|
||||
config.InsertLines(playerMail->itemConfig);
|
||||
const auto claimed = inv->ReceiveItem(playerMail->itemID, playerMail->itemLOT, playerMail->itemCount, eLootSourceType::MAIL, config, playerMail->itemSubkey);
|
||||
// Live sent the mail's ID with the attachment
|
||||
ReceiveItemOptions options{};
|
||||
options.metrics.mailId = static_cast<uint64_t>(mailID);
|
||||
const auto claimed = inv->ReceiveItem(playerMail->itemID, playerMail->itemLOT, playerMail->itemCount, eLootSourceType::MAIL, config, playerMail->itemSubkey, false, options);
|
||||
Database::Get()->ClaimMailItem(mailID);
|
||||
DashboardNotify::Changed("mail", playerMail->receiverId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user