From f1e27d81831a8e3bf64d23b517b5508bf6bbc63e Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Sat, 13 Jun 2026 18:15:23 +0200 Subject: [PATCH] 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 --- README.md | 8 +++++-- init.lua | 57 ++++++++++++++++++++++++++++++++++++++++++++++++- manifest.module | 3 ++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 389238a..3b0d316 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ puppet control model: leg orientation decoupled from body via procedural callback, foot-body-orientation ("tactical twist"), scale-deformation walk cycle, and inheritance-decoupled foot sprites. -**Version:** 0.4.4 +**Version:** 0.7.2 **Module-ID:** vagrant-skeleton **Requires:** lib-core.input >=0.4.0, lib-core.camera >=0.3.0, lib-core.render >=0.1.0, lib-core.maps >=0.1.2, lib-core.puppet >=0.4.4, lib-core.interaction >=0.1.0, lib-asset.prototype-subterrain >=0.1.0 **Tags:** test-chamber, puppet, walking-sim, interaction @@ -22,9 +22,13 @@ cycle, and inheritance-decoupled foot sprites. - **W A S D** — direct movement (4-way, normalized for diagonals) - **Shift + WASD** — sprint (2x player speed + 2x walk-anim cadence) - **Mouse** — body + head look-at targets (same position, different smoothing) -- **E** — interact with nearest proximity-trigger in range +- **E** — interact with nearest proximity-trigger in range (pickup nearby item into backpack) +- **Q** — drop most-recent item from backpack at player position + re-register pickup trigger - **ESC** — return to launcher +> **Note:** Q (drop) and E (item pickup) are groundwork for B.4 (rock on ground) and +> B.5 (backpack-as-container) — not yet exercisable end-to-end until those slices land. + ## Demonstrates - lib-core.puppet v0.4.3 integration: diff --git a/init.lua b/init.lua index 34e2ce5..bdb29b8 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,4 @@ --- sporel-module-vagrant-skeleton v0.7.0 +-- sporel-module-vagrant-skeleton v0.7.2 -- Sprite-mode test-chamber: 13-bone humanoid puppet + sprite-tilemap + -- hardcoded furniture. Subterrain-style puppet control model: -- multi-look-target (aim/soft), slerp body rotation, hip-static legs, @@ -24,6 +24,7 @@ local puppet = require("lib-core.puppet") local interaction = require("lib-core.interaction") local composition = require("lib-core.composition") local actor = require("lib-core.actor") +local inventory = require("lib-core.inventory-list") local M = {} @@ -68,6 +69,25 @@ composition.define_template{ tags = {}, -- intentionally untagged: not renderable } +-- Item-Template-Convention (Phase B): +-- An "item" is a composition-template with: +-- - properties.stack_mode = "individual" (required by inventory-list) +-- - properties.sprite_atlas + sprite_uv (Atlas-UV render path) +-- - properties.position = {x = 0, y = 0} (world anchor) +-- - tags = {"renderable", "item"} ("renderable" → drawn by +-- render.draw_entities; +-- "item" → reserved/visible to +-- future inventory queries) +-- Pickup: register_pickup(item) registers an interaction-trigger at the +-- item's current position; on interact, the item moves into state.backpack +-- via inventory.add (renderable-tag flips off → world stops drawing it). +-- Drop: input-action "drop" pops the last item out of state.backpack, +-- re-parents it to the world at the player position, and re-registers a +-- pickup-trigger at the new location. +-- +-- Rock template (B.4) and container block on backpack (B.5) activate this +-- convention end-to-end. B.3 establishes the glue only. + local state = { player = nil, -- puppet handle (state-bearing for animation) actor = nil, -- composition-entity owning position @@ -96,6 +116,24 @@ local ci_assets_traced = false -- All 4 directional walk animation ids. local WALK_ANIMS = {"walk_fwd_lower", "walk_back_lower", "walk_left_lower", "walk_right_lower"} +-- register_pickup(item) +-- Registers an interaction-trigger at the item's current world position. +-- When the player presses E within INTERACTION_RANGE, the item is moved +-- into state.backpack via inventory.add (renderable-tag flips off) and +-- the trigger is unregistered so the item no longer shows as interactable. +-- Called by B.4 after placing the rock, and by drop-glue after relocation. +local function register_pickup(item) + local x = item:get_property("position.x") + local y = item:get_property("position.y") + local trigger_id + trigger_id = interaction.register(x, y, INTERACTION_RANGE, "interact", + function() + inventory.add(state.backpack, item) + interaction.unregister(trigger_id) + if CI_FRAME_PERF then engine.print("vagrant: event=pickup") end + end) +end + -- Signed angle between two 2D vectors (in degrees, range [-180, 180]). -- Sporel uses Y-down screen-coords. Substrate's math assumes Y-up; the cross -- component is flipped so "positive num = move-direction is CCW from body-fwd @@ -279,6 +317,7 @@ function M.init(ctx) input.bind("walk_down", { "s" }) input.bind("sprint", { "shift" }) -- held while walking → 2x speed input.bind("interact", { "e" }) -- fires nearest proximity-trigger + input.bind("drop", { "q" }) -- drop most-recent item from backpack input.bind("quit_to_launcher", { "escape" }) -- Proximity trigger on the backpack-Entity. Anchor read from the @@ -311,6 +350,22 @@ function M.update(ctx, dt) return end + -- Drop: Q pops the most-recently-added item from backpack, relocates + -- it to world at player position + 30px right offset, and re-registers + -- a pickup-trigger. inventory.remove restores the renderable tag. + if input.was_action_pressed("drop") then + local items = inventory.contents(state.backpack) + if #items > 0 then + local item = inventory.remove(state.backpack, items[#items]) + local px = state.actor:get_property("position.x") + local py = state.actor:get_property("position.y") + item:set_property("position.x", px + 30) + item:set_property("position.y", py) + register_pickup(item) + if CI_FRAME_PERF then engine.print("vagrant: event=drop") end + end + end + -- WASD input → normalized move vector. local dx, dy = 0, 0 if input.is_action_down("walk_left") then dx = dx - 1 end diff --git a/manifest.module b/manifest.module index cb8cd9f..9239d44 100644 --- a/manifest.module +++ b/manifest.module @@ -1,6 +1,6 @@ { "id": "vagrant-skeleton", - "version": "0.7.1", + "version": "0.7.2", "kind": "module", "api": "^0.1", "ci_frames": 60, @@ -20,6 +20,7 @@ {"id": "lib-core.maps","version":"0.5.7"}, {"id": "lib-core.puppet", "version": "0.5.0"}, {"id": "lib-core.interaction", "version": "0.1.0"}, + {"id": "lib-core.inventory-list", "version": "0.1.0"}, {"id": "lib-asset.prototype-subterrain", "version": "0.2.0"}, {"id": "lib-asset.prototype-blob-geom", "version": "0.1.0"} ]