| | | 1 | | namespace RaidLoop.Core; |
| | | 2 | | |
| | | 3 | | public sealed class LootTierProfile |
| | | 4 | | { |
| | | 5 | | private readonly (Rarity Tier, int Weight)[] _weights; |
| | | 6 | | |
| | 8 | 7 | | public LootTierProfile(int commonWeight, int uncommonWeight, int rareWeight, int epicWeight, int legendaryWeight) |
| | | 8 | | { |
| | 8 | 9 | | _weights = |
| | 8 | 10 | | [ |
| | 8 | 11 | | (Rarity.Common, commonWeight), |
| | 8 | 12 | | (Rarity.Uncommon, uncommonWeight), |
| | 8 | 13 | | (Rarity.Rare, rareWeight), |
| | 8 | 14 | | (Rarity.Epic, epicWeight), |
| | 8 | 15 | | (Rarity.Legendary, legendaryWeight) |
| | 8 | 16 | | ]; |
| | | 17 | | |
| | 48 | 18 | | if (_weights.Any(entry => entry.Weight < 0)) |
| | | 19 | | { |
| | 0 | 20 | | throw new ArgumentOutOfRangeException(nameof(commonWeight), "Tier weights cannot be negative."); |
| | | 21 | | } |
| | | 22 | | |
| | 18 | 23 | | if (_weights.All(entry => entry.Weight == 0)) |
| | | 24 | | { |
| | 0 | 25 | | throw new ArgumentOutOfRangeException(nameof(commonWeight), "At least one tier weight must be positive."); |
| | | 26 | | } |
| | 8 | 27 | | } |
| | | 28 | | |
| | | 29 | | public Rarity Roll(IRng rng, IReadOnlyCollection<Rarity> availableTiers) |
| | | 30 | | { |
| | 10015 | 31 | | ArgumentNullException.ThrowIfNull(rng); |
| | 10015 | 32 | | ArgumentNullException.ThrowIfNull(availableTiers); |
| | | 33 | | |
| | 10015 | 34 | | var weightedAvailable = _weights |
| | 50075 | 35 | | .Where(entry => entry.Weight > 0 && availableTiers.Contains(entry.Tier)) |
| | 10015 | 36 | | .ToArray(); |
| | | 37 | | |
| | 10015 | 38 | | if (weightedAvailable.Length == 0) |
| | | 39 | | { |
| | 0 | 40 | | throw new InvalidOperationException("No weighted tiers are available to roll."); |
| | | 41 | | } |
| | | 42 | | |
| | 60073 | 43 | | var totalWeight = weightedAvailable.Sum(entry => entry.Weight); |
| | 10015 | 44 | | var roll = rng.Next(0, totalWeight); |
| | 10015 | 45 | | var cumulative = 0; |
| | | 46 | | |
| | 43061 | 47 | | foreach (var entry in weightedAvailable) |
| | | 48 | | { |
| | 16523 | 49 | | cumulative += entry.Weight; |
| | 16523 | 50 | | if (roll < cumulative) |
| | | 51 | | { |
| | 10015 | 52 | | return entry.Tier; |
| | | 53 | | } |
| | | 54 | | } |
| | | 55 | | |
| | 0 | 56 | | return weightedAvailable[^1].Tier; |
| | | 57 | | } |
| | | 58 | | } |