Commit Graph

65 Commits

Author SHA1 Message Date
calic
d862a250c4 crafting v0.5.0 + composition v0.4.0: Quality & Condition (Phase J)
lib-core.composition v0.4.0: un-defer quality/condition as inert numeric
properties (loud-error removed); composition stores them without semantics.

lib-core.crafting v0.5.0: quality-block (multi-contributor product-quality
formula: skill-band with min=requires-floor + named ingredient/tool qualities),
optional slot name, tool wear_per_use (condition decrement + wear report).
affordance stays boolean. Additive to v0.4.0.

vagrant-skeleton v0.22.0: branch quality-band RNG at spawn; stone_hammer
condition=1.0; knap+axe quality-blocks; hammer wears out. Headless-verified 20/20.

Design: meta/docs/design/2026-08-03-crafting-quality-condition-design.md.
Docs synced: crafting-model.md, composition-model.md, libraries.md, READMEs.
2026-08-03 09:14:56 +00:00
calic
f93fef5990 crafting: actor-precondition (requires) + reward (grants) — Skills half of Phase H (ADR-0056)
lib-core.crafting v0.4.0: two optional domain-free recipe fields.
- `requires`: a match-table evaluated against ctx.actor (not container items) — a hard gate. Failing -> {ok=false, error="requires_unmet", unmet={keys}}; fail-closed when ctx.actor is nil. Same predicate machinery as slots; distinct from is_known (discovery vs lock).
- `grants`: property->number reward, returned as `granted` from craft(); the consuming MODULE applies it to the actor (crafting stays container-scoped). Crafting knows no 'skill' vocabulary (ADR-0001).

vagrant-skeleton v0.21.0: player-actor carries skill.knapping (entity property, Phase-A lesson); knap_sharp_stone grants knapping XP, craft_stone_axe requires knapping>=3; module applies granted; skill-locked recipes show 'Skill too low'. Gate->earn->unlock loop headless-verified (axe locked @0 requires_unmet -> 3 knaps -> unlocks).

Quality-band reserved (Phase J): the requires threshold = the future quality floor (no re-authoring). Docs synced: ADR-0056, crafting-model.md (v0.4.0 + Actor-Precondition section), libraries.md, crafting README, vagrant README.
2026-07-31 10:00:27 +00:00
calic
b28afd5290 crafting: retire form, unify on affordance capability axis (ADR-0055 amendment)
Recipe roles now match on a single `affordance.*` axis, required by both consumed `inputs` and non-consumed `tools` (the inputs/tools split carries consumption, not a separate axis). `form` — which conflated geometry, identity and capability — is removed. Its functional members folded into affordances (blade->cutting, shaft->leverage, plus knappable/spinnable/binding); identity members became template-id (chop_tree) or material+weight (log, hammer head).

vagrant-skeleton v0.20.0; no crafting/composition lib bump (they never knew `form`). Verified headless via the tool-harness: 16/16 checks pass — role-flexibility (stick OR branch hafts), weight discrimination, tool-gating (tool not consumed), and anti-recursion guards (sharp_stone not re-knappable, cordage not re-spinnable).
2026-07-31 07:43:08 +00:00
calic
4825d01426 feat(vagrant): v0.19.0 — role-based Stone-Age recipes (match by form/material/weight/affordance, not item id); rock/stick get form roles 2026-07-28 12:22:51 +00:00
calic
60093522f5 feat(vagrant): v0.18.0 — Stone-Age round-out (stone_hammer+knap-gate, chop_tree, break_branch, sharpen_stick) in content pack 2026-07-28 12:09:25 +00:00
calic
e9085c0317 refactor(vagrant): v0.17.0 — extract Stone-Age content to content/stone_age.lua (T1-modder content packs via content facade) 2026-07-28 12:01:45 +00:00
calic
ff9d50937d feat(vagrant): v0.16.0 stone-age tech chain (knap/twist/haft → stone_axe); fix crafting manifest.lib to 0.3.0 2026-07-28 11:38:23 +00:00
calic
8994b24567 feat(vagrant): v0.15.0 stone-age slice — saw_planks property-constraint recipe (log→4 planks, cutting tool); crafting output-alias for bw-compat icon resolvers 2026-07-28 10:42:21 +00:00
calic
08413e9c29 feat(crafting): lib-core.crafting v0.3.0 — property-constraint slots + non-consumed tools + multi-output (ADR-0055); vagrant-skeleton debug-drive hook for headless scenario testing 2026-07-28 10:35:57 +00:00
calic
c3290058c1 feat(vagrant): v0.14.0 — TC_Basics first-consumer + UI item icons
ADR-0054 Item-Visual-Identity validated end-to-end.

World-sprite migration off the proprietary Subterrain world-atlas:
  - Bed + Bench promoted to composition-entities with renderable tag;
    rendered via the existing draw_entities path (the hardcoded
    draw_sprite_transform calls for furniture are gone).
  - Backpack sprite source: Subterrain backpack_001 → TC_Basics sack1.
  - Stick visual: blob_rect_stone slot_04_straight → TC_Basics log_pile1.
  - rock_pick crafted-output visual: blob_rect_stone slot_05_tee_open →
    TC_Basics spade.
  - rock + rock_pile + workbench stay on blob_rect_stone (no TC_Basics
    equivalent yet).

Scale resolution is now atlas-level (no more module-side constants):
M.init reads tc_meta.atlas_meta.pixels_per_meter and divides into
PROJECT_PIXELS_PER_METER (128 per puppet shoulder anchor) to derive
tc_scale, applied per-entity via lib-core.render v0.3.0's sprite_
scale property.

UI item icons via ADR-0054 §3 Konsum:
  - Backpack + Workbench-Inventory rows now show item icons via the
    inventory-list-display v0.2.0 default resolver (fallback chain
    icon_atlas → sprite_atlas), fit-to-bounds.
  - Backpack-Crafting + Workbench-Crafting panels get an icon column
    via crafting-display v0.3.0; vagrant supplies a small recipe-
    output → {atlas, uv} lookup (craft_icons) and wires it as
    icon_resolver on both widgets.

Deps cascaded: lib-core.render 0.2.0 → 0.3.0, lib-core.inventory-
list-display 0.1.1 → 0.2.0, lib-core.crafting-display 0.2.0 → 0.3.0,
lib-asset.prototype-tc-basics 0.1.0 → 0.3.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 11:45:24 +02:00
Axel Meyer
088e14aeb2 chore: bump lib-core.panel dep to 0.4.0
Engine resolver does exact strcmp on dep versions, so consumer manifests
must pin the new lib-core.panel 0.4.0 to keep load-time resolution green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-15 03:05:25 +02:00
Axel Meyer
d69d2bd95d chore: bump lib-core.panel dep to 0.3.0 2026-06-15 02:26:04 +02:00
Axel Meyer
1fa0628c83 feat: v0.13.0 Workbench multi-panel via panel v0.2.0
D.2-revisit closes the Workbench Gate-2 walkthrough: right-click
on Workbench now opens workbench_crafting (left-half layout-slot)
+ workbench_inv (right-half) simultaneously, replacing the v0.12.0
auto-switch workaround. Both panels visible at the same time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-15 02:01:39 +02:00
Axel Meyer
5cd42caaa7 chore: bump lib-core.panel dep to 0.2.0
Track lib-core.panel v0.2.0 (multi-active panels with layout-slots).
No behavioral change in this consumer — the v0.1.1 call sites remain
compatible via the panel framework's bw-compat shim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-15 01:46:43 +02:00
Axel Meyer
644bfe98fd feat: v0.12.0 Workbench-Integration
Workbench-Entity bei (350, 380) als Crafting-Context-Erweiterung.
Right-Click oeffnet Workbench-Crafting-Panel + Workbench-Inventory.
Crafting nutzt Multi-Source-Locale {backpack, workbench} mit sink
= workbench; Take-Action verschiebt vom Workbench-Inventory zum
Backpack. C-Key Backpack-Crafting bleibt unveraendert via Bw-
Compat-Shim in crafting v0.2.0.

Deps: crafting 0.1.0 -> 0.2.0, crafting-display 0.1.0 -> 0.2.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 20:04:04 +02:00
Axel Meyer
f16c8954d9 fix: notify channel hygiene + craft-output sprites
- Drop "craft" tag from Inspect-Recipe payload; multi-line detail
  posts now route only to the inspect/detail channel, not the toast
  events channel.
- Wire rock_pick + rock_pile templates to blob_rect_stone atlas
  slots (slot_05_tee_open + slot_13_solid) so crafted items render
  in inventory + on drop instead of magenta fallback.
- Drop dead "crafting" tag from events filter (no post emitted it).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 14:09:17 +02:00
Axel Meyer
31333111c0 feat: v0.11.0 crafting integration
Stick pickup neben rock spawnt; 2 Recipes (rock_pick, rock_pile);
C-key oeffnet Crafting-Panel via lib-core.crafting-display.
Craft + Inspect Actions konsumieren notify-Channels fuer Erfolg +
Detail-Modal.

Deps: +crafting 0.1.0, +crafting-display 0.1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 13:57:19 +02:00
Axel Meyer
0658e87066 chore: bump lib-core.composition dep to 0.3.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 11:57:40 +02:00
Axel Meyer
e310494d39 fix(vagrant): ESC closes open panel before quitting to launcher
Previously ESC unconditionally switched to the launcher, leaving no way
to dismiss an open inspect-detail (or any panel-widget opened via
notify.post without a toggle key). Now ESC closes the active panel
first; only when no panel is open does it quit to the launcher.
2026-06-14 02:36:40 +02:00
Axel Meyer
99f3583e91 chore: bump lib-core.panel dep to 0.1.1 2026-06-14 02:22:51 +02:00
Axel Meyer
6b4c698984 feat(vagrant): notification system — Inspect modal, pickup-float, toast events, game-log
- manifest: bump to v0.10.0; add deps lib-core.notify, lib-core.notify-display,
  lib-core.world-overlay (all v0.1.0)
- Inspect action migrated from engine.print to notify.post{tags={"inspect"}, data={...}};
  routes to modal detail-panel via notify-display detail-channel
- Pickup callback: world_overlay.spawn fires "+1 <name>" float anchored on player
  (yellow, rise_px=24, ttl=1.2s) + notify.post pickup event-toast/log entry
- Drop action (right-click menu): notify.post{tags={"drop","inventory"}} added
  after existing relocate+close_menu logic
- Setup block: 3 channels (inspect/events/log), 2 panel widgets
  (inspect-detail/game-log), 3 attach_mode calls; L bound to game-log panel
- M.update: notify_display.update + world_overlay.update after panel.update pause-guard
- M.draw: camera_handle constructed after camera.finish(); world_overlay.render between
  camera.finish and panel.render; notify_display.render at end (toasts on top)
- README: version 0.10.0, Requires expanded, Controls section updated, changelog entry added
2026-06-14 02:05:35 +02:00
Axel Meyer
f66ffc7f12 feat(vagrant): rock template gains player-facing properties
Rock template now declares name="Rock", a description, weight (kg),
volume (L), and composition.stone=1.0. The module-side label_resolver
override is removed — display lib's default reads name now.

Inspect action prints a structured block (name, description, weight,
volume, composition.<material>, reg_id) to the console. Future
notification system will route this to an in-game text panel; for now
the console output makes Inspect useful instead of silent.
2026-06-14 00:26:29 +02:00
Axel Meyer
60eac65bce feat(vagrant): Tab-Toggle inventory panel + right-click context menu
- lib-core.panel and lib-core.inventory-list-display added to deps (v0.1.0 each)
- backpack-widget created in M.init with label-resolver returning "Rock"
- Drop action registered: removes from backpack, relocates to player position,
  re-registers pickup trigger
- Inspect action registered: prints reg_id via engine.print
- M.update: panel.update(dt) + is_pausing() early-return added after
  quit_to_launcher check
- interaction.update wrapped in panel.is_open() guard to block world triggers
  while panel is visible
- M.draw: panel.render() added at z-top after CI traces
- Q-drop (LIFO quick-drop via Q key) unchanged and parallel to panel Drop action
2026-06-13 23:42:55 +02:00
Axel Meyer
e38d396b87 feat(vagrant): backpack as inventory container — end-to-end pickup/drop demo
- Add container={kind="list"} to the backpack template so inventory.add
  accepts it as a valid list-container
- Remove old backpack proximity-trigger (print-only callback, pre-B.5);
  the rock's register_pickup is now the sole interaction trigger
- Emit unconditional inventory inspection trace after every add/remove:
  backpack count + item reg-ids for user-facing demo feedback
- Add CI-gated tree-check traces: tree_check_after_pickup=ok and
  tree_check_after_drop=ok verify composition-tree child placement
- Bump version 0.7.3 -> 0.8.0 across init.lua header, manifest.module,
  and README
- README: rewrite Controls section into full demo walkthrough; add Demo
  Walkthrough section; update Demonstrates + Interactions sections;
  add v0.8.0 CHANGELOG entry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 19:00:12 +02:00
Axel Meyer
f874813498 feat(vagrant): spawn rock entity with pickup trigger
- Rock template (stack_mode=individual, tags=renderable+item) defined
  alongside backpack and vagrant_player templates.
- state.rock entity created in M.init using slot_00_isolated UV from
  the blob_rect_stone atlas (lib-asset.prototype-blob-geom); position
  (270, 400) — 80px left of the backpack.
- register_pickup(state.rock) wires an interaction trigger; existing
  render.draw_entities{tag="renderable"} draws the rock with no
  special-case render code.
- CI trace: engine.print("vagrant: rock_spawned") emitted once on init.
- Version bump 0.7.2 -> 0.7.3.
2026-06-13 18:27:25 +02:00
Axel Meyer
f1e27d8183 feat(vagrant): pickup/drop glue + lib-core.inventory-list dep
- Add lib-core.inventory-list v0.1.0 to manifest deps; bump module
  version 0.7.1 -> 0.7.2
- Import inventory = require("lib-core.inventory-list") in init.lua
- Add Item-Template-Convention comment block after vagrant_player
  template: documents stack_mode/tags/sprite/position contract that
  B.4 (rock) and B.5 (backpack-as-container) will fulfill
- Add register_pickup(item) factory: reads item position, registers
  interaction trigger; callback calls inventory.add + unregisters
  trigger on pickup
- Bind "drop" action to Q; drop handler in M.update pops last item
  from backpack via inventory.remove (renderable tag restored by
  library), repositions item at player pos +30px, re-registers pickup
- Update README Controls section: document E (pickup) and Q (drop)
  with note that end-to-end use requires B.4 + B.5
2026-06-13 18:18:52 +02:00
Axel Meyer
342adf64a1 chore: bump lib-core.composition dep to 0.2.0 2026-06-13 14:07:46 +02:00
Axel Meyer
a305314819 feat: ship manifest.launcher.md for master-detail launcher v0.7.1 2026-06-11 07:57:41 +02:00
Axel Meyer
3c5e63ea18 feat(0.7.0): Player als Actor-Entity, Puppet syncs (Phase A.6)
Refactor: Player gesplittet in zwei Handles. state.actor (composition-
Entity) ist canonical position-owner. state.player (puppet handle)
bleibt für Animation + Render zuständig und syncs each frame via
puppet.move_to(state.player, actor.position(state.actor)).

vagrant_player-Template ist UNTAGGED — render.draw_entities sieht ihn
nicht, da puppet.render(state.player) das Sprite-Rendering schon macht.
Tag-Konflikt vermieden.

Movement-Refactor in M.update:
- CI_DRIVE-Branch: actor.move(state.actor, dx*speed*dt, 0)
- Normal-Movement: actor.move(state.actor, mx*speed*dt, my*speed*dt)
- Sync-Punkt nach beiden Branches: puppet.move_to(state.player,
  actor.position(state.actor))
- interaction.update + camera.set_target lesen actor.position

Sprint-Logic unverändert (eigene WALK_SPEED constants; movement_speed
auf actor ist informational/120).

Bumps: 0.6.0 → 0.7.0; +actor v0.1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 14:14:18 +00:00
Axel Meyer
c976353637 feat(0.6.0): Backpack as composition-Entity (Phase A.4)
Refactor: Backpack ist composition-Entity mit Atlas-UV-Render-Pfad.
Template at top-level declares sprite_atlas + sprite_uv.{x,y,w,h} +
position. create() in M.init nach atlas-load setzt reale UV-Werte aus
state.furniture_uvs["backpack_001"].

render.draw_entities{tag="renderable"} ersetzt den direkten
draw_sprite_transform-Call für Backpack. interaction.register liest
position aus entity-properties.

Bed + Bench bleiben hardcoded Atlas-Furniture — kein
Interaction-Trigger, kein Demo-Pflicht zur Entity-Promotion in
Phase A. Phase B (container-on-bed) oder Phase D wäre der Trigger.

Atlas-Texture wird doppelt geladen (state.world_tex für bed/bench,
render-internal-cache für backpack) — ineffizient aber nicht
kaputt; single-handle-merge ist späterer Slice.

Bumps: render 0.1.0 → 0.2.0; +composition v0.1.0; module 0.4.4 → 0.6.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 13:51:02 +00:00
Axel Meyer
77550149cb chore(deps): bump lib-core.maps 0.5.6 -> 0.5.7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 22:44:25 +02:00
Axel Meyer
b5278bd24d chore(deps): bump lib-core.maps 0.5.5 -> 0.5.6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 17:19:18 +02:00
Axel Meyer
c04dea7f3e ESC -> lib-management.launcher (renamed per ADR-0045)
The launcher migrated from lib-sporel.launcher to lib-management.launcher
per ADR-0045 (three-tier library naming). Update the quit_to_launcher
handler to match the new module id.
2026-05-31 00:22:30 +02:00
calic
7ebd17209f chore(deps): bump lib-core.maps 0.5.4 -> 0.5.5 2026-05-29 09:56:49 +02:00
calic
c64a85e5de chore(deps): bump lib-core.maps 0.5.3 -> 0.5.4 2026-05-29 01:37:42 +02:00
calic
cff86c3e65 chore(deps): bump lib-core.maps 0.5.2 -> 0.5.3 2026-05-29 01:29:22 +02:00
calic
930591c564 chore(deps): bump lib-core.maps 0.5.1 -> 0.5.2 2026-05-28 23:53:55 +02:00
calic
1293876e9f deps: bump lib-core.maps 0.5.0 -> 0.5.1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 23:10:24 +02:00
calic
6a48653569 vagrant: migrate map to v3 multi-layer + autotile + overrides
manifest.module
  + new dep on lib-asset.prototype-blob-geom v0.1.0 (companion lib
    for the design paper's reference asset set + Python atlas-packer)
  + asset_aliases entry for blob_testbench (mixed 3-material atlas:
    grass/stone/wood x 14 slots = 42 tiles) and blob_rect_stone
    (single-material atlas for vertex-painted autotile)
  - removed subterrain_tiles asset_alias (no longer used)
  bumped lib-core.maps dep 0.4.0 -> 0.5.0

vagrant_test.map.json rewritten as native schema-v3 with three non-
empty terrain layers, exercising all renderer paths in a single map:
  - surface (tiles[] path, multi-material via blob_testbench):
      grass-solid floor across all 400 cells
      14-wide x 3-tall showcase strip on rows 10-12 columns 2-15
      displays every slot of every material the atlas ships (slot 0
      through 13 x grass/stone/wood, ids 1..42 visible at a glance)
  - topsurface (tiles[] path): 2x4 wood overlay decoration on rows
      3-4 columns 2-5
  - wall (vertex-painted autotile with blob_rect_stone material):
      21x21 vertex grid; 80 vertices painted in a border-ring pattern
      so the renderer's bitmask + 47->14 slot lookup produces the
      visually-correct stone wall around the 18x18 interior; plus
      3 interior pillars (cells 9:7, 7:15, 13:15) authored as
      overrides with slot 0 (isolated), demonstrating that the
      override sublayer can place truly-1-cell-isolated material
      which the any-corner vertex rule alone cannot express

assets/tiles/vagrant_test.tilemap.json removed; under schema v3 the
engine resolves the palette directly from the atlas's tiles.atlas.json,
the standalone tilemap.json was unused (atlas-bootstrap stub path
took over since M.2).

Closure verifies SPOREL_CI=1 ./Sporel.exe --module=vagrant-skeleton
rc=0 with 60 render_frame_ok, both atlases load (no magenta-
placeholders), walkability rule (surface present + wall absent)
correctly treats border + pillars as non-walkable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:49:26 +02:00
Axel Meyer
7cdb95f5d6 Bump lib-core.maps dep to 0.4.0
Picks up the new write APIs (set_cell_gid, set_roof, save_to_disk).
No source changes — lib is purely additive.
2026-05-24 00:53:46 +02:00
Axel Meyer
b5b8318aa3 Migrate vagrant-skeleton to atlas-uv consumers
Asset-aliases now reference the three baked subterrain atlas-sets
(subterrain_player, subterrain_tiles, subterrain_world) rather than
the legacy indexed pack labels. The rig asset_pack updates to
subterrain_player and each bone gains a calibrated anchor offset.
Furniture-draw loads the subterrain_world atlas once and renders
via source-rect draw_sprite_transform. The map tilemap field updates
to subterrain_tiles to match the new atlas-id. Dep-bumps for
lib-core.maps 0.3.0, lib-core.puppet 0.5.0, and
lib-asset.prototype-subterrain 0.2.0. Replace r_lib.draw_map with
draw_map_pre/post_entities.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 23:28:24 +02:00
Axel Meyer
7c4b147608 Bump dep on lib-core.maps to 0.2.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:14:27 +02:00
Axel Meyer
733db11821 docs(vagrant): README sync to v0.4.4 — sprint + interaction 2026-05-19 00:29:50 +02:00
Axel Meyer
c4f2c9cda9 feat(vagrant): sprint (shift+wasd) + backpack interaction
Sprint: holding shift while WASD doubles player_speed (120 → 240) and
walk-anim play-speed (0.45 → 0.9). Mid-walk sprint toggle uses puppet
v0.4.4 set_play_speed → no cycle restart. Releasing shift or stopping
WASD reverts to normal speed in next frame.

Interaction: 'interact' bound to E. Proximity trigger registered on
the backpack sprite at (350, 400) with range 40px. Pressing E within
range fires callback that prints a log message with the actor distance.
Uses existing lib-core.interaction (registered at init, polled by
interaction.update(player.x, player.y) each frame).

New dep: lib-core.interaction ^0.1.0. Module version 0.4.0 → 0.4.4
(syncs with puppet bump).
2026-05-18 23:46:23 +02:00
Axel Meyer
a064825160 docs(vagrant): README sync to v0.4.3 — Subterrain-model puppet features
Updates README to describe the Subterrain-style puppet control model
implemented across v0.3.1–v0.4.3. Previous README described v0.2.0
state and predated the multi-look-target, slerp, inherit_scale,
procedural orientation, and tactical-twist foot behavior.

Demonstrates section updated: multi-look-target (soft/aim), scale-
deformation walk cycle, procedural leg orientation, foot-body-orientation
(tactical twist), inherit_scale=false on feet, per-channel conflict guard,
camera.begin/finish world-space rendering.

Interactions section updated to describe the v0.4.3 visual behavior.
Full CHANGELOG from v0.2.0 through v0.4.3 with per-version summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:00:51 +02:00
Axel Meyer
cfd5d71546 fix(vagrant): walk anim speed 0.4 → 0.45 (user tuning)
Note re user observation 'hat sich die animationslänge durch negative
skalierung verändert': no, anim duration (0.8s) and play speed (the
dt multiplier) are independent of bone-state values. The full cycle
visually traverses scl=+1 → 0 → -1 → 0 → +1 over 0.8s × 1/0.45 ≈
1.78s effective. Previous 0.4 gave 2.0s — slightly slower than
desired walking cadence.
2026-05-18 22:38:06 +02:00
Axel Meyer
b66c4ca4dd fix(vagrant): substrate leg.scl cycle restored; feet inherit_scale=false
User feedback after iteration-4: legs SHOULD cycle through +1/0/-1
(substrate-style — leg renders forward, under body, then behind body).
But feet must NOT Y-flip when leg.scl_y goes negative, and must NOT
collapse when leg.scl_y=0. They should follow leg-end position only.

Three changes:
1. walk_fwd_lower keyframes restored to substrate-style (leg.scl_y
   sign-flip on both halves: leg_l +1↔-1, leg_r -1↔+1). foot.pos
   animations REMOVED — cascade through leg.world.scl now correctly
   moves foot to leg-end position automatically (foot.local.pos
   stays at rest 25 in y).
2. foot.rest.scl: [1, -1] → [1, 1] (no Y-flip in rest, natural
   sprite orientation). inherit_scale=false → foot.world.scl stays
   at foot.local.scl=[1,1] regardless of leg.scl_y. Foot sprite
   never flips, never collapses.
3. Procedural extended: writes foot.local.rot = -leg.local.rot so
   foot.world.rot = body.world.rot (feet stay body-oriented even
   when legs rotate to walk-direction).

Speed slowed further from 0.5 → 0.4 (user: still too fast at 0.5).
2026-05-18 22:31:42 +02:00
Axel Meyer
bf5fe12e4c fix(vagrant): walk anim — slow to 0.5x, no leg.scl_y sign flip
User manual-test feedback after iteration-3 hip-stable + leg-rotation
fixes:

1. Animation too fast for actual map traversal → play walk_fwd_lower
   and walk_upper with speed=0.5 (effective 1.6s cycle, was 0.8s).
2. Second half visually broken → was substrate's sign-flip trick where
   leg.scl_y goes +1 (opposite of rest -1) and foot.pos.y flips
   negative. Cascade foot.world.scl_y = +1 * -1 = -1 → foot rendered
   Y-flipped. User: 'die füße ... darf hier die skalierung nicht negativ
   werden'.

   New cycle: each half extends ONE leg (scl_y=-1 matching rest) while
   the other stays at scl_y=0 (collapsed/invisible). foot.world.scl_y
   never goes negative — only [0, +1]. Alternating-leg gait. Substrate
   first-half preserved verbatim; second-half mirrors with role swap.
2026-05-18 22:13:56 +02:00
Axel Meyer
77f3e726ae fix(vagrant): hip-anchors body-relative; leg-orientation procedural
User feedback: 'anchorpoints sind hüftgelenke und können sich nicht
frei drehen. hüfte bleibt zum körper statisch'.

Architecture:
- legs.parent = body (was lower_control). Hip position cascades from
  body.world.rot, so hips stay at body-frame left/right regardless of
  body rotation. lower_control virtual bone removed (no longer needed).
- Procedural 'leg_orientation' sets leg.local.rot = walk_dir - body.rot
  each frame, so leg.world.rot = walk_dir (independent of body cascade).
  Requires puppet v0.4.2 per-channel write_bone (walk_anim writes leg.scl
  while procedural writes leg.rot — disjoint channels).

Result: legs visually attach at body's anatomical left/right hips no
matter where body faces; stride oscillation aligns with WASD walk
direction. Hip position no longer drifts with walk direction.
2026-05-18 21:57:20 +02:00
Axel Meyer
0a7ef7f270 fix(vagrant): legs rotate to walk direction (user preference)
User feedback: 'Beine sollten in die richtung oszillieren, in die
gegangen wird, nicht nach norden/süden relativ zum fenster.'

Old: lower_control.rot = wedge_deg (substrate's body-relative ±30°
sub-angle), legs always oscillated near world-up axis.

New: lower_control.rot = atan(move_x, -move_y) = walk direction in
sprite-top-up convention. Legs visually rotate to align with WASD
direction → stride animation cycles along the walk axis.

Side-effect: 4-direction-anim picker collapsed to single
walk_fwd_lower (the rotation handles directional differentiation;
4 anims kept on disk for later gait-style work). Bumps puppet dep
to 0.4.1 (head south-flick fix).
2026-05-18 21:48:10 +02:00