Экономика, этапы 1 и 3: склады и лимиты, добыча через рабочих
This commit is contained in:
@@ -1,71 +1,92 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
|
||||
// Ресурс на верхней панели (этап 1): "запас / лимит" и прирост в час.
|
||||
// - Дерево, камень, металл, золото, еда, кристаллы: "820 / 1000" и строкой ниже "+50/ч" (у еды -- добыча минус расход);
|
||||
// - Люди: "300 / 350" (население / предел жилья) и прирост людей в час.
|
||||
// Числа без сокращений 1.2K / 1.5M: по документу нормальный масштаб -- сотни и тысячи.
|
||||
[RequireComponent(typeof(TMP_Text))]
|
||||
public class ResourceUIText : MonoBehaviour
|
||||
{
|
||||
public ResourceType resourceType;
|
||||
|
||||
[Tooltip("Сокращать большие числа (1200 -> 1.2K, 1500000 -> 1.5M), как на референсе HUD")]
|
||||
public bool useShortFormat = true;
|
||||
[Tooltip("Показывать лимит склада: \"820 / 1000\"")]
|
||||
public bool showCapacity = true;
|
||||
|
||||
[Tooltip("Показывать прирост в час второй строкой: \"+50/ч\"")]
|
||||
public bool showRate = true;
|
||||
|
||||
[Tooltip("Устарело (этап 1): сокращения 1.2K / 1.5M убраны")]
|
||||
[HideInInspector] public bool useShortFormat;
|
||||
|
||||
private TMP_Text label;
|
||||
private float next;
|
||||
private string lastText;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
label = GetComponent<TMP_Text>();
|
||||
|
||||
// В сцене на ячейках дерева, камня, металла, золота и кристалла по ошибке висит второй такой же компонент
|
||||
// с типом "Люди" -- он перебивал число ресурса. Если рядом есть компонент с настоящим ресурсом -- выключаемся.
|
||||
if (resourceType == ResourceType.Population)
|
||||
{
|
||||
foreach (var other in GetComponents<ResourceUIText>())
|
||||
{
|
||||
if (other != this && other.resourceType != ResourceType.Population)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
// Ждём, пока ResourceManager точно проинициализируется (Awake порядок не гарантирован)
|
||||
if (ResourceManager.Instance != null)
|
||||
next = 0f;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Time.unscaledTime < next) return;
|
||||
next = Time.unscaledTime + 0.5f;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Refresh()
|
||||
{
|
||||
string text = BuildText();
|
||||
if (text == lastText) return;
|
||||
lastText = text;
|
||||
label.text = text;
|
||||
}
|
||||
|
||||
string BuildText()
|
||||
{
|
||||
// Люди -- из модуля Населения
|
||||
if (resourceType == ResourceType.Population && GameServices.TryGet(out IPopulation pop))
|
||||
{
|
||||
Subscribe();
|
||||
}
|
||||
else
|
||||
{
|
||||
Invoke(nameof(TrySubscribeDelayed), 0.1f);
|
||||
string value = showCapacity ? $"{pop.Total} / {pop.HousingCap}" : pop.Total.ToString();
|
||||
return showRate ? value + RateLine(pop.GrowthPerHour) : value;
|
||||
}
|
||||
|
||||
if (!GameServices.TryGet(out IEconomy economy)) return "0";
|
||||
int amount = Mathf.FloorToInt(economy.Get(resourceType));
|
||||
float cap = economy.GetCapacity(resourceType);
|
||||
string main = showCapacity && !float.IsInfinity(cap) ? $"{amount} / {Mathf.RoundToInt(cap)}" : amount.ToString();
|
||||
if (!showRate || resourceType == ResourceType.Power) return main;
|
||||
|
||||
float rate = GameServices.TryGet(out IProduction production) ? production.RatePerHour(resourceType) : 0f;
|
||||
if (resourceType == ResourceType.Food && GameServices.TryGet(out IPopulation p)) rate -= p.FoodPerHour;
|
||||
if (resourceType == ResourceType.Gems) return main; // кристалл не добывается рабочими (разломы на карте мира)
|
||||
return main + RateLine(rate);
|
||||
}
|
||||
|
||||
void TrySubscribeDelayed()
|
||||
static string RateLine(float rate)
|
||||
{
|
||||
if (ResourceManager.Instance != null)
|
||||
Subscribe();
|
||||
}
|
||||
|
||||
void Subscribe()
|
||||
{
|
||||
ResourceManager.Instance.OnResourceChanged += HandleResourceChanged;
|
||||
// сразу показать текущее значение при старте, не дожидаясь первого изменения
|
||||
UpdateText(ResourceManager.Instance.GetResource(resourceType));
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if (ResourceManager.Instance != null)
|
||||
ResourceManager.Instance.OnResourceChanged -= HandleResourceChanged;
|
||||
}
|
||||
|
||||
void HandleResourceChanged(ResourceType type, float newValue)
|
||||
{
|
||||
if (type != resourceType) return; // реагируем только на "свой" ресурс
|
||||
UpdateText(newValue);
|
||||
}
|
||||
|
||||
void UpdateText(float value)
|
||||
{
|
||||
label.text = useShortFormat ? FormatShort(value) : Mathf.FloorToInt(value).ToString();
|
||||
}
|
||||
|
||||
string FormatShort(float value)
|
||||
{
|
||||
if (value >= 1_000_000f)
|
||||
return (value / 1_000_000f).ToString("0.#") + "M";
|
||||
if (value >= 1_000f)
|
||||
return (value / 1_000f).ToString("0.#") + "K";
|
||||
return Mathf.FloorToInt(value).ToString();
|
||||
string color = rate < 0 ? "#ff8a80" : "#9be29b";
|
||||
string sign = rate > 0 ? "+" : "";
|
||||
return $"\n<size=60%><color={color}>{sign}{rate:0.#}/ч</color></size>";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user