Files
MVP1/Assets/Scripts/App/DebugPanel.cs
T

157 lines
7.0 KiB
C#

#if UNITY_EDITOR || DEVELOPMENT_BUILD
using TMPro;
using UnityEngine;
using UnityEngine.UI;
// ОТЛАДОЧНАЯ ПАНЕЛЬ для проверки баланса: кнопка "DEV" слева на экране.
//
// Есть только в редакторе и в Development Build -- в релизную сборку этот файл не попадает совсем.
// "+1 час" не имеет своей логики: он двигает GameClock, и модули досчитывают время по своим обычным правилам,
// ровно как при возвращении игрока в игру. Поэтому проверяешь настоящие правила, а не кнопку.
//
// Перемотка действует на то, что берёт время из GameClock (сейчас -- Население). Походы и обучение
// войск пока идут по реальным часам.
public class DebugPanel : MonoBehaviour
{
static DebugPanel instance;
GameObject panel;
TextMeshProUGUI info;
float nextRefresh;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static void Create()
{
if (instance != null) return;
var go = new GameObject("DebugPanel", typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
DontDestroyOnLoad(go);
var canvas = go.GetComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 1500; // поверх HUD и окон
var scaler = go.GetComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920, 1080);
scaler.matchWidthOrHeight = 0.5f;
instance = go.AddComponent<DebugPanel>();
instance.Build();
}
void Build()
{
// Кнопка-переключатель слева посередине: там нет кнопок HUD
var toggle = UIKit.Button(transform, "DEV", new Color(0.55f, 0.15f, 0.55f, 0.85f), Toggle, 110, 64, 26);
var trt = (RectTransform)toggle.transform;
trt.anchorMin = trt.anchorMax = new Vector2(0, 0.5f);
trt.pivot = new Vector2(0, 0.5f);
trt.anchoredPosition = new Vector2(12, 0);
trt.sizeDelta = new Vector2(110, 64);
var card = UIKit.Card(transform, new Color(0.08f, 0.08f, 0.11f, 0.95f), 20, 10);
card.anchorMin = card.anchorMax = new Vector2(0, 0.5f);
card.pivot = new Vector2(0, 0.5f);
card.anchoredPosition = new Vector2(135, 0);
card.sizeDelta = new Vector2(620, 0);
card.gameObject.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
panel = card.gameObject;
var title = UIKit.Text(card, "ОТЛАДКА БАЛАНСА", 30, UIKit.Theme.Gold, TextAlignmentOptions.Center);
title.fontStyle = FontStyles.Bold;
info = UIKit.Text(card, "", 24, UIKit.Theme.Text);
var row1 = UIKit.Row(card, 70, 10);
Btn(row1, "+1 час", UIKit.Theme.Blue, () => GameClock.Advance(3600));
Btn(row1, "+10 часов", UIKit.Theme.Blue, () => GameClock.Advance(36000));
var row2 = UIKit.Row(card, 70, 10);
Btn(row2, "+100 всех ресурсов", UIKit.Theme.Green, AddAllResources);
Btn(row2, "+1000 еды", UIKit.Theme.Green, () => AddResource(ResourceType.Food, 1000));
var row3 = UIKit.Row(card, 70, 10);
Btn(row3, "Еда = 0", UIKit.Theme.Red, ZeroFood);
Btn(row3, "Сбросить перемотку", UIKit.Theme.Gray, () => { GameClock.ResetOffset(); Refresh(); });
var row4 = UIKit.Row(card, 70, 10);
Btn(row4, "Рабочие", UIKit.Theme.Blue, () => BuildingWindow.Open(null));
panel.SetActive(false);
}
static void Btn(Transform row, string label, Color color, System.Action onClick)
{
var b = UIKit.Button(row, label, color, onClick, -1, 70, 24);
UIKit.Size(b, -1, 70, 1);
}
void Toggle()
{
panel.SetActive(!panel.activeSelf);
if (panel.activeSelf) Refresh();
}
void Update()
{
if (panel == null || !panel.activeSelf || Time.unscaledTime < nextRefresh) return;
nextRefresh = Time.unscaledTime + 0.5f;
Refresh();
}
void Refresh()
{
if (info == null) return;
var sb = new System.Text.StringBuilder();
if (GameServices.TryGet(out IPopulation p))
{
sb.Append($"Население: <b>{p.Total}</b> / {p.HousingCap}\n");
sb.Append($" жители {p.Civilians}: на работе {p.Workers}, свободно {p.FreeWorkers} из {p.Workforce}; воины {p.Soldiers}\n");
sb.Append($"Еда в час: <color=#ff8a80>-{p.FoodPerHour:0.#}</color> прирост в час: +{p.GrowthPerHour:0.#}\n");
if (p.IsStarving) sb.Append("<color=#ff5252><b>ГОЛОД: еды не хватает, прирост остановлен</b></color>\n");
}
else sb.Append("Модуль Населения не зарегистрирован\n");
if (GameServices.TryGet(out IProduction prod))
sb.Append($"Добыча в час: еда +{prod.RatePerHour(ResourceType.Food):0.#}, дерево +{prod.RatePerHour(ResourceType.Wood):0.#}, " +
$"камень +{prod.RatePerHour(ResourceType.Stone):0.#}, металл +{prod.RatePerHour(ResourceType.Iron):0.#}, золото +{prod.RatePerHour(ResourceType.Gold):0.#}\n");
if (GameServices.TryGet(out IEconomy e))
sb.Append($"Склад: еда {e.Get(ResourceType.Food):0}/{Cap(e, ResourceType.Food)} дерево {e.Get(ResourceType.Wood):0}/{Cap(e, ResourceType.Wood)} " +
$"камень {e.Get(ResourceType.Stone):0}/{Cap(e, ResourceType.Stone)}\n");
else sb.Append("Экономика не найдена (нет ResourceManager на сцене)\n");
long off = GameClock.OffsetSeconds;
sb.Append(off > 0 ? $"Перемотано: +{off / 3600f:0.#} ч" : "Время: реальное");
info.text = sb.ToString();
}
static string Cap(IEconomy e, ResourceType t)
{
float c = e.GetCapacity(t);
return float.IsInfinity(c) ? "∞" : c.ToString("0");
}
void AddAllResources()
{
ResourceType[] types = { ResourceType.Wood, ResourceType.Food, ResourceType.Stone, ResourceType.Iron, ResourceType.Gold, ResourceType.Gems };
foreach (var t in types) AddResource(t, 100);
}
void AddResource(ResourceType type, float amount)
{
if (GameServices.TryGet(out IEconomy e)) e.Add(type, amount);
Refresh();
}
void ZeroFood()
{
if (GameServices.TryGet(out IEconomy e)) e.Add(ResourceType.Food, -e.Get(ResourceType.Food));
Refresh();
}
void OnDestroy()
{
if (instance == this) instance = null;
}
}
#endif