Files
MVP1/Assets/Scripts/WorldMap/MarchManager.cs
T

164 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using Bogatyri.World;
using UnityEngine;
// Хранит мир и походы игрока. Живёт между сценами (создаётся сам при запуске игры),
// поэтому войско идёт и возвращается, даже пока игрок в городе.
//
// Точка расширения под мультиплеер: сейчас WorldSimulation крутится прямо здесь.
// Позже StartMarch будет отправлять запрос на сервер, а походы и их итоги -- приходить с сервера.
// WorldMapController при этом менять не придётся: он работает через события этого класса.
public class MarchManager : MonoBehaviour
{
public const string LocalPlayerId = "local_player";
public static MarchManager Instance { get; private set; }
public WorldSimulation World { get; private set; }
public event Action<MarchData> OnMarchStarted;
public event Action<MarchData> OnBattleResolved;
public event Action<MarchData> OnMarchReturned;
// Время мира. В мультиплеере -- время сервера, а не телефона
public static long NowMs => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
private readonly List<WorldEvent> events = new List<WorldEvent>();
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void CreateInstance()
{
var go = new GameObject("MarchManager");
DontDestroyOnLoad(go);
go.AddComponent<MarchManager>();
}
void Awake()
{
Instance = this;
World = new WorldSimulation(WorldMapLayout.CreateDefault());
// [объединение] походы хранятся в нашем progress.json (GameProgress), а не в SaveManager
var saved = GameProgress.Instance.Data.sashaMarches;
if (saved != null && saved.Count > 0) World.LoadMarches(saved);
}
void SaveToProgress()
{
GameProgress.Instance.Data.sashaMarches = GetMarchesForSave();
GameProgress.Instance.MarkChanged();
}
void Update()
{
// Без ResourceManager некуда зачислять вернувшихся солдат -- ждём, пока загрузится город
if (ResourceManager.Instance == null) return;
events.Clear();
World.Advance(NowMs, events);
foreach (var e in events)
{
if (e.Type == WorldEventType.BattleResolved) HandleBattleResolved(e.March);
else if (e.Type == WorldEventType.MarchReturned) HandleMarchReturned(e.March);
}
if (events.Count > 0) SaveToProgress();
}
public bool TryStartMarch(string targetId, int soldiers, out string error)
{
if (ResourceManager.Instance == null)
{
error = "Нет данных о войске -- запусти игру из города";
return false;
}
// [объединение] солдаты = наши воины в городе (все типы войск)
if (ArmyBridge.SoldiersAtHome < soldiers)
{
error = "Не хватает воинов. Наймите их в Казармах";
return false;
}
MarchData march = World.StartMarch(LocalPlayerId, WorldMapLayout.PlayerCityId, targetId, soldiers, NowMs, out error);
if (march == null) return false;
// Ушедшие воины недоступны дома, пока не вернутся
ArmyBridge.Take(march.id, soldiers);
GameProgress.Instance.Data.marchesSent++;
GameProgress.Instance.Data.dailyMarches++;
SaveToProgress();
Debug.Log($"[ПОХОД] {soldiers} солдат выступили на {World.GetNode(targetId).displayName}");
OnMarchStarted?.Invoke(march);
return true;
}
void HandleBattleResolved(MarchData march)
{
MapNode target = World.GetNode(march.targetNodeId);
Debug.Log($"[ПОХОД] Бой у {target.displayName}: {(march.victory ? "ПОБЕДА" : "поражение")}. " +
$"{march.soldiers} против {target.garrison}, возвращаются {march.survivors}.");
OnBattleResolved?.Invoke(march);
}
// Солдаты и добыча зачисляются, только когда войско дошло до дома
void HandleMarchReturned(MarchData march)
{
ResourceManager rm = ResourceManager.Instance;
ArmyBridge.Return(march.id, march.survivors);
if (march.victory) GameProgress.Instance.Data.worldWins++;
foreach (var reward in march.loot)
{
if (Enum.TryParse(reward.resource, out ResourceType type))
rm.AddResource(type, reward.amount);
else
Debug.LogWarning($"[ПОХОД] Неизвестный ресурс награды: {reward.resource}");
}
Debug.Log($"[ПОХОД] Войско вернулось: {march.survivors} солдат, добыча: {FormatLoot(march.loot)}");
OnMarchReturned?.Invoke(march);
}
// ---------------- СОХРАНЕНИЕ ----------------
public List<MarchData> GetMarchesForSave()
{
return new List<MarchData>(World.Marches);
}
public void LoadMarches(List<MarchData> saved)
{
World.LoadMarches(saved);
}
// ---------------- ТЕКСТ ДЛЯ UI ----------------
public static string FormatLoot(List<RewardEntry> loot)
{
if (loot == null || loot.Count == 0) return "нет";
var parts = new List<string>();
foreach (var r in loot)
{
parts.Add($"+{r.amount} {GetResourceName(r.resource)}");
}
return string.Join(", ", parts);
}
static string GetResourceName(string resource)
{
switch (resource)
{
case "Food": return "еды";
case "Wood": return "дерева";
case "Stone": return "камня";
case "Iron": return "металла";
case "Gold": return "золота";
case "Gems": return "кристаллов";
default: return resource;
}
}
}