# lib-core.interaction P.0 proximity-trigger + action-dispatch lib. Register triggers with `(target_x, target_y, range, action_name, callback)`; per-frame `update(actor_x, actor_y)` checks distance + `was_action_pressed` and fires the nearest matching trigger per `action_name`. - Lib-ID: `lib-core.interaction` - Version: `0.1.0` - Spec: `meta/docs/superpowers/specs/2026-05-10-p0-lib-interaction-design.md` Forward-compat stubs (DEPRECATED-MVP) for AABB-targets, action-effect- pipeline integration, visual-feedback / moodlet, action-cycling, hold-vs-press, per-action-resolution-override, callback pcall-wrap, target-entity-binding, range-shape variants. ## API - `interaction.register(target_x, target_y, range, action_name, callback) → id` - `interaction.unregister(id)` — silent no-op if id unknown - `interaction.update(actor_x, actor_y)` — proximity-check + dispatch - `interaction.list() → array of { id, target_x, target_y, range, action_name }` - `interaction.trigger_count() → integer` ## Conventions - Targets are points (not AABBs in P.0). `range` is scalar pixel-radius. - Distance: `engine.spatial.distance(actor, target) ≤ range`. - Multi-match resolution: per `action_name`, only NEAREST in-range trigger fires per update. Different `action_name`s are independent (all may fire the same frame). - Was-pressed semantics: `input.was_action_pressed` (single-frame edge). - Callback receives `info = { actor_x, actor_y, target_x, target_y, distance, trigger_id, action_name }`. Closures may ignore the arg (`function() ... end` is legal). - Loud Lua-errors on API misuse (non-number coords, non-positive range, non-string action_name, non-function callback). - Silent-accept for `action_name` that hasn't been registered with `lib-core.input` — the trigger simply never fires (matches input-lib's silent-false convention). - Callback errors bubble up (no pcall-wrap in P.0). Resilience is E.9 refactor target. ## Consumer pattern ```lua local interaction = require("lib-core.interaction") local input = require("lib-core.input") input.bind("interact", { engine.input.KEY_E }) local sign = { x = 144, y = 144, text = "Hier steht: ..." } interaction.register(sign.x, sign.y, 40, "interact", function(info) engine.print(sign.text) end) function update(ctx, dt) -- (after player.update; reads player center) interaction.update(player_center_x, player_center_y) end ```