Энкаунтеры
Excel-style грид инициативы для боёвки D&D 5e. DM управляет всем; игрок фиксирует урон и броски по своему PC. Завершённый энкаунтер переходит в режим read-only; лут генерируется через бухгалтерию.
Создание энкаунтера
DM создаёт энкаунтер из вкладки app/c/[slug]/encounters/. При создании
автоматически создаётся зеркальная нода типа encounter в каталоге — через
BEFORE INSERT триггер trg_encounter_create_mirror (миграция
039_encounter_mirror_and_loot_drafts.sql). Зеркало нужно как якорь для
лута и летописи; в самом каталоге и сайдбаре оно не отображается.
Участники и грид инициативы
После создания DM добавляет участников двумя способами:
- Из каталога — выбирает ноду (PC, NPC, monster).
max_hpиacсидируются изnode.fields. Монстров можно добавить несколькими экземплярами с одной ноды (addParticipantFromCatalogвlib/encounter-actions.tsпринимает массив HP). - Вручную — произвольное имя и HP без ноды-источника.
Грид строится компонентом components/encounter/encounter-grid.tsx.
Столбцы: инициатива, имя, HP (текущий/макс), AC, условия и эффекты (пилл-редактор),
смерть-бросок. Порядок строк определяется initiative DESC NULLS LAST, sort_order.
HP и урон
current_hp и max_hp — колонки encounter_participants. Временные
HP (temp_hp) добавлены миграцией 004_participant_role_temp_hp.sql. Ячейка
HP — компонент components/encounter/hp-cell.tsx. Изменение HP доступно:
- DM — для любого участника.
- Игрок — только для своего PC (
canEditизlib/auth.ts, зеркалит SQL-функциюcan_edit_node).
AC и спасброски смерти
Миграция 023_ac_and_death_saves.sql добавила два поля на encounter_participants:
ac int— класс доспеха для этого энкаунтера. Nullable; сидируется изnode.fields.acпри добавлении из каталога; после этого живёт отдельно (может меняться в бою).death_saves jsonb—{"successes": 0..3, "failures": 0..3}. Локальное состояние только для этого боя; сбрасывается при HP > 0 или по завершении энкаунтера. Компонент:components/encounter/death-saves-cell.tsx.
Условия и эффекты (пилл-редактор)
Условия (Poisoned, Stunned, …) и эффекты на каждом участнике хранятся в JSONB
(миграции 003_conditions.sql, 005_effects_and_encounter_details.sql,
016_conditions_temporal.sql). Пилл-редактор — components/encounter/pill-editor.tsx:
список цветных пилюль с quick-add и inline-delete. Текущее состояние пиллов
видно всем участникам в реальном времени.
Лог боя
Таблица encounter_log (миграция 015_encounter_log.sql) — хронологический
лог текстовых записей DM о ходах. Поля: author_name, content, meta jsonb
(структурированные данные в будущем), status. Компонент:
components/encounter/encounter-log.tsx.
Status gate: active vs read-only
Поле encounters.status: 'active' или 'completed'. Только активные
энкаунтеры показывают кнопки действий (encounter-controls.tsx). Завершённый
энкаунтер — просмотр лога без редактирования. DM переключает статус вручную.
Лут энкаунтера
После завершения энкаунтера DM генерирует лут через таблицу
encounter_loot_drafts (миграция 039). Черновик лута — lines jsonb
с записями вида {kind: 'coin' | 'item', ...} плюс loop_number, day_in_loop.
После утверждения лут конвертируется в транзакции бухгалтерии.
Подробнее — accounting/README.md.
Mirror-нода и технические детали
Устройство mirror-триггеров, pill-редактора и auth-гейтинг DM/player
расписаны в technical.md.