Files
MVP1/Assets/Scripts/Modules/Economy/Rules/CrystalStorage.cs
T

64 lines
3.9 KiB
C#
Raw Normal View History

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<Tier> tiers;
public CrystalStorage(int baseCapacity, IEnumerable<Tier> tiers)
{
BaseCapacity = Math.Max(0, baseCapacity);
this.tiers = new List<Tier>();
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<IReadOnlyList<ResourceAmount>, bool> trySpend)
{
if (WhyNot(townHallLevel) != null || trySpend == null) return false;
if (!trySpend(Next.Cost ?? new ResourceAmount[0])) return false;
Level++;
return true;
}
}