| | | 1 | | using System.Text.Json.Serialization; |
| | | 2 | | |
| | | 3 | | namespace RaidLoop.Core; |
| | | 4 | | |
| | | 5 | | public enum ItemType |
| | | 6 | | { |
| | | 7 | | Weapon, |
| | | 8 | | Armor, |
| | | 9 | | Backpack, |
| | | 10 | | Consumable, |
| | | 11 | | Sellable, |
| | | 12 | | Material |
| | | 13 | | } |
| | | 14 | | |
| | | 15 | | public enum OpeningContactState |
| | | 16 | | { |
| | | 17 | | MutualContact, |
| | | 18 | | PlayerAmbush, |
| | | 19 | | EnemyAmbush |
| | | 20 | | } |
| | | 21 | | |
| | | 22 | | public enum OpeningSide |
| | | 23 | | { |
| | | 24 | | None, |
| | | 25 | | Player, |
| | | 26 | | Enemy |
| | | 27 | | } |
| | | 28 | | |
| | | 29 | | public sealed record OpeningPhaseContext( |
| | | 30 | | OpeningContactState ContactState, |
| | | 31 | | int PlayerInitiative, |
| | | 32 | | int EnemyInitiative, |
| | | 33 | | int TimeOfDayVisibilityModifier = 0, |
| | | 34 | | int EnvironmentAwarenessModifier = 0, |
| | | 35 | | int PlayerGearAwarenessModifier = 0, |
| | | 36 | | int EnemyLocalizationModifier = 0); |
| | | 37 | | |
| | | 38 | | [JsonConverter(typeof(ItemJsonConverter))] |
| | | 39 | | public sealed record Item( |
| | | 40 | | string Name, |
| | | 41 | | ItemType Type, |
| | | 42 | | int Weight, |
| | | 43 | | int Value = 1, |
| | | 44 | | int Slots = 1, |
| | | 45 | | Rarity Rarity = Rarity.Common, |
| | | 46 | | DisplayRarity DisplayRarity = DisplayRarity.Common) |
| | | 47 | | { |
| | | 48 | | [JsonPropertyName("itemDefId")] |
| | | 49 | | public int ItemDefId { get; init; } |
| | | 50 | | } |
| | | 51 | | |
| | | 52 | | public sealed class GameState |
| | | 53 | | { |
| | | 54 | | public List<Item> Stash { get; } = []; |
| | | 55 | | |
| | | 56 | | public GameState(IEnumerable<Item> initialStash) |
| | | 57 | | { |
| | | 58 | | Stash.AddRange(initialStash); |
| | | 59 | | } |
| | | 60 | | } |
| | | 61 | | |
| | | 62 | | public sealed class RaidState |
| | | 63 | | { |
| | | 64 | | public int Health { get; set; } |
| | | 65 | | public int BackpackCapacity { get; set; } |
| | | 66 | | public int MaxEncumbrance |
| | | 67 | | { |
| | | 68 | | get => Inventory.MaxEncumbrance; |
| | | 69 | | set => Inventory.MaxEncumbrance = value; |
| | | 70 | | } |
| | | 71 | | public List<Item> BroughtItems { get; } = []; |
| | | 72 | | public RaidInventory Inventory { get; } |
| | | 73 | | public List<Item> RaidLoot => Inventory.CarriedItems; |
| | | 74 | | public bool IsDead => Health <= 0; |
| | | 75 | | |
| | | 76 | | public RaidState(int health, int backpackCapacity, List<Item> broughtItems, List<Item> raidLoot) |
| | | 77 | | { |
| | | 78 | | Health = health; |
| | | 79 | | BackpackCapacity = backpackCapacity; |
| | | 80 | | BroughtItems = broughtItems; |
| | | 81 | | Inventory = RaidInventory.FromItems(broughtItems, raidLoot, backpackCapacity); |
| | | 82 | | } |
| | | 83 | | |
| | | 84 | | public RaidState(int health, RaidInventory inventory) |
| | | 85 | | { |
| | | 86 | | Health = health; |
| | | 87 | | Inventory = inventory; |
| | | 88 | | BackpackCapacity = inventory.BackpackCapacity; |
| | | 89 | | BroughtItems = inventory.GetExtractableItems().ToList(); |
| | | 90 | | } |
| | | 91 | | } |
| | | 92 | | |
| | | 93 | | public sealed class RaidInventory |
| | | 94 | | { |
| | 207 | 95 | | public Item? EquippedWeapon { get; set; } |
| | 133 | 96 | | public Item? EquippedArmor { get; set; } |
| | 179 | 97 | | public Item? EquippedBackpack { get; set; } |
| | 193 | 98 | | public List<Item> CarriedItems { get; } = []; |
| | 138 | 99 | | public List<Item> DiscoveredLoot { get; } = []; |
| | 133 | 100 | | public int MedkitCount { get; set; } |
| | 133 | 101 | | public int BackpackCapacity { get; set; } |
| | 88 | 102 | | public int MaxEncumbrance { get; set; } = CombatBalance.GetMaxEncumbranceFromStrength(PlayerStatRules.MinimumScore); |
| | | 103 | | |
| | | 104 | | public IEnumerable<Item> GetExtractableItems() |
| | | 105 | | { |
| | 50 | 106 | | if (EquippedWeapon is not null) |
| | | 107 | | { |
| | 36 | 108 | | yield return EquippedWeapon; |
| | | 109 | | } |
| | | 110 | | |
| | 50 | 111 | | if (EquippedArmor is not null) |
| | | 112 | | { |
| | 4 | 113 | | yield return EquippedArmor; |
| | | 114 | | } |
| | | 115 | | |
| | 50 | 116 | | if (EquippedBackpack is not null) |
| | | 117 | | { |
| | 29 | 118 | | yield return EquippedBackpack; |
| | | 119 | | } |
| | | 120 | | |
| | 124 | 121 | | foreach (var item in CarriedItems) |
| | | 122 | | { |
| | 12 | 123 | | yield return item; |
| | | 124 | | } |
| | | 125 | | |
| | 116 | 126 | | for (var i = 0; i < MedkitCount; i++) |
| | | 127 | | { |
| | 8 | 128 | | yield return ItemCatalog.Create("Medkit"); |
| | | 129 | | } |
| | 50 | 130 | | } |
| | | 131 | | |
| | | 132 | | public static RaidInventory FromItems(List<Item> broughtItems, List<Item> carriedItems, int backpackCapacity) |
| | | 133 | | { |
| | 46 | 134 | | var inventory = new RaidInventory |
| | 46 | 135 | | { |
| | 37 | 136 | | EquippedWeapon = broughtItems.FirstOrDefault(x => x.Type == ItemType.Weapon), |
| | 67 | 137 | | EquippedArmor = broughtItems.FirstOrDefault(x => x.Type == ItemType.Armor), |
| | 69 | 138 | | EquippedBackpack = broughtItems.FirstOrDefault(x => x.Type == ItemType.Backpack), |
| | 46 | 139 | | BackpackCapacity = backpackCapacity |
| | 46 | 140 | | }; |
| | | 141 | | |
| | 161 | 142 | | foreach (var item in broughtItems.Where(x => x.Type is not (ItemType.Weapon or ItemType.Armor or ItemType.Backpa |
| | | 143 | | { |
| | 0 | 144 | | if (CombatBalance.IsMedkit(item)) |
| | | 145 | | { |
| | 0 | 146 | | inventory.MedkitCount++; |
| | 0 | 147 | | continue; |
| | | 148 | | } |
| | | 149 | | |
| | 0 | 150 | | inventory.CarriedItems.Add(item); |
| | | 151 | | } |
| | | 152 | | |
| | 126 | 153 | | foreach (var item in carriedItems) |
| | | 154 | | { |
| | 17 | 155 | | if (CombatBalance.IsMedkit(item)) |
| | | 156 | | { |
| | 0 | 157 | | inventory.MedkitCount++; |
| | 0 | 158 | | continue; |
| | | 159 | | } |
| | | 160 | | |
| | 17 | 161 | | inventory.CarriedItems.Add(item); |
| | | 162 | | } |
| | | 163 | | |
| | 46 | 164 | | return inventory; |
| | | 165 | | } |
| | | 166 | | } |
| | | 167 | | |
| | | 168 | | public sealed record OpeningPhaseResult( |
| | | 169 | | OpeningContactState ContactState, |
| | | 170 | | OpeningSide SurpriseSide, |
| | | 171 | | OpeningSide InitiativeWinner, |
| | | 172 | | int OpeningActionsRemaining, |
| | | 173 | | bool SurprisePersistenceEligible); |