88 lines
3.9 KiB
C#
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();
|
|
}
|
|
}
|