Files
DarkflameServer/dGame/dUtilities/Loot.h
Aaron Kimbrell ed2d329781 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>
2026-09-30 07:46:05 -05:00

69 lines
3.3 KiB
C++

#pragma once
#include "dCommonVars.h"
#include "eLootSourceType.h"
#include <map>
#include <unordered_map>
#include <utility>
#include <vector>
class Entity;
struct LootMetrics;
struct CDActivityRewards;
struct CDCurrencyTable;
namespace GameMessages {
struct DropClientLoot;
};
namespace Loot {
struct Info {
LWOOBJID id = 0;
LOT lot = 0;
int32_t count = 0;
// The LOT of the object it dropped from (1 when a player was the source), 0 when that object was not found.
// Sent back as the item's source when it is picked up (LootMetrics::sourceLot).
LOT sourceLot = 0;
};
using Return = std::map<LOT, int32_t>;
Loot::Return RollLootMatrix(Entity* player, uint32_t matrixIndex);
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);
/**
* Drops the loot of an activity's reward for the given rating, spawning at the source object.
* fromPlayer: the DropClientLoot source is the player instead of the object, as live sent quickbuild, chest and
* wishing well rewards (use_position true, spawn position the object's).
*/
void DropActivityLoot(Entity* player, const LWOOBJID source, uint32_t activityID, int32_t rating = 0, bool fromPlayer = true);
/**
* The coin range {min, max} of an ActivityRewards row, as live rolled it: the reward's ChallengeRating is the
* CurrencyTable npcminlevel, and level 1 is used when the currency index has no row for that level.
* currencyRows are the CurrencyTable rows of the reward's CurrencyIndex. {0, 0} when neither level has a row.
*/
std::pair<uint32_t, uint32_t> GetActivityCoinRange(const std::vector<CDCurrencyTable>& currencyRows, uint32_t challengeRating);
std::pair<uint32_t, uint32_t> GetActivityCoinRange(const CDActivityRewards& reward);
// How far from where it spawns a dropped item lands, as live dropped them (median 10.0 units, uniform direction).
constexpr float ITEM_DROP_DISTANCE = 10.0f;
/**
* Fills DropClientLoot's use_position and final_position the way live did (12,501 live DropClientLoot).
* use_position is set only when a player is the source (activity rewards such as the dragon and BONS chests):
* otherwise the client spawns the loot at the source object where it is on the client, and only falls back
* to the spawn position if that object is gone. Coins land where they spawn; items land ITEM_DROP_DISTANCE away
* at the given angle (radians, around Y).
* Nothing is set when there is no spawn position.
*/
void SetDropPositions(GameMessages::DropClientLoot& lootMsg, bool sourceIsPlayer, float angle);
};