- Mark: a debug non-collidable named destination (pixel-art target icon),
editor tool + name modal, globally-unique names, programmatic Room:addMark
- NPCs walk to Marks: each RGB copy is a per-room resident (like the player),
running its own A* on its own colour layer, transferring rooms as it crosses
seams; rendered and collided by the room it currently stands in
- Player copies are obstacles in NPC pathfinding
- A* is footprint-aware for multi-cell NPCs
- Editor: click an NPC to open a filterable destination picker
- Ink: Dialogue.open binds walk_to; Jorge can be sent to "end"/"begin"
- Fix: a blocked NPC now replans each tick and resumes instead of freezing
- [npc] move diagnostics under DEBUG (start/goal/route or block reason)
- Docs (adding-npcs) + CLAUDE.md LÖVE 11.x/float-colour corrections
- Fix test harness loadSprite stub; movement tests green (28)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the fraction-of-window positioning (which overlapped and didn't
scale) with a small layout system: the sidebar is authored in one fixed
virtual coordinate space and rendered at native panel resolution, so
element sizes stay constant relative to the panel at any window size and
fonts scale with it.
- level_editor/layout.lua: sections, scrolling list (with clip + hit-test
by point), scrollbar. Clip rects are scaled to real canvas pixels.
- Room view split into non-overlapping divs: search/back header, a
scrollable asset list (replaces the old row-paging + forward buttons),
a status strip, and a compact bottom control cluster.
- Mouse wheel scrolls the list; clicks map from window coords into the
virtual space via the same transform used to render.
- Sidebar canvas is panel-sized and blitted 1:1 (nearest filter, never
averaged) to stay crisp; editorDraw runs under a scale transform.
- Center text-only fields (level name) in their rect.
Also carried in main.lua (share the file, can't split cleanly here):
narrator require path fixed via love.filesystem.setRequirePath; sfxr
static uses waveform=NOISE again after the field rename; low-pass +
lower volume on the static loop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>