| 2026-09-07 |
feat(game): диалоги в JSON + dialogueRules (чистый анализ графов) + CLI dry-run
...
- графы диалогов — 6 JSON-файлов в data/dialogues/ (4 пробела + \n),
реестр dialogues.ts собирается JSON-импортами
- новый data/dialogueRules.ts: чистые checkGraph/analyzeGraph — реестры
параметрами, одна истина для валидатора, CLI и будущего редактора
- validate.ts делегирует графы в checkGraph; новые инварианты:
textless-cycle (error), silent-end (warn), string-unknown, item-unknown,
do-item/do-custom-unknown, quest-stage-unreachable (error)
- CLI npm run dialogues:dry [<id>] — прогон графов через DialogueRunner
на пресетах состояния (fresh / quest-taken+flowers / quest-done)
- доки: ui-and-dialogue.md (раздел «Графы в JSON и dry-run»), practices.md,
CLAUDE.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
7 hours ago
|

feat(game): квест-стадии на DialogueConditions; чистка флагов знакомств + миграция v2
...
- QuestStage.ready — данные (DialogueConditions) вместо замыкания; стадия
сдачи — whenVars flowers >= 3. questDialogueFor(state, npc, world?)
фильтрует через движковый evalConditions.
- Двойной учёт знакомств устранён: npcs.flagKey → FLAGS.met_elder/met_mila,
графы уже ставят их сами — talkTo перестал ставить флаг вручную;
camelCase-ключи metElder/metTrader удалены из ids.ts.
- data/migrations.ts: registerStateMigrations + migrateV1toV2
(metElder→met_elder, metTrader→met_mila); Game регистрирует при старте.
- Движок: фикс цикла миграций в GameState.load — выход при достижении
dataVersion (миграция, забывшая повысить version, не портит данные);
контракт задокументирован в core.md, оси версий — в assets-audio-save.md.
- Тесты: две миграции по порядку, незабампленная миграция не применяется
дважды, старый сейв v1 читается, готовность стадии через whenVars.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
7 hours ago
|
feat(game): do[]-эффекты в контенте через EffectSink; QuestEffect-свитч удалён
...
- data/effects.ts: реестр DIALOGUE_CUSTOM (plant_flowers) — имена сюжетных
эффектов, как FLAGS/VARS.
- systems/DialogueEffects.ts: DialogueEffectSink + applyDialogueEffect
(give/take в сумку, sound, toast, custom; unknown kind — тихий игнор,
валидатор = error).
- DialogueSystem: registerSink + runner.onEffect → sink.
- Контент на do[]: elder_hand_in.accept → custom plant_flowers;
trader_first.give_cloth → giveItem cloth. Удалены QuestEffect,
EXTRA_EFFECTS, questEffectFor, поле QuestStage.effect и ручной switch
в onDialogueFinished (custom откладывается до конца диалога — кат-сцена
не рвёт реплику).
- Валидатор: do[].id give/take ∈ ITEMS, custom ∈ DIALOGUE_CUSTOM (error).
- Сценарий interact-world: первый advance теперь догоняет печать —
двойное нажатие.
- Тесты: give/take в Inventory, custom до sink, unknown игнор.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
7 hours ago
|
game: формат сейва — в saveData.ts, слоты конфигом, дефолт хазарда в контент
...
- scenes/saveData.ts: SAVE_VERSION/ReturnToData/SaveData/normalizeSave вынесены
из MenuScene (формат сейва больше не живёт в файле меню); MenuScene
реэкспортирует для совместимости.
- data/saves.ts: SAVE_SLOTS/slotTitle/canDelete вместо хардкода
['autosave','slot1'...] в SaveSlotsScene (дважды).
- HazardDef.requiresItem стал обязательным — контент уже задаёт 'cloth',
мёртвый фолбэк ?? 'cloth' в LocationScene снят (дефолт — в контенте).
- Тест: слоты/подписи/canDelete (510 всего).
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
8 hours ago
|
UX-пачка: подсказки, клик-зоны, моты, коллизия домов, сундук, тихая вода
...
- Тосты держатся по длине текста (до 6 с) + подсказка сбора колокольчиков
при первом входе в пруды (флаг hint_bells).
- Клик по «телу» объекта: RouterDeps.pixelTile как фолбэк на голом клике —
bbox тел NPC/интерактивов (без подписей) + ремап на высокий тайл (дома).
- Моты: заметная насыпь с пульсирующей искрой, HUD-счётчик, вьюха
растворяется с искрами при поднятии (InteractSink.onConsumed).
- Движок: TallSpec.shadow — тайл (tx-1,ty-1) за домом блокируется
(shadowTilesOf в collision.ts + isWalkable карты, тесты).
- Интерьеры: бронзовый контур проёма + подпись «выход».
- Спрайт сундука (tiles/chest.png) вместо ящика-плейсхолдера.
- Вода прудов: radius 2.5, volume 0.22 — только вплотную и тихо.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
18 hours ago
|
Фикс десинка вью героя (SpriteMotion не двигает blink-view) + звук: ветер, шорохи, тише вода
...
- Движок: SpriteMotion перезаписывает позицию/поворот только при bob/sway —
view с чистым blink/pulse можно двигать извне (герой прибивало к точке
спавна, ходьба выглядела камерным скроллом, по прибытии спрайт
«возвращался»); detach симметричен; тесты SpriteMotion
- PlayerController: syncView на точном прибытии в waypoint (кадр не отстаёт)
- Звук: ambience/wind — глобальный слой (AmbienceLayerDef.radius опционален,
нет at/tiles — константная громкость) на лугах и прудах; вода прудов
тише (0.6→0.35, радиус 6→5); sfx/rustle — редкие дальние шорохи пепла
из тика сцены (rng сцены, случайные pan/rate). Птиц в мире нет по лору
- Доки: anim.md (правило позиционирования), practices.md (глобальные
слои, шорохи, «птицы молчат»)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 hours ago
|
Аудио: стерео-музыка, динамические темы (бой/настороженность), room tone интерьеров
...
- Движок: renderMusicStereo (interleaved L,R, equal-power pan треков,
нормализация по общему пику каналов), createBuffer(channels 1|2);
моно renderMusic бит-в-бит прежним сэмплам
- Игра: темы боя и tension-стем в data/music.ts; threat-тик
LocationScene.updateMusic — chase → тема боя, wary → тихий стем
(setVolume с флагом stemPending против шторма перезапусков)
- Room tone интерьеров: ROOM_TONES (hum-спеки, шина ambience),
запуск в enter, стоп в exit, validate-тест ключей
- checks/music.mjs: инвариант «тема лугов не перезапускается»
(динамические темы/стем — легитимная реакция на врага)
- Доки: assets-audio-save.md (стерео), practices.md (динамическая
музыка, pending-флаг), plan.md (Работа G — сделано)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 hours ago
|
| 2026-09-06 |
audio: палитра спеков (tone/wobble/sweep/layers) — все sfx на спек-синтезе (E4)
...
- SoundSpec: kind 'tone' (чистый тон + свип freqTo), параметры w/attack/
fadeTo/wobbleHz|Depth|Base|Phase, доп. голоса layers (SpecVoice с delay);
без модификаторов бит-в-бит прежним формулам
- data/sfxSpecs.ts: 16 спеков — все бывшие файловые sfx, включая шаги
(StepVariants: варианты renderSpec с сидами base+i·10, fallback — базовый
спек); ui_click во всех сценах через playSfx
- gen.mjs остался только амбиенту; assets/audio/sfx/ удалён; формулы
бывших sfx экспортированы для парити-теста (bit-в-бит / eps 1e-5)
- мост: scene:synthesize принимает kind tone; доки: agent.md,
assets-audio-save.md, practices.md, plan.md (E4 ✅)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 hours ago
|
audio: миграция bell_hit/whoosh на спек-синтез (E3), мёртвый door.wav удалён
...
- SoundSpec: флаг swell (огибающая «0 → 1 → 0» у hit/scrape), у chime 4-й
партиал и константная амплитуда клика — формулы совпали с gen.mjs дословно
- data/sfxSpecs.ts: реестр SPEC_SFX + playSfx — единая точка проигрывания
sfx (AudioSystem, useTransition, collectFlower); ключи в AUDIO_KEYS
- gen.mjs: CLI-гвард (WAV при импорте не пишутся), формулы bellHit/whoosh
экспортированы для парити-теста sfxSpecs.test.ts (бит-в-бит равенство)
- доки: plan.md (E1–E3 ✅, F/G ✅), practices.md, assets-audio-save.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
19 hours ago
|
Движок: секвенсор renderMusic + playLoopBuffer; игра — тема лугов (работа G)
...
Партитура MusicSpec (bpm, beats, партии-стемы: pluck/bell/pad) чисто
компилируется в луп; playLoopBuffer играет буфер памяти на любой шине.
Тема лугов — правило-базовый генератор в data/music.ts (сид, ля-минорная
пентатоника), компиляция в рантайме — WAV для музыки не нужен; у области
поле theme, у Game — playTheme с guard-ом и кроссфейдом. Проба
checks/music.mjs в agent:check. Секвенция тем (бой) — до боевой темы.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
20 hours ago
|
Игра: шаги по поверхностям, звуки предметов, локальные амбиент-слои
...
- Шаги: sfx/step_grass|ash|water|floor по тайлу под ногами (stepKey), старый sfx/step удалён
- Предметы: моты → mote_pickup, сундук → chest_open, знаки/записка → note, whoosh на переходах
- Фауна: событие fauna:startle (FaunaSystem слышит combat:attack) → sfx/deer_startle
- AudioSystem.setLayers: несколько амбиент-слоёв сразу, синхронный дедуп, тик-фейд громкости
- AreaDef.ambienceLayers: вода прудов, гул башни (точка), скрипы домов (тайлы)
- validate-тест покрывает новые ключи через AUDIO_KEYS
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 hours ago
|
Игра: амбиент на шину ambience вместо music, слайдер «Амбиент»
...
- gen.mjs: ключи ambience/meadows|ponds|zvenets -> assets/audio/ambience/ (music/ удалён)
- AUDIO_KEYS вынесен в data/audio.ts (валидатор в node-тестах без ?url-импортов Game)
- Game.playAmbience(key, 0.7) c guard ключа; '' — stopAmbience; шина ambience в settings
- AreaDef: визуальное ambience -> atmosphere, аудио ambience?: string (интерьеры — тишина)
- SettingsScene: Общая / Амбиент / Звуки (ползунок music не показываем — треков нет)
- validate-тест: area.ambience и Interactables.responses[].sound ∈ AUDIO_KEYS
- хвосты music/ в доках вычищены; agent:check зелёный
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
21 hours ago
|
Батч 7: декор-слой (микро-кусты, камни, проплешины)
...
- engine: DecorData + TileMapData.decor; decorLayer между землёй и объектами;
addDecor (возвращает спрайт, один на тайл, повторный заменяет) / clearDecor;
setTile декор не трогает
- engine: MapFileV1.decor + validateDecor (границы, целые, dx/dy — числа)
- game: DECOR-реестр (tuft/stone/bald, id 15-17), buildDecor на createRng(seed+7919)
(~10% наземных тайлов, только GRASS/ASH, смещение не по сетке);
mulberry32 заменён на движковый createRng
- art: decor_tuft/stone/bald 16×16 (рисунок в ромб 16×8, палитра G/P)
- фикс fresh-теста: Math.round -> -0 теряется в JSON, нормализация +0
- тесты: порядок слоёв, addDecor/clearDecor, границы, round-trip + валидация decor
- доки: maps.md (раздел «Декор»), art-style.md, practices.md (ситуация
«меняю генераторы арта или карт», грабля -0)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
22 hours ago
|
Батч 6: варианты текстур тайлов (микс по хэшу координат)
...
- engine: hashTile(x,y,seed) — чистый хэш координат (math/rng.ts)
- engine: TileMapData.variants + setTileVariants + публичный variantOf;
анимация сильнее вариантов (setTileAnimation снимает их)
- engine: MapFileV1.variants (строковые ключи) + validateVariants в parseMap
- game: GRASS_V1/V2, ASH_V1, PATH_V1 (id 11-14), GROUND_VARIANTS в трёх
генераторах карт, новые текстуры в ASSET_KEYS и tileTextures()
- art: grass_2/grass_3/path_2/ash_2 (32×16, та же палитра, другой seed)
- тесты: hashTile (детерминизм/разброс), выбор варианта стабилен при setTile,
анимация vs варианты, round-trip + валидация variants
- доки: maps.md (раздел «Варианты текстур»), art-style.md, art-pipeline.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
22 hours ago
|

Движковые коллизии: круг поверх сетки + LOS по пропам
...
Новый чистый модуль map/collision.ts в движке: gridOf (Grid из
TileMapData с footprint пропов), точная проверка круга circleFits
(ближайшая точка квадрата Blocked-тайла — ловит угловой прокол по
диагонали), moveCircle со скольжением по осям, pushOutOfWalls для
телепортов, separateCircles для будущего расталкивания тел.
Дедупликация четырёх копий worldToTile+isWalkable: движение героя
(moveFree), шаги врагов, фауна и валидатор контента теперь на одних
функциях. IsometricTileMap.isPropBlocked публичен.
Бой против стен: конус удара требует прямой видимости (hasLineOfSight
по tall + пропам), снаряды гасятся о стены и дома (вода прозрачна —
плевок летит над прудом). Отброс героя — только если тело помещается
(circleFits): прищёлкивание к центру тайла после отброса меняло
динамику погонь у прудов и валило пробу interact-world.
14 юнит-тестов на коллизии (скольжение, угловой прокол, совместимость
с A*-маршрутом, push-out, separateCircles). Доки: maps.md (раздел
«Коллизии»), README.md, llms.txt.
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
22 hours ago
|
Сцена на SceneRegistry: NPC/интерактивы/пропы/фауна/враги в одном реестре
...
- дефы получают юниты: NpcDef.pos + atlas?, InteractableDef.pos + view?
(tile вычисляется при загрузке модуля — сейвы/снапшот/валидатор без миграций)
- SceneObjects: фасад реестра области (npc/int/prop с footprint)
- клик-роутинг: npcAt/interactableAt/enemyAt через реестр; чистый
resolveClick и приоритеты не тронуты (пробы transitions/interact зелёные)
- шов врагов ECS: запись с pos по ссылке, move после шага, remove при смерти
- фауна регистрируется (kind 'fauna'), вьюхи NPC — def.atlas, интерактивов —
def.view.tex
- инвариант registry-consistent (реестр согласован с ECS)
Co-Authored-By: Claude Code <noreply@anthropic.com>
root
committed
23 hours ago
|
Реестры флагов/варов + кросс-валидация + pre-commit хук
...
- data/ids.ts: FLAGS/VARS (id = значение, doc — семантика), типы
FlagId/VarId, usedFlag() для used:<id> (была конкатенация в 3 местах).
- Контент и сцена на константах: dialogues/interactables/quests/npcs,
LocationScene (vars), Interactables, GameAgent; QuestStage.effect —
union QuestEffect, doneFlag/flagKey/progressKey типизированы.
- validateReferences(): флаг/вар вне реестра — error, мёртвый ключ —
warn, битые ссылки квестов на NPC/диалоги — error (+3 теста).
- pre-commit хук .githooks/ (check:fast = typecheck+guard+тесты),
автоподключение через "prepare". Доки: CLAUDE.md, practices.md.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|

Батч 4: ИИ врагов (LOS, шум, патруль, настороженность, отступление)
...
- los.ts: линия видимости по сетке (дискретизация 0.25 юнита), тайлы с
tall-объектами непрозрачны; кэш LOS раз в 3 тика в EnemySystem.
- EnemyBrain: состояния patrol/wary/flee/return поверх существующего цикла;
расширенные сенсоры (pos, canSee, noise, patrolPoints, home, hpFraction);
бег при отступлении (run в EnemyIntent.move); warySec-таймер.
- CombatWorld.noise(pos, level): шаги героя 0.35, удар конусом 1.0, плевок и
смерть 0.6; спящих будит только уровень >= 0.7, бодрых слышат от 0.35 в
hearRadius (окно слышимости 0.5 с).
- Патруль — per-spawn (AREAS[*].enemies patrol {points, pauseSec}): тяжеловес
и плевун на лугах бродят по маршрутам, ползуны спят в пепле как раньше.
- Поля ИИ в EnemyKindDef + withDefaults; инварианты enemy-state-legal и
enemy-in-bounds; команды scene:noise и scene:damageEnemy.
- Сценарий tools/checks/ai.mjs (7 проверок) в agent check; 14 новых юнит-
тестов (EnemyAI) + 6 (los); доки: agent.md, practices.md, demo.md.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Батч 3: взаимодействие с миром шире (знаки, моты, колокол)
...
- Предмет mote («Пепельный мот») — зачаток экономики по docs/world.md.
- InteractResponse.addVar: прибавление к вару (подбор мотов копит, не затирает).
- Контент: столбы у троп (луга, пруды, Звенец), три пепельных мота на лугах,
верёвка колокола башни (флаг rang_tower, повтор с другим текстом).
- Мила: повторный диалог trader_repeat с веткой по вару (whenVar motes >= 1);
чинён dialogueRepeat (был trader_first — полотно давалось повторно).
- Инвариант interact-used-consistent в мосте: флаг used:<id> <=> снапшот used.
- walkTo моста пропускает узлы-объекты на пути (клик в мот/цветок больше
не ломает маршрут); docs/agent.md и practices.md обновлены.
- Плейсхолдеры-вью по видам: столб/рычаг/кучка с искрой/ящик.
- Сценарий tools/checks/interact-world.mjs (7 проверок) в agent check.
- Тесты: addVar, ветка trader_repeat (dialogues.test.ts).
Co-Authored-By: Claude Code <noreply@anthropic.com>
|

Батч 2: интерьеры и интерактивные объекты
...
- Интерьеры house_elder/shop: buildInteriorMap (тайлы FLOOR/WALL), двери
кликом внутрь, выход через проём (transition kind 'return' по returnTo).
- InteractableDef/INTERACTABLES: реакции по when (flag/notFlag/varAtLeast),
once -> флаг used:<id>, эффекты setFlags/clearFlags/setVar/gives/sound.
- Системы: resolveInteractable (чистый) + Interactables (InteractSink);
pendingInteraction в LocationScene, подписи объектов при близости.
- Сундук/очаг/записка (дом Ирвина), прилавок (лавка Милы).
- Снапшот interactables; GameAgent.waitFor ждёт по полному снапшоту игры.
- Валидатор: переходы в существующие области + объекты в границах.
- Сейвы v3 (returnTo), миграция v1/v2.
- Исправление: колодец (22,20) перенесён в buildMeadowsMap (индекс 582
за пределами 28x20 молча дорастал массив).
- Сценарий tools/checks/interact.mjs (7 проверок); тесты резолвера/рантайма.
- Доки: agent.md (waitFor по полному снапшоту, валидация), practices.md
(ситуация «интерьер/объект»), demo.md, CLAUDE.md.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
| 2026-09-05 |

Батч 1: единый механизм переходов + телепортация
...
- data/locations.ts: TransitionDef/TransitionTarget/AreaDef/AREAS/areaOf —
выходы между областями (step) и двери/колодцы (click) в одном механизме
- data/transitions.ts: чистый resolveTransition (триггер, условия
requiresFlag/requiresItem с lockedText, дисарм тайла входа) + 8 тестов
- LocationScene: checkExits -> checkTransitions, клик-переходы в
handleWorldClick (NPC -> переход -> остальное), returnTo для kind 'return',
тост «заперто» без спама, дисарм при входе через переход
- Сейвы v3: SaveData.area + returnTo, normalizeSave для v1/v2
- Новые тайлы FLOOR/WALL/WELL + арт (колодец — бронзовый обруч), WELL на
карте: парные колодцы Звенец (9,6) <-> луга (22,20), duration 0.2
- Валидатор: переходы вместо exits (существование области, entry проходим)
- tools/checks/transitions.mjs (step + клик туда/обратно + снапшот) в check
- docs: практики (мимо-картная запись в генераторе, async-шаг Checks),
дорожная карта, легенда колодцев в world.md
Co-Authored-By: Claude Code <noreply@anthropic.com>
|

Батч 0: агентный набор инструментов (мост, валидация, CLI, доки)
...
Движок (packages/engine/src/agent/):
- types.ts: SceneAgent/AgentHost/Invariant/SnapshotLayer — каркас жанронезависим
- EngineAgent: снапшот+инварианты, step/waitFor, атомарные tapVirtual/press/key
- invariants.ts: checkFinite/checkRange/checkBounds/checkWalkable
- Engine.stepTick/stepTicks/tickCount; GameLoop.setManual/resetTiming
- InputManager.inject*: инъекция через те же структуры ввода
- DialogueRunner: nodeId/choices/waitingForChoice раскрыты для снапшота
Игра (apps/game):
- agent/GameAgent.ts: window.__agent (DEV): snapshot/step/waitFor/walkTo/runDialogue
- agent/snapshot.ts: чистые слои hero/enemies/npcs/dialogue/game
- data/validate.ts: runtime-валидация контента → Invariant[] (нашла 4 врага на воде)
- сцены реализуют SceneAgent: whitelist-команды, lastToast в снапшоте
Инструменты и доки:
- tools/agent-lib.mjs (openGame/AgentClient/Checks), tools/agent.mjs (CLI check/run/snapshot/screenshot/dev)
- tools/checks/agent-invariants.mjs; смоуки переписаны на мост; maps:fresh в gen.test.ts
- docs/llms.txt, docs/engine/agent.md, docs/engine/practices.md (живой документ)
- CLAUDE.md, docs/engine/README.md, docs/demo.md обновлены
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
пейзажная фауна: безгласные олени и мотыли
...
- спрайты chars/fauna_deer_1/2.png (выцветший, без тёплых пикселей)
-> атлас chars/fauna_sheet.json, грузится в BootScene
- FaunaSystem: мини-StateMachine (idle/wander/approach) - стоит,
бродит по соседним тайлам, на громкий звон рядом подходит к источнику
- мотыли: серые частицы, дрейф вверх от точки звона (combat:attack)
- спавны: два оленя на лугах, один у прудов
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
зоны наката у прудов + полотно-маска; починен атлас героя
...
- HazardDef в locations.ts: разметка низин у Серых прудов (требуют cloth)
- герой в накате без маски: скорость x0.5, дымка-оверлей, тост при входе;
с полотном - только лёгкая дымка
- звон как 'проверка воздуха': резонанс в низине подсвечивает пепел
вспышками и шипением
- PlayerController.speedMul - множитель скорости, управляется сценой
- фикс: hero_sheet собирался data.set с неверным строковым шагом -
кадры жались в полосы; теперь построчное копирование
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
локация Звенец: деревня-хаб вокруг башни с колоколом
...
- buildZvenetsMap (28x20): площадь, тропа с лугов, башня-талл 2.5 юнита,
три дома-талла 1.75 юнита; безопасный хаб без врагов
- спрайты tiles/tower.png и tiles/house.png в генераторе арта
- Ирвин и Мила переезжают в Звенец (диалоги без изменений)
- луга получают обратный переход в Звенец (26,14) с расчисткой
- амбиент-трек music/zvenets: низкий колокольный тон из рельсов
- смоук tools/smoke-zvenets.mjs, чеклист арт-библии и доки
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
квестовая система: декларативные стадии
...
- data/quests.ts переписан: QuestDef/QuestStage, реестр QUESTS;
состояние квеста — флаги/вары GameState (ставятся графами диалогов);
- API: questTaken/questDone/activeStage, questDialogueFor (диалог NPC
по активной стадии), questEffectFor (побочные эффекты из стадий +
знакомства), questLog (журнал с прогрессом);
- LocationScene.talkTo/onDialogueFinished: хардкод-ветки заменены
квест-моделью (полотно — эффект trader_first);
- тесты: 199/199 (новые — стадии квеста и сумка).
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
сейвы v2 + предметы + инвентарь
...
- движок: Inventory — контейнер Map<id, count> (add/remove/count/has/all,
onChange), inventoryFromData; тесты;
- Game.inventory: сумка героя, сброс в новой игре;
- SaveData v2: поле version + items, normalizeSave дополняет сейвы v1;
- data/items.ts: реестр предметов (cloth, bellflower, salt, water_flask);
- сбор цветка кладёт bellflower в сумку; полотно выдаётся предметом
после диалога Милы (флаг got_cloth остаётся меткой);
- InventoryScene: строки сумки из инвентаря (имя + ×N);
- тесты: 192/192.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Фаза 4: TallSpec.height в мировых юнитах
...
- плейсхолдер-колонна: h = tall.height * iso.tileW (вместо px);
- удалён устаревший map.screenSize (остался worldBounds в юнитах);
- data/map.ts: высота дерева 1.5 юнита (те же 48 px на экране);
- .map-файлы перегенерированы (diff — только height: 48 -> 1.5);
- parseMap отвергает tall.height > 16 как высоту в px (защита от
протухших карт-файлов);
- тесты: 186/186.
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
Фаза 3: мир игры в мировых юнитах
...
PlayerController, CombatWorld, EnemyBrain, CombatViews и LocationScene
переведены с виртуальных пикселей на мировые юниты (1 юнит = 1 тайл):
- позиции/дистанции/скорости в юнитах (герой 1.75 юн/с, скорости и
радиусы врагов, knockback 0.75, INTERACT_RANGE 1.5);
- конус/окружности через inConeW/inCircleW (метрика проекции);
- вью-позиции — через worldToScreen, округление до px только на границе;
- гистерезис дистанции плевуна ±0.4 юнита, attackStop 0.85 юнита;
- тесты EnemyBrain/stats обновлены под юниты (185/185).
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
игра: квест «Три цветка» — сбор, журнал, сумка, сдача и крючок акта 1
...
- движок: IsometricTileMap.setTile — изменение тайла с перерисовкой ячейки (+тест);
InputManager: одна клавиша маппится на несколько действий (Space = advance+attack)
- data/quests.ts: журнал квестов и предметы из флагов/варов GameState
- сбор лунных колокольчиков кликом на прудах (тайл зеленеет, прогресс flowers)
- сдача квеста Ирвину (elder_hand_in) — посадка цветов у тропы, крючок «Машина дышит»
- повторные реплики Милы (trader_repeat/trader_after)
- InventoryScene: сумка и журнал на Panel (клавиша I / геймпад Y)
- tools/smoke-quest.mjs: смоук диалога и сумки
Co-Authored-By: Claude Code <noreply@anthropic.com>
|