| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- -- The native pickup grants the cell and the receptacle owns its usability/item criteria.
- -- Ownership Sense distinguishes held, dropped and missing cells. Only accepted receptacle
- -- interaction completes delivery; proximity and the recording's timing cannot complete it.
- return function(api, tag, pickup, receptacle, on_pickup, on_deposit)
- local function key(suffix) return "ember.carry." .. tag .. "." .. suffix end
- local function generation(s) return s:variable(key("generation")) or 1 end
- local function recovery(s) return "ember.carry.recover." .. tag .. "." .. generation(s) end
- local region = tag == "processing" and 56 or 0
- local obj = {}
- function obj.start(c, s)
- if s:variable(key("started")) then return end
- c:set_variable(key("started"), true)
- c:set_variable(key("receptacle_generation"), generation(s))
- api.slot(c, pickup):set_interactable_object{generation = generation(s), track_owner = true}
- api.slot(c, receptacle):set_interactable_object{generation = generation(s)}
- end
- function obj.interaction(c, s, e)
- if not s:variable(key("started")) or s:variable(key("done")) then return end
- if api.matches(c, e, receptacle) and e.generation == s:variable(key("receptacle_generation")) then
- -- Require a pickup receipt as well as native accepted use of the receptacle.
- if not s:variable(key("notified")) then return end
- c:set_variable(key("done"), true)
- c:cancel_timer(recovery(s))
- c:clear_variable(key("recover_armed"))
- c:clear_variable(key("recover_pending"))
- c:set_variable(key("held"), false)
- c:set_variable(key("present"), false)
- -- Native 9F19F0 destroys the old entity on a newer generation and
- -- active=false prevents replacement. Includes cells attached to a player.
- -- Keep the pickup generation for stale-event guards; a reset advances by two.
- api.slot(c, pickup):set_interactable_object{
- generation = generation(s) + 1, active = false, track_owner = true}
- on_deposit(c, s)
- elseif api.matches(c, e, pickup) and e.generation == generation(s) and not s:variable(key("notified")) then
- c:set_variable(key("notified"), true)
- c:set_variable(key("seen"), true)
- c:set_variable(key("held"), true)
- on_pickup(c, s)
- end
- end
- function obj.state(c, s, e)
- if not s:variable(key("started")) or s:variable(key("done"))
- or e.generation ~= generation(s) or not api.matches(c, e, pickup) then return end
- -- Expired cells may retain an entity for cleanup after they stop being alive.
- -- That entity cannot be carried or inserted and must not suppress recovery.
- local usable = e.present and e.alive ~= false
- c:set_variable(key("present"), usable)
- if usable then
- c:set_variable(key("seen"), true)
- c:cancel_timer(recovery(s))
- c:clear_variable(key("recover_armed"))
- if e.owner_known then c:set_variable(key("held"), e.has_owner) end
- if e.has_owner and not s:variable(key("notified")) then
- c:set_variable(key("notified"), true); on_pickup(c, s)
- end
- else
- c:set_variable(key("held"), false)
- -- Also recover when the first acknowledged generation is already missing;
- -- a late subscription must not require an earlier present/held event.
- if not s:variable(key("recover_armed")) then
- c:set_variable(key("recover_armed"), true)
- c:start_timer(recovery(s), 2000)
- end
- end
- end
- function obj.timer(c, s, e)
- if e.timer_name ~= recovery(s) then return false end
- c:clear_variable(key("recover_armed"))
- if s:variable(key("done")) or s:variable(key("present")) then return true end
- if s:variable("ember.region") ~= region then c:set_variable(key("recover_pending"), true); return true end
- c:set_variable(key("generation"), generation(s) + 2)
- c:clear_variable(key("seen")); c:clear_variable(key("notified"))
- api.slot(c, pickup):set_interactable_object{generation = generation(s), track_owner = true}
- -- Preserve the receptacle's current generation. A cell's expiry is not a new objective.
- return true
- end
- function obj.resume(c, s)
- if s:variable(key("recover_pending")) then
- c:clear_variable(key("recover_pending")); c:start_timer(recovery(s), 2000)
- end
- end
- function obj.reset(c, s)
- c:cancel_timer(recovery(s))
- api.objects(c, {pickup, receptacle}, false)
- c:set_variable(key("generation"), generation(s) + 2)
- for _, suffix in ipairs({"started", "done", "seen", "held", "present", "notified", "recover_pending", "recover_armed"}) do c:clear_variable(key(suffix)) end
- end
- function obj.held(s) return s:variable(key("held")) == true end
- function obj.done(s) return s:variable(key("done")) == true end
- return obj
- end
|