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

88 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
// МОСТ между картой мира Саши (армия = просто число "солдат") и нашей армией (4 типа войск в GameProgress).
// - "Солдаты дома" = все наши воины в городе.
// - При отправке похода берём воинов из всех типов пропорционально и запоминаем состав похода.
// - При возвращении выживших раздаём обратно по тем же типам в той же пропорции.
// Благодаря этому одна армия на всю игру: наняли в казармах -> можно отправить и с нашей карты (МИР),
// и с большой карты мира (сцена WorldMap).
public static class ArmyBridge
{
[Serializable]
public class MarchUnits
{
public int marchId;
public int[] units = new int[4];
}
static ProgressData D { get { return GameProgress.Instance.Data; } }
public static int SoldiersAtHome { get { return GameProgress.Instance.TotalTroops; } }
// Забрать count воинов из города в поход marchId
public static bool Take(int marchId, int count)
{
var troops = D.troops;
int total = 0;
foreach (var t in troops) total += t;
if (count <= 0 || count > total) return false;
// пропорционально, остаток раздаём по самым многочисленным типам
var taken = new int[troops.Length];
int given = 0;
var remainders = new List<KeyValuePair<int, float>>();
for (int i = 0; i < troops.Length; i++)
{
float exact = (float)count * troops[i] / total;
taken[i] = Mathf.Min(troops[i], Mathf.FloorToInt(exact));
given += taken[i];
remainders.Add(new KeyValuePair<int, float>(i, exact - taken[i]));
}
remainders.Sort((a, b) => b.Value.CompareTo(a.Value));
for (int k = 0; given < count && k < remainders.Count * 2; k++)
{
int i = remainders[k % remainders.Count].Key;
if (taken[i] < troops[i]) { taken[i]++; given++; }
}
for (int i = 0; i < troops.Length; i++) troops[i] -= taken[i];
var entry = new MarchUnits { marchId = marchId };
for (int i = 0; i < 4 && i < taken.Length; i++) entry.units[i] = taken[i];
D.sashaMarchUnits.RemoveAll(e => e.marchId == marchId);
D.sashaMarchUnits.Add(entry);
GameProgress.Instance.MarkChanged();
return true;
}
// Вернуть survivors выживших из похода marchId по типам войск
public static void Return(int marchId, int survivors)
{
var entry = D.sashaMarchUnits.Find(e => e.marchId == marchId);
var troops = D.troops;
if (entry == null)
{
troops[0] += Mathf.Max(0, survivors); // состав неизвестен (старое сохранение) -- считаем пехотой
}
else
{
int sent = 0;
foreach (var u in entry.units) sent += u;
int back = 0;
for (int i = 0; i < entry.units.Length && i < troops.Length; i++)
{
int n = sent > 0 ? Mathf.FloorToInt((float)survivors * entry.units[i] / sent) : 0;
troops[i] += n;
back += n;
}
// остаток округления -- в самый многочисленный тип похода
int best = 0;
for (int i = 1; i < entry.units.Length; i++) if (entry.units[i] > entry.units[best]) best = i;
troops[best] += Mathf.Max(0, survivors - back);
D.sashaMarchUnits.Remove(entry);
}
GameProgress.Instance.MarkChanged();
}
}