Files
MVP1/Docs/Modules/World.md
T
AlexanderandClaude Opus 5.5 b1a396e9a2 Лагеря разбойников (PvE) на карте мира
Модуль Мира (Bogatyri.World.Simulation, без Unity):
- 12 лагерей трёх уровней: Стан разбойников, Логово лиходеев, Становище Соловья-разбойника
  (гарнизон 6–9 / 14–17 / 26–29, добыча — еда, дерево, золото, металл)
- ставятся отдельным генератором после городов: замок, твой город и соседи остались на местах
- бой в поле (без стен), у разбойников нет осадных
- после победы лагерь разбит на 30 минут (CampRules.RespawnMs), напасть нельзя
- бои считаются по времени прихода: второе войско к разбитому лагерю — без боя, все домой, добычи нет
- секция сохранения world хранит разбитые лагеря (camps); сброс — все лагеря на месте
- MarchReturnedEvent.TargetEmpty, окно в городе пишет «лагерь уже был разбит»

Интерфейс карты:
- лагерь — фиолетовый круг с подписью «название, ур. N, гарнизон»; разбитый — серый с таймером
- окно атаки: уровень лагеря, «бой в поле» / «за стенами», прогноз с учётом стен
- окно «ЛАГЕРЬ ПУСТ», подсказка при нажатии на разбитый лагерь

Тесты: расстановка лагерей, бой в поле без осадных, разбит → второе войско находит пустым → сохранение → появляется снова.
Документы World, Battle, Save, Core, README обновлены. Числа требуют балансировки.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 16:46:54 +01:00

97 lines
10 KiB
Markdown
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.
# Глобальный мир
Карта и перемещения: замок с боссом, 20 соседних городов, 12 лагерей разбойников, походы по реальному времени (идут, даже когда игра закрыта).
- **Сборки:**
- `Bogatyri.World.Simulation` — карта и походы, чистый C# без Unity (переедет на сервер);
- `Bogatyri.World` — `MarchManager`, Unity-часть.
- **Папка:** `Assets/Scripts/Modules/World`.
- **Зависит от:** ядра. Войска — через `IArmy`, добыча — через `IEconomy`, бой — через `IBattleSystem`.
## Контракт `IWorld`
| Член | Что делает |
| --- | --- |
| `ActiveMarches` | Сколько походов в пути. |
| `TryStartMarch(targetId, soldiers, out error)` | Отправить войско на цель. |
Получить: `GameServices.Get<IWorld>()`. Интерфейсу карты (`WorldMapController`) можно обращаться к `MarchManager.Instance` и его C#-событиям: там полные данные похода.
## События
**Публикует:**
- `MarchStartedEvent` — войско выступило;
- `MarchBattleResolvedEvent` — бой у цели прошёл;
- `MarchReturnedEvent` — войско вернулось, солдаты и добыча зачислены. Поля: `MarchId`, `Victory`, `Survivors`, `Sent`, `TargetEmpty` (лагерь уже был разбит, боя не было), `TargetName`, `LootText`.
**Слушает:** ничего.
По этим событиям `App/GameModules`:
- считает статистику для заданий (`marchesSent`, `dailyMarches`, `worldWins`);
- показывает окно «ВОЙСКО ВЕРНУЛОСЬ» в городе (`UI/MarchReturnPopup.cs`): куда ходили, победа или поражение, сколько вернулось из скольких, добыча.
- Окно появляется и за походы, закончившиеся, пока игра была закрыта: сразу после входа в город.
- Несколько возвращений — окна по очереди.
- На карте мира окно своё (`WorldMapController`).
## Сохранение
Секция `"world"`: `{ "marches": [ MarchData ], "camps": [ { "id", "respawnMs" } ] }` — походы и разбитые лагеря с моментом их появления. Старые сохранения без `camps` читаются: все лагеря на месте.
Сброс (`ResetState`): все походы отменяются, все лагеря на месте. Войска в походе не возвращаются: их сбрасывает `GameProgress` вместе с армией.
Раньше походы лежали в `progress.json` (`sashaMarches`). При первом запуске `App/GameModules` переносит их в модуль Мира и удаляет из `progress.json` только после записи `save.json`.
## Файлы
| Файл | Что это |
| --- | --- |
| `MarchManager.cs` | Ведёт походы, реализует `IWorld` и `ISaveParticipant`. Создаётся сам при запуске игры. |
| `Simulation/WorldMapLayout.cs` | Карта: замок, город игрока, 20 соседей и 12 лагерей из seed. |
| `Simulation/WorldSimulation.cs` | Походы: старт, бой по прибытии, возвращение. Бой получает через `IBattleSystem`. |
**Бой с типами войск:**
- у похода есть состав по типам (`MarchData.units`, берётся у Армии при выступлении) и выжившие по типам (`survivorUnits`);
- у цели — состав гарнизона `WorldMapLayout.GarrisonUnits(node)`. Он вычисляется из id цели, а не из генератора карты, поэтому карта осталась прежней. У Змея Горыныча 40% пехоты, 30% лучников, 20% кавалерии, 10% осадных; у соседей пропорции свои у каждого;
- замок и города сражаются за стенами;
- выжившие возвращаются в Армию точно по типам (`IArmy.ReturnUnits`). Старые походы без состава — как раньше, по пропорции;
- окно атаки показывает состав гарнизона и ожидаемый исход: силу сторон, «скорее победа / поражение» и примерные потери. Расчёт тот же, что сделает модуль Боя.
**Лагеря разбойников (PvE):**
- 12 лагерей, по 4 каждого уровня. Ставятся отдельным генератором после городов (`seed ^ CampSeedSalt`), поэтому замок, твой город и соседи остались на прежних местах. Лагерь может стоять ближе к городу (2,6 клетки), чем город к городу (3,6).
| Уровень | Название | Гарнизон | Добыча | Нужно пехоты (примерно) |
| --- | --- | --- | --- | --- |
| 1 | Стан разбойников | 6–9 | 15 еды, 15 дерева | 8–12 |
| 2 | Логово лиходеев | 14–17 | 25 еды, 25 дерева, 8 золота | 18–21 |
| 3 | Становище Соловья-разбойника | 26–29 | 40 еды, 40 дерева, 15 золота, 8 металла | 34–37 |
- бой в поле: стен нет (`WorldMapLayout.IsFortified`), у разбойников нет осадных — их доля уходит пехоте;
- после победы лагерь **разбит** на 30 минут (`CampRules.RespawnMs`, отсчёт от момента боя): на карте серый, с таймером, напасть нельзя;
- если к лагерю шли два войска, бьётся первое пришедшее (бои считаются по времени прихода). Второе находит лагерь пустым: боя нет, домой идут все, добычи нет (`MarchData.targetEmpty`, окно «ЛАГЕРЬ ПУСТ»);
- на карте лагерь — фиолетовый круг, подпись «название, ур. N, гарнизон».
**Время** походов — по `GameClock`: кнопки «+1 час» / «+10 часов» в отладочной панели проматывают и походы.
В слое приложения остаются `WorldMap/WorldMapController.cs`, `MarchView.cs`, `MapCameraController.cs`, `SceneNavigator.cs`.
**В игре одна карта мира** — сцена WorldMap. Открывается кнопкой «БОЙ» и кнопкой «МИР» в городе (`UIPanelManager.Open("World")` ведёт в эту сцену).
## Решения и план
- **Этап 0, решено 19.10.2026:** осталась одна карта мира — эта. Маленькая карта (панель «МИР», `Meta/World`) удалена. Перед удалением проверены ссылки в коде, сценах и префабах. Перенос сохранений: солдаты из её походов (`marches` в `progress.json`) возвращаются в город при загрузке — отправленные, а если отряд уже шёл назад, то выжившие. Добыча таких походов не переносится.
- **Этап 4 (утверждён без изменений):** у позиций на карте — месторождения и их качество.
- **Этап 6:** временные ресурсные точки и кристальные разломы; войска на точке недоступны дома.
- **Лагеря:** числа (гарнизон, добыча, 30 минут до появления) — предложение, требуют балансировки. Позже их можно перенести в `EconomyConfig`. В мультиплеере разбитый лагерь — общий для всех игроков, его состояние будет вести сервер.
## Журнал изменений
| Дата | Кто | Что |
| --- | --- | --- |
| 27.10.2026 | Claude | Лагеря разбойников (PvE): 12 лагерей трёх уровней, бой в поле, после победы лагерь разбит на 30 минут, второе войско находит его пустым. Секция `world` хранит разбитые лагеря, в `MarchReturnedEvent` добавлен `TargetEmpty`. Тесты: расстановка лагерей, разбит и появляется снова, сохранение. |
| 27.10.2026 | Claude | Бой с типами войск: состав похода и гарнизона, стены у замка и городов, выжившие по типам, ожидаемый исход в окне атаки. Время походов — по `GameClock` (перемотка в DEV проматывает походы). |
| 23.10.2026 | Claude | Окно «ВОЙСКО ВЕРНУЛОСЬ» в городе. В `MarchReturnedEvent` добавлены `Sent`, `TargetName`, `LootText`. |
| 19.10.2026 | Claude | Маленькая карта мира (`Meta/World`: WorldSystem, WorldMapPanel, WorldData, WorldLine) удалена, окно `Panel_World` убрано из сцены города. Кнопка «МИР» открывает эту карту. Солдаты из походов старой карты возвращаются в город. |
| 19.10.2026 | Claude | `ResetState()`: при сбросе сохранений походы отменяются. |
| 19.10.2026 | Claude | Модуль выделен. `MarchManager` больше не обращается к `GameProgress` и `ResourceManager`: войска через `IArmy`, добыча через `IEconomy`, сохранение — своя секция `"world"`, статистика — через события. Формула боя вынесена в модуль Боя. |