using Theriapolis.Core.Data;
using Theriapolis.Core.Items;
using Theriapolis.Core.Util;
namespace Theriapolis.Core.Loot;
///
/// Phase 7 M2 — container-level deterministic loot rolls. Wraps
/// with a per-container
/// derived from the dungeon's layout seed and the container's slot index,
/// so the same (worldSeed, poiId, slotIdx) always rolls the same
/// items.
///
/// Per Phase 7 plan §4.4 / §5.5:
/// lootContainerSeed = dungeonLayoutSeed ^ C.RNG_DUNGEON_LOOT ^ slotIdx
///
/// The path is the encounter-drop pipeline (uses
/// the encounter's RNG); this path is for static dungeon containers and
/// does not advance any encounter-time stream.
///
public static class LootGenerator
{
///
/// Roll a single container's contents.
///
/// Loot-table id (e.g. loot_dungeon_imperium_t2).
///
/// Per-container seed. Caller is expected to derive this as
/// worldSeed ^ C.RNG_DUNGEON_LAYOUT ^ poiId ^ C.RNG_DUNGEON_LOOT ^ slotIdx.
///
/// Loot-table dictionary from .
/// Item dictionary from .
/// An array of ready to drop into an inventory.
public static ItemInstance[] RollContainer(
string tableId,
ulong containerSeed,
IReadOnlyDictionary tables,
IReadOnlyDictionary items)
{
var rng = new SeededRng(containerSeed);
var drops = LootRoller.Roll(tableId, tables, items, rng);
var result = new ItemInstance[drops.Count];
for (int i = 0; i < drops.Count; i++)
result[i] = new ItemInstance(drops[i].Def, drops[i].Qty);
return result;
}
///
/// Convenience overload that resolves the per-container seed from the
/// dungeon layout seed + slot index per the Phase 7 dice contract.
///
public static ItemInstance[] RollContainer(
string tableId,
ulong dungeonLayoutSeed,
int slotIdx,
IReadOnlyDictionary tables,
IReadOnlyDictionary items)
{
ulong containerSeed = dungeonLayoutSeed ^ C.RNG_DUNGEON_LOOT ^ (ulong)slotIdx;
return RollContainer(tableId, containerSeed, tables, items);
}
}