VanguardReMaster/.opencode/skills/vanguard-remaster/workflow-and-decisions.md

17 KiB
Raw Blame History

Решения, процесс и антипаттерны

1. Источники аудита

[C] Проверены:

  • .opencode/skills/vanguard-remaster/SKILL.md (прежняя версия);
  • AGENTS.md, docs/SESSION-STATE.md, docs/HANDOFF.md, docs/game-rules.md, docs/ability-implementation.md, docs/protocol.md, docs/client-visual-direction.md, docs/3d-ux-backlog.md, docs/translation-rules.md;
  • локальная база OpenCode: две сессии Vanguard ReMaster (1259 и 5617 сообщений), включая сообщения пользователя и финальные тексты ассистента;
  • исходный код server/client, YAML-контент, тесты, README.md, DEVELOPMENT_CHECKLIST.md, content/cards-mvp.md.

История доступна локально, но не является «полной истиной»: часть решений могла быть принята вне OpenCode. В спорных местах ниже стоит [O], а не выдуманное правило.

2. Подтверждённые решения

Игра и контент

  • [D] Фанатский ремейк Vanguard, формат Classic, BT01 + TD01/TD02, 94 карты / 124 принта.
  • [D] Две триал-деки: TD01 «Blaster Blade», TD02 «Dragonic Overlord»; полный декбилдер.
  • [D] Официальные арты; локализация EN + RU.
  • [D] В коллекции нет лимита копий/артов; 4 копии по имени — только при сборке колоды.
  • [D] Смешивать кланы в колоде разрешено; эффекты с клановыми условиями могут не работать. Это осознанное правило проекта.
  • [D] Сайд-дека нет, матч BO1.
  • [D] Ride Deck/Persona Ride не входят в Classic/текущую игру.
  • [D] Стартовый авангард — grade 0 без триггера; после обучения игрок получает триал-деку на выбор и 5 токенов; 1 токен = 1 бустер.
  • [D] Таймер: 90 с на ход + банк 5 мин; отсутствие/сдача/разрыв — поражение.
  • [D] В первый ход нельзя атаковать и переходить в Battle.
  • [D] Локализация: RU+EN; «ё» разрешена; «усиленная карта»; «уничтожить» оставляем; фазы — Основная/Боевая/Завершающая/Подъёма/Добора/Смены; close step — завершающий шаг; call — призвать; названия зон не переводим; имена карт остаются английскими (nameRu — задел). Детали — docs/translation-rules.md.

Бустеры и экономика

  • [D] В бустере 5 карт: 4 C + 1 гарантированная R+.
  • [C] Текущие веса R+: R 70% / RR 22% / RRR 7% / SP 1% (content/pack_odds.yaml). Пользователь поручил подобрать вероятности, но точные числа не перепроверял; это конфиг, а не вечный закон.
  • [D] Дубли считаются по printingId, порог 4; SP — отдельный принт; при отсутствии замены карта остаётся в коллекции и разбирается в пыль.
  • [D] Gold начисляется за победу и поражение; [C] текущая конфигурация — 30 / 15 / 20 (победа/поражение/ничья), Gold = XP / 5. Точные числа — балансный конфиг, можно менять.
  • [C] Бустер 100 Gold, триал-дека 500 Gold; за сдачу/АФК награды не начисляются (RewardsForForfeit = false по умолчанию).
  • [C] Пыль: разбор C/R/RR/RRR = 5/10/25/100, крафт ×4; фойл ×2.
  • [C] XP пишется с первого дня; баттлпасс/квесты/Draft — после MVP.

Клиент и UX

  • [D] 3D-сцена, отдельные сцены Login/Lobby/DeckBuilder/Battle; HUD — uGUI; reference 1920×1080.
  • [D] Анимации описываются для локального игрока. Для противника применяются те же правила, но зеркально с его стороны поля: направление, сторона появления карты, наклон веера и порядок перекрытия зеркальны; камера также отражается относительно центра стола. Отдельные «противнические» анимации не делать, если это не подтверждённое исключение.
  • [D] Камера в покое фиксирована по центру поля с небольшим наклоном; временно двигается только CameraDirector в trigger-последовательности.
  • [D] Выбор карты/круга/зоны/цели — клик/драг по объекту; кнопки только для глобальных действий/подтверждений.
  • [D] Guard: карты из руки с grade ≤ grade своего Vanguard; одна кнопка «Не защищаться»/«Защищаться»; выбранные подсвечиваются, щит считается сразу, после подтверждения — в Guardian.
  • [D] Карты противника нельзя драгать; можно выбирать целью, смотреть детали и зоны. Клик по своей карте — меню валидных действий.
  • [D] Зоны открываются общим горизонтальным CardListView; сверху — последняя добавленная карта; из списка доступен CardDetailOverlay.
  • [D] Call в занятый RC разрешён; старый юнит → Drop.
  • [D] Move: RC↔RC в колонке; занятые меняются; при единственном доступном круге клиент перемещает сразу.
  • [D] Draw: после цели силы сразу тянет карту; Heal: только своя зона урона и только при условиях; Tejas: задний ряд своей колонки.
  • [D] Optional AUTO — оверлей «Активировать/Пропустить»; ACT из руки — меню карты; оплата — по объектам, подтверждение в панели/оверлее.
  • [D] Mulligan: выбор карт в руке; после замены этап завершается автоматически, неактивная кнопка «Закончить муллиган» не остаётся.
  • [D] Панель фаз переименована в «Действия» и содержит guard, подтверждение оплаты и глобальные действия; список всех возможных смен там не показывается.
  • [D] Под картами V/R показываются динамические Power/Critical; верхний CombatStats strip — допустимый HUD; world-space Power/Shield — отложенный долг.
  • [D] Отдельный CostPaymentOverlay для multi-target стоимости нужен; текущий CB в панели «Действия» — промежуточная реализация.

3. Фактическое устройство (не путать с договорённостью)

  • [C] GameEngine — авторитарное ядро; MatchGrain сериализует интенты; MatchProjection скрывает информацию.
  • [C] Multi-target CB уже поддержан DamageIndexes в ActivateAbilityIntent; старый DamageIndex оставлен.
  • [C] CardMoveAnimator, CameraDirector, TriggerCheckSequence, ArrowDirector есть; анимации на Tick, без UniTask/DOTween.
  • [C] CardMoveAnimator имеет таймаут и CancelCard; это исправление зависшего card-move-лока (коммит fd21a96).
  • [C] DropZoneFaceDown есть, default false.
  • [C] DeckValidator не проверяет единство клана; это соответствует решению «смешивать можно».
  • [C] CombatStats — верхний uGUI strip; отдельного боевого overlay нет.
  • [C] docs/protocol.md ранее указывал неверный порядок отображения урона; фактически сначала открытые, затем закрытые.

4. Процесс разработки

Формальный двухэтапный процесс (анализ → план → реализация; обе стадии выполняет DeepSeek, но раздельно) описан в docs/Development/AGENT-WORKFLOW.md; активный план задачи — в docs/Development/IMPLEMENTATION_PLAN.md. Ниже — краткие правила, без дублирования шаблона плана.

  1. Прочитай Skill и связанные docs; найди существующую реализацию.
  2. Проверь, не решён ли вопрос в коде/истории. Не спрашивай о том, что уже установлено.
  3. Если есть существенная неопределённость — question с 2–4 вариантами.
  4. Вноси минимальные изменения; не трогай несвязанное.
  5. Для правил: тест на сценарий; для карт — тест на триггер/активацию; для клиента — EditMode/smoke.
  6. Серверные проверки — только ssh home/Docker; Unity batch — копия без Library.
  7. После блока: validate, translations check, коммит/push.
  8. Геймплей вручную проверяет пользователь; не выдавай свой тест за приёмку.

5. Антипаттерны

Не делать Почему Как делать
Список кнопок вместо клика по карте/кругу Нарушает принятый UX Подсветка объектов + клик/драг
transform.position = ... в игровой логике Ломает анимации/локи Card3D/CardMoveAnimator/SetPose
Дублировать эффект в нескольких CardScript Расходится поведение Один CardScript, общий движок или флаг
OnPlace без проверки VC/RC Срабатывает не в той зоне IsVanguardOf/IsRearGuardOf
Менять GameState на клиенте Рассинхрон с сервером Только IntentPayload, рисовать snapshot
Запускать dotnet/Docker локально Запрещено пользователем ssh home/Docker
Второй Unity с тем же проектом Ломает Library/импорт Копия без Library
Заявлять тест без запуска Вводит в заблуждение Указать, что проверено, а что нет
Самому проходить геймплей как приёмку Пользователь проверяет лично Автотесты + передать сценарий
Менять Vanguard.Shared без пересборки DLL Unity увидит старый контракт Собрать netstandard2.1 и заменить DLL
Вечный InputLock без таймаута Блокирует ход/смену try/finally, timeout, CancelCard
Освобождать карту из пула во время анимации/обмена Дубли/неактивные карты Сначала распределить по InstanceId, потом release
Новый универсальный effect/DSL без нужды Усложняет и дублирует Расширять существующие AbilityDefinition
Хранить вычисленную силу как истину CONT пересчитывается EffectivePower/модификаторы
Показывать все возможные смены в панели Пользователь это запретил Действия из меню карты/валидных интентов
Перехватывать клики информационным оверлеем Мешает выбору по объекту raycastTarget = false/скрыть ввод
Считать printingId и nameId одним Ломает лимиты/коллекцию nameId — 4 копии, printingId — принт
Perfect Guard даёт щит без оплаты Неверная защита Без оплаты 0 щита и нет nullify
Heal просит цель при невыполненных условиях Лишний выбор/зависание Сначала серверная проверка, потом AskDamageChoice

6. Известные ошибки и уроки

  • Зависший card-move-лок (2026-10-24): карта освобождалась из пула, оставаясь в _active; Tick больше не вызывался, InputLock не снимался. Исправлено таймаутом/CancelCard. Не возвращать.
  • Дубли/нахлёст при обмене RC: нельзя освобождать карту из занятого ключа, если она должна переехать в другой ключ. Сначала распределение по InstanceId, затем release.
  • Conroe долго не имел AUTO OnRideOver — проверять весь текст, а не только очевидные ACT/CONT.
  • Barcgal: при выборе призыва из колоды клиент должен показать оверлей доступных карт; не подставлять первый круг/карту автоматически.
  • Ride после хода противника ломался из-за клиентского ввода/логики, а не только сервера; проверять lock и LegalIntents.
  • Пустой Mulligan: после замены карт кнопка «Закончить муллиган» не должна оставаться неактивной; муллиган завершается автоматически.
  • Guard дубли: Guardian и Battle.GuardCards могут содержать одну карту; клиент дедуплицирует по InstanceId.
  • Perfect Guard: без discard карта даёт 0 щита; не считать Sentinel обычным щитом.
  • Trigger check: карта сначала в Trigger, затем эффект, затем hand/ damage; не переставлять.

7. Открытые вопросы

  • [O] Отдельная проверка «авангард исчез» в GameEngine отсутствует; нужно ли добавлять — решать пользователю.
  • [O] OnPlace + OnRideOver при pending-способности OnPlace: текущая реализация может не запустить OnRideOver; нужно ли чинить — отдельное решение.
  • [O] Multi-target Soul Blast/другие стоимости: протокол и UI ещё не сделаны.
  • [O] CostPaymentOverlay требуется, но его форма/EffectConfig и момент включения ещё не реализованы; текущий CB — промежуточный.
  • [O] World-space Power/Shield: верхний strip принят как HUD, перенос — долг.
  • [O] AttackResolutionQueue и несколько boost-стрелок — будущая архитектура, сейчас бой с одной целью.
  • [O] DropZoneFaceDown UX: default false; нужен ли другой режим — не решено.
  • [O] Точная легальность формата/banlist и обязательность ровно одного стартового авангарда в DeckValidator не выделены.
  • [O] Полная история вне OpenCode недоступна; спорные места не считаются восстановленными.