482 lines
41 KiB
Markdown
482 lines
41 KiB
Markdown
# Vanguard ReMaster — состояние сессии
|
||
|
||
**Дата:** 2026-10-27
|
||
|
||
**HEAD:** см. `git log -1`
|
||
**Коротко:** сервер готов, клиент — рабочий каркас с 3D-сценами.
|
||
|
||
## Правила работы
|
||
|
||
- Ответы короткие, без повторов и длинных вступлений — экономия токенов.
|
||
- Любое сомнение/вопрос — диалог: 2–4 варианта с рекомендацией, выбор за
|
||
пользователем (или его свободный ответ). Не угадывать.
|
||
- Полный свод правил — `AGENTS.md`.
|
||
- Новые изменения: анализ DeepSeek → план в
|
||
`docs/Development/IMPLEMENTATION_PLAN.md` → реализация. Обе стадии выполняет
|
||
DeepSeek, раздельно по проходам. Код на этапе анализа не меняется; процесс — `docs/Development/AGENT-WORKFLOW.md`.
|
||
|
||
## Сервер
|
||
|
||
- .NET 10 / ASP.NET Core, EF Core, PostgreSQL, Redis, опциональный Orleans.
|
||
- Реализовано: auth/JWT, онбординг, коллекция, колоды, магазин, экономика,
|
||
матчмейкинг, WebSocket-матч, история, реплеи.
|
||
- Orleans включается `Orleans:Enabled`; в compose включён. Один silo,
|
||
in-process реестр соединений.
|
||
- Тесты: **151** правил + **45** серверных, CI зелёный.
|
||
- Стенд: `http://192.168.31.158:18080`, `/health` → ok.
|
||
- Диагностика Ride в `MatchGrain`: входящие интенты, результат, события,
|
||
снапшоты и `rideReady` по руке/рангам; логи через `docker compose logs`.
|
||
- Документация: `docs/server-api.md`, `docs/protocol.md`,
|
||
`docs/game-rules.md`, `docs/HANDOFF.md`.
|
||
|
||
## Клиент
|
||
|
||
- **Unity 6000.6.6f1**, URP; проект в `client/`.
|
||
- Пакеты: URP, Input System, Addressables, Localization, Newtonsoft.Json,
|
||
VContainer (OpenUPM).
|
||
- Визуальное направление: **3D**, отдельные сцены-экраны:
|
||
`Login`, `Lobby`, `Community`, `DeckBuilder`, `Battle`.
|
||
`DeckBuilder` совмещает коллекцию и колоды; `Boot` — стартовая служебная
|
||
сцена; `VanguardApp` персистентный.
|
||
- Переходы — `SceneFlow`; очередь, магазин и история — экраны **Lobby**;
|
||
выбор стартовой триал-деки — отдельный экран до Lobby.
|
||
- 3D-окружение сейчас из примитивов (`SceneEnvironment`): камера, свет,
|
||
пол, тематические кубы. UI — code-generated uGUI, пока gray-box.
|
||
- Login переведён на референс: полноэкранный арт
|
||
`Resources/Login/login_bg`, неоновая панель, меню (язык, версия, адрес
|
||
сервера). Tab/Shift+Tab переключают поля, Enter отправляет форму, Esc
|
||
закрывает меню. 3D-окружение в `Login` больше не строится
|
||
(`TASK-2026-021`).
|
||
- Lobby — 2D-дашборд по референсу (`TASK-2026-022`): процедурный фон,
|
||
топбар с MMR и меню, BATTLE/DECK BUILDER/SHOP, миссии, балансы,
|
||
заглушки чата и друзей; «Рейтинг» — заглушка, «Сообщество» — отдельная
|
||
сцена `Community` с вкладками «Гайды / Колоды / Тикеты». BATTLE
|
||
открывает оверлей выбора колоды и режима (Ranked / С ботом). 3D в Lobby
|
||
не строится; `MetaView` удалён.
|
||
- Интерфейс рассчитан на reference **1920×1080** (`CanvasScaler`,
|
||
`matchWidthOrHeight = 0.5`); standalone принудительно открывается в
|
||
1920×1080 fullscreen, `defaultIsNativeResolution` выключен.
|
||
- Login: тёмный неон + 3D-карточный стол, форма по центру на
|
||
полупрозрачной панели.
|
||
- Сервисы: `ApiClient`, `AuthService`, `MetaService`, `TokenStore`,
|
||
`PlayerState`, `GameConnection`.
|
||
- Работает: логин/регистрация/refresh, онбординг, коллекция с разбором,
|
||
декбилдер (слева карточная сетка коллекции с мультифильтрами, справа
|
||
панель «Мои колоды» ⇄ «Колода»; список карт колоды — грейд→имя,
|
||
превью-иллюстрации), магазин (бустер/триал-дека), история матчей и
|
||
реплей, очередь, WebSocket-матч (snapshot, интенты, маллиган, сдача,
|
||
`GameFinished`), таймер, результат.
|
||
- Декбилдер: `DeckBuilderView` (один экран), `DeckListFilter`
|
||
(`DeckFilter`/`DeckListModel`); каталог метаданных — `GET /api/cards`
|
||
(grade, trigger, clan, rarity, printing, power/shield/type, текст
|
||
способности), клиент объединяет с коллекцией.
|
||
Превью карт — иллюстрация (верхние 59% арта) без искажений; полный арт
|
||
остаётся в карточке и 3D-поле.
|
||
- ПКМ по карте — оверлей с картой, способностями, разбором в пыль и
|
||
крафтом; SP/TD не разбираются и не крафтятся.
|
||
- Локализация RU/EN: `Loc` + `LocalizedText`; переключатель в Login и
|
||
Lobby (кнопка `EN`/`RU`), выбор сохраняется в `PlayerPrefs`. Русские
|
||
строки остаются ключами, переводятся и статические, и динамические
|
||
подписи; имена/тексты карт берутся из `nameRu/nameEn` и `textRu/textEn`.
|
||
- Тренировка с ботом: кнопка «С ботом» в редакторе колоды; сервер
|
||
создаёт casual-матч против случайного бота (`POST /api/game/practice`),
|
||
без истории, MMR и наград.
|
||
- Боевой экран: поле, рука и стопки — **3D** (`GameBoard3D`), HUD/кнопки
|
||
остаются uGUI. Карты — тонкие 3D-объекты с артом, рубашкой, торцом и
|
||
коллайдером. Rest (атака/поддержка) — поворот по часовой стрелке вокруг Y,
|
||
урон лежит на боку против часовой; закрытость — переворот вокруг X.
|
||
Рубашка — стандартная VF Vanguard (`Resources/CardArt/vanguard_back.png`),
|
||
общая для 2D и 3D. Рука закреплена в поле зрения камеры снизу по центру
|
||
и всегда смотрит на игрока, а не лежит на столе; уменьшена, чтобы не
|
||
закрывать задний ряд RC. Камера фиксирована по центру поля под небольшим
|
||
углом к горизонту и не двигается игроком: `(0, 4.2, -8)`, цель
|
||
`(0, 0, 0)`, FOV 46; наклон только по X, без бокового смещения. Драг-н-дроп
|
||
на плоскость стола с подсветкой целей и плавным снапом.
|
||
Все карты на столе и в руке увеличены на 25% (`cardScale = 1.25`).
|
||
- Поле: у каждого игрока два ряда `R V R` / `R R R` (V + 5 RC), у
|
||
противника зеркально; между полями общий круг защиты; колода, дроп,
|
||
триггер-зона и урон — 3D-зоны. Локальный игрок всегда снизу, даже если
|
||
он за вторым местом. Карты в кругах V/R принудительно показываются
|
||
лицом вверх; урон — один вертикальный ряд, карта входит открытой.
|
||
Над колодой — зона проверки триггера. Под картами V/R — динамические
|
||
`P/C`.
|
||
- Смена: в фазе Ride доступны карты того же ранга и на 1 выше. На первом
|
||
ходу переход в Battle не предлагается; атака по-прежнему запрещена.
|
||
Смена — драг карты из руки на VC. Списки всех возможных смен в панелях
|
||
убраны; действия доступны из меню выбранной карты в руке.
|
||
- Призыв: клик по карте в руке открывает меню действий (Призвать / Сменить /
|
||
Активировать способность / Подробнее), drag в RC/VC выполняет призыв/смену.
|
||
Если у RC доступен единственный круг перемещения, перемещение выполняется
|
||
сразу, без выбора цели.
|
||
Призыв разрешён и в занятый RC; прежний юнит уходит в Дроп. Правило
|
||
действует для обычного призыва, призыва из души/колоды и выбора круга
|
||
способностями.
|
||
- Аудит всех 66 карт со способностями и правила реализации:
|
||
`docs/ability-implementation.md`. Conroe получил AUTO-call при ride-over.
|
||
- Способности: кнопка «Активировать способность» одна на карту; при
|
||
нескольких вариантах открывается overlay выбора способности. Карта для
|
||
сброса выбирается **кликом по карте в руке**, а не пунктом меню.
|
||
Perfect Guard также просит выбрать карту сброса в руке. Клик по карте в
|
||
руке с активируемой способностью открывает меню действий; пункт активации
|
||
показывается, если фаза и условия позволяют способность.
|
||
- Триггеры: Draw после выбора цели силы сразу тянет карту; Heal выбирает
|
||
карту только в своей зоне урона и только при выполнении условий, иначе
|
||
дополнительный эффект не активируется.
|
||
- Оплата способности: выбранные карты цены подсвечиваются в руке, а для
|
||
Counter Blast — доступные и выбранные карты в зоне урона. Подтверждение
|
||
оплаты — кнопка «Подтвердить оплату» в панели «Действия»; правый клик
|
||
отменяет выбор.
|
||
- Защита: в панели «Действия» одна кнопка — «Не защищаться» без выбора и
|
||
«Защищаться» с выбранными картами. Защитник из руки должен быть не выше
|
||
ранга своего авангарда. Карты защиты и перехвата выбираются
|
||
кликом/драгом по объектам; допустимые подсвечиваются, выбранные — зелёным.
|
||
Щит выбранных карт сразу учитывается в счётчике; после подтверждения карты
|
||
уходят в зону защиты, шаг защиты завершается. Дубли карт в Guardian
|
||
устранены.
|
||
- Локальный standalone работает в фоне (`runInBackground`), чтобы heartbeat
|
||
WebSocket не останавливался при потере фокуса.
|
||
- При потере соединения весь бой блокируется полноэкранным overlay
|
||
«Соединение потеряно»; автоматический reconnect идёт с задержками
|
||
0/2/10/30 с, после успеха overlay скрывается и поле показывается снова.
|
||
Кнопка внутри overlay позволяет выйти в меню.
|
||
- Правую панель действий можно временно скрыть кнопкой «Скрыть панель»
|
||
в верхней строке; поле остаётся видимым, вернуть — «Показать панель».
|
||
При скрытии панель действий и блоки противника сдвигаются вправо, а рука
|
||
центрируется по горизонтали; при показе возвращается влево.
|
||
- Кнопка муллигана находится в панели «Действия» и динамическая: без выбора —
|
||
«Закончить муллиган», с выбором — «Заменить X карт».
|
||
- Trigger-зона у противника расположена над его колодой по направлению
|
||
к центру стола (зеркально своей), а не за дальним краем.
|
||
- Статистика карт — отдельное UI-наложение: своя панель снизу слева,
|
||
противника — сверху справа. Блоки `Рука/Колода/Дроп/Душа/Урон/Защита/Триггер`
|
||
кликабельны и открывают общий горизонтальный `CardListView`; из списка
|
||
открывается `CardDetailOverlay`. Для колоды и руки противника показываются
|
||
только закрытые карты. Душа — юниты под VC: отдельной стопки нет,
|
||
ПКМ по VC открывает список. Дроп по умолчанию пуст; сверху показывает
|
||
последнюю карту, ЛКМ — список всего дропа. Колода и дроп поменяны
|
||
местами (колода ближе к игроку). Справа от круга защиты — панель действий:
|
||
конец муллигана (авто после обмена), скип смены, конец главной/боевой;
|
||
боевая завершается сама, если нет атак и активаций. Рука противника —
|
||
веер закрытых карт у дальнего края стола, только рубашки.
|
||
- Зона урона: карты лежат открытыми и на боку; после Counter Blast
|
||
выбранная карта переворачивается рубашкой. Heal выбирает карту урона;
|
||
Counter Blast — открытую карту до активации способности.
|
||
- Маллиган: один раз на игрока, оба игрока; выбранные карты уходят в низ
|
||
колоды, добираются новые, затем shuffle. Клик по руке выбирает карты;
|
||
кнопка динамическая: без выбора — «Закончить муллиган», с выбором —
|
||
«Заменить X карт».
|
||
- Анимации: event-фидбек (атака, guard, drive, урон, retire, heal) поверх
|
||
стола; ввод заблокирован до завершения через `InputLockService`, очередь
|
||
событий + кнопка «Пропустить анимации». Длительности и скорости карт —
|
||
`AnimationConfig` (`Resources/AnimationConfig`). Guard/drive/intercept
|
||
показывают имя карты и держатся 1.5–2 с. 3D-карты плавно снапятся,
|
||
поворачиваются в Rest и переворачиваются; подсветка целей и точки броска
|
||
обновляются на каждом снимке. Зависшие причины `InputLockService`
|
||
снимаются, когда reconnect/overlay/ability/card-menu/feedback уже
|
||
неактивны; `board`-лок больше не накапливается на каждом снапшоте.
|
||
- 3D UX (P0/P1): `CardMoveAnimator` переносит карты по дуге с
|
||
stagger/`InputLock`; diff идёт по `InstanceId`, пул сохраняет карту при
|
||
смене зоны. `AnimationConfig` расширен (`moveDuration`,
|
||
`importantMoveDuration`, `moveDelayBetweenCards`, `arcHeight`,
|
||
camera/grow/dash). Trigger Zone: своя +90°, противника −90° относительно
|
||
базы; `DropZoneFaceDown` в конфиге. `CameraDirector` +
|
||
`TriggerCheckSequence`: zoom → hold → return, цепочка, точный Restore;
|
||
`EnsureCamera` не перезаписывает камеру во время цепочки.
|
||
`ArrowDirector`: красная attack и синяя boost-стрелка, grow/arc/dash
|
||
(UV-tile), якоря у края карт. Multi-target Counter Blast: выбранные карты
|
||
урона уходят массивом `DamageIndexes`, сервер снимает именно их; счётчик
|
||
выбора показывается в панели «Действия». Детали —
|
||
`docs/3d-ux-backlog.md`.
|
||
- Опциональные AUTO-способности (Barcgal после рейда Marron) открывают
|
||
модальный оверлей «Способность» с «Активировать»/«Пропустить»; в боковой
|
||
панели этих кнопок нет. После подтверждения призыва сервер предлагает
|
||
`AskEmptyRearGuardChoice`, клиент подсвечивает свободные RC и принимает
|
||
выбор кликом по кругу — первого круга по умолчанию нет и отдельных
|
||
кнопок выбора тоже. Сама панель пока оставлена.
|
||
- Общий верхний `ActionPrompt` показывает, что сейчас требуется: муллиган,
|
||
смена, защита, бой, выбор карты/круга/цели, триггер, порядок триггеров,
|
||
опциональная способность. Он не перехватывает клики и скрыт в ход
|
||
противника.
|
||
- Правило: выбор карты/круга/зоны/цели делается кликом/драгом по объекту
|
||
на поле, не кнопками; кнопки — только глобальные действия/подтверждения.
|
||
Зафиксировано в `AGENTS.md` и `docs/client-visual-direction.md`.
|
||
- Бой: динамическая плашка `POWER X vs SHIELD Y` (Power атакующего против
|
||
Power защищающегося + GuardShield), пересчитывается на каждом снимке, в
|
||
том числе после Guard. От атакующего к цели идёт затухающая 3D-стрелка,
|
||
которая следует за картами. ЛКМ по своей карте V/R открывает контекстное
|
||
меню с действиями из `LegalIntents` (атака/boost, перемещение, способность,
|
||
подробнее); карты противника и зоны открывают детали/списки. ПКМ по VC —
|
||
душа. Guardian-карты повёрнуты на 90° и уложены с перекрытием ~30%,
|
||
новые сверху; Trigger-зона зеркальна у противника. 3D-подписи зон скрыты,
|
||
включаются флагом `showZoneLabels`.
|
||
- Tejas может атаковать задний ряд противника своей колонки как с RC, так и
|
||
с VC (центральный задний ряд).
|
||
- Drag в бою: задний ряд → свой передний круг/Авангард объявляет поддержку,
|
||
после чего атаковать можно только поддерживаемой картой; передний круг →
|
||
карта противника объявляет атаку. Авангард поддерживается центральным
|
||
задним кругом. Barcgal имеет ACT `[Rest]` — поиск Llew/Flogal в колоде с
|
||
выбором круга призыва; найденные карты показываются оверлеем с плитками
|
||
карт и выбираются кликом по карте. Morgana после принятия способности
|
||
просит сбросить карту: доступные карты в руке подсвечиваются, выбор —
|
||
кликом по карте.
|
||
- Реальные арты: `imageKey` из `/api/cards` + `CardImageService` ищет
|
||
`Resources/CardArt/{imageKey}`. Скачаны все 124 арта. Импорт:
|
||
`tools/import_card_art.py`.
|
||
- Взаимодействие в бою: клик по картам/зонам, подсветка целей,
|
||
группировка действий (карты → цели, глобальные кнопки отдельно),
|
||
выбор силы/эффекта триггера, журнал последних событий. Позванные
|
||
rear-guard'ы входят в стоячем положении; rest — только после атаки/буста.
|
||
Атака проходит при силе атакующего **>=** силы защищающегося.
|
||
В первый ход атака запрещена; первый игрок определяется сидом.
|
||
- Отдельная сцена `Collection` и `CollectionView` удалены; коллекция
|
||
открывается из Lobby кнопкой «Коллекция» (сцена `DeckBuilder`).
|
||
- Не готово: 3D-модели карт/стола (пока процедурные примитивы и арты),
|
||
звук, настройки (язык уже есть), DOTween, drag&drop и live-валидация
|
||
декбилдера. Камера боя в покое фиксирована, но `CameraDirector` временно
|
||
ведёт trigger-последовательность. Не перенесены отдельные retire/ghost
|
||
анимации, `AttackResolutionQueue`, multi-target Soul Blast, world-space
|
||
Power/Shield.
|
||
|
||
## Запуск
|
||
|
||
Сервер (на `ssh home`):
|
||
|
||
```bash
|
||
cd ~/VanguardReMaster
|
||
docker compose up -d --build
|
||
curl http://127.0.0.1:18080/health
|
||
```
|
||
|
||
Клиент:
|
||
|
||
1. Unity Hub → `client`, редактор **6000.6.6f1**.
|
||
2. Открыть `Assets/Scenes/Boot.unity`, Play.
|
||
3. Стенд по умолчанию — `http://192.168.31.158:18080`.
|
||
|
||
Standalone Windows:
|
||
|
||
- В редакторе: `Vanguard → Build Windows Standalone`.
|
||
- Из CLI (пример для копии проекта):
|
||
```powershell
|
||
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
|
||
-batchmode -nographics -projectPath client `
|
||
-executeMethod Vanguard.Editor.StandaloneBuild.BuildWindowsCli -quit
|
||
```
|
||
- Результат: `client/Builds/Windows/VanguardReMaster.exe` (папка в
|
||
`.gitignore`). Это обычное приложение, не Play Mode; сервер должен быть
|
||
доступен по адресу из `AppConfig`.
|
||
|
||
## Проверки клиента
|
||
|
||
```powershell
|
||
# EditMode
|
||
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
|
||
-batchmode -nographics -projectPath client `
|
||
-runTests -testPlatform EditMode -testResults client\TestResults.xml
|
||
|
||
# Boot → Login + 3D environment
|
||
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
|
||
-batchmode -nographics -projectPath client `
|
||
-executeMethod Vanguard.Editor.SceneSmoke.Run
|
||
|
||
# 3D playmat sandbox
|
||
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
|
||
-batchmode -nographics -projectPath client `
|
||
-executeMethod Vanguard.Editor.SceneSmoke.RunPlaymat
|
||
```
|
||
|
||
Клиентские проверки: **67/67** EditMode (включая новые тесты TASK-2026-001:
|
||
повторный render скрытых карт, открытие урона, source-позиция нового юнита,
|
||
coalescing `CardMoveAnimator`; сборка всех экранов, импорт арта, перевод
|
||
строк, live-переключение языка, рендер 3D-доски, геометрия поля, правила
|
||
перемещения, рука в поле зрения камеры, обмен колоды/дропа, триггер-зона,
|
||
CardListView/Detail, зоны и рука противника, InputLock, контекстное меню,
|
||
стрелка атаки, prefab-оверлеи, раскладка на 1920×1080, авто-завершение
|
||
муллигана, одна кнопка защиты, отсутствие дублей в Guardian), `SCENE_SMOKE
|
||
success=True`, `PLAYMAT_SMOKE success=True cards=25 hand=5/5 fieldVisible=True`.
|
||
|
||
`SceneSmoke` заменяет PlayMode-тест загрузки сцен: Single-загрузка сцены
|
||
ломает стандартный PlayMode test runner. `SceneBuilder` пересобирает сцены:
|
||
|
||
```powershell
|
||
& '...\Unity.exe' -batchmode -nographics -projectPath client `
|
||
-executeMethod Vanguard.Editor.SceneBuilder.BuildAll
|
||
```
|
||
|
||
## Ключевые файлы клиента
|
||
|
||
```
|
||
client/Assets/Vanguard/Runtime/App/
|
||
VanguardApp.cs composition root, персистентный
|
||
SceneFlow.cs переходы Login/Lobby/DeckBuilder/Battle
|
||
SceneEnvironment.cs 3D-фон сцен
|
||
SceneControllerBase.cs
|
||
LoginSceneController.cs
|
||
LobbySceneController.cs
|
||
DeckBuilderSceneController.cs
|
||
BattleSceneController.cs
|
||
client/Assets/Vanguard/Runtime/UI/
|
||
LoginView.cs OnboardingView.cs
|
||
LobbyView.cs LobbyBackdrop.cs LobbyIcon.cs StubUi.cs
|
||
BattleEntryOverlay.cs ComingSoonOverlay.cs HamburgerMenu.cs
|
||
CommunityView.cs
|
||
DeckBuilderView.cs QueueView.cs BattleView.cs
|
||
UiKit.cs NeonUi.cs Localization.cs
|
||
client/Assets/Vanguard/Runtime/UI/Overlays/
|
||
OverlayNavigationService.cs стек список → детали
|
||
CardListView.cs общий горизонтальный список
|
||
CardDetailOverlay.cs крупная карта и текст
|
||
CardListModels.cs зоны и скрытые карты
|
||
ZoneBlockStripView.cs кликабельные блоки зон
|
||
CardActionMenuView.cs контекстное меню карты
|
||
OverlayPrefabs.cs загрузка prefab-оверлеев
|
||
client/Assets/Vanguard/Editor/
|
||
OverlayPrefabBuilder.cs сборка Resources/Overlays/*.prefab
|
||
StandaloneBuild.cs Windows standalone build
|
||
client/Assets/Vanguard/Runtime/Battle/
|
||
AnimationConfig.cs длительности/скорости анимаций
|
||
InputLockService.cs блокировка ввода по причинам
|
||
GameConnection.cs
|
||
client/Assets/Vanguard/Runtime/Board3D/
|
||
Config/PlaymatLayoutConfig.cs ScriptableObject-раскладка
|
||
Data/BoardTypes.cs зоны, круги, CardState3D, refs
|
||
Logic/PlaymatLayout.cs геометрия, рука, поиск цели броска
|
||
Logic/BoardPlacementRules.cs Ride/Call/Move/Guard
|
||
View/GameBoard3D.cs стол, круги, пул карт, drag&drop
|
||
View/Card3D.cs карта: лицо/рубашка/торец, Rest, флип
|
||
View/AttackArrowView.cs стрелка атаки с наконечником
|
||
PlaymatSandbox.cs демо без сервера
|
||
client/Assets/Vanguard/Resources/AnimationConfig.asset настройки анимаций
|
||
client/Assets/Vanguard/Resources/Overlays/*.prefab prefab-оверлеи
|
||
client/Assets/Vanguard/Resources/CardArt/vanguard_back.png рубашка VF
|
||
client/Assets/Vanguard/Scenes/GameBoard3D.unity песочница поля
|
||
client/Assets/Vanguard/Runtime/Api/ApiClient.cs + ApiContracts.cs
|
||
client/Assets/Vanguard/Editor/SceneBuilder.cs + SceneSmoke.cs
|
||
client/Assets/Vanguard/Scenes/*.unity
|
||
client/Assets/Plugins/Vanguard.Shared + MessagePack
|
||
```
|
||
|
||
## Решения
|
||
|
||
- 3D-визуал, отдельные сцены; подробно — `docs/client-visual-direction.md`.
|
||
- `Boot` не показывается; `VanguardApp`/сервисы не пересоздаются.
|
||
- Очередь — оверлей Lobby; DeckBuilder «В бой» возвращает в Lobby с
|
||
выбранной колодой в `SceneFlow.PendingQueueDeck`.
|
||
- Токены в `PlayerPrefs` — dev; для релиза защищённое хранилище.
|
||
- HTTP разрешён только для dev (`insecureHttpOption: 2`); для релиза HTTPS.
|
||
- `GameConnection` использует `System.Net.WebSockets.ClientWebSocket`
|
||
(Windows/десктоп first); WebGL потребует другого транспорта.
|
||
- Сервер авторитарный; клиент отправляет только интенты, скрытые данные
|
||
не покидают сервер.
|
||
|
||
## Следующие шаги
|
||
|
||
1. **TASK-2026-021 — Login по референсу: реализован, ждёт ручной приёмки**
|
||
(C10). EditMode 60/60, `SCENE_SMOKE success=True`, standalone собран.
|
||
**TASK-2026-022 — Lobby по референсу: реализован C1–C11, ждёт ручной
|
||
приёмки.** EditMode 62/62, `SCENE_SMOKE`, `PLAYMAT_SMOKE`, standalone
|
||
собраны и запущены. **TASK-2026-023 — DeckBuilder (один экран,
|
||
мультифильтры, список колоды): реализован C1–C11, ждёт ручной
|
||
приёмки.** EditMode 67/67, `SCENE_SMOKE`, `PLAYMAT_SMOKE`; standalone.
|
||
**TASK-2026-024 — DeckBuilder по референсу (топбар Lobby, крупные
|
||
карты, фильтры в оверлее): план готов**, реализация — следующим
|
||
проходом. После приёмки — **TASK-2026-019** (загрузочная сцена, fade,
|
||
кадр без покадровых аллокаций).
|
||
2. **TASK-2026-001 — ручная проверка пользователем** (C10): draw, call, ride,
|
||
move/swap, guard, trigger, drive/damage, retire, search, открытие скрытого
|
||
урона, рука противника, повторные клики UI во время/после анимации.
|
||
Автотесты 47/47; код изменён в `GameBoard3D`, `CardMoveAnimator`,
|
||
`BattleView`, `AnimationConfig.asset` + тесты.
|
||
2. **TASK-2026-002 — реализован D1–D8, остались серверные проверки и
|
||
ручная приёмка.** Реализованы: hold-at-source для queued-карт,
|
||
drag-and-drop без локального `DropAt`, Tejas-колонка через границу
|
||
игроков, стадийный Perfect Guard (отдельная способность Sentinel после
|
||
размещения), боевые паузы 1.5 с, скрытие руки на trigger-зуме.
|
||
Клиентские EditMode-тесты 50/50. Серверные тесты (`Vanguard.Rules`)
|
||
— только на `ssh home`; ручная проверка — пользователь.
|
||
3. **TASK-2026-003 — боевой HUD по мокапу: реализовано, требуется ручная
|
||
приёмка.** Готово: правая панель действий убрана, подтверждения в правом
|
||
нижнем углу, debug-панель по кнопке, верхний HUD с Turn/фазами/таймером/
|
||
банком, центральный баннер хода, компактные панели игроков, `Drop/Soul`
|
||
из бара, `Deck` неинтерактивен, счётчик `x/6` над уроном, пластины
|
||
слотов, рамка/имя/бейдж триггера карты, статы под картой (`▲`/`◆`, крит
|
||
только >1), конкретные подписи триггеров (`+5000`, `Крит +1`,
|
||
`Поднять юнита`, `Взять карту`, `Лечить`), trigger-зум с плашкой
|
||
«Без триггера». Карты урона идут сверху вниз с перекрытием 30%, новая
|
||
поверх старой; trigger-карта повёрнута на 90° против часовой. Имена карт
|
||
на поле убраны; панель действий — компактные кнопки справа снизу; рука
|
||
центрируется по экрану; подсказка муллигана — в верхней панели, при
|
||
выборе карт появляется «Заменить N карт»; центральный баннер убран;
|
||
левый бар — `Колода, Душа, Рука, Сброс`, `Душа/Сброс` кликабельны.
|
||
EditMode 50/50, серверные правила 155/155, standalone собран, клиент
|
||
запущен. Триггер: фокус камеры → анимация раскрытия карты → пауза
|
||
0,75 с → резолв; затем выбор `+5000` и эффекта (`Critical` — RC/VC,
|
||
`Stand` — только повёрнутый RC, `Draw` — авто, `Heal` — карта урона);
|
||
подсказки в верхнем блоке. Урон переворачивается вокруг длинной стороны.
|
||
Tejas: колонка `V↔1/3↔2/4↔0`, сервер пересобран и задеплоен на
|
||
`ssh home`. В Основной фазе — только кнопка «Боевая фаза». Рамка карты —
|
||
тонкая чёрная по краю, в руке рамка скрыта; карты лежат широким веером,
|
||
своя рука заполняется слева направо, новая карта добавляется правее и
|
||
остаётся поверх предыдущей, ширина сохраняется до 10 карт и плавно
|
||
уменьшается начиная с 11-й. Рука противника — зеркальный камеро-зависимый
|
||
веер ниже верхней панели: новая карта слева, наклон и глубина зеркальны;
|
||
позы обеих рук обновляются каждый кадр, добор не летит к устаревшей цели.
|
||
Это закреплено тестом `Hands_Fill_Mirrored_And_Newest_Is_On_Top` (58/58).
|
||
Возврат карт в колоду: старая карта уходит из руки по дуге под низ колоды
|
||
с переворотом рубашкой вверх; следующая стартует только после завершения
|
||
предыдущей. Рука идёт ступенчатым reflow: после каждого ухода оставшиеся
|
||
карты, включая ожидающие возврата, сдвигаются под новое количество.
|
||
Длительность как у добора (`DrawDuration` / `introDrawDuration = 0.6`),
|
||
у противника зеркально. Стартовый
|
||
Авангард закрыт до конца муллиганов (`MatchProjection` передаёт реальный
|
||
`FaceUp`), затем переворачивается вокруг длинной оси слева направо
|
||
(у противника зеркально).
|
||
Старт боя: камера над стороной игрока лицом к столу, 1,5 с → дуга вниз
|
||
на основную позицию → пауза 1,5 с → одновременный добор обеих рук →
|
||
только потом муллиган. Добор общий: карта стартует ровно над колодой
|
||
полного размера (`cardScale`), рубашкой вверх, летит в руку с переворотом
|
||
лицом вверх; длительность как в муллигане — `introDrawDuration = 0.6 с`.
|
||
Любой добор последовательный — следующая карта только после предыдущей.
|
||
Частично: bloom/свет
|
||
и HUD-анимации. 2026-10-27: боевые feedback-баннеры, вспышки и кнопка
|
||
«Пропустить анимации» удалены; журнал событий и trigger-подсказки
|
||
оставлены. Рука перестраивается под новое количество одновременно с
|
||
перемещением уходящей карты (любой выход из руки). При доборе новые
|
||
карты показываются по одной, а рука расширяется после каждой. Раскладка
|
||
руки идёт через единый `_visualHandCards`: остатки, возвращаемые и уже
|
||
добранные карты участвуют в сдвиге после каждого изменения. Hover карты
|
||
в руке плавно поднимает её на 10% высоты и возвращает после ухода курсора.
|
||
Карта из руки при зажатии ЛКМ не двигается и остаётся в руке
|
||
приподнятой; курсор наводится на зону, при отпускании над VC выполняется
|
||
смена. Цель определяется raycast-ом по VC-карте/кругу, затем плоскостью.
|
||
Невалидный drop оставляет карту в руке. Валидные для смены карты
|
||
подсвечиваются в руке; по логу это были TD02/007EN и BT01/015EN.
|
||
Карты поля сохраняют обычный drag. EditMode 58/58.
|
||
Детали — `docs/Development/IMPLEMENTATION_PLAN.md`.
|
||
4. 3D UX: P0 (движение, ориентации, камера/триггер) и базовый P1 (стрелки,
|
||
multi-target Counter Blast) готовы. Осталось: `AttackResolutionQueue`,
|
||
multi-target Soul Blast/прочие стоимости, отдельный `CostPaymentOverlay`,
|
||
world-space Power/Shield (верхний strip принят как HUD), world-space
|
||
dash shader; полировка позиций на конкретном мониторе.
|
||
4. Декбилдер: drag&drop карт, пресеты, предупреждение о
|
||
несохранённых изменениях, «Все/Ничего» по секциям фильтра.
|
||
5. 3D-наполнение: модели карт/стола, prefab-экраны сцен, анимации retire/ghost.
|
||
6. Звук и настройки, DOTween.
|
||
7. Лаунчер WPF.
|
||
|
||
Тренировка с ботом и боевой UI с артами/анимациями/локализацией уже есть.
|
||
|
||
## Подводные камни
|
||
|
||
- Не запускать `dotnet`/Docker на рабочем ПК; сервер проверяется на `ssh home`.
|
||
- В Unity нельзя открыть два экземпляра одного проекта: для batch-проверок
|
||
делать копию проекта (без `Library`) или закрывать редактор.
|
||
- Сцены ссылаются на скрипты по GUID; при копировании сцен копировать и
|
||
`.meta` контроллеров.
|
||
- `Vanguard.Shared.dll` — netstandard2.1 + MessagePack 3.1.12; при изменении
|
||
протокола пересобрать DLL и заменить в `client/Assets/Plugins`.
|
||
- `UiKit.CreateCanvas` по умолчанию **не** персистентный: Canvas принадлежит
|
||
сцене; EventSystem остаётся персистентным.
|
||
- Сцена `Boot` должна быть первой в Build Settings; сейчас там
|
||
`Boot`, `Login`, `Lobby`, `DeckBuilder`, `Battle`.
|