using System; using System.Collections.Generic; // ХРАНИЛИЩЕ СИНИХ КРИСТАЛЛОВ: вместимость и платное расширение // (Регламент валют, кристаллов и торговли от 05.11.2026, разд. 8; «Ответ Володе» от 06.11.2026, п. 1). // Документ: Docs/Modules/Economy.md, раздел «Синие кристаллы». // // - Старт -- BaseCapacity (ТЕСТ 50). Ступени (ТЕСТ): Ратуша 3 -- 75, 5 -- 100, 7 -- 150, 9 -- 200. // - Ступень НЕ открывается сама с уровнем Ратуши: Ратуша только разрешает её, игрок покупает за золото и // обычные ресурсы. Ступени -- по порядку, одна покупка -- одна ступень. // - Цена списывается один раз: ступень растёт, только если списание прошло (всё или ничего). Повторное // нажатие без следующей ступени или без нужной Ратуши ничего не списывает. // - Сохраняется номер купленной ступени (Level), вместимость по нему считается заново -- числа можно менять. // Без Unity: те же правила будут на сервере и в тестах. Числа и цены даёт слой приложения (EconomyConfig). public sealed class CrystalStorage { public sealed class Tier { public int TownHallLevel; // с какого уровня Ратуши можно купить public int Capacity; // вместимость после покупки public ResourceAmount[] Cost; // цена: золото и обычные ресурсы } public readonly int BaseCapacity; readonly List tiers; public CrystalStorage(int baseCapacity, IEnumerable tiers) { BaseCapacity = Math.Max(0, baseCapacity); this.tiers = new List(); if (tiers != null) foreach (var t in tiers) if (t != null) this.tiers.Add(t); } // Сколько ступеней куплено (0 -- только стартовая вместимость) public int Level { get; private set; } public int TierCount => tiers.Count; public int Capacity => Level <= 0 ? BaseCapacity : Math.Max(BaseCapacity, tiers[Level - 1].Capacity); // Следующая ступень; null -- все куплены public Tier Next => Level < tiers.Count ? tiers[Level] : null; // Восстановить из сохранения (номер ступени; лишнее обрезается, если ступеней стало меньше) public void SetLevel(int level) => Level = Math.Max(0, Math.Min(level, tiers.Count)); // Почему сейчас нельзя расширить: null -- можно (если хватит ресурсов -- это проверяет списание) public string WhyNot(int townHallLevel) { var next = Next; if (next == null) return "Хранилище расширено до предела"; if (townHallLevel < next.TownHallLevel) return $"Расширение до {next.Capacity} откроется на Ратуше {next.TownHallLevel} ур."; return null; } // Купить следующую ступень. trySpend -- списание цены «всё или ничего» (Экономика). true -- ступень куплена public bool TryExpand(int townHallLevel, Func, bool> trySpend) { if (WhyNot(townHallLevel) != null || trySpend == null) return false; if (!trySpend(Next.Cost ?? new ResourceAmount[0])) return false; Level++; return true; } }