Модуль Боя (Bogatyri.Battle, без Unity и float): - сила стороны по типам войск, сила воина — из GameData.Troops (4/5/9/16) - контры +25%: пехота > кавалерия > лучники > пехота (по составу врага) - стены +20% защитникам; осадные +50% против стен, −25% в поле - потери по типам: проигравший — половина, победитель — до половины (чем ровнее бой, тем больше) - BattleRequest/BattleOutcome расширены (состав, стены, бонусы, сила сторон); бой «числом» считается пехотой - формула — предложение, числа константами в BattleSystem.cs, ждёт утверждения командой Мир и Армия: - состав гарнизона у каждой цели (WorldMapLayout.GarrisonUnits, из id — карта не изменилась) - поход хранит состав по типам; выжившие возвращаются точно по типам (IArmy.GetMarchUnits/ReturnUnits) - время походов по GameClock: перемотка в DEV-панели проматывает и походы Интерфейс карты: - окно атаки: состав гарнизона и ожидаемый исход (сила сторон, победа/поражение, потери) - верхняя панель: воины в походах (а не число отрядов) Тесты: контры, стены, осадные, потери в пределах состава, состав гарнизонов. Документы Battle, World, Army, Core, README обновлены. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
6.9 KiB
Markdown
78 lines
6.9 KiB
Markdown
# Армия
|
|
|
|
Войска и их характеристики: сколько воинов каждого типа в городе, сколько в походах, обучение, потери, уход в поход и возвращение. **Единственное место, где хранятся войска.**
|
|
|
|
- **Сборка:** `Bogatyri.Army` (без Unity).
|
|
- **Папка:** `Assets/Scripts/Modules/Army`.
|
|
- **Зависит от:** ядра.
|
|
|
|
## Контракт `IArmy`
|
|
|
|
| Член | Что делает |
|
|
| --- | --- |
|
|
| `TypeCount` | Типов войск — 4 (пехота, лучники, кавалерия, осадные; порядок как в `GameData.Troops`). |
|
|
| `GetTroops(type)` | Воинов этого типа в городе. |
|
|
| `SoldiersAtHome` | Всего воинов в городе. |
|
|
| `TroopsInMarches` | Воинов в походах. |
|
|
| `AddTroops(type, count)` | Добавить воинов (обучение в Казармах). |
|
|
| `LoseFraction(fraction)` | Потери в бою: от каждого типа погибает доля (с округлением вниз); возвращает, сколько погибло. |
|
|
| `TakeForMarch(marchId, count)` | Забрать воинов в поход пропорционально составу армии и запомнить состав. |
|
|
| `ReturnFromMarch(marchId, survivors)` | Вернуть выживших по тем же типам (пропорционально). |
|
|
| `GetMarchUnits(marchId)` | Состав похода по типам — для боя с типами войск. |
|
|
| `ReturnUnits(marchId, survivorUnits)` | Вернуть выживших точно по типам, как посчитал бой. Больше, чем ушло, не вернётся. |
|
|
|
|
Получить: `GameServices.Get<IArmy>()`. Регистрирует `App/GameModules`. `GameProgress` (обучение, кампания, арена, сила армии) и панели работают с войсками только через этот контракт.
|
|
|
|
## Правило «один солдат в одном месте»
|
|
|
|
Воин либо в городе, либо в походе. Поход забирает воинов из города и запоминает состав, возвращение раздаёт выживших по тем же типам. Тест `ArmyService_MarchNeverCreatesOrLosesSoldiers` проверяет, что «дома + в походах» всегда равно общему числу.
|
|
|
|
## События
|
|
|
|
- **Публикует:** `TroopsChangedEvent` (воинов в городе и в походах) — при обучении, потерях, походе, возвращении, загрузке, сбросе. По нему `App/GameModules` перерисовывает панели HUD.
|
|
- **Слушает:** ничего.
|
|
|
|
## Сохранение
|
|
|
|
Секция `"army"`. Модуль без Unity, поэтому формат — простые строки:
|
|
|
|
```
|
|
troops=<пехота>,<лучники>,<кавалерия>,<осадные>
|
|
march=<id похода>:<пехота>,<лучники>,<кавалерия>,<осадные>
|
|
```
|
|
|
|
Сброс (`ResetState`): войск и походов нет.
|
|
|
|
**Перенос из старых сохранений:**
|
|
- Раньше войска лежали в `progress.json`: `troops` хранил `GameProgress`, `sashaMarchUnits` — мост `ArmyBridge`.
|
|
- Если в `save.json` нет секции `"army"`, после загрузки `App/GameModules` переносит их в модуль (`ImportLegacy`).
|
|
- Из `progress.json` они удаляются только после записи `save.json`. Флаг `armyInModule` отмечает, что перенос сделан.
|
|
|
|
## Файлы
|
|
|
|
| Файл | Что это |
|
|
| --- | --- |
|
|
| `ArmyService.cs` | Хранилище войск, реализует `IArmy` и `ISaveParticipant`. |
|
|
| `ArmyMath.cs` | `TakeProportional` — кого взять в поход; `SplitSurvivors` — как вернуть выживших. |
|
|
|
|
## Решения и план
|
|
|
|
- **Этап 5 (план разработки):** солдат стоит 1 человека, 15 еды, 5 металла, 5 золота; содержание 0,2 еды в час; погибшие уменьшают население. Делается вместе с модулем «Население».
|
|
- **Решение команды от 19.10.2026:**
|
|
- войска набираются из населения с сохранением гражданского минимума;
|
|
- гарнизон поселения: часть солдат назначается защищать город;
|
|
- общая армия = гарнизон + доступные отряды + войска в походах, на точках и в гарнизоне Круга, **один солдат не может быть в двух местах**;
|
|
- гарнизон ест еду и участвует в защите;
|
|
- при голоде дебаффы действуют и на гарнизон, и на походы.
|
|
- **Следующий шаг модуля:** гарнизон — третье место для солдата рядом с «дома» и «в походе».
|
|
- Описания типов войск (`GameData.Troops`: цена, сила, время обучения) пока в слое приложения; цены перейдут в `EconomyConfig`.
|
|
|
|
## Журнал изменений
|
|
|
|
| Дата | Кто | Что |
|
|
| --- | --- | --- |
|
|
| 27.10.2026 | Claude | `GetMarchUnits` и `ReturnUnits`: бой с типами войск получает состав похода, выжившие возвращаются точно по типам. |
|
|
| 23.10.2026 | Claude | Войска переехали в модуль: `ArmyService` — единственное хранилище войск (секция `"army"`), `IArmy` расширен (типы, обучение, потери, войска в походах), событие `TroopsChangedEvent`. Перенос из `progress.json` с удалением старых данных только после записи `save.json`. `ArmyBridge` удалён — контракты и перенос сохранений проверены тестами. |
|
|
| 19.10.2026 | Claude | `ArmyBridge.TroopsInMarches` для панели «Войска». После удаления маленькой карты войска в походах учитываются только здесь (`sashaMarchUnits`). |
|
|
| 19.10.2026 | Claude | Модуль создан: `ArmyMath` (правила деления войск, без Unity, тесты на отсутствие двойного учёта). `ArmyBridge` сохранён и теперь реализует `IArmy` через `ArmyMath`; формат `sashaMarchUnits` не изменён. |
|