192 KiB
Implementation Plan
Активный журнал задач и планов изменений. Постоянные правила проекта хранятся
в Skill vanguard-remaster; история старых блоков — в IMPLEMENTATION_CHECKLIST.md,
DEVELOPMENT_CHECKLIST.md и docs/HANDOFF.md. Этот файл не заменяет их и не
является источником игровых правил.
Процесс
- DeepSeek анализирует пожелание, код и зависимости, задаёт вопросы и создаёт/обновляет раздел задачи. Игровой код на этом этапе не меняется.
- DeepSeek (реализация) читает
AGENTS.md, Skill и раздел задачи, сверяет план с текущим кодом, реализует, проверяет и обновляет статусы. - Передача — только через файлы репозитория и Git. Память модели и чат не считаются общим контекстом.
- Если план устарел или требования изменились, реализация останавливает зависимую часть, фиксирует причину и при необходимости возвращает задачу на анализ.
- Нельзя удалять чужие задачи, невыполненные пункты и историю статусов.
Подробный процесс — docs/Development/AGENT-WORKFLOW.md.
Статусы
[ ]— не выполнено;[x]— выполнено и подтверждено доступными проверками;[!]— заблокировано или ждёт решения;[-]— больше не требуется после согласованного изменения плана.
Для каждого пункта храни отдельно:
- Реализация: выполнена / не выполнена / не требуется.
- Проверка: выполнена (что именно) / не выполнена (почему).
[x] нельзя ставить, если реализация есть, а проверка не запускалась.
Журнал задач
| ID | Статус | Название | Фаза | Проверка |
|---|---|---|---|---|
| TASK-2026-001 | [!] |
Плавность карточных перемещений и корректные источники | DeepSeek: анализ; реализация выполнена, ждёт ручной проверки C10 | EditMode 46/46; ручная — пользователь |
| TASK-2026-019 | [ ] |
Загрузочная сцена и кадр без покадровых аллокаций | DeepSeek: план готов; реализация ожидает | не выполнена |
| TASK-2026-020 | [x] |
Парсер карт и артов с официального сайта | DeepSeek: анализ и реализация | идемпотентность 0 diff; validate не запускался |
| TASK-2026-021 | [!] |
Login по референсу: 2D-арт и неоновый UI | DeepSeek: C1–C9, Tab/Enter/Esc; ждёт приёмки | EditMode 60/60; SCENE_SMOKE success=True; standalone собран; ручная — пользователь |
| TASK-2026-022 | [!] |
Lobby по референсу: дашборд, заглушки, сцена Community | DeepSeek: C1–C11 реализованы; ждёт ручной приёмки | EditMode 62/62; SCENE_SMOKE, PLAYMAT_SMOKE, standalone; ручная — пользователь |
| TASK-2026-023 | [!] |
DeckBuilder: один экран, мультифильтры и список колоды | DeepSeek: C1–C11 реализованы; ждёт ручной приёмки | EditMode 67/67; SCENE_SMOKE, PLAYMAT_SMOKE; ручная — пользователь |
| TASK-2026-024 | [!] |
DeckBuilder по референсу: топбар Lobby, крупные карты, фильтры | DeepSeek: C1–C10 реализованы; ждёт ручной приёмки | EditMode 69/69; SCENE_SMOKE, PLAYMAT_SMOKE; ручная — пользователь |
Новые задачи добавляются в конец файла отдельными разделами. Не используй один раздел для нескольких независимых задач.
Шаблон задачи (не является активной задачей)
TASK-YYYY-NNN — краткое название
- Статус:
[ ] - Создано: YYYY-MM-DD
- Анализ: DeepSeek
- Реализация: DeepSeek
- Затронутые системы: ...
A. Цель и требования
- Что просит пользователь.
- Ожидаемое поведение.
- Обязательные правила Skill.
- Ограничения, которые нельзя нарушать.
- Критерии готовности.
B. Текущее состояние
- Как работает сейчас.
- Какие системы и файлы проверены.
- Существующие механики, которые нужно сохранить.
- Подтверждённые факты и открытые вопросы.
C. Чек-лист изменений
Каждый пункт:
[ ]MODIFY/CREATE/DELETE/TEST/VERIFY- путь к файлу (если известен);
- класс/метод (если существует);
- конкретная логика;
- причина изменения;
- ожидаемый результат;
- зависимости от других пунктов;
- Реализация: не выполнена;
- Проверка: не выполнена.
Пример формата:
- [ ] MODIFY `client/Assets/.../BattleView.cs` — `BattleView.SomeMethod`
Логика: ...
Причина: ...
Результат: ...
Зависит от: ...
Реализация: не выполнена
Проверка: не выполнена
D. Последовательность выполнения
Нумерованный порядок с обязательными зависимостями. Разделяй работу по системам на небольшие шаги.
E. Проверки
- Какие тесты/команды доступны и подтверждены проектом.
- Какие механики проверить на регрессию.
- Критерии готовности.
- Что остаётся на ручную проверку пользователя.
F. Риски и неизвестные вопросы
- Противоречия и побочные эффекты.
- Вопросы, требующие ответа пользователя.
- Что нельзя реализовывать до ответа.
G. Результат
- Реализовано: ...
- Проверки: ...
- Не завершено/заблокировано: ...
- Skill обновлён: да/нет, почему.
- Git: commit hash, изменённые файлы.
TASK-2026-001 — Плавность карточных перемещений и корректные источники
- Статус:
[!] - Создано: 2026-10-24
- Анализ: DeepSeek выполнен
- Реализация: Kimi выполнена
- Проверка: автотесты 46/46; ручная C10 — пользователь
- Затронутые системы:
GameBoard3D,Card3D,CardMoveAnimator,BattleView,AnimationConfig, EditMode-тесты.
A. Цель и требования
Пользователь сообщил: анимации движения карт «отрабатывают рвано», запускаются ненужные анимации, карты двигаются не из нужных позиций. Нужно исправить именно презентационный слой, не меняя правила игры.
Ожидаемое поведение:
- анимация запускается только при реальном переходе карты между зонами/слотами или при изменении позы, а не при каждом UI-рендере;
- источник анимации — фактическая старая зона/поза карты (рука, поле, Trigger, Damage, Drop, Soul, Guardian, Deck), а не всегда колода;
- рубашка/лицо источника учитываются: карта из колоды начинает движение рубашкой вверх, а не лицом;
- повторный снапшот или локальный
Renderне создаёт второй запрос на ту же карту и не откатывает её в середину пути; - скрытые карты (рука противника, закрытый урон) не пересоздаются и не летят
из колоды на каждом
Render; - существующие правила, серверные контракты,
InputLockService, пул карт и публичные визуальные эффекты не ломаются.
Ограничения:
- не менять
GameEngine, правила, сервер, протокол и YAML-контент; - не добавлять DOTween/UniTask/новые пакеты;
- не менять сцены/префабы без отдельного решения;
- не переписывать
CardMoveAnimatorна другой animation stack; - геймплей вручную проверяет пользователь; автотесты показывают только техническую корректность.
B. Текущее состояние и найденные причины
Проверены:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs;client/Assets/Vanguard/Runtime/Board3D/Animation/CardMoveAnimator.cs;client/Assets/Vanguard/Runtime/Board3D/View/Card3D.cs;client/Assets/Vanguard/Runtime/Board3D/Data/BoardTypes.cs;client/Assets/Vanguard/Runtime/Board3D/Logic/PlaymatLayout.cs;client/Assets/Vanguard/Runtime/UI/BattleView.cs;client/Assets/Vanguard/Runtime/Battle/AnimationConfig.cs;client/Assets/Vanguard/Resources/AnimationConfig.asset;client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs.
Факты:
- Скрытые карты с
InstanceId = 0пересоздаются. ВGameBoard3D.AddOpponentHandSpecs(OH:player:i) иGameBoard3D.AddDamageSpecs(D:player:i) для скрытых картBoardCardRef.InstanceIdравен0. ВGameBoard3D.Renderраспределение старых карт идёт только черезpreviousByInstanceи условиеspec.Ref.InstanceId != 0. Поэтому при каждомRenderтакие карты арендуются заново, старые освобождаются, а новые получаютmoved = trueи анимацию изSourcePose. BattleView.Render()вызывается не только на снапшот. Локальные действия (выбор guard, меню карты, подтверждение, статус) тоже вызываютBattleView.Render→GameBoard3D.Render. В сочетании с п.1 это даёт «ненужные анимации» на каждый клик.SourcePoseвсегда использует колоду. МетодGameBoard3D.SourcePoseвозвращает_layout.DeckPosition(localSeat)и базовый yaw без состояния лица. Новая карта, пришедшая из Soul, Drop, Guardian, Trigger или Damage, начинает полёт из колоды; карта из колоды начинает путь лицом вверх, хотя должна быть рубашкой вверх.- У Damage ключ по индексу, а не по личности.
D:player:iостаётся тем же при смене открытой карты или при открытии закрытой. Текущий branchsameInstanceосвобождает старую карту и создаёт новую сSourcePose(колода), хотя это может быть переворот/смена карты на месте. - Нет coalescing в
CardMoveAnimator.Enqueueне отменяет старый queued/active request той жеCard3D. Если карта успевает сменить зону до старта предыдущего запроса, второй запрос может стартовать из устаревшей позиции; активная запись при этом может остаться в_active. Card3D.SetPoseне является точкой начала движения. Для существующей картыRenderвызываетSetPose(меняет target), затемEnqueue; для новой картыPlaceImmediate+SetPose. При повторномRendertarget может быть обновлён до/после старта, а старый arc не всегда согласован с новым request.- Конфиг анимаций не синхронизирован с кодом. В
AnimationConfig.assetнет новых полейmoveDuration,importantMoveDuration,moveDelayBetweenCards,arcHeight, camera/arrow полей, хотя они объявлены вAnimationConfig.cs. Нужно проверить фактические значения после импорта Unity; нельзя считать asset настроенным, пока поля не сериализованы. UpdateHandViewкаждый кадр делаетSetPoseдля руки. Это может перетирать target во время движения карты в руку и мешать стабильности arc; нужно проверить и, если подтверждено, не менять target у карты, которая уже летит, либо синхронизировать target с move request.- Пул карт и
InputLockуже имеют защиту (CancelCard, таймаут,CancelAll); её нельзя удалять. Исправления должны сохранить отсутствие вечногоcard-move-лока.
Что сохранить:
GameBoard3Dкак единственный рендер-дифф и владелец пула;CardMoveAnimatorкак единый планировщик;Card3Dкак визуальную карту и arc-интерполяцию;InputLockServiceи существующие long-running последовательности;- серверный snapshot как источник состояния.
C. Чек-лист изменений
-
C1.
MODIFYGameBoard3D.Render— стабильная идентичность анонимных карт.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs. - Добавлена ветка reuse-by-key до поиска по
InstanceId. - Переиспользуется
Card3Dпоspec.Key, если старая/новая карта анонимна или совпадают реальныеInstanceId; иначе используетсяpreviousByInstanceилиRentCard. - При смене
0→realв том же слоте карта сохраняется и обновляетсяBind/SetArt/SetPoseбез анимации. - Карты с исчезнувшими ключами освобождаются через
ReleaseCard. - Реализация: выполнена.
- Проверка:
Repeated_Render_Reuses_Hidden_Cards_And_Does_Not_Enqueue_Moves,Revealing_Face_Down_Damage_Reuses_Card_And_Stays_In_Damage_Zone— проходят. - Зависит от: C2, C4.
- Файл:
-
C2.
MODIFYGameBoard3D.AddOpponentHandSpecs/AddDamageSpecs— стабильные ключи и явная политика анимации.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs. - Ключи
OH:player:iиD:player:iоставлены;InstanceId=0не считается личностью. - Скрытые карты при стабильном ключе не анимируются; новая скрытая карта в конце анимируется из Deck.
- Для урона: смена
0↔realилиreal→realв том же слоте обрабатывается reuse-by-key, а не полётом из Deck. - Реализация: выполнена.
- Проверка: см. C1 +
Board_Renders_Field_Hand_Guardian_Damage_And_Soul. - Зависит от: C1.
- Файл:
-
C3.
MODIFYGameBoard3D— карта источника из предыдущегоMatchView.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs. - Сохраняются
_previousViewи_sourceByInstanceдо замены_view. - Построен
Dictionary<int, CardSourcePose>дляSoul,Drop,FaceUpDamage; источникиHand/Guardian/Trigger/Fieldпокрываются существующимиCard3DчерезpreviousByInstance. ResolveSourcePose(spec): приоритет —Card3D(transfer), затем зона из_sourceByInstance, затемDeckPositionс рубашкой вверх.- Источники:
- Deck:
DeckPosition, рубашка вверх (baseYaw * X-flip 180°); - Soul:
SoulPosition, лицом вверх; - Drop:
DropPosition, лицом вверх; - FaceUpDamage:
DamagePosition, лицом вверх и на боку; - Hand/Guardian/Trigger/Field — через
previousByInstance/transfer.
- Deck:
- Fallback Deck используется только с комментарием и покрывается тестами.
PlaceImmediateполучает rotation с учётом flip.- Реализация: выполнена.
- Проверка:
New_Field_Unit_Starts_From_Hand_Not_Deck— проходит. - Зависит от: C1, C2.
- Файл:
-
C4.
MODIFYCardMoveAnimator.Enqueue— один активный/queued request на карту.- Файл:
client/Assets/Vanguard/Runtime/Board3D/Animation/CardMoveAnimator.cs. - В начале
EnqueueвызываетсяCancelCard(card), что удаляет queued/ active request этой же карты, не трогая другие. - Источник (
from*) передаётся изGameBoard3Dкак текущая визуальная позиция карты; target проверяется вCard3D.StartArcMove. CancelCard,CancelAll, timeout и снятиеcard-move-лока сохранены.- Реализация: выполнена.
- Проверка:
CardMoveAnimator_Coalesces_Requests_For_Same_Card,CardMoveAnimator_Releases_Input_Lock_When_Card_Is_Cancelled— проходят. - Зависит от: C1.
- Файл:
-
C5.
MODIFYGameBoard3D.Render+BattleView.Render— явно различать snapshot-рендер и локальный UI-рендер.- Файлы:
GameBoard3D.cs,client/Assets/Vanguard/Runtime/UI/BattleView.cs. GameBoard3D.Renderполучил параметрbool animateMoves = trueбез изменения DTO.BattleView.Render(bool animateMoves = true);OnSnapshotвызываетRender()(true); все локальные вызовы заменены наRender(animateMoves: false).- При
animateMoves: falsemove-анимации не запускаются; идентичность карт не меняется. Появление реально новой карты логирует warning. - Реализация: выполнена.
- Проверка:
Repeated_Render_Reuses_Hidden_Cards_And_Does_Not_Enqueue_Moves,ClientSmokeTests.Battle_Renders_3D_Damage_And_Rested_Cards— проходят. - Зависит от: C1, C2.
- Файлы:
-
C6.
MODIFYGameBoard3D.UpdateHandView— не перетирать движение руки.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs. - В
UpdateHandViewдобавлено условие: пропускать карту, еслиcard.IsMoving, чтобыSetPoseне менял target во время arc-перехода. GetHandViewPoseи привязка руки к камере не изменены.- Реализация: выполнена.
- Проверка:
Hand_Is_Anchored_To_Camera_Bottom_Center_And_Faces_Player,New_Field_Unit_Starts_From_Hand_Not_Deck— проходят. - Зависит от: C3, C4.
- Файл:
-
C7.
MODIFYAnimationConfig.asset+ проверка значений.- Файл:
client/Assets/Vanguard/Resources/AnimationConfig.asset. - Добавлены/сериализованы все поля из
AnimationConfig.cs:moveDuration: 0.5,importantMoveDuration: 0.9,moveDelayBetweenCards: 0.18,arcHeight: 0.45,cameraZoomDuration: 0.35,triggerRevealHold: 1.2,cameraReturnDuration: 0.4,cameraRezoomDuration: 0.3,growDuration: 0.35,dashScrollSpeed: 1.5,boostGrowDuration: 0.3,boostThickness: 0.8,arrowFadeDuration: 0.2. - Длительности feedback не менялись.
- Реализация: выполнена.
- Проверка:
CardOverlayTests.Animation_Config_Asset_Is_Loaded_From_Resources, полеarcHeightчитается вGameBoard3D.Render— проходят. - Зависит от: C5 (можно параллельно).
- Файл:
-
C8.
TESTGameBoard3DTests— регрессии анимаций.- Файл:
client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs. - Добавлены тесты:
Repeated_Render_Reuses_Hidden_Cards_And_Does_Not_Enqueue_Moves;Revealing_Face_Down_Damage_Reuses_Card_And_Stays_In_Damage_Zone;New_Field_Unit_Starts_From_Hand_Not_Deck;CardMoveAnimator_Coalesces_Requests_For_Same_Card.
- В
CardMoveAnimatorдобавлены read-only seam-свойства:PendingCount,ActiveCount,IsCardQueued,IsCardActive. - Исправлен
ClientSmokeTests.Battle_Renders_3D_Damage_And_Rested_Cardsдля вызоваRenderс новой сигнатурой через reflection. - Реализация: выполнена.
- Проверка: все новые тесты + старые — 46/46.
- Зависит от: C1–C6.
- Файл:
-
C9.
VERIFYsmoke / compile / EditMode.- Скопирован проект без
Library;Unity 6000.6.6f1 -batchmode -nographics -runTests -testPlatform EditMode. - EditMode: 46/46 passed (включая 15
GameBoard3DTests, 12ClientSmokeTests, 6CardOverlayTests, 12PlaymatLayoutTests, 1 Addressables stub). PLAYMAT_SMOKE success=True board=True cards=25 hand=5/5 fieldVisible=True.SCENE_SMOKE success=True active=Login env=True login=True.- Ошибок компиляции нет; warning CS8632 в
ClientSmokeTests— pre-existing. - Реализация: выполнена.
- Проверка: выполнена.
- Зависит от: C1–C8.
- Скопирован проект без
-
C10.
VERIFYручная проверка пользователем.- Пользователь проверяет: draw, call, ride, move/swap, guard, trigger, drive/damage, retire, search, открытие скрытого урона, руку противника, повторные клики по UI во время/после анимации.
- Ожидаемо: нет полёта скрытых карт из колоды при каждом клике; источник совпадает с зоной; нет рывков/двойных стартов; ввод не зависает.
- Реализация: не применима.
- Проверка: остаётся на пользователе.
- Зависит от: C9.
D. Последовательность выполнения
- C1 + C2: стабилизировать идентичность/ключи, убрать пересоздание скрытых карт. Без этого остальные исправления будут маскировать симптом.
- C3: добавить source map и корректные source pose/face. Проверить Deck, Hand, Trigger, Damage, Soul/Drop/Guardian.
- C4: coalescing в аниматоре и отмена старого request.
- C5: разделить snapshot/UI-рендер, убрать лишние запуски.
- C6: проверить hand target; не менять без подтверждённой необходимости.
- C7: синхронизировать asset.
- C8: тесты; C9: проверки; C10: ручная проверка пользователя.
E. Проверки
- Client EditMode:
GameBoard3DTests+ новые тесты из C8. - Compile/Assembly: Unity batch mode в копии без
Library. - Smoke:
Vanguard.Editor.SceneSmoke.RunPlaymat;Runтолько при изменении сцен/сборки. git diff --check, просмотрgit diff, отсутствие изменений в Rules/Server/Shared/Content.- Повторный
Renderс неизменным view: число карт и move-request не растёт. - Повторный snapshot во время движения: нет двойного старта/сброса в источник.
- Ручная проверка — пользователем; не заменять её автотестом.
Команды (подтверждены проектом):
# клиентская копия без Library
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
-batchmode -nographics -projectPath <copy> `
-runTests -testPlatform EditMode -testResults <copy>\TestResults.xml
Серверные тесты не требуются, если не меняются Rules/Server/Shared; при
изменении контрактов — только ssh home/Docker.
F. Риски и неизвестные вопросы
- Анонимные карты:
InstanceId=0не является уникальной личностью; нельзя использовать его для глобального map. Нужны стабильные ключи по зоне/индексу и отдельная политика для reveal. - Источник вне видимых зон: Deck не содержит
InstanceId; для карты из колоды источник всегда Deck. Для карты из Soul/Drop/Guardian/Trigger/Damage источник можно восстановить из previous view; иначе fallback Deck. - Смена открытого урона: при перестановке face-up damage возможна неоднозначность. Не анимировать перемещение между слотами урона, если это не подтверждено; приоритет — не «телепорт из колоды».
AnimationConfig.asset: после добавления полей Unity может сохранить старые значения; проверить Inspector, не считать defaults автоматически настроенными.UpdateHandView: если менять target каждый кадр, можно ухудшить плавность; C6 требует подтверждения тестом/наблюдением, а не слепой правки.- Не менять
CardMoveAnimatortimeout/CancelCard/CancelAllбез сохранения защиты от зависшегоInputLock. - Не расширять задачу на рефакторинг
BattleViewили замену animation stack.
G. Результат
- Реализовано: C1–C8 (см. чек-лист).
- Проверки: EditMode 46/46 в копии без
Library; компиляция без ошибок. - Не завершено/заблокировано: C10 — ручная проверка пользователем.
- Skill обновлён: не требуется; изменения технические, не затрагивают подтверждённые правила/архитектуру.
- Git: будут изменены
GameBoard3D.cs,CardMoveAnimator.cs,BattleView.cs,AnimationConfig.asset,GameBoard3DTests.cs,ClientSmokeTests.cs,IMPLEMENTATION_PLAN.md,docs/SESSION-STATE.md,docs/HANDOFF.md.
TASK-2026-002 — Боевой UX и правила после TASK-2026-001
- Статус:
[ ] - Создано: 2026-10-24
- Анализ: DeepSeek выполнен, код не менялся
- Реализация: не начата
- Проверка: не выполнена
- Затронутые системы:
Card3D,CardMoveAnimator,GameBoard3D,BattleView,AnimationConfig,TriggerCheckSequence,CameraDirector,Vanguard.Rules(Tejas, Perfect Guard), тесты.
A. Цель и требования
Исправить семь замечаний после первого блока анимаций:
- При взятии карты из колоды она не должна сначала появляться в руке, затем исчезать и только потом лететь по дуге.
- При размещении карты из руки не должно быть двойного визуального размещения: сначала в поле, затем исчезновение и дуга.
- При призыве из души не должно быть отдельного перемещения перед дугой.
- Tejas должен атаковать задний ряд только в колонке, расположенной напротив его колонки, а не в зеркально противоположной.
- Perfect Guard: сначала поместить карты в защиту, затем проверить способности и активировать их; текущая логика оплаты/отмены должна быть приведена к этому порядку.
- После атаки, drive check, trigger-зоны, урона и других боевых событий нужны паузы около 1.5 с; анимации должны быть длиннее.
- При фокусе камеры на trigger-зону скрывать руку; после возврата камеры возвращать руку.
Ограничения:
- не менять серверные контракты без необходимости; при изменении протокола
пересобрать
Vanguard.Shared.dll; - серверные тесты запускать только на
ssh home/Docker; - не менять сцены/префабы без отдельного решения;
- геймплей вручную проверяет пользователь.
B. Анализ причин
- Предварительное smooth-движение queued-карт.
CardMoveAnimatorставит запросы в очередь со stagger. Пока запрос ждёт в_queue,Card3D.Tickуже выполняет обычное экспоненциальное движение к_targetPosition. КогдаStartNextвызываетStartArcMove, карта возвращается вFromPositionи начинает дугу. Визуально это выглядит как «сначала переместилась, потом исчезла, потом дуга». Это объясняет п.1 и п.3, а также часть п.2 при нескольких перемещениях. - Локальный
DropAtдо снапшота.GameBoard3D.FinishDragвызываетcard.DropAt(target)сразу после отпускания мыши. Карта визуально встаёт в поле, затем авторитарный снапшот делаетPlaceImmediate(hand/soul)и запускает дугу. Это отдельная причина п.2, не связанная с очередью. - Tejas:
SameColumnиспользуется и для Move, и для Attack. ВGameEngine.SameColumnзашито0↔3,2↔4,-1↔1. Для перемещения внутри своего поля это верно. Для атаки по противнику это неверно: клиент зеркалит половину противника (PlaymatLayout.CirclePosition), поэтому атака из слота 3 должна попадать в слот 2, из 4 — в 0, из V — в 1. Текущий тестTejas_Attacks_Back_Row_In_Its_Columnзакрепляет неверную пару3→0, его нужно исправить вместе с правилом. - Perfect Guard сейчас — одна команда.
GuardIntentсодержит и карту защиты, иDiscardPrintingId;GameEngine.Guardсразу добавляет карту в Guardian, сбрасывает карту оплаты и ставитbattle.Nullified. Отдельной стадии «карты уже в защите → проверить/активировать способности» нет. ТестыPerfect_Guard_*описывают упрощённую модель. - Задержки не образуют боевой такт. Длительности feedback уже есть в
AnimationConfig(attackDeclare,driveCheck,trigger,damageи др.), но текст события и движение карт идут разными путями:OnEventsставит feedback в очередь, аRequestSnapshotAsyncотдельно запускаетCardMoveAnimator. Нет явной паузы после боевого события и нет гарантии, что движение карты завершилось до следующего события. Движение карт (moveDuration = 0.5,importantMoveDuration = 0.9) короче, чем нужно пользователю. - Рука следует за камерой.
TriggerCheckSequenceдвигаетCameraDirector, но не сообщаетGameBoard3Dо фокусе.UpdateHandViewкаждый кадр привязывает руку к камере, поэтому при зуме на trigger-зону рука оказывается перед камерой.
C. Чек-лист изменений
-
D1.
MODIFYCard3D— hold-at-source для queued-перемещений.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/Card3D.cs. - Добавить состояние «ожидает arc» и метод
HoldAtSource(position, rotation, scale). - Пока карта ожидает
StartArcMove,Tickне должен выполнять smooth interpolation к target; карта остаётся в source pose. StartArcMoveснимает hold и запускает дугу изFromPosition.StopMove/CancelHoldснимают hold; если запрос отменён, карта может продолжить обычное smooth-движение к актуальному target.- Реализация: не начата.
- Проверка: новый EditMode-тест «вторая карта в очереди не двигается до старта arc».
- Зависит от: D2.
- Файл:
-
D2.
MODIFYGameBoard3D.Render— ставить карту на hold до Enqueue.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs. - После
PlaceImmediateдля перемещаемой карты вызыватьHoldAtSource(source); target остаётся финальной позой изSetPose. - При
animateMoves: false,ReleaseCard,Clear,CancelAllhold снимать, чтобы карта не зависла в источнике. - Убедиться, что
UpdateHandViewне снимает hold и не двигает карту до старта arc. - Реализация: не начата.
- Проверка: тесты D1 + smoke; визуально одна дуга без предварительного перемещения.
- Зависит от: D1.
- Файл:
-
D3.
MODIFYdrag-and-drop — убрать двойное размещение.- Файл:
client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs,client/Assets/Vanguard/Runtime/UI/BattleView.cs. - Решение пользователя: вариант A — после отпускания мыши не вызывать
DropAtдля server-authoritative перемещения. - Оставить карту в source (или показать временный ghost/индикатор цели), а после снапшота один раз анимировать из source в target.
- Ошибка/отказ сервера возвращает карту в source без второй анимации.
- Реализация: не начата.
- Проверка: call из руки и move/swap не показывают «поставилась → исчезла → дуга».
- Зависит от: D1–D2.
- Файл:
-
D4.
TESTклиентские регрессии перемещения.- Файл:
client/Assets/Vanguard/Tests/Editor/GameBoard3DTests.cs. - Добавить тесты:
- вторая карта в очереди не двигается до
StartArcMove; - отмена queued-запроса не оставляет карту в hold;
Removing_Card_From_Hand...и существующие тесты не ломаются;- повторный рендер после drag-drop не создаёт второй arc-запрос.
- вторая карта в очереди не двигается до
- Реализация: не начата.
- Проверка: EditMode в копии без
Library. - Зависит от: D1–D3.
- Файл:
-
D5.
MODIFYVanguard.Rules— колонка Tejas через границу игроков.- Файлы:
server/src/Vanguard.Rules/Engine/GameEngine.cs,server/tests/Vanguard.Rules.Tests/GameEngineTests.cs. - Оставить
SameColumnдля перемещений внутри поля. - Добавить
SameColumnAcrossPlayers(attackerSlot, defenderSlot):3↔2,4↔0,-1↔1— подтверждено пользователем. - Использовать новую функцию в
LegalCommandsдляAttackCommandи вAttackпри проверкеtargetSlot is 0/1/2. - Исправить тест
Tejas_Attacks_Back_Row_In_Its_Column: атакующий 3 → защитник 2; добавить 4→0, V→1 и негативный тест на противоположную колонку. - Проверить, что клиентские
LegalIntentsи подсветка цели не требуют изменений: сервер начнёт присылать правильныйTargetSlot. - Реализация: не начата.
- Проверка: серверные тесты на
ssh home/Docker. - Зависит от: нет.
- Файлы:
-
D6.
MODIFYPerfect Guard — стадийная защита и полная модель.- Файлы:
server/src/Vanguard.Rules/Engine/GameEngine.cs,server/src/Vanguard.Shared/Protocol/Intents.cs,client/Assets/Vanguard/Runtime/UI/BattleView.cs, тесты. - Решение пользователя: полная модель, оплата спрашивается после размещения всех карт защиты.
- Целевой порядок:
- игрок выбирает и помещает карты защиты в Guardian (включая Sentinel, пока без оплаты);
- после размещения сервер проверяет способности карт защиты;
- для Sentinel открывается pending ability «оплатить сброс карты того же клана»;
- при активации — сброс, выбор атакованного юнита, который не может быть поражён до конца боя; при отказе — щит 0, атака проходит.
- Текущее упрощение
battle.Nullified = trueзаменить на корректную модель «защищённый юнит не может быть поражён» (поле боя/флаг protected unit), если она не эквивалентна текущемуNullifiedв рамках одного защищающегося. GuardIntent.DiscardPrintingIdбольше не должен быть обязательной частью размещения; оплата идёт отдельным guard-ability intent (ResolveAbilityIntent/новый тип). При изменении протокола пересобратьVanguard.Shared.dllи обновить replay codec.- Обновить
Perfect_Guard_*тесты: размещение без оплаты → pending ability → оплата/отказ; добавить тест «сначала все карты, потом оплата». - Реализация: не начата.
- Проверка: серверные тесты на
ssh home/Docker; ручная проверка пользователем. - Зависит от: D5 (общий серверный блок можно делать параллельно).
- Файлы:
-
D7.
MODIFYAnimationConfig+ боевой такт.- Файлы:
client/Assets/Vanguard/Runtime/Battle/AnimationConfig.cs,client/Assets/Vanguard/Resources/AnimationConfig.asset,client/Assets/Vanguard/Runtime/UI/BattleView.cs. - Решение пользователя: паузы 1.5 с после атаки, drive check, trigger-зоны, урона и других боевых событий.
- Добавить
eventPause = 1.5,postDrivePause = 1.5,postTriggerPause = 1.5,postDamagePause = 1.5. - Увеличить движение:
moveDuration = 0.8,importantMoveDuration = 1.3,moveDelayBetweenCards = 0.22,triggerRevealHold = 1.5,cameraZoomDuration/cameraReturnDuration= 0.5. - Связать feedback и завершение
CardMoveAnimator: не отпускатьfeedback/boardlock и не начинать следующий такт, пока не истекла пауза и не завершились карточные перемещения. - Сохранить кнопку «Пропустить анимации» и корректное снятие всех lock.
- Реализация: не начата.
- Проверка: smoke + визуальная проверка пользователем.
- Зависит от: D1–D2.
- Файлы:
-
D8.
MODIFYtrigger-камера и рука.- Файлы:
client/Assets/Vanguard/Runtime/Battle/TriggerCheckSequence.cs,client/Assets/Vanguard/Runtime/UI/BattleView.cs,client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs. - Добавить в
TriggerCheckSequenceсобытиеFocusChanged(bool):trueпри первомShowTrigger,falseпри возврате камеры в Idle,EndChain/Cancel. - В
BattleViewподписаться и вызыватьGameBoard3D.SetHandVisible(!focused). - Решение пользователя: скрывать руку только на trigger-зуме.
- В
GameBoard3Dдобавить_handVisibleи методSetHandVisible(bool): скрывать/показывать только свою руку;UpdateHandViewиRenderне должны возвращать скрытые карты. - Восстанавливать руку при
Clear, reconnect, завершении боя и отмене цепочки. - Реализация: не начата.
- Проверка: EditMode-тест hide/show + ручная проверка trigger.
- Зависит от: D7 (общая цепочка такта).
- Файлы:
-
D9.
VERIFYсборка и проверки.- Клиент: EditMode в копии без
Library,PLAYMAT_SMOKE,SCENE_SMOKE, компиляция. - Сервер (только при D5/D6): тесты правил и серверные на
ssh home,validate, при изменении текста карт —translations check. - Проверить, что изменения в
Vanguard.Rules/Vanguard.Sharedне затрагивают клиентскуюVanguard.Shared.dllбез пересборки. - Реализация: не начата.
- Проверка: после реализации.
- Зависит от: D1–D8.
- Клиент: EditMode в копии без
-
D10.
VERIFYручная проверка пользователем.- draw, call из руки, call из души, ride, move/swap, guard, Perfect Guard (оплата/отказ), trigger, drive/damage, retire, Tejas слева/справа/центр, скрытие/возврат руки при trigger-камере.
- Ожидаемо: одна дуга без предварительного перемещения; Tejas бьёт визуально в свою колонку; Perfect Guard сначала размещает карты, затем спрашивает способность; паузы ~1.5 с; рука не мешает trigger-зуму.
- Реализация: не применима.
- Проверка: только пользователь.
- Зависит от: D9.
D. Последовательность выполнения
- D1–D2: hold-at-source, убрать предварительное smooth-движение. Это устраняет основную причину п.1 и п.3.
- D3–D4: drag-and-drop и тесты; проверить п.2.
- D5: Tejas (отдельный серверный блок, можно параллельно).
- D6: Perfect Guard — полная модель и стадийная оплата после размещения.
- D7–D8: длительности, боевой такт, рука и trigger-камера.
- D9–D10: проверки и ручная приёмка.
E. Проверки
- Клиент: EditMode (в копии без
Library),PLAYMAT_SMOKE,SCENE_SMOKE, компиляция без ошибок. - Сервер:
Vanguard.Rules.Tests,Vanguard.Server.Testsнаssh home;validate;translations checkтолько при изменении текста карт. - Регрессии: draw, call из руки/души, move/swap, guard, trigger, damage, Tejas, Perfect Guard.
git diff --check; не должно быть случайных изменений сцен/префабов.
F. Решения и риски
Зафиксировано пользователем:
- Drag-and-drop: вариант A — не ставить карту локально, одна дуга после снапшота.
- Perfect Guard: полная модель; оплата спрашивается после размещения всех карт защиты.
- Tejas: колонки
3↔2,4↔0,V↔1. - Длительности: паузы 1.5 с;
moveDuration = 0.8,importantMoveDuration = 1.3. - Рука: скрывать только на trigger-зуме.
Технические риски:
- Протокол Perfect Guard: изменение
GuardIntent/GuardCommandможет потребовать пересборкиVanguard.Shared.dll, обновления replay codec и клиентскогоBattleView. Делать одним согласованным блоком. - Полная модель Perfect Guard: может понадобиться отдельное состояние
«защищённый юнит» и событие выбора юнита; текущий
battle.Nullifiedнельзя считать полной моделью. - Drag-and-drop вариант A: карта может визуально вернуться в source, пока ждёт снапшот. Нужен ghost/индикатор цели, чтобы это не выглядело как откат.
- Длинные анимации: паузы 1.5 с удерживают
feedback/boardlock; кнопка «Пропустить анимации» должна снимать все lock и не оставлять очередь. - Серверные проверки: Tejas и Perfect Guard затрагивают
Vanguard.Rules, тесты иvalidate— только наssh home/Docker. - Тест Tejas: текущий
Tejas_Attacks_Back_Row_In_Its_Columnзакрепляет неверную пару3↔0; при реализации он должен быть изменён.
Открытых вопросов, блокирующих старт, нет.
G. Результат
- Реализовано: D1–D8.
- Проверки: EditMode 50/50 в копии без
Library; компиляция клиента чистая. - Не проверено: D5/D6 — серверные тесты правил только на
ssh home; D10 — ручная проверка пользователем. - Примечание по D6: Perfect Guard реализован как отдельная
автоматическая способность Sentinel, срабатывающая после размещения
конкретной карты в Guardian. Полное откладывание способности до момента
«все карты защиты размещены» (до
PassGuard) потребует дополнительного серверного состояния; текущий вариант устраняет основную жалобу «сначала карта, потом способность». - Skill обновлён: после прохождения серверных тестов и ручной проверки
обновить
docs/game-rules.mdи Skill (Tejas, Perfect Guard).
TASK-2026-003 — Визуальный редизайн боевого HUD по мокапу
- Статус:
[ ] - Создано: 2026-10-25
- Анализ: DeepSeek выполнен, код не менялся
- Реализация: не начата
- Проверка: не выполнена
- Затронутые системы:
BattleView,ZoneBlockStripView,GameBoard3D,PlaymatLayoutConfig,BoardSlotView,BoardZoneView,Pile3D,Card3D,UiKit, локализация, EditMode/smoke.
A. Цель
Приблизить боевой экран к мокапу: тёмный неоновый 3D-стол, тонкий верхний HUD с номером хода и фазовой шкалой, компактные панели игроков, полноширинное поле без постоянной правой панели, крупная рука и понятные глобальные действия. Мокап — визуальный ориентир, а не замена принятым UX-правилам.
B. Что в мокапе уже совпадает с текущим клиентом
- 3D-стол с двумя зеркальными половинами, V по центру переднего ряда и R-кругами 3×2.
- Рука игрока веером снизу, рука противника — сверху.
- Колода и урон сбоку; у локального игрока урон слева, колода справа, у противника зеркально.
- Тёмная палитра, синие/красные акценты, разделительная линия по центру.
- Карты — 3D-объекты с артом, рубашкой, Rest и подсветкой.
- Часы и банк времени уже приходят с сервера (
ClockView), номер хода и фаза уже есть вMatchView.
C. Расхождения и необходимые доработки
-
V1. Убрать постоянную правую панель «Действия» и
PhasePanel.- Сейчас
IntentPanelшириной 456 px постоянно занимает правую часть экрана; мокап показывает поле на всю ширину. - Панель действий и
PhasePanelудалить из боевого HUD. - Все подтверждения перенести в правый нижний угол:
End Turn,В бой,Защищаться/Не защищаться,Закончить муллиган,Подтвердить оплату,Пропустить способностьи аналогичные контекстные подтверждения. - Нижняя панель показывает только доступные сейчас подтверждения; при отсутствии действий она пустая/скрыта, а не занимает место постоянно.
ActionPromptоставить неблокирующим информационным слоем.- Журнал, статус и отладочные сведения не входят в обычный HUD. Временная кнопка «Показать/скрыть панель» открывает только debug-панель; она скрыта по умолчанию. Это временное решение, не финальный HUD.
- Сейчас
-
V2. Верхний HUD: номер хода + фазовая шкала.
- Добавить
Turn Nи неинтерактивную шкалуStandby → Main → Battle → End(дляMulligan— отдельная подпись). - Источник:
MatchView.TurnNumber,MatchView.Phase,MatchView.Step. - Текущая фаза подсвечивается; пройденные — приглушены;
Guard/Drive/ Trigger/Ability/Choiceпоказывать как подпись текущего шага, не ломая шкалу фаз. - Локализовать через
Loc; не хардкодить английские строки.
- Добавить
-
V3. Верхний HUD: таймер и банк.
- Разделить на два визуальных блока:
00:00— время хода,Bank 03:52— банк. Сейчас они склеены в одну строку. - Оставить серверный источник времени и текущую логику
UpdateClock. - При остановленном таймере (
Clock.IsRunning == false) показывать—, не запускать локальный отсчёт.
- Разделить на два визуальных блока:
-
V4. Кнопки
Concedeи меню.Сдаться— компактная кнопка с иконкой флажка; подтверждение оставить.- Кнопку «Показать/скрыть панель» оставить временно; она открывает только debug-панель (журнал/статус/лог). Панель по умолчанию скрыта; кнопка не должна занимать место, когда панель не нужна.
- Если понадобится меню настроек/выхода — использовать отдельную компактную кнопку, не совмещённую с debug-панелью.
-
V5. Компактные панели игроков вместо двух рядов зон.
- Мокап:
Hand / Deck / Damage / Shield / Triggerв одной строке. - Сейчас
ZoneBlockStripViewпоказывает 7 зон в двух рядах, включаяDrop,Soul,Guardian. - Основная панель: 5 ключевых счётчиков. В баре игрока оставить доступ к
DropиSoul;Guardianв бар не добавлять — он показывается только в боевом контексте. Отдельную кнопку «Зоны» не вводить. - Содержимое зон не выкладывать на стол: по клику на
Drop/Soulв баре слева снизу (свой игрок) или справа сверху (противник) открывать оверлей соответствующей зоны. - Смотреть списком можно только
DropиSoul. СчётчикDeck— неинтерактивный, по клику ничего не открывает. Shieldпоказывать только в боевом контексте (текущийGuardShield), вне боя —0; не путать со статическим щитом карты.- Имя игрока и метка
ВЫ/ПРОТИВНИК— в заголовке панели.
- Мокап:
-
V6. Полноширинное поле и центральный баннер хода.
- После V1 пересчитать безопасные отступы камеры/поля под 16:9 и 21:9.
- Добавить центральный баннер
YOUR TURN · MAIN PHASE(world-space или screen-space,raycastTarget = false), скрывать его во время trigger-камеры и боевых оверлеев. - Баннер не должен перекрывать drag&drop и клики по кругам.
-
V7. Прямоугольные слоты вместо круглых рамок.
- Мокап: прямоугольные пластины с внутренней рамкой, лёгким свечением и
метками
R; V — акцентная пластина по центру. - Сейчас
BoardSlotViewиспользуетBoardMeshLibrary.Frame(рамка), что визуально читается как круг/контур. - Добавить меш прямоугольной пластины (или собрать из двух quads) и
сохранить существующий
BoxCollider/логику drop-таргетов. - Подсветка валидных целей и выбранных кругов должна работать как сейчас.
- Мокап: прямоугольные пластины с внутренней рамкой, лёгким свечением и
метками
-
V8. Зоны урона и колоды.
- Урон — красный вытянутый прямоугольник сбоку, как в мокапе; карты
остаются в текущих позициях
DamagePosition. - Над зоной урона — счётчик
x/6(например,0/6), у противника зеркально и ближе к центру. Счётчик не должен перекрывать карты урона. - Колода — стопка с читаемой рубашкой и счётчиком; счётчик
Deckнеинтерактивный, по клику ничего не открывает. Hover/подсветка стопки допустимы, но не должны выглядеть как кнопка. - Выровнять размеры и отступы зон урона/колоды для обеих половин.
- Урон — красный вытянутый прямоугольник сбоку, как в мокапе; карты
остаются в текущих позициях
-
V9. Карточный шаблон лица и статы под картой.
- Мокап показывает рамку, имя, силу/крит, иконку триггера и уровень.
Сейчас
Card3Dрисует арт и отдельныйTextMeshсо статами. - Добавить процедурный или prefab-шаблон лица: рамка по клану, полоса имени, иконка триггера, затемнение под текст.
- Счётчик силы и крита вынести под карту, а не на лицо: сила всегда,
крит — только если он больше 1. Перед числом использовать иконки
(сила/крит), не буквы
P/C. - Не менять
BoardArt/CardArtконтракт; шаблон — слой поверх арта. - Для закрытых карт — единая рубашка с логотипом Vanguard.
- Мокап показывает рамку, имя, силу/крит, иконку триггера и уровень.
Сейчас
-
V10. Свет, свечение и материал стола.
- Усилить неоновые направляющие, мягкое свечение слотов и краёв стола.
- Использовать существующие URP-материалы/эмиссию; не добавлять новые пакеты (DOTween/UniTask запрещены).
- Проверить, что bloom/тонмаппинг не ухудшает читаемость карт и текста.
-
V11. Анимации HUD и карт.
- Плавное появление/затухание фазового баннера, подсветка смены фазы, hover-подъём карт в руке, мягкое свечение выбранной карты.
- Не менять уже принятые
CardMoveAnimator/CameraDirectorтайминги без отдельного решения; новые эффекты не должны блокировать ввод.
-
V12. Локализация и доступность.
- Все новые подписи — через
Loc(RU/EN), включаяTurn, фазы,Bank,Shield,Hand,Deck,Damage,Trigger,Concede. - Использовать подготовленный русский текст способностей из
content/translations/ru.yaml(textRu) в карточном оверлее, списках зон и подсказках способностей; не показывать только EN. - При отсутствии
textRu— fallback на EN, ноtranslations checkдолжен проходить без пропусков. - Проверить 1920×1080, 16:10 и ultrawide; панели не должны перекрывать руку и кнопки.
- Контраст текста на тёмном фоне, размеры кнопок не меньше текущих.
- Все новые подписи — через
-
V13. Не копировать из мокапа буквально.
- Постоянные кнопки
Ride,Call,Guardв нижнем правом углу конфликтуют с правилом «выбор карты/круга — клик/драг по объекту, кнопки — только глобальные действия и подтверждения». - Принято: панель действий не возвращать. В правом нижнем углу — только
подтверждения (
End Turn,В бой, guard-pass/confirm, муллиган, оплата способности).Ride/Callостаются действиями из меню карты/ круга и не дублируются постоянными кнопками. Shieldв панели игрока не должен выглядеть как ещё один статический ресурс; показывать только актуальный боевой щит.
- Постоянные кнопки
-
V14. Техническая реализация без новых систем.
- Переиспользовать
BattleView,ZoneBlockStripView,UiKit,BoardSlotView,BoardZoneView,BoardMeshLibrary,Pile3D. - Новые визуальные элементы — небольшие view-компоненты/методы, без
дублирования
CombatStats,PhasePanelиIntentPanel. - Серверные контракты не менять:
TurnNumber,Phase,Clockуже есть. - Сцены/префабы менять только после отдельного решения; сначала code-generated вариант.
- Переиспользовать
-
V15. Сохранить drag&drop-сценарии как альтернативу клику.
- Прямой выбор карты кликом остаётся.
- Из руки в круг — призыв/смена (Call/Ride); перемещение по полю — RC↔RC в своей колонке.
- Во время атаки: перетащить карту заднего ряда на карту переднего ряда — это поддержка (Boost): карта поворачивается, показывается стрелка, сила пересчитывается. Затем карту переднего ряда можно перетащить на цель — атака.
- После объявления атаки проверяются способности поддержки и атакующей карты в порядке, определённом сервером; клиент не должен сам менять правила.
- Учесть уже сделанные исправления TASK-2026-002: не вызывать локальный
DropAt, не создавать вторую дугу, не ломатьInputLock. - Проверки: EditMode на drop-таргеты и порядок интентов; ручная проверка цепочки boost → attack.
-
V16. Зум на trigger-зону всегда, карты — после зума.
- При drive check и damage check камера всегда зумится на trigger-зону, даже если триггера нет.
- Карты помещаются в trigger-зону после окончания зума, а не до него.
- Если триггера нет — показать плашку «Без триггера» и вернуть камеру.
- Руку скрывать на время зума и возвращать после возврата камеры (сохранить поведение TASK-2026-002).
- Скоординировать
TriggerCheckSequence, снапшот и события так, чтобы карта не появлялась в trigger-зоне раньше камеры. - Проверки: ручная проверка drive/damage с триггером и без; отсутствие преждевременного появления карты.
-
V17. Триггеры: конкретные подписи действий при распределении.
- Сейчас при выборе цели пишется общее «выберите цель эффекта», а интенты называются «сила/эффект». Заменить на конкретные действия.
- Первый шаг (PowerTarget):
+5000/+5K— цель для силы. - Второй шаг (EffectTarget) по типу триггера:
Critical→Крит +1;Stand→Поднять юнита;Draw→Взять карту(без второго таргета);Heal→Лечить(выбор карты урона на сервере).
- Показывать действие в статусе/подсказке и, если возможно, меткой над валидными картами; не оставлять безликое «эффект».
- Учитывать, что
Critical/Standмогут выбирать силу и эффект на разные цели; клиент не должен сам объединять их без правила. - Локализовать подписи RU/EN; иконки — по возможности.
-
V18. Проверки.
- EditMode: маппинг фаз/шагов в подписи, счётчики панели,
Deckнеинтерактивен,Drop/Soulоткрывают списки, скрытие/раскрытие debug-панели, отсутствие raycast-перехвата у баннера, drop-таргеты и порядок boost → attack, подписи trigger-действий. - Smoke
SceneSmoke.RunиRunPlaymat; сборка standalone — на копии проекта безLibrary. - Ручная приёмка пользователем: 1920×1080, drag&drop, guard, trigger с триггером и без, боевые оверлеи, длинные имена/локали.
- EditMode: маппинг фаз/шагов в подписи, счётчики панели,
D. Порядок работ
- V1–V4: верхний HUD, временная кнопка панели, отказ от постоянной правой панели, подтверждения в правом нижнем углу.
- V5–V6: панели игроков, полноширинное поле, баннер хода.
- V7–V8: слоты, зоны урона/колоды, счётчик
x/6. - V9–V10: карточный шаблон, статы под картой, свет.
- V11–V12: анимации, локализация, русский текст способностей, адаптивность.
- V15–V16: drag&drop-сценарии и trigger-зум.
- V17: конкретные подписи trigger-действий.
- V13–V14, V18: UX-сверка, тесты, smoke, ручная приёмка.
E. Открытые вопросы
- [O] Временная кнопка «Показать/скрыть панель»: панель по умолчанию скрыта; когда её убирать — после стабилизации HUD.
- [O] Делать карточный шаблон процедурным или prefab-ассетом после появления финальных рамок?
- [O] Нужен ли фазовый баннер в world-space (на столе) или screen-space (поверх HUD)? Рекомендация — screen-space, чтобы не спорить с камерой.
F. Результат
- Реализовано: V1–V9, V12–V18.
- Частично: V10 — добавлены пластины слотов и рамки карт, без отдельного bloom-объёма; V11 — новых HUD-анимаций нет.
- Новые правки после мокапа: карты урона укладываются сверху вниз
(зеркально у противника), шаг
damageStackOffset = 0.3от ширины карты, новая карта приподнята по Y и рисуется поверх; trigger-карта повёрнута на 90° против часовой стрелки (локально-90°для себя,+90°для противника); на карте показывается бейдж триггера (имена убраны); no-trigger damage check определяется поDamageTakenViewс подавлением повторного зума после trigger-карты. - Правки по замечаниям: имена карт на поле убраны; панель действий
сжата до автоподстраиваемого столбца кнопок справа снизу (без заголовка,
фона и скролла); рука центрируется по экрану (
handViewportX = 0.5); подсказка муллигана перенесена в верхнийActionPrompt, при выборе карт показывается кнопка «Заменить N карт»; центральный баннер хода убран; левый нижний бар —Колода, Душа, Рука, Сброс, безЩит/Триг, все блоки одинаковые,Душа/Сброскликабельны. - Порядок триггера: камера всегда фокусируется на trigger-зоне;
после фокуса карта раскрывается анимацией (
triggerRevealDuration), затем паузаtriggerRevealHold = 0.75 с, затем резолв. Выбор цели открывается только после этой паузы. Сначала+5000на свою карту в RC/VC, затем эффект:Critical— RC/VC,Stand— только повёрнутый RC,Draw— автоматически,Heal— выбор карты урона при выполнении условий. Подсказки пишутся в верхнем информационном блоке. Нетриггерная карта просто пропускается. - Tejas: исправлена атака заднего ряда по колонке через границу
игроков:
V↔1,3↔2,4↔0. Сервер пересобран и задеплоен наssh home, контейнерserverперезапущен. - Основная фаза: в панели подтверждений остаётся только кнопка «Боевая фаза». «Закончить ход» и список всех действий скрыты; активация способностей — через меню карты.
- Рамки карт: собственная рамка карты — тонкая чёрная по её краю; подсветка выбора/цели тоже ужата до размера карты, больше не наезжает на соседние карты. В руке рамки скрыты, карты уложены широким веером: новая карта перекрывает предыдущую и за счёт шага по глубине всегда рисуется поверх неё. Своя рука заполняется слева направо: первая карта слева, новые добавляются правее и остаются поверх. Веер сохраняет ширину до 10 карт, а начиная с 11-й шаг плавно уменьшается. Рука противника — зеркальный камеро-зависимый веер ниже верхней панели: новая карта появляется слева и остаётся поверх предыдущей, наклон и порядок глубины зеркальны. Позы обеих рук пересчитываются каждый кадр под текущую камеру, поэтому добор не улетает к устаревшей цели.
- Стартовый Авангард: лежит закрытым во время муллигана; после
завершения муллиганов обоих игроков открывается с анимацией
(
vanguardRevealDuration = 0.8 с), затем начинается первая фаза. Переворот идёт вокруг длинной оси карты слева направо, у противника зеркально.MatchProjectionбольше не форсируетFaceUpдля Vanguard и передаёт реальное состояние карты; клиент блокирует ввод на время переворота. - Старт боя: камера стартует над стороной игрока лицом к столу, пауза 1,5 с; затем по дуге опускается на основную позицию, пауза 1,5 с; затем одновременно раздаются обе руки — своя и противника — с анимацией из колод. Панель муллигана появляется только после окончания всех доборов. Ввод заблокирован до конца интро.
- Взятие карт: карта создаётся ровно над колодой рубашкой вверх (рисунок рубашки ориентирован правильно) и летит в руку по дуге с переворотом лицом вверх. Любой добор идёт последовательно: следующая карта стартует только после завершения анимации предыдущей. В стартовой раздаче своя и чужая руки идут парами, внутри каждой пары — по одной.
- Урон: face-up/face-down переворот карт урона идёт вокруг длинной стороны карты, а не поперёк.
- Проверки: клиентские EditMode в копии без
Library— 50/50; серверныеVanguard.Rulesнаssh home— 155/155; standalone- сборка Windows — успешно; клиент запущен изclient/Builds/Windows/VanguardReMaster.exe. - Не проверено: ручная игровая приёмка пользователем.
- Открытые вопросы: bloom/свет, HUD-анимации, надёжность эвристики no-trigger damage check.
2026-10-27 — TASK-2026-004: убрать боевые баннеры
Решение пользователя: все боевые баннеры не нужны; убираем их
полностью, чтобы пересобрать анимации блоками. Верхний ActionPrompt
(муллиган/смена/подсказки), StatusToast и trigger-сообщения не являются
боевыми баннерами и остаются.
Анализ:
- Центральный
BattleFeedbackи полноэкранныйBattleFlash— это один feedback-блок: текст события, вспышка damage/heal, кнопка «Пропустить анимации», очередь и паузыeventPause/post*Pause. - Паузы feedback сейчас задают темп событий, но не являются источником
истины; после удаления темп держат
CardMoveAnimator, trigger-последовательность и серверные снапшоты. InputLock("feedback")и_feedbackLockHeldсуществуют только для этого блока; их нужно убрать вместе с ним._turnBanner/_turnBannerTextобъявлены, но не строятся; удалить как мёртвый код.AnimationConfig.attackDeclare/guard/driveCheck/trigger/battleResolved/ damage/heal/intercept/perfectGuard/eventPause/postDrivePause/ postTriggerPause/postDamagePause/retireDurationпосле удаления станут неиспользуемыми; пока оставляем поля, чтобы не менять контракт ассета.
Реализация:
- Удалить
BattleFeedback,BattleFlash,SkipFeedbackи весьFeedbackStep-механизм. - Убрать вызовы
ShowFeedback/EnqueuePause/ShowFeedbackFor. - Убрать
InputLock("feedback")и связанные поля/сбросы. - Удалить неиспользуемые
_turnBanner/_turnBannerText. - Оставить журнал событий,
Describe, trigger-последовательность,ActionPromptиStatusToast.
Проверка:
- EditMode в копии без
Library— 51/51. - Standalone Windows собирается.
- Вручную: в бою нет центральных баннеров и вспышек, события идут без зависаний; журнал и trigger-подсказки работают.
2026-10-27 — TASK-2026-005: порядок набора руки
Решение пользователя: рука локального игрока должна набираться слева направо: первая карта слева, новые добавляются правее. Рука противника по правилу зеркальности набирается с его стороны поля, то есть на экране справа налево: новая карта слева.
Реализация:
GetHandViewPose: вернутьx = center + offset * step,roll = -offset * roll.GetOpponentHandViewPose: сделать зеркально —x = center - offset * step,roll = +offset * roll.- Обновить тест
Hands_Fill_Mirrored_And_Newest_Is_On_Topпод новое направление и новые карты.
Проверка:
- EditMode в копии без
Library— 51/51. - Standalone Windows собирается.
- Вручную: новая карта в своей руке появляется справа; у противника — слева.
2026-10-27 — TASK-2026-006: возврат карт из руки в колоду
Решение пользователя: карта уходит из руки в колоду по дуге под низ колоды с переворотом рубашкой вверх во время движения. Возврат идёт справа налево; следующая карта стартует только после завершения предыдущей анимации. Для противника — то же зеркально с его стороны.
Анализ:
- Сервер уже сообщает о возврате:
MulliganView(игрок, количество) иCardReturnedToDeckView(игрок,PrintingId). Отдельного per-card события для муллигана нет, поэтому карты определяются по исчезновению из старой руки. - Старый
Card3Dруки сейчас просто освобождается вGameBoard3D.Render; чтобы анимировать, его нужно вынуть из_cards, оставить в отдельном списке, провести дугой и только потом вернуть в пул. - Для последовательности используем
CardMoveAnimatorсsequential: true; для скрытия после дуги — callback завершения. Это переиспользует общий arc/flip и очередь, не создаёт отдельный аниматор. - Цель — позиция колоды минус небольшой
Y, рубашкой вверх; во время движенияStartArcMoveинтерполирует поворот от лица к рубашке.
Реализация:
GameBoard3D.QueueHandReturnToDeck+ обработкаMulliganViewиCardReturnedToDeckViewизBattleView.- Выбор старых карт руки, удаление из
_cards, дуга под колоду, переворот, возврат в пул после завершения. CardMoveAnimator.EnqueueполучилonCompleted; последовательная очередь используется для возврата.- Тесты:
Hand_Return_To_Deck_Starts_Right_To_Left_And_Targets_Deck_Bottom,CardMoveAnimator_Runs_Sequential_Requests_And_Completes_Each.
Проверка:
- EditMode в копии без
Library— 53/53. - Standalone Windows собирается.
- Вручную: при муллигане/возврате карты уходят по дуге под колоду, переворачиваются рубашкой вверх, следующая стартует после предыдущей; у противника зеркально.
2026-10-27 — TASK-2026-007: общий добор карты
Решение пользователя: добор после муллигана должен выглядеть так же, как добор в муллигане: карта появляется над колодой полного размера, рубашкой вверх, летит в руку по дуге и переворачивается лицом вверх.
Анализ:
AnimateHandDrawуже стартует с_config.cardScaleиcard.FaceDownRotation.- Обычный добор шёл через
ResolveSourcePose: для карты руки он бралspec.Scale * cardScale(размер руки) и плоскую ориентацию колоды, поэтому над колодой появлялась маленькая карта. - Нужно вынести общий старт добора: позиция над колодой, полный масштаб, рубашка в ориентации будущей карты руки.
Реализация:
GameBoard3D.GetDrawSource— общая позиция/масштаб старта добора.ResolveSourcePoseдляBoardZone.Handиспользует полный масштаб иspec.BaseRotation * FaceDownFlip.AnimateHandDrawиспользует тот жеGetDrawSource.- Длительность нового добора —
introDrawDuration(0.6 с), как в муллигане. - Тест проверяет, что новая карта стартует над колодой в
cardScale.
Проверка:
- EditMode в копии без
Library— 53/53. - Standalone Windows собирается.
- Вручную: добор после муллигана визуально совпадает с муллиганом; карта не маленькая.
2026-10-27 — TASK-2026-008: длительность возврата как у добора
Решение пользователя: анимация возврата карты в колоду должна идти столько же, сколько добор из колоды.
Реализация:
- Общая
GameBoard3D.DrawDuration(introDrawDuration, 0.6 с). StartHandReturnиспользуетDrawDurationвместоmoveDuration.- Обычный добор использует ту же
DrawDuration.
Проверка:
- EditMode в копии без
Library— 53/53. - Standalone Windows собирается.
- Вручную: возврат в колоду по длительности совпадает с добором.
2026-10-27 — TASK-2026-009: последовательный возврат карт
Проблема: карты возвращались одновременно. Card3D.SetPose ставил
цель под колодой, а _returningCards тикали все сразу; очередь
CardMoveAnimator стартовала дуги по одной, но карты уже плавно уезжали
к цели параллельно.
Решение: пока карта ждёт в очереди, удерживать её в исходной позе руки
через Card3D.HoldAtSource. Старт следующей — только после завершения
предыдущей (sequential: true).
Реализация:
StartHandReturnвызываетHoldAtSourceдоCardMoveAnimator.Enqueue.- Тест проверяет, что обе возвращаемые карты остаются в руке до старта своей анимации.
- Порядок: самая правая карта первой; у противника зеркально.
Проверка:
- EditMode в копии без
Library— 53/53. - Standalone Windows собирается.
- Вручную: сначала уходит самая правая карта, затем следующая.
2026-10-28 — TASK-2026-010: рука перестраивается при выходе карты
Решение пользователя: при любом выходе карты из руки остальные карты должны перестраиваться под новое количество одновременно с её перемещением.
Анализ:
UpdateHandViewуже считает позы по новомуHandCountиз свежегоRender.- Перекомпоновка руки (
Hand → Hand) не ставится вCardMoveAnimator(NeedsMoveвозвращает false), поэтому не ждёт анимацию уходящей карты. - Уходящая карта удаляется из
_handBindings/_cards, а остальные карты сразу получают новые цели; hand reflow идёт своим smooth-слоем.
Реализация:
- Проверка поведения для hand → field.
- Проверка поведения для возврата в колоду: остальные карты получают новые цели, пока возвращаемая карта ещё ждёт/летит.
- Тесты
Hand_Reflows_While_A_Card_Leaves_From_Handи расширенныйHand_Return_To_Deck_Starts_Right_To_Left_And_Targets_Deck_Bottom.
Проверка:
- EditMode в копии без
Library— 54/54. - Вручную: при выходе карты рука сдвигается одновременно с её движением.
2026-10-28 — TASK-2026-011: ступенчатый reflow руки при муллигане
Решение пользователя: во время муллигана рука должна сдвигаться после каждого ухода карты, а не один раз под окончательное количество.
Проблема: новый Render сразу содержал финальный HandCount (старые
остатки + новые карты). Остальные карты получали финальные позы, а
возвращаемые удерживались. Визуально рука перестраивалась один раз.
Решение:
- Ступенчатый список
_stagedReturnCards: старые карты руки в исходном порядке, включая ожидающие возврата; новые карты в него не входят. - Пока идёт возврат,
UpdateHandViewстроит позы только для этого списка. - После завершения каждой карты она убирается из списка, и оставшиеся карты (включая ожидающие) плавно сдвигаются под новое количество.
- Ожидающие карты не удерживаются на месте: при старте своей анимации они
получают цель под колодой через
OnStartи стартуют из текущей позы (fromCurrent). - После последнего возврата staged-режим выключается; новые карты добираются в финальную руку.
Реализация:
BuildStagedReturnHand,_stagedReturnCards,_stagedReturnPlayer.CardMoveAnimatorполучилonStartиfromCurrent.OnHandReturnCompletedубирает карту из staged-списка и сразу пересчитывает руку.- Тест проверяет: до первого ухода рука не сдвигается, после первого — сдвигается; ожидающая карта остаётся в руке до своей очереди.
Проверка:
- EditMode в копии без
Library— 54/54. - Standalone Windows собирается.
- Вручную: муллиган с двумя возвратами — рука сдвигается после каждого.
2026-10-28 — TASK-2026-012: добор по одной карте и ступенчатый reflow
Проблема: при доборе все новые карты сразу появлялись над колодой рубашкой вверх, а рука перестраивалась один раз под финальное количество.
Решение:
- Новые карты своей руки скрываются на время очереди и показываются только
в
CardMoveAnimator.onStart— по одной. _stagedDrawCardsхранит уже видимые карты (старые остатки + завершённые доборы); новые карты добавляются только после завершения их дуги.- После каждого добора рука пересчитывается под текущее видимое количество, а не под финальное.
- После последнего добора staged-режим выключается; финальная рука совпадает с текущей.
Реализация:
BuildStagedDrawHand,_stagedDrawCards,_stagedDrawTargetCount.BeginHandDrawArcпоказывает карту, ставит цель в следующий слот и запускает дугу из текущей позиции.OnHandDrawCompletedдобавляет карту в staged-список и пересчитывает руку.- Повторный snapshot без новых доборов не сбрасывает уже начатую staged раздачу — иначе остатки руки перестают сдвигаться.
- Тест
Hand_Draw_Stages_New_Cards_One_By_One.
Проверка:
- EditMode в копии без
Library— 55/55. - Standalone Windows собирается.
- Вручную: при доборе над колодой видна одна карта; рука расширяется после каждой.
2026-10-28 — TASK-2026-013: единый механизм раскладки руки
Проблема: остатки руки после муллигана переставали сдвигаться:
отдельные _stagedReturnCards и _stagedDrawCards не всегда содержали
одни и те же карты, а повторные snapshot/переходы между режимами ломали
раскладку.
Решение: один визуальный список _visualHandCards и один override
_handLayoutOverride:
- в список сразу входят все оставшиеся карты руки и ожидающие возврата;
- новые добранные карты добавляются только после завершения их дуги;
- после каждого возврата/добора список пересчитывается, поэтому остатки руки всегда участвуют в сдвиге;
- пока override активен,
UpdateHandViewиспользует только визуальный список; после завершения всех возвратов/доборов возвращается обычный_handBindings; - повторный Render не пересоздаёт список и не сбрасывает прогресс.
Реализация:
BuildVisualHand,_visualHandCards,_pendingDrawCards,_handLayoutOverride.- Удалены раздельные staged-списки возврата/добора.
- Тест
Mulligan_Remaining_Cards_Reflow_After_Each_Return.
Проверка:
- EditMode в копии без
Library— 56/56. - Standalone Windows собирается.
- Вручную: после муллигана остатки руки сдвигаются после каждого возврата и каждого добора.
2026-10-28 — TASK-2026-014: подъём карты в руке при наведении
Решение пользователя: карта под курсором плавно приподнимается на 10% своего размера; после ухода курсора плавно возвращается.
Реализация:
handHoverLift = 0.1теперь доля высоты карты, а не мировое смещение.GameBoard3D.UpdateHandHover: raycast по своей руке, только когда нет UI/лока/драга/анимаций; оппонент и поле игнорируются.SetHoveredHandCardпересчитывает руку;ApplyHandHoverдобавляет камера-вверх наcardHeight * scale * cardScale * handHoverLift.- Плавность — существующий
Card3D.SetPose/Tick; отдельного твина нет. - Тест
Hand_Hover_Lifts_Card_By_Ten_Percent(подъём и возврат цели).
Проверка:
- EditMode в копии без
Library— 57/57. - Standalone Windows собирается.
- Вручную: наведение поднимает карту, уход курсора возвращает.
2026-10-28 — TASK-2026-015: drag карты из руки, смена через VC
Решение пользователя: карта из руки, отпущенная на VC, делает смену; пока кнопка мыши удерживается, карта остаётся приподнятой; отпускание в неположенном месте плавно возвращает её в руку; без дёрганья.
Реализация:
Card3D.EndDragAtCurrentфиксирует карту в точке drop-а, не возвращая её в руку и не сбрасывая подъём/масштаб.GameBoard3D.FinishDrag: для карты из руки больше не вызываетReturnToOriginдо ответа сервера; держит карту в_dropPendingCard.GameBoard3D.ReturnDroppedCard: снимает hold и плавно возвращает в руку, если drop не стал интентом/отклонён.BattleView: возвращает карту при отсутствии интента, отказе сервера, ошибке отправки, guard-выборе и раннем выходе.- Валидный Ride/Call: карта ждёт снапшот и летит в target уже из точки drop-а; в руку не возвращается.
- Тест
Dropped_Hand_Card_Holds_At_Drop_Until_Returned.
Проверка:
- EditMode в копии без
Library— 58/58. - Standalone Windows собирается.
- Вручную: drag в VC на смену, удержание, возврат из неверного места.
2026-10-28 — TASK-2026-016: карта при drag под курсором
Проблема: при перетаскивании карта уезжала вниз-влево от курсора:
луч наводился на плоскость cardLift, а карта висела на dragLift; плюс
DragTo сбрасывал hand-ориентацию в плоский Euler(0,yaw,0).
Решение:
- Плоскость drag-а считается на фактической высоте карты
(
Card3D.DragLift), поэтому карта остаётся под курсором. - Для карты из руки
DragLift= hover-подъём 10% высоты; для карты поля — прежнийdragLift. DragToсохраняет_dragOriginRotation, поэтому hand-карта не переворачивается на стол при перетаскивании._dragPointerOffsetсохраняет точку захвата: карта не прыгает центром под курсор при старте drag-а.
Проверка:
- EditMode — 58/58.
- Standalone Windows собирается.
- Вручную: карта у курсора, hand-ориентация сохранена.
2026-10-28 — TASK-2026-017: drag не двигает карту в момент старта
Проблема: в момент старта drag-а вызывался UpdateDrag, карта сразу
переносилась к курсору/поднималась. Кроме того, после старта UpdateDrag
больше не вызывался каждый кадр — карта не следовала за мышью.
Решение:
OnPointerHeldтолько включает drag и запоминает точку захвата; позицию не меняет.HandlePointerпри_draggingкаждый кадр вызываетUpdateDrag, поэтому карта следует за курсором.OnPointerReleasedбольше не дублируетUpdateDrag; last target уже обновлён в этом кадре.
Проверка:
- EditMode — 58/58.
- Standalone Windows собирается.
- Вручную: при начале drag-а карта остаётся на месте, затем следует за курсором.
2026-10-28 — TASK-2026-018: выбор зоны без перемещения карты из руки
Решение пользователя: карта из руки при зажатии ЛКМ не должна перемещаться. Курсор наводится на зону; карта остаётся в руке приподнятой; при отпускании над VC выполняется смена.
Реализация:
- Для
source.IsHanddrag заменён на_handTargeting: карта не вызываетBeginDrag/DragToи остаётся в hand-раскладке. UpdateHandHoverудерживает hover-подъём нажатой карты, пока идёт targeting.UpdateHandTargetingсчитает только целевую зону по курсору и показывает drop indicator; карта не двигается.- Цель сначала определяется raycast-ом по карте/кругу (VC-карта даёт ровно Vanguard), затем fallback на плоскость.
FinishHandTargetingна release отправляетCardDropped; при валидном VC срабатывает RideIntent, при невалидном карта остаётся в руке.- Field-карты сохраняют старый drag с движением.
- По серверному логу
rides=[TD02/007EN, BT01/015EN]— только эти карты были доступны для смены. Валидные Ride-карты теперь подсвечиваются в руке; добавлен fallback direct RideIntent и диагностические логи[HandTargeting]/[Drop].
Проверка:
- EditMode — 58/58.
- Standalone Windows собирается.
- Вручную: ЛКМ на карте, наведение на VC, отпускание — смена; карта всё время остаётся в руке.
TASK-2026-019 — загрузочная сцена и кадр без покадровых аллокаций
- Статус:
[ ] - Создано: 2026-10-30
- Анализ: DeepSeek выполнен (пункты A1, C1–C3 в
docs/Development/CLIENT-SCENES-3D-ANIMATIONS.md) - Реализация: не начата
- Проверка: не выполнена
- Затронутые системы:
SceneFlow,VanguardApp,Boot, новыйLoadingOverlay,GameBoard3D(стрелки, рука),ArrowDirector,AttackArrowView,BattleView.UpdateClock,Localization,InputLockService, EditMode-тесты.
A. Цель и требования
Первый блок бэклога «сцены, 3D, анимации». Четыре независимых результата:
- Переход между экранами без вспышки:
Boot— загрузочная сцена с прогрессом и fade, затемLogin; тот же overlay используется для остальных переходов. - Стрелки атаки/буста не создают мусор в кадре.
- Рука не пересчитывается дважды за кадр и не пересчитывается впустую.
- Строки HUD и локализации не обновляются каждый кадр без изменения значения.
Ограничения:
- без новых пакетов (DOTween/UniTask запрещены);
- HUD из TASK-2026-003 не перекомпоновывать; в
BattleViewдопустима только точечная правкаUpdateClock; - правила, сервер, протокол, контент не меняются;
CardMoveAnimatorостаётся единственным планировщиком перемещений;AnimationConfigв этом блоке не меняется (это отдельный пункт C6);- геймплей вручную проверяет пользователь.
Критерии готовности:
- переход
Boot → LoginиLogin → Lobbyбез видимой вспышки, прогресс отображается; - в бою без движения карт и стрелок — 0 B/кадр по Profiler (Allocation Call Stacks);
- позы руки не пересчитываются, если не менялись состав руки, камера, hover и staged-список;
- таймер/банк и локализованные подписи обновляются только при изменении;
- существующие EditMode-тесты и оба smoke проходят.
B. Текущее состояние
SceneFlow.LoadAsync—LoadSceneAsync(sceneName, LoadSceneMode.Single), ожиданиеisDoneбез progress/fade (SceneFlow.cs:63-80).Bootсодержит камеру, свет и Global Volume; контроллера и UI нет,VanguardAppсоздаётся вRuntimeInitializeOnLoadMethod(ClientBootstrap.cs:11-19),StartгрузитLogin(VanguardApp.cs:59-67).GameBoard3D.UpdateBoostArrowsсоздаётnew List<(Vector3, Vector3)>на каждый вызов (GameBoard3D.cs:1219-1227),BattleCardиспользуетPlayers.FirstOrDefault(lambda)(:1319-1320),ArrowAnchorищет карту линейным перебором_cards.Values(:1293-1301,:1332-1341).GameBoard3D.Updateза кадр вызываетUpdateHandView,_moveAnimator.Tick,TickHandDraw,_cameraDirector.Tick,card.Tickпо всем картам,_returningCards, затем_arrowDirector.TickиUpdateAttackArrowPoints(:2220-2255). Стрелки обновляются двумя путями.AttackArrowView.ApplyColorсоздаётnew[] { _shaft, _head }(:267) и вызывается изTickиSetStyle, т.е. несколько раз за кадр на стрелку.UpdateHandViewвызывается изUpdate,Render, hover и колбэков (:183, 511, 607, 732, 1163, 2230, 2372); позы обеих рук считаются каждый кадр.BattleView.UpdateClockпишет текст таймера и банка каждый кадр;LocalizedText.LateUpdateпроходитLoc.Translateна каждый лейбл;InputLockService.Describeсобирает строку через LINQ при активном локе.
Что сохранить:
- пул
Card3Dи переиспользование по ключу/InstanceId; CardMoveAnimatorкак единственный планировщик, егоCancelCard/CancelAllи таймаут;- общий
TickизGameBoard3D(безUpdateна каждой карте); Time.unscaledDeltaTimeи текущую интерполяцию (Card3D.Tick);- геометрию стрелок, раскладку руки, hover-подъём и staged-reflow.
C. Чек-лист изменений
-
C1.
CREATEclient/Assets/Vanguard/Runtime/UI/LoadingOverlay.cs— персистентный overlay загрузки.- Canvas + фон + текст прогресса на объекте
VanguardApp,raycastTarget = false, поверх сцены; APIShow(float progress),Hide(). - Не использовать
UiKit.CreateCanvasдля сцены: Canvas должен переживатьLoadSceneMode.Single. - Реализация: не выполнена. Проверка: не выполнена.
- Зависит: нет.
- Canvas + фон + текст прогресса на объекте
-
C2.
MODIFYRuntime/App/SceneFlow.cs— переход с прогрессом и fade.- Показывать overlay до
LoadSceneAsync, обновлять прогресс поoperation.progress,allowSceneActivation = falseдо готовности, затем активировать сцену и скрывать overlay после первого кадра. - Защита от повторного вызова во время перехода (idempotent
LoadAsync). - Реализация: не выполнена. Проверка: не выполнена.
- Зависит: C1.
- Показывать overlay до
-
C3.
MODIFYRuntime/App/VanguardApp.cs+Scenes/Boot.unity— Boot как загрузочная сцена.Bootпоказывает overlay и грузитLoginпосле инициализации сервисов; прогрев не дублируется вStart, если сцена уже целевая.- Реализация: не выполнена. Проверка: не выполнена.
- Зависит: C1, C2.
-
C4.
MODIFYBoard3D/View/GameBoard3D.cs— стрелки без LINQ и покадровых списков.- Переиспользуемый буфер пар boost-стрелок, индексированный поиск игрока
вместо
FirstOrDefault, один проход по_cardsдля якорей. - Реализация: не выполнена. Проверка: не выполнена.
- Зависит: нет.
- Переиспользуемый буфер пар boost-стрелок, индексированный поиск игрока
вместо
-
C5.
MODIFYAnimation/ArrowDirector.cs+View/AttackArrowView.cs— одно обновление геометрии за кадр.- Убрать двойной путь
Tick+UpdateAttackArrowPoints; обновлять точки один раз; убрать массивnew[] { _shaft, _head }вApplyColor. - Реализация: не выполнена. Проверка: не выполнена.
- Зависит: C4.
- Убрать двойной путь
-
C6.
MODIFYBoard3D/View/GameBoard3D.cs—UpdateHandViewпо dirty-флагу.- Пересчитывать позы только при изменении состава руки, камеры, hover, staged-списка; оставить ровно один вызов за кадр.
- Реализация: не выполнена. Проверка: не выполнена.
- Зависит: нет.
-
C7.
MODIFYUI/BattleView.cs—UpdateClock. Обновлять текст таймера и банка только при изменении отображаемого значения.- Реализация: не выполнена. Проверка: не выполнена.
- Зависит: нет.
-
C8.
MODIFYUI/Localization.cs—LocalizedText. Кешировать результат перевода до смены языка или ключа, не вызыватьLoc.Translateкаждый кадр.- Реализация: не выполнена. Проверка: не выполнена.
- Зависит: нет.
-
C9.
MODIFYBattle/InputLockService.cs—Describe. Не собирать строку/LINQ в кадровом пути: кешировать описание при изменении набора причин.- Реализация: не выполнена. Проверка: не выполнена.
- Зависит: нет.
-
C10.
TESTрегрессии блока.- EditMode: overlay
Show/Hideидемпотентны;UpdateHandViewне меняет позы при неизменных входах (seam-счётчик), hover/добор/муллиган по-прежнему сдвигают руку;ApplyColorне создаёт массив (статическая проверка или отсутствие регрессии поведения). - Существующие
Hand_*,CardMoveAnimator_*,GameBoard3DTests— без изменений ожиданий. - Реализация: не выполнена. Проверка: не выполнена.
- Зависит: C1–C9.
- EditMode: overlay
-
C11.
VERIFYавтотесты, smoke, сборка.- EditMode в копии без
Library;SceneSmoke.Run;SceneSmoke.RunPlaymat; standalone-сборка. - Profiler: Allocation Call Stacks в бою без движения — 0 B/кадр.
- Реализация: не выполнена. Проверка: не выполнена.
- Зависит: C10.
- EditMode в копии без
-
C12.
VERIFYручная проверка пользователем.- Переход
Boot → Login → Lobby → Battleбез вспышки; видимый прогресс; стрелки атаки/буста без визуальных изменений; hover, добор, муллиган, reflow руки; таймер и подписи. - Реализация: не применима. Проверка: остаётся на пользователе.
- Зависит: C11.
- Переход
D. Последовательность выполнения
- C1 → C2 → C3: загрузочный overlay и Boot. Проверить переходы смоуком.
- C4 → C5: стрелки; визуально сравнить до/после.
- C6: рука по dirty-флагу; прогнать
Hand_*-тесты. - C7 → C8 → C9: строки и локализация.
- C10 → C12: тесты, проверки, ручная приёмка.
E. Проверки
- Клиентские EditMode в копии проекта без
Library(команда вdocs/SESSION-STATE.md). SceneSmoke.RunиSceneSmoke.RunPlaymat.- Standalone-сборка на копии: переходы и overlay.
- Profiler: Allocation Call Stacks до/после для боя без движения.
git diff --check; отсутствие изменений вVanguard.Rules,Vanguard.Shared,Vanguard.Server,content/.- Ручная приёмка — пользователем.
F. Риски и неизвестные вопросы
- Overlay на персистентном Canvas: может перехватывать клики или висеть
после загрузки —
raycastTarget = false, скрытие вfinallyи по таймауту. - Смоук-таймауты:
SceneSmokeждёт 6 с; если Boot начнёт грузить Login позже, таймаут придётся увеличить или ждать по состоянию. - Dirty-флаг руки: легко сломать hover, staged-reflow и муллиган; менять
только после зелёных
Hand_*-тестов. - Якоря стрелок: карты двигаются каждый кадр, поэтому кешировать можно буферы и результаты поиска карт, но не позиции.
- Порядок вызовов: у
BattleSceneController.UpdateиGameBoard3D.UpdateнетDefaultExecutionOrder; правки не должны завязываться на порядок. - HUD TASK-2026-003 ещё не принят вручную: в
BattleViewменять толькоUpdateClock, не разметку. - Открытых вопросов, блокирующих старт, нет.
G. Результат
- Реализовано: —
- Проверки: —
- Не завершено/заблокировано: —
- Skill обновлён: —
- Git: —
TASK-2026-020 — парсер карт и артов с официального сайта
- Статус:
[x] - Создано: 2026-10-30
- Анализ: DeepSeek
- Реализация: DeepSeek
- Проверка: побайтовое совпадение с текущими YAML (0 diff), 94/124, скачивание арта
- Затронутые системы:
tools/import_official.py(новый),README.md;content/sets/*.yamlиCardArtне изменялись.
A. Цель и требования
Один инструмент, который берёт с en.cf-vanguard.com и параметры карт, и
картинки, и пишет тот же YAML-формат, что и текущий импорт. Причины:
- сейчас параметры идут с сайта (
view=text), а триггеры и редкости — изcontent/cards-mvp.md(выгрузка из вики), арты — с Fandom; - официальная карточка
/cardlist/?cardno=…содержит иrarity, иgift(тип триггера), поэтому вики больше не нужна; - картинки официального сайта лежат рядом с данными:
/wordpress/wp-content/images/cardlist/{set}/{CODE}.png.
Ограничения: только стандартная библиотека Python; не менять схему YAML и
CardEntry/PrintingEntry; не терять ручные поля; не создавать в Resources
два ассета с одним именем.
B. Текущее состояние и что выяснено
tools/import_cards.py: список/cardlist/cardsearch/?expansion=N&view=text, регэксп по<li>, триггеры/редкости изcards-mvp.md, записьset/cards/printings, SP-принтыBT01/S01EN…S12ENпомечаютсяisParallel+basePrintingId.tools/import_card_art.py: Fandom-галереи, коды толькоTD\d{2}.- Сайт:
expansion=5→ BT01 (92 принта, 4 страницы),3→ TD01 (16),4→ TD02 (16); всего 94 определения и 124 принта — совпадает с README. - Карточка содержит
type,group(клан),race,nation,grade,power,critical,shield,skill,gift(напримерCritical Trigger +5000),effect,flavor,rarity,number. - Список сетов с id —
/cardlist/?change_ex(47 сетов,BT01=5,TD01=3,TD02=4), можно не хардкодить id. - Сайт отдаёт 404 на запросы без браузерного
User-Agent— нужен UA.
C. Чек-лист изменений
- C1.
CREATEtools/import_official.py— единый парсер.discover_sets()по/cardlist/?change_ex;--list-sets.list_codes()со всех страниц (max_pageиз HTML) и сверка с «N Results».parse_card()по карточке: тип, клан, grade/power/critical/shield, триггер изgift, редкость, текст, флагиsentinel/restraint.write_set()— тот же формат и порядок полей, что у старого импорта.- Реализация: выполнена. Проверка: см. C5.
- C2.
CREATEскачивание артов —{imageKey}.pngвCardArt.- Пропуск, если файл с любым расширением уже есть (иначе Unity увидит два
ассета с одним именем);
--force-artудаляет старый файл и его.meta. - Реализация: выполнена. Проверка: TD01, 16/16 файлов, ~350–430 КиБ.
- Пропуск, если файл с любым расширением уже есть (иначе Unity увидит два
ассета с одним именем);
- C3.
MODIFYдедупликация определений между сетами.- При прогоне одного сета читаются
nameIdиз остальных YAML папки, чтобы не дублировать карты, определённые в BT01. - Реализация: выполнена. Проверка: BT01 80 + TD01 7 + TD02 7 = 94.
- При прогоне одного сета читаются
- C4.
MODIFYсохранение ручных полей.nameRu,textRu,snipeBackRow,boostпереносятся из существующего файла поnameId(на сайте их нет; иначе терялся бы Tejas).- Реализация: выполнена. Проверка:
snipeBackRowу Tejas сохраняется.
- C5.
VERIFYидемпотентность.- Прогон
--sets BT01,TD01,TD02в копиюcontent/sets:Compare-Objectпо каждому файлу — 0 строк различий, размеры совпали (37116 / 3771 / 3989 байт). - Реализация: не применима. Проверка: выполнена.
- Прогон
- C6.
MODIFYREADME.md— команда нового импорта, режимы, предупреждение про заглушкуpythonв Microsoft Store (py).- Реализация: выполнена. Проверка: прочитано.
D. Последовательность выполнения
- C1: разбор списка и карточки, запись YAML.
- C2: арты и защита от дублей в
Resources. - C3–C4: дедупликация и ручные поля.
- C5: прогон в копию и сверка.
- C6: README.
E. Проверки
py tools/import_official.py --list-sets.py tools/import_official.py --sets TD01 --limit 4 --out <tmp> --art-dir <tmp>.- Полный прогон в копию
content/sets+Compare-Objectс репозиторием. dotnet run --project server/src/Vanguard.Cli -- validate— не запускался (нуженssh home/Docker); косвенно покрыт побайтовым совпадением YAML.- Скачивание арта проверено на TD01 (16 файлов) и на
--force-art.
F. Риски и открытые вопросы
- Разметка сайта нестабильна: любой редизайн ломает регэкспы. Симптом — «не найдено имя карты» или расхождение с «N Results».
- Сайт отвечает 404 без браузерного
User-Agent— UA обязателен,curlбез заголовка вводит в заблуждение. - Полный прогон — ~2–6 минут на 124 карточки (по одному запросу на карту,
пауза
--delay). Для нескольких сетов сразу это нормально, для правки одной карты — избыточно. - Официальные арты — PNG ~350–430 КиБ; текущие в репозитории — JPG. Массовая
замена не делалась:
--force-artменяет расширение и удаляет.meta. pythonв Microsoft Store — заглушка, нуженpy(отражено в README).- Открытый вопрос: переносить ли
skill(Boost/Twin Drive!!) в полеboost— сейчас не переносится, чтобы не менять игровые данные.
G. Результат
- Реализовано: C1–C6.
- Проверки: полный прогон в копию — 0 различий с
content/sets; 94 определения / 124 принта; арт TD01 16/16;--force-artзаменяет.jpgна.pngбез дублей. - Не завершено:
validateнаssh home. - Skill обновлён: не требуется.
- Git:
0620ec5(парсер, README, план), арты —f2ae6b9.
TASK-2026-021 — Login по референсу: 2D-арт и неоновый UI
- Статус:
[!] - Создано: 2026-10-31
- Анализ: DeepSeek (по референсу в чате от 2026-10-31)
- Реализация: DeepSeek: C1–C9 выполнены
- Проверка: EditMode 60/60;
SCENE_SMOKE success=True; standalone собран; ручная приёмка — за пользователем - Затронутые системы:
LoginView,LoginSceneController,SceneEnvironment,UiKit, новыйNeonUi, новыйLoginMenu,Localization,Resources/Login/*,SceneSmoke, EditMode-тесты.
A. Цель и требования
Привести экран Login к референсу: полноэкранный 2D key art, поверх —
центрированная неоновая панель с двумя полями и кнопкой «Войти».
Состав экрана (сверху вниз, координаты для 1920×1080):
- Фон — один арт на весь экран, cover (без полос по краям), лёгкое затемнение под панелью для читаемости текста.
- Логотип — по центру, ширина ≈ 520 px, верх ≈ 140 px. В MVP входит в состав арта; отдельным слоем — только если дадут прозрачный PNG.
- Панель — 560×420, центр по X, центр по Y ≈ 600 (чуть ниже середины):
- радиус 24, заливка
rgba(7,17,43,0.82); - рамка 2 px
#2E7DFF, внешнее свечение ≈ 24 pxrgba(46,125,255,0.35); - тонкая внутренняя рамка
rgba(150,200,255,0.18).
- радиус 24, заливка
- Поле ввода — 480×64, радиус 10, заливка
rgba(4,12,30,0.9), рамкаrgba(46,125,255,0.45); слева иконка 22×22 (16 px от края), текст 18 px, placeholderrgba(130,150,190,0.9); фокус — рамка#6CC0FF+ свечение.- «Логин» — иконка пользователя;
- «Пароль» — иконка замка + глаз справа (показать/скрыть).
- «Забыли пароль?» — 15 px,
#5FB0FF, справа под полем пароля. - Кнопка «Войти» — 480×72, срезанные углы 14 px, градиент
#1B5FC9 → #2E8BFF, рамка 1.5 px#7CC4FF, свечение; текст 22 px bold, белый. Hover +10 % яркости, pressed −8 %, disabled 45 % + «Подключение…». - «Создать аккаунт» — вторичная ссылка 15 px
#7FA8E0по центру под кнопкой (решение 2026-10-31: регистрация остаётся доступной). - Статус — 14 px под ссылками, автоскрытие через 6 с; ошибка
#FF7A6B, успех#6BE08A. - Гамбургер — 56×56, правый верхний угол 28/28, радиус 12, рамка
#2E7DFF, три линии 22×2. Открывает меню:RU/EN, версия клиента, адрес сервера (dev-поле), «Закрыть». Выхода нет — сессии ещё нет. - Тэглайн — левый нижний угол 40/36: щит 44×44 + две строки
FIGHT TOGETHER./BUILD YOUR FUTURE., 11 px, трекинг 2,rgba(150,195,255,0.65). - Копирайт — правый нижний угол, 12 px
rgba(130,165,215,0.5):© Cardfight!! Vanguard Fan Project.
Ограничения:
- без новых пакетов и без Addressables (арт из
Resources, как арт карт); - auth-контракты не меняются; серверного сброса пароля нет;
- правила, сервер, протокол и контент не трогаются;
- имя
LoginScreenсохраняется (на него опираетсяSceneSmoke); - 3D-окружение в
Loginне строится — это исключение из «3D в каждой сцене», зафиксированное вCLIENT-SCENES-3D-ANIMATIONS.md(8.7).
Критерии готовности:
- композиция и цвета совпадают с референсом на 1920×1080;
- на 16:10 и 21:9 фон заполняет экран, панель остаётся по центру;
- вход, регистрация, ошибки и busy-состояние работают как раньше;
- RU/EN переключается из меню, строки локализованы;
SceneSmoke.Runпроходит на сценеLoginбез 3D-окружения.
B. Текущее состояние
LoginView(Runtime/UI/LoginView.cs): панельLoginScreen+ карточка 620×820 с eyebrow/title/subtitle, полем адреса сервера, полем имени, паролем, кнопкой «ВОЙТИ», кнопкой «СОЗДАТЬ АККАУНТ», статусом, футером с версией/стендом и кнопкой языка в правом верхнем углу.LoginSceneControllerвызываетSceneEnvironment.Build(SceneTheme.Login): камера, свет, пол, 14 кубов (стол, «карты», неон). 3D-стол виден по краям панели.UiKitумеет только прямоугольныеImageс плоским цветом: скруглений, рамок, свечения и 9-slice нет;CreateInput— стандартный uGUIInputField.- Шрифт —
LegacyRuntime.ttf(кириллица есть, геометрия нейтральная). SceneSmoke(Editor/SceneSmoke.cs:116-123) требует наличия объектаVanguard 3D Environmentв активной сцене; после отказа от 3D в Login проверка упадёт.- Сервер: endpoint сброса пароля отсутствует (
forgot/resetне находятся), поэтому «Забыли пароль?» — только заглушка.
Что сохранить:
AuthService,AppConfig, обработкуApiExceptionи формат ошибок;- имя
LoginScreenи вызов_onAuthenticatedпосле успеха; UiKit.CreateCanvasи текущий CanvasScaler (1920×1080, match 0.5);- кнопку языка как функцию (переезжает в меню, но не исчезает).
C. Чек-лист изменений
-
C1.
CREATERuntime/UI/NeonUi.cs— 9-slice атомы интерфейса.- Спрайты панели, поля, кнопки с фаской, свечения генерируются в рантайме
(по образцу
BoardTextures) либо берутся из одного PNG-атласа; кеш статический. - API:
Body(...),Bevel(...),Glow(...),Circle/Ring/HorizontalBar,AddImage/AddAnchored; свечение — отдельный спрайт позади тела. - Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: нет.
- Спрайты панели, поля, кнопки с фаской, свечения генерируются в рантайме
(по образцу
-
C2.
CREATERuntime/UI/LoginBackdrop.cs— фон экрана.Resources/Login/login_bg→Texture2D→Sprite.Create(какCardImageService), cover-масштаб черезAspectRatioFitter, поверх — затемняющий слой под панелью.- Если файла нет — процедурный градиент-заглушка, без падения.
- Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: арт-файл от пользователя.
-
C3.
MODIFYRuntime/UI/LoginView.cs— новая композиция.- Лого/тэглайн/копирайт, панель 560×420, два поля с иконками, «Забыли пароль?», кнопка «Войти», ссылка «Создать аккаунт», статус.
- Убрать с панели поле адреса сервера, eyebrow/title/subtitle и футер с версией; адрес и версия уезжают в меню.
- Tab / Shift+Tab между полями (
Runtime/UI/TabFocus.cs); Enter отправляет форму (TabFocus.EnterPressed, обработчик вTabFocusDriver); в открытом меню Enter форму не отправляет. - Реализация: выполнена. Проверка: EditMode 60/60, визуальный прогон.
- Зависит: C1, C2.
-
C4.
CREATERuntime/UI/LoginMenu.cs— гамбургер и панель меню.- Кнопка 56×56 в правом верхнем углу, три линии.
- Меню 340 px: переключатель
RU/EN, версия, поле адреса сервера (сохраняет вAppConfig/PlayerPrefs), «Закрыть». - Закрытие по Esc (
LoginMenu.IsOpen+Close), по кнопке и клику вне панели; не перехватывает ввод у формы, когда закрыто. - Реализация: выполнена. Проверка: EditMode 60/60, визуальный прогон.
- Зависит: C1.
-
C5.
MODIFYRuntime/App/LoginSceneController.cs+Runtime/App/SceneEnvironment.cs.Loginбольше не вызываетSceneEnvironment.Build; камера — заливка цветом фона, без пола/кубов/точечных источников.- Ветка
SceneTheme.Loginв окружении остаётся, но не используется (удалять только вместе с остальными темами). - Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: C2.
-
C6.
MODIFYEditor/SceneSmoke.cs— проверка Login без 3D.- Для
LoginтребоватьLoginScreenи фон (LoginBackdrop/LoginBackground),Vanguard 3D Environment— только дляLobby. - Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: C3.
- Для
-
C7.
MODIFYRuntime/UI/Localization.cs— новые ключи.- «Логин / Email», «Пароль», «Забыли пароль?», «Войти», «Создать аккаунт», «Подключение…», пункты меню, заглушка сброса пароля.
- Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: C3.
-
C8.
CREATEассеты —Resources/Login/.login_bg.png|jpg(1920×1080+, без текста и панели), при наличии — логотип и атлас иконок (пользователь/замок/глаз/меню/щит).- Импорт:
Texture2D(не Sprite), max size 2048,sRGB; отдельный.metaв репозитории. - Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: файлы от пользователя.
-
C9.
TESTEditMode.- Панель: два поля, кнопка, ссылки; поля без адреса сервера.
- Busy/ошибка/успех меняют статус и блокируют кнопки.
- Enter отправляет форму; меню открывается/закрывается, язык переключается.
SceneSmoke.Run— Login безVanguard 3D Environment.- Реализация: выполнена. Проверка: компиляция, EditMode 58/58, визуальный прогон.
- Зависит: C1–C8.
-
C10.
VERIFYсборка и ручная приёмка.- Standalone на копии проекта; проверка 1920×1080, 16:10, 21:9.
- Ручная сверка с референсом — пользователем.
- Реализация: выполнена. Проверка: standalone собран в копии без
Library, EditMode 60/60,SCENE_SMOKE success=True; визуальная приёмка — за пользователем. - Зависит: C9.
D. Последовательность выполнения
- C1: атомы (панель, поле, кнопка, свечение) — без них остальное не собрать.
- C2: фон и затемнение; проверить cover на 16:9/21:9.
- C3: новая композиция формы, сохранение текущей логики входа.
- C4: меню (язык, версия, адрес сервера).
- C5–C6: убрать 3D из Login, поправить смоук.
- C7–C8: локализация и ассеты.
- C9–C10: тесты, сборка, сверка с референсом.
E. Проверки
- EditMode в копии проекта без
Library(команда вdocs/SESSION-STATE.md). SceneSmoke.Run—SCENE_SMOKE success=True active=Login.- Standalone-сборка и запуск на 1920×1080; при возможности 21:9.
- Проверка входа: успех, неверный пароль, нет сети (сообщения прежние).
git diff --check; сцены/префабы не менялись без отдельного пункта.
F. Риски и неизвестные вопросы
- Арт-файла ещё нет в проекте — в чате только превью 1680×945. До появления файла C2 работает на градиенте; финальный вид не принять.
- Логотип — часть арта; отдельный слой потребует прозрачного PNG и аккуратного позиционирования, иначе логотип «поедет» на другом AR.
- Свечение в uGUI — bloom пост-обработки не действует на Screen Space Overlay: glow только запечённый в спрайт (несколько слоёв, без шейдеров).
- Шрифт:
LegacyRuntimeдаёт нейтральную геометрию; для совпадения с референсом нужен TTF с кириллицей (Inter/Exo 2) — ждём решение. - Отказ от 3D в Login ломает
SceneSmokeи может задеть EditMode-тесты, которые искали окружение; правится в C6/C9. - Адрес сервера без UI — смена стенда только через меню (C4) или
PlayerPrefs; в README нужно оставить инструкцию. - Сброс пароля — заглушка; если появится API, экран расширяется отдельной задачей.
- Открытых вопросов, блокирующих C1–C7, нет; C2/C8 ждут арт.
G. Результат
- Реализовано: C1–C9.
- Проверки: компиляция без ошибок; EditMode 60/60 (в копии без
Library,+Login_Hotkeys_Dispatch_Submit_And_Cancel);SceneSmoke.Run—success=True active=Login env=False backdrop=True login=True; standalone собран в копии; экран снят на 1920×1080 в прошлом проходе; меню открывается и закрывается. - Не завершено:
- C10: ручная сверка с референсом, поведение Enter/Esc и меню на standalone — за пользователем.
- Замечания: панель и поля полупрозрачные (0.94 / 0.97) — сквозь них
видно арт; если нужно плотнее, поднять альфу. Иконки собраны из примитивов
(
Compose), шрифт —LegacyRuntime. - Skill обновлён: не требуется.
- Git: не коммитилось.
TASK-2026-022 — Lobby по референсу: дашборд, заглушки и сцена Community
- Статус:
[!] - Создано: 2026-10-31
- Анализ: DeepSeek выполнен (референс Lobby от 2026-10-31, решения ниже)
- Реализация: DeepSeek: C1–C11 выполнены
- Проверка: EditMode 62/62;
SCENE_SMOKE,PLAYMAT_SMOKE, standalone; ручная приёмка — за пользователем - Затронутые системы:
LobbySceneController, новыйLobbyView(вместоMetaView), новыйLobbyBackdrop, новыйBattleEntryOverlay, меню, новая сценаCommunity+CommunitySceneController/CommunityView,SceneFlow,SceneBuilder,SceneSmoke,Localization, EditMode-тесты. Сервер, правила и протокол не меняются.
A. Цель и требования
Привести Lobby к композиции референса, но оставить только реально
поддержанные функции; отсутствующие в сервере блоки — честные заглушки
«скоро» без фейковых цифр.
Состав экрана (1920×1080):
- Верхняя панель (≈96 px): аватар (инициалы, ассетов нет), ник,
RankedMmr, бейдж сезона-заглушки; справа — «Рейтинг», «Сообщество», «Меню». - Левая колонка (≈560 px): три крупные плашки с иконкой, заголовком и
подписью —
BATTLE,DECK BUILDER,SHOP. - Блок миссий под плашками: заголовок «Ежедневные / еженедельные задания» и 2–4 строки-заглушки с замком и «скоро». Прогресс и таймер обновления не рисуются: серверной модели нет.
- Балансы внизу слева: Gold, Dust, Tokens; клик открывает магазин.
- Центр: большая панель
Chat— заглушка «скоро» с полем ввода в состоянии disabled. - Справа: панель
Friends Online— заглушка: счётчик без данных не показывать, 3–5 строк-заглушек, «скоро». - Фон: процедурный тёмный неоновый градиент с сеткой и виньеткой в
стиле Login. 3D-окружение в
Lobbyне строится.
Поведение:
- BATTLE открывает модальный оверлей: список колод, режим
Рейтинговый/С ботом, кнопка «В бой». Без колод или без валидной колоды кнопка disabled и есть переход «Собрать колоду» вDeckBuilder. Рейтинговый режим уходит в существующую очередьclassic-ranked(Flow.OpenLobbyWithQueueAsync), «С ботом» —StartPracticeAsyncиLoadBattleAsync. Серверные контракты не меняются. - Rating — оверлей-заглушка «Рейтинг — скоро». Лидерборд (top-100 по
RankedMmr) — отдельная задача с серверным endpoint. - Community — отдельная сцена-каркас с вкладками «Гайды / Колоды / Тикеты», внутри каждой — заглушка. Реальные гайды, публичные колоды и отправка тикетов — отдельные задачи с сервером.
- Меню — гамбургер: язык RU/EN, версия, адрес сервера, «Выйти», «Закрыть»; Esc и клик вне панели закрывают.
- Онбординг в Lobby не показывается: ни статуса, ни кнопки. Выбор стартовой триал-деки остаётся отдельным экраном до Lobby; когда появится обучение, он будет заменён им.
Ограничения:
- без новых пакетов и без Addressables;
- сервер, правила, протокол и контент не меняются;
QueueView,StoreView,HistoryView,DeckBuilderиBattleсохраняют текущее поведение;Loginне должен измениться визуально при выносе общего меню;- геймплей и визуальную приёмку проверяет пользователь.
Критерии готовности:
- композиция и стиль совпадают с референсом на 1920×1080, на 16:10 и 21:9 фон заполняет экран, панели не разъезжаются;
- все несерверные блоки визуально помечены «скоро» и не кликабельны;
- BATTLE доводит до очереди или практики без захода в редактор колоды;
- Community открывается как отдельная сцена, вкладки переключаются;
- в Lobby нет упоминаний онбординга;
- существующие EditMode-тесты и смоуки обновлены и проходят.
B. Текущее состояние
LobbySceneControllerстроит 3D-окружение (SceneEnvironment.Build), создаётMetaView,OnboardingView,QueueView,StoreView,HistoryView; при!OnboardingCompletedпоказывает онбординг вместо лобби; «В бой» ведёт вDeckBuilder.MetaView(Runtime/UI/MetaView.cs): топбарVANGUARD+ ник + язык + «Выйти», 5 статистик (Gold/Dust/Tokens/Ranked/Casual), 4 кнопки (Коллекция/Магазин/История/В бой), запись, статус, кнопка выбора триал-деки. Полностью заменяется.QueueView— толькоclassic-ranked; практика запускается изDeckBuilderView(«С ботом»).- Сервер:
UserEntityхранитUserName,RankedMmr,Matches,Wins, но endpoint лидерборда, миссий, чата, друзей, сезонов и тикетов отсутствует. - Аватаров в проекте нет; ассетов фона Lobby нет.
SceneSmokeтребуетVanguard 3D EnvironmentдляLobby; тестыClientSmokeTestsсоздаютMetaViewнапрямую и проверяютMetaScreen,OnboardingScreen.- Общие визуальные атомы —
NeonUiизTASK-2026-021.
Что сохранить:
AuthService,MetaService,PlayerState, обработку 401 → Login;- существующие экраны магазина, истории, очереди, реплеев;
SceneFlowкак единственный переход между сценами;UiKit/NeonUi, CanvasScaler 1920×1080;- текущий визуальный язык Login.
C. Чек-лист изменений
-
C1.
CREATERuntime/UI/LobbyBackdrop.cs— процедурный фон.- Вертикальный градиент, сетка, центральное свечение и виньетка; спрайт кешируется статически, создаётся один раз.
- Cover-масштабирование на 16:9/16:10/21:9 без полос; при появлении арта заменяется одним изображением без правки раскладки.
- Объект называется
LobbyBackdropдля смоука. - Реализация: выполнена. Проверка: EditMode 62/62,
SCENE_SMOKE. - Зависит: нет.
-
C2.
CREATERuntime/UI/LobbyView.cs— новый дашборд вместоMetaView.- Топбар: аватар-инициалы, ник, MMR, сезон-заглушка, «Рейтинг», «Сообщество», «Меню».
- Левая колонка: BATTLE / DECK BUILDER / SHOP с иконками и подписями; блок миссий-заглушка; балансы Gold/Dust/Tokens с переходом в магазин.
- Центр:
Chat-заглушка; справа:Friends Online-заглушка. - Корневой объект
LobbyScreen; тексты черезLoc. - Реализация: выполнена. Проверка:
Lobby_Shows_Actions_Stubs_And_Balances_Without_Onboarding. - Зависит: C1, C9.
-
C3.
MODIFYRuntime/App/LobbySceneController.cs— сборка Lobby без 3D и безMetaView.- Убран
SceneEnvironment.Build(SceneTheme.Lobby); создаютсяLobbyBackdrop,LobbyView,BattleEntryOverlay, рейтинг-заглушка иHotkeysDriver(Esc). - Убраны статус и кнопка онбординга из лобби; при
!OnboardingCompletedпо-прежнему открывается отдельный экран выбора триал-деки. - Подключены BATTLE-оверлей, рейтинг-заглушка, Community →
SceneFlow. - Реализация: выполнена. Проверка: EditMode 62/62,
SCENE_SMOKE. - Зависит: C2, C4, C5, C6.
- Убран
-
C4.
CREATERuntime/UI/BattleEntryOverlay.cs— выбор колоды и режима.- Загрузка колод
MetaService.GetDecksAsync, выбор карточкой, режимы «Рейтинговый» / «С ботом», кнопка «В бой», «Собрать колоду». - Валидация через
ValidateDeckAsyncперед запуском; ошибки — в панели. - Ranked закрывает оверлей и открывает существующую очередь
(
LobbySceneController.OnRanked→QueueView.Show); практика —StartPracticeAsync+Flow.LoadBattleAsync. - Закрытие: крестик и Esc (фон блокируется).
- Реализация: выполнена. Проверка: компиляция, EditMode 62/62; сетевой сценарий — ручная проверка.
- Зависит: C2.
- Загрузка колод
-
C5.
CREATEсценаCommunity.Scenes/Community.unity,CommunitySceneController,Runtime/UI/CommunityViewс вкладками «Гайды / Колоды / Тикеты» и заглушками; кнопка «Назад» в Lobby.SceneFlow: константаCommunityиLoadCommunityAsync;SceneBuilder: создание сцены и добавление в Build Settings послеLobby.- Серверных вызовов нет.
- Реализация: выполнена. Проверка:
Community_Tabs_Switch_Content, сцена собрана (6 сцен в Build Settings). - Зависит: C2.
-
C6.
MODIFYменю — общий гамбургер для Login и Lobby.LoginMenuвынесен в общийRuntime/UI/HamburgerMenu.cs(язык, версия, адрес сервера, закрыть; для Lobby дополнительно «История матчей» и «Выйти»).Loginиспользует его без визуальных изменений; в Lobby «Выйти» переехал из топбара в меню.- Esc закрывает меню через
HotkeysDriver; клик вне панели работает. - Реализация: выполнена. Проверка: EditMode 62/62, Login не изменён.
- Зависит: C2.
-
C7.
DELETE/MODIFYRuntime/UI/MetaView.cs— удалить после переноса функций вLobbyView.- Обновление профиля и обработка 401 → Logout перенесены в
LobbyView;MetaViewудалён вместе с.meta. - Реализация: выполнена. Проверка: EditMode 62/62, ссылок на
MetaViewне осталось. - Зависит: C2, C3.
- Обновление профиля и обработка 401 → Logout перенесены в
-
C8.
MODIFYEditor/SceneSmoke.cs+Editor/SceneBuilder.cs.Lobbyпроверяется поLobbyBackdropиLobbyScreen; 3D-окружение для неё больше не требуется.SceneBuilderсоздаётCommunityи добавляет её в Build Settings послеLobby.- Реализация: выполнена. Проверка:
SCENE_SMOKE success=True active=Login backdrop=True; сцена Community собрана. - Зависит: C2, C5.
-
C9.
MODIFYRuntime/UI/Localization.cs— новые ключи.- Рейтинг, Сообщество, подписи плашек, задания, чат, друзья, «скоро», режимы, ошибки проверки колоды, вкладки Community.
- Реализация: выполнена. Проверка: дубликатов ключей нет, EditMode 62/62.
- Зависит: C2, C4, C5, C6.
-
C10.
TESTEditMode.LobbyView: три плашки, балансы, «скоро», отсутствие онбординга.CommunityView: переключение вкладок.- Существующий
Client_Views_Buildпереведён сMetaViewнаLobbyView; проверкаLobbyScreen. - Реализация: выполнена. Проверка: EditMode 62/62 в копии без
Library. - Зависит: C1–C9.
-
C11.
VERIFYEditMode, smoke, standalone.- Копия проекта без
Library;SceneSmoke.Run,RunPlaymat; standalone-сборка и запуск. - Реализация: выполнена. Проверка: EditMode 62/62,
SCENE_SMOKE success=True,PLAYMAT_SMOKE success=True,WINDOWS_BUILD result=Succeeded errors=0; визуальная сверка с референсом — за пользователем. - Зависит: C10.
- Копия проекта без
D. Последовательность выполнения
- C1 → C2: фон и раскладка дашборда; проверить 16:9/16:10/21:9.
- C6: общее меню; убедиться, что Login не изменился.
- C3 → C4: контроллер Lobby, убрать 3D/онбординг, BATTLE-оверлей.
- C5: сцена Community и переход.
- C7 → C9: удаление
MetaView, смоук, локализация. - C10 → C11: тесты, smoke, standalone, ручная приёмка.
E. Проверки
- Клиентские EditMode в копии без
Library. SceneSmoke.Run(Login/Lobby), проверкаCommunity.SceneSmoke.RunPlaymat— поле не должно пострадать.- Standalone-сборка и запуск на 1920×1080; при возможности 16:10, 21:9.
git diff --check; отсутствие изменений вserver/,content/,Vanguard.Rules/Shared.- Ручная проверка: BATTLE → очередь/бот, магазин, история, коллекция, Community, меню, Esc, отсутствие онбординга в Lobby.
F. Решения и риски
Зафиксировано пользователем (2026-10-31):
- Блоки без сервера (миссии, чат, друзья, сезон, рейтинг) — заглушки «скоро».
- Центральный 3D-блок убрать, область отдать большой панели чата.
- Rating — в будущем топ игроков по рейтингу; сейчас заглушка.
- Community — отдельная сцена: гайды, колоды, тикеты; первая версия — каркас с заглушками.
- BATTLE — оверлей выбора колоды и режима.
- Онбординг в Lobby не показывать; выбор триал-деки остаётся отдельным экраном до появления обучения.
- Фон Lobby — процедурный, арт позже.
Риски:
- Пустая область чата: большая заглушка может выглядеть как дыра; нужен аккуратный placeholder (иконка, пояснение, «скоро»), иначе экран проигрывает референсу.
- Процедурный фон без арта будет плоским; заменить на key art, когда появится, без правки раскладки.
- Аватаров нет — инициалы; при появлении загрузки аватаров заменить.
- Удаление
MetaViewзатрагиваетClientSmokeTestsиSceneSmoke; менять их в том же блоке. - Новая сцена требует
SceneBuilderи Build Settings; иначеLoadSceneAsyncвернёт ошибку. - Онбординг новых аккаунтов: выбор триал-деки нельзя потерять, иначе новый игрок останется без колоды.
- Общее меню не должно менять поведение Login (Tab/Enter/Esc).
- BATTLE-оверлей не должен блокировать бой из-за пустой коллекции: причина disabled должна быть видимой.
Открытых вопросов, блокирующих старт, нет.
G. Результат
- Реализовано: C1–C11. Lobby — 2D-дашборд: процедурный фон, топбар
(инициалы, ник, MMR, сезон-заглушка), три плашки, миссии-заглушка,
балансы, чат- и друзья-заглушки, меню с историей и выходом. BATTLE —
оверлей выбора колоды/режима с серверной валидацией. Rating — заглушка.
Community — отдельная сцена с вкладками.
MetaViewудалён. - Проверки: EditMode 62/62 в копии без
Library;SCENE_SMOKE success=True active=Login env=False backdrop=True;PLAYMAT_SMOKE success=True board=True cards=25 hand=5/5;WINDOWS_BUILD result=Succeeded errors=0; standalone запущен. - Не завершено: визуальная сверка с референсом, BATTLE → очередь/бот, магазин/история/коллекция, Community и меню — ручная проверка пользователя.
- Замечания: сцены
Login/Lobby/DeckBuilder/BattleпослеSceneBuilder.BuildAllсодержали только churn fileID — откачены; в репозиторий добавлена только новаяCommunity.unity. Арт фона Lobby отсутствует, фон процедурный. - Skill обновлён: не требуется; правила и архитектура не менялись.
- Git: не коммитилось.
TASK-2026-023 — DeckBuilder: один экран, мультифильтры и список колоды
- Статус:
[!] - Создано: 2026-10-31
- Анализ: DeepSeek выполнен
- Реализация: DeepSeek: C1–C11 выполнены
- Проверка: EditMode 67/67;
SCENE_SMOKE,PLAYMAT_SMOKE; ручная приёмка — за пользователем - Затронутые системы:
Runtime/UI/DeckBuilderView.cs,Runtime/UI/CardImageService.cs,Localization.cs, EditMode-тесты. Сервер, правила, протокол и YAML не меняются.
A. Цель и требования
Переделать декбилдер по решениям пользователя от 2026-10-31:
- Один экран вместо двух: слева коллекция, справа панель, которая переключается между «Мои колоды» и «Колода» при входе в редактор.
- Мультивыбор фильтров по клану, грейду и триггеру в модальном оверлее; выбранные значения подсвечены, есть «Применить» и «Сбросить».
- Корректный список колод справа: имя,
50/50,T 16/16, формат, распределение по грейдам, бейдж валидности, подсветка открытой колоды. - В редакторе справа вместо списка колод — карты этой колоды: превью
только иллюстрации карты (без рамки и текста, без искажений), имя,
количество; сортировка грейд → имя; группировка по
nameId. - Live-валидация 50/16/4; «Сохранить» и «В бой» активны только для валидной сохранённой колоды.
- Поведение сохранения, создания, удаления, крафта и разбора не меняется.
- Геймплей и визуальную приёмку проверяет пользователь.
Критерии готовности:
- переключение «список колод ⇄ колода» не пересоздаёт сцену и не теряет выбранные фильтры;
- мультивыбор клана/грейда/триггера реально фильтрует коллекцию и отображается в сводке;
- в списке колоды одна строка на карту (
nameId), превью — иллюстрация без растяжения, порядок грейд → имя; - список колод показывает валидность и счётчики, открытая колода подсвечена;
- существующие EditMode-тесты и смоуки проходят.
B. Текущее состояние
DeckBuilderView(1435 строк) строит два полноэкранных режима (DeckListиDeckEditor) с отдельными топбарами и двумя гридами коллекции; переключение —ShowEditor/BackToList.- Правая колонка фиксирована на 300 px: в списке — ряды 76 px
(
имя,N/50 · classic), в редакторе — ряды 64 px (превью 36×50,G, имя,×N · триггер). - Колода хранится как список
printingId; в редакторе группируется поprintingIdи сортируется по нему же. Одна карта в разных принтах даёт две строки, хотя лимит 4 копии считается поnameId. - Фильтры — модальный оверлей: одиночные значения (клан, грейд, триггер), выбранное состояние не подсвечивается, сводка показывает по одному значению.
CardImageService.ApplyставитpreserveAspect = false: арты 350×511 растягиваются в область 174×112 (сетка) и 36×50 (список).- Валидация выполняется только при сохранении; кнопки активны всегда.
- Тестов на фильтрацию/сортировку нет;
ClientSmokeTestsтолько создаётDeckBuilderView.
Что сохранить:
- загрузку коллекции/каталога/колод и контракты
MetaService; - лимиты 50/16/4 и правила добавления/удаления;
- оверлей карты (ПКМ), крафт/разбор;
- сцена
DeckBuilderи переходыSceneFlow; - 3D-окружение сцены не трогать в этой задаче.
C. Чек-лист изменений
-
C1.
MODIFYRuntime/UI/CardImageService.cs— превью иллюстрации.ApplyIllustration(Image, imageKey, fallback): спрайт из верхней части карты —Rect(0, h * 0.41, w, h * 0.59)(350×511), с отдельным кешем.preserveAspect = true; при отсутствии арта — процедурный fallback.- Полный арт (
Apply) не изменён. - Реализация: выполнена. Проверка: EditMode 67/67, ручная — позже.
- Зависит: нет.
-
C2.
MODIFYRuntime/UI/DeckBuilderView.cs— один экран.- Убраны
_listView/_editorView; один кореньDeckBuilderScreen: топбар (назад в Lobby, заголовок, сводка фильтров, фильтры, сброс) и тело (коллекция + правая панель 380 px). - Правая панель:
DeckListPanelиDeckPanel; переключение без смены сцены; статус — под коллекцией. - Реализация: выполнена. Проверка: EditMode 67/67, панели в
Client_Views_Build. - Зависит: C1, C3, C4.
- Убраны
-
C3.
MODIFYсписок колод.- Строка: имя,
N/50,T N/16,Classic,G0…G3, бейдж «Готова / Не готова»; валидность считается локально. - Открытая колода подсвечена; «Создать» — в шапке панели.
- Реализация: выполнена. Проверка: EditMode 67/67, ручная — позже.
- Зависит: C2.
- Строка: имя,
-
C4.
MODIFYсписок карт колоды.- Группировка по
nameId; счётчик — сумма принтов; превью — иллюстрация последнего принта группы. - Строка 84 px: превью 64×54, имя,
G,×N, триггер и клан; сортировка грейд → имя. - Клик — убрать копию; ПКМ — карточка.
- Реализация: выполнена. Проверка:
GroupDeck_*тесты, EditMode 67/67. - Зависит: C1, C2.
- Группировка по
-
C5.
MODIFYфильтры — мультивыбор.DeckFilterс наборами клана/грейда/триггера; пустой набор = «все».- Оверлей: чипы с подсветкой, «Сбросить» (черновик), «Отмена»,
«Применить»; сводка
Клан: … · Ранг: … · Триггер: …. - Применение пересобирает коллекцию; счётчики обновляются точечно.
- Реализация: выполнена. Проверка: тесты фильтра, EditMode 67/67.
- Зависит: C2, C6.
-
C6.
CREATERuntime/UI/DeckListFilter.cs.DeckFilter,DeckCardGroup,DeckValidation,DeckListModel:Matches,GroupDeck,Validate,IsTrigger.- Реализация: выполнена. Проверка: 4 теста
DeckBuilderTests. - Зависит: C4, C5.
-
C7.
MODIFYячейки коллекции.- Иллюстрация
ApplyIllustration, область арта 174×144 без растяжения. - Счётчик по
nameId; при лимите 4 или 16 триггеров цифры красные; добавление по-прежнему блокируется с сообщением. - Реализация: выполнена. Проверка: EditMode 67/67, ручная — позже.
- Зависит: C1, C5.
- Иллюстрация
-
C8.
MODIFYlive-валидация.UpdateStats: счётчики, распределение, «не сохранено», цвет; «Сохранить» — при валидной колоде, «В бой»/«С ботом» — только для сохранённой валидной колоды; «Удалить» — для сохранённой.- Ошибки — в статусе, без модальных окон.
- Реализация: выполнена. Проверка: EditMode 67/67, ручная — позже.
- Зависит: C3, C4.
-
C9.
MODIFYRuntime/UI/Localization.cs— новые ключи.- «Создать», «К списку колод», «Готова/Не готова», варианты триггеров, «Сбросить», «Применить», «Удалить колоду», «не сохранено», ошибки.
- Реализация: выполнена. Проверка: дубликатов ключей нет.
- Зависит: C2–C5.
-
C10.
TESTEditMode.DeckBuilderTests: пустой фильтр, мультивыбор, группировка/сортировка, неизвестный принт, валидация 50/16/4.Client_Views_Build: провереныDeckListPanel,DeckPanel,FilterOverlay.- Реализация: выполнена. Проверка: EditMode 67/67 в копии без
Library. - Зависит: C1–C9.
-
C11.
VERIFYEditMode, smoke, standalone.- Копия без
Library; EditMode;SCENE_SMOKE;PLAYMAT_SMOKE. - Реализация: выполнена. Проверка: EditMode 67/67,
SCENE_SMOKE success=True,PLAYMAT_SMOKE success=True; ручная проверка — за пользователем. - Зависит: C10.
- Копия без
D. Последовательность выполнения
- C1 + C6: обрезка иллюстрации и чистые функции фильтра/сортировки/групп.
- C2: один экран и переключение правой панели.
- C3–C4: список колод и список карт колоды.
- C5 + C7: мультифильтры и ячейки коллекции.
- C8–C9: валидация и локализация.
- C10–C11: тесты, smoke, standalone, ручная приёмка.
E. Проверки
- EditMode в копии без
Library. SceneSmoke.Run,RunPlaymat, standalone-сборка.git diff --check; нет изменений вserver/,content/,Vanguard.Rules.- Ручная проверка — пользователь.
F. Решения и риски
Зафиксировано пользователем (2026-10-31):
- Один экран с двумя панелями.
- Превью — только иллюстрация карты (без рамки и текста).
- Фильтры — модальный оверлей с мультивыбором.
- Триггерный фильтр — тоже мультивыбор.
- Сортировка карт колоды — грейд → имя; группировка по названию.
Риски:
- Границы иллюстрации: доля 0.59 снята с BT01/TD01 (350×511); если встретится другой макет карты, полоса флейвора может попасть в кадр. Константы вынести в одно место и проверить на нескольких сетах.
- Группировка по
nameId: при смешанных принтах в строке показывается иллюстрация первого; удаление уменьшает суммарный счётчик. - Один экран: легко потерять состояние (открытая колода, черновик фильтров). Хранить явно и сбрасывать только по действию пользователя.
- Пересборка грида: при смене фильтра она неизбежна; не пересобирать на каждый клик добавления — обновлять счётчики точечно.
- Валидность: локальная проверка должна совпадать с серверной
(
DeckValidator), иначе «Сохранить» включится, а сервер откажет. - 3D-фон DeckBuilder остаётся; если позже переведём на 2D, это отдельная задача.
Открытых вопросов, блокирующих старт, нет.
G. Результат
- Реализовано: C1–C11. DeckBuilder — один экран: коллекция с
мультифильтрами (клан/грейд/триггер), справа панель «Мои колоды» ⇄
«Колода». Список колод показывает
50/50, триггеры, грейды и валидность; список колоды группируется поnameId, сортируется грейд → имя, превью — иллюстрация карты без искажений. Live-валидация управляет «Сохранить»/«В бой»/«С ботом». - Проверки: EditMode 67/67 в копии без
Library(+5 тестовDeckBuilderTests);SCENE_SMOKE success=True;PLAYMAT_SMOKE success=True. - Не завершено: ручная проверка фильтров, переключения панелей, добавления/удаления, сохранения, «В бой»/«С ботом», ПКМ-карточки.
- Замечания: граница иллюстрации 0.59 подобрана по BT01/TD01 (350×511); при другом макете карты константу нужно проверить. Правка имени колоды помечает колоду как несохранённую.
- Продолжение: визуальная компоновка переработана по референсу в
TASK-2026-024(топбар Lobby, крупные карты, фильтры в оверлее). Логика фильтров, группировки и валидации переиспользуется. - Skill обновлён: не требуется.
- Git:
ecb7314.
TASK-2026-024 — DeckBuilder по референсу: топбар Lobby, крупные карты, фильтры
- Статус:
[!] - Создано: 2026-11-01
- Анализ: DeepSeek выполнен (референс DeckBuilder от 2026-11-01)
- Реализация: DeepSeek: C1–C10 выполнены
- Проверка: EditMode 69/69;
SCENE_SMOKE,PLAYMAT_SMOKE; ручная приёмка — за пользователем - Затронутые системы:
LobbyView, новыйPlayerTopBar,HamburgerMenu,DeckBuilderView,DeckBuilderSceneController,CardImageService,DeckListFilter,Localization, EditMode-тесты. Сервер, правила и контент не меняются.
A. Цель и требования
Привести DeckBuilder к композиции референса, сохранив логику
TASK-2026-023 (фильтры, группировка, live-валидация):
- Топбар как в Lobby: аватар, ник, MMR, сезон,
RatingиCommunityнеактивны,Menu— язык, версия, адрес сервера, история, «В лобби», «Выйти». - Без вкладок Collection/Deck Builder — это элемент референса, не функция.
- Коллекция — крупные карты со скроллом (6 в ряд): номер грейда, иллюстрация, плашка имени поверх, строка количества, камень редкости. Пагинации нет.
- Режим просмотра: карты коллекции только смотрят, крафтят и разбирают; ЛКМ по карте ничего не делает, ПКМ открывает карточку. В этом режиме под картой — «есть ×N».
- Режим колоды: при выборе колоды справа появляется её состав, добавление/удаление включается; ЛКМ по карте коллекции добавляет копию, ПКМ — карточка. Под картой — «в колоде ×N · есть ×M».
- Список колод: кнопка
+ Новый набор, строки с эмблемой клана, именем,N/50иT N/16, кебаб-меню (открыть/удалить), подсветка выбранной. - Фильтры — в модальном оверлее: мультивыбор клана, грейда, триггера и редкости (C/R/RR/RRR/SP), плюс поиск по названию; «Сбросить», «Отмена», «Применить», сводка в шапке.
- Визуальный язык — неоновые панели/свечение/фаски из
NeonUi, как в Login и Lobby.
Ограничения:
- сервер, правила, протокол и контент не меняются;
- 3D-окружение сцены DeckBuilder не трогаем;
- сохранение/создание/удаление/крафт/разбор сохраняют поведение;
- Lobby не должен визуально измениться после выноса топбара;
- ручная приёмка — пользователь.
Критерии готовности:
- DeckBuilder открывается с топбаром Lobby и меню, «В лобби» работает;
- в режиме просмотра клик по карте не добавляет её в колоду;
- после выбора колоды справа состав, ЛКМ добавляет, клик по строке состава убирает;
- крупные карты не растянуты, имя и количество читаются, скролл плавный;
- мультифильтры + редкость + поиск реально фильтруют и отражаются в сводке;
- EditMode и смоуки проходят.
B. Текущее состояние
DeckBuilderView(ecb7314) — один экран со своим топбаром (назад, заголовок, сводка, фильтры, сброс), коллекция 174×238 сApplyIllustration, правая панель 380 px со списком колод и составом.- Клик по карте коллекции всегда добавляет копию (в обоих режимах).
- Фильтры — модальный оверлей без редкости и поиска.
- Топбар Lobby реализован внутри
LobbyView(TopBar,AddTopAction), меню —HamburgerMenu. LobbyViewпоказывает аватар-инициалы, ник, MMR, сезон, Rating, Community и гамбургер.DeckBuilderSceneControllerрезолвит толькоMetaService/AuthService.
Что сохранить:
DeckListModel/DeckFilter/DeckValidationи тесты;CardImageService.ApplyIllustration;- правую панель со списком колод/составом и live-валидацию;
- крафт/разбор и ПКМ-карточку;
- Lobby: расположение и поведение элементов после выноса топбара.
C. Чек-лист изменений
-
C1.
CREATERuntime/UI/PlayerTopBar.cs;MODIFYLobbyView.cs.- Топбар вынесен: аватар, ник, MMR, сезон, две кнопки, гамбургер;
подписка на
PlayerState;HamburgerMenuс «В лобби». null-действие отключает кнопку;LobbyViewиспользует компонент.- Реализация: выполнена. Проверка: EditMode 69/69,
SCENE_SMOKE. - Зависит: нет.
- Топбар вынесен: аватар, ник, MMR, сезон, две кнопки, гамбургер;
подписка на
-
C2.
MODIFYRuntime/App/DeckBuilderSceneController.cs.- Резолвит
PlayerState/AppConfig; создаётPlayerTopBarс неактивными Rating/Community и «В лобби» → Lobby; освобождает его. - Реализация: выполнена. Проверка: EditMode 69/69.
- Зависит: C1.
- Резолвит
-
C3.
MODIFYDeckBuilderView— каркас.- Собственный топбар убран; тело под
PlayerTopBar(верх -120). - Панели
DeckListPanel/DeckPanel, статус под коллекцией, отдельная строка фильтров со сводкой. - Реализация: выполнена. Проверка: EditMode 69/69.
- Зависит: C1, C2.
- Собственный топбар убран; тело под
-
C4.
MODIFYсетка коллекции.- 6 колонок (
FixedColumnCount), ячейка 216×242, вертикальный скролл. - Ячейка: иллюстрация 216×182, номер грейда в углу, плашка имени поверх низа, строка количества, камень редкости.
- ЛКМ в просмотре не добавляет; ПКМ — карточка; в режиме колоды ЛКМ добавляет.
- Количество: «есть ×N» / «в колоде ×N · есть ×M».
- Реализация: выполнена. Проверка: EditMode 69/69, ручная — позже.
- Зависит: C3, C5.
- 6 колонок (
-
C5.
MODIFYрежимы просмотра и колоды.- Режим определяется
_deckOpen: просмотр — панель колод, добавление выключено; открытие/создание колоды включает добавление. - «К списку колод» сбрасывает
_editing, состав и возвращает просмотр (несохранённые изменения отбрасываются). - Реализация: выполнена. Проверка: EditMode 69/69, ручная — позже.
- Зависит: C3.
- Режим определяется
-
C6.
MODIFYсписок колод по референсу.+ Новый наборна всю ширину.- Строка: эмблема клана (процедурная), имя,
N/50 · T N/16(цвет — валидность), кебаб с меню «Открыть / Удалить / Отмена»; открытая колода подсвечена. - Реализация: выполнена. Проверка: EditMode 69/69, ручная — позже.
- Зависит: C3.
-
C7.
MODIFYфильтры.DeckFilter:Rarities(C/R/RR/RRR/SP) иSearch.- Оверлей: поиск, редкость, клан, грейд, триггер; «Сбросить», «Отмена», «Применить»; сводка включает редкость и поиск.
- Реализация: выполнена. Проверка:
Rarity_And_Search_Filter_Are_Applied. - Зависит: C3.
-
C8.
MODIFYLocalization.cs— «В лобби», «Новый набор», «Поиск по названию», «Редкость», «есть», «в колоде», «Открыть».- Реализация: выполнена. Проверка: дубликатов ключей нет.
- Зависит: C4–C7.
-
C9.
TESTEditMode.DeckBuilderTests: редкость и поиск;ClientSmokeTests:PlayerTopBarс неактивными кнопками,DeckListPanel/DeckPanel/FilterOverlay.- Реализация: выполнена. Проверка: EditMode 69/69.
- Зависит: C1–C8.
-
C10.
VERIFYEditMode, smoke, standalone.- Реализация: выполнена. Проверка: EditMode 69/69,
SCENE_SMOKE success=True,PLAYMAT_SMOKE success=True; ручная — пользователь. - Зависит: C9.
- Реализация: выполнена. Проверка: EditMode 69/69,
D. Последовательность выполнения
- C1:
PlayerTopBarи меню; проверить, что Lobby не изменился. - C2–C3: DeckBuilder с топбаром Lobby.
- C4–C5: крупная сетка и режимы просмотра/колоды.
- C6: список колод по референсу.
- C7–C8: фильтры, поиск, локализация.
- C9–C10: тесты, смоуки, standalone, ручная приёмка.
E. Проверки
- EditMode в копии без
Library. SceneSmoke.Run,RunPlaymat, standalone.- Проверка Lobby после выноса топбара (визуально и смоуком).
git diff --check; нет изменений вserver/,content/,Vanguard.Rules.- Ручная приёмка — пользователь.
F. Решения и риски
Зафиксировано пользователем (2026-11-01):
- Топбар как в Lobby;
Rating/Communityнеактивны; «В лобби» — в меню. - Вкладки Collection/Deck Builder не реализуем.
- Коллекция — крупные карты, вертикальный скролл, без пагинации.
- Просмотр: ЛКМ не добавляет, ПКМ открывает карточку.
- В режиме колоды справа состав, ЛКМ добавляет, клик по строке убирает.
- Количество: «есть ×N» / «в колоде ×N · есть ×M».
- Фильтры — всё в оверлее, включая редкость C/R/RR/RRR/SP и поиск.
Риски:
- Вынос топбара затрагивает принятый Lobby: менять аккуратно, проверять смоук и раскладку.
- ПКМ-only в просмотре может быть неочевидным: нужна подсказка «ПКМ — подробности» в статусе/шапке коллекции.
- Несохранённые изменения при возврате к списку теряются; при необходимости добавить подтверждение отдельным пунктом.
- Крупные ячейки уменьшают число видимых карт: скролл должен быть плавным, без пересоздания пула на каждый кадр.
- Кебаб-меню требует отдельного маленького оверлея; не дублировать существующие меню.
- Редкости SP в каталоге есть; если у принтов встретится другая строка, чип не совпадёт — показывать как есть.
Открытых вопросов, блокирующих старт, нет.
G. Результат
- Реализовано: C1–C10. Общий
PlayerTopBarдля Lobby и DeckBuilder (Rating/Community неактивны, «В лобби» в меню). Крупная сетка коллекции 6×N со скроллом: грейд, иллюстрация, имя поверх, количество, камень редкости. Просмотр без добавления (только ПКМ-карточка), режим колоды включает добавление. Список колод с+ Новый набор, эмблемами, счётчиками, кебаб-меню. Фильтры в оверлее: клан, грейд, триггер, редкость, поиск. - Проверки: EditMode 69/69 в копии без
Library;SCENE_SMOKE success=True;PLAYMAT_SMOKE success=True. - Не завершено: ручная проверка топбара/меню, крупной сетки, скролла, фильтров и поиска, режимов, добавления/удаления, кебаб-меню, сохранения и боя.
- Замечания: в просмотре карта открывается только по ПКМ — нужна подсказка в статусе. Несохранённые изменения при «К списку колод» отбрасываются. Ячейка 216×242 (план допускал 216×286 — уменьшено под пропорцию иллюстрации).
- Skill обновлён: не требуется.
- Git: не коммитилось.