@@ -174,6 +174,10 @@ P.act_set = act_set
174174local Port = {}
175175Port .__index = Port
176176
177+ -- What a redefine keeps: the spawn event that bound `ent` will not fire again (ent = 0 would stop
178+ -- the brain), and the hit tables in the game belong to the entity, not to the declaration.
179+ local KEEP = { " ent" , " _hit_id" , " _hit_last" , " _hit_cap" , " _atk_caps" }
180+
177181--- Declare a ported monster.
178182--
179183-- name identifier, also the hot-reload key
@@ -190,16 +194,14 @@ Port.__index = Port
190194--
191195-- Returns a port handle. Safe to call again (hot reload): the injector is armed once per boot.
192196function P .define (spec )
193- -- a redefine keeps the bound entity: the spawn event that bound it will not fire again, and
194- -- ent = 0 would stop the brain. The rest of the state resets.
195197 local prev = P .ports [spec .name ]
196198 local self = setmetatable ({
197199 name = spec .name ,
198200 species = spec .species ,
199201 clips = spec .clips or {},
200202 moves = spec .moves or {},
201203 replace = spec .replace or {},
202- ent = prev and prev . ent or 0 ,
204+ ent = 0 ,
203205 clip = nil , -- currently latched executor a1, nil = hands off
204206 move = nil , -- currently scripted move name
205207 pinned = nil , -- {x, y, z} while the coordinate lock is on
@@ -214,6 +216,7 @@ function P.define(spec)
214216 _native_armed = false ,
215217 _req = nil , -- a play() issued through the seam, until it lands
216218 }, Port )
219+ if prev then for _ , k in ipairs (KEEP ) do self [k ] = prev [k ] end end
217220 -- declared pairs the engine enters on its own get the port's clip too (the action hook paints
218221 -- them), so the mapping holds whoever picked the move; first name wins for a pair declared twice
219222 local names = {}
511514-- in the quest, but beside a native of the same species this re-skins the native too.
512515--
513516-- Applied once the entity is live in-area, re-checked every tick against one record and one grid
514- -- byte, and re-applied with a log line if either changed (an overlay reload shows up here).
517+ -- byte, and re-applied with a log line if either changed (an overlay reload shows up here) or a
518+ -- re-export registers a new content id.
515519--
516520-- Attacks go the other way: a handler spawns an attack by id, and ATTACK_RECORD `id` at
517521-- attack_tables.records names a volume set (VOLUME_SET), reached through the overlay's pointer
@@ -541,9 +545,7 @@ P._hit = P._hit or {} -- port name -> table, from the generated module
541545--- x states} | nil }. Keyed by PORT name so the data module and the brain module
542546--- can load in either order; the tick joins them.
543547function P .hit (name , tbl )
544- P ._hit [name ] = tbl
545- local port = P .ports [name ]
546- if port then port ._hit_id = nil end -- a re-export applies on the next tick
548+ P ._hit [name ] = tbl -- a new id applies on the next tick (hit_tick)
547549 local nsets = 0
548550 if tbl .attack_sets then for _ in pairs (tbl .attack_sets ) do nsets = nsets + 1 end end
549551 log (" [port:%s] hit tables registered: %s volume(s), %s grid state(s), %d attack "
@@ -776,18 +778,20 @@ local function hit_apply(port, tbl)
776778end
777779
778780--- Called from the tick for a live, in-area port. Applies on the first
779- --- opportunity and whenever the live bytes stop matching.
781+ --- opportunity, on a new export id and whenever the live bytes stop matching.
780782local function hit_tick (port )
781783 local tbl = P ._hit [port .name ]
782784 if not tbl then return end
783785 if port ._hit_id == tbl .id and hit_intact (port , tbl ) then return end
784- local why = port ._hit_id == tbl .id and " live table changed under us"
785- or (port ._hit_id and " new export" or " first contact" )
786+ -- _hit_id is what is in place (nil after a failed apply, so it retries); _hit_last names
787+ -- what got in last, for the log
788+ local id = tostring (tbl .id )
789+ local why = port ._hit_last == nil and " first contact"
790+ or (port ._hit_last == id and " live table changed under us" or " new export" )
786791 local ok , what = hit_apply (port , tbl )
787792 if ok then
788- port ._hit_id = tbl .id
789- log (" [port:%s] HIT TABLES APPLIED (%s): %s id=%s" , port .name , why , what ,
790- tostring (tbl .id ))
793+ port ._hit_id , port ._hit_last = tbl .id , id
794+ log (" [port:%s] HIT TABLES APPLIED (%s): %s id=%s" , port .name , why , what , id )
791795 else
792796 port ._hit_id = nil
793797 if (port ._hit_fail or 0 ) % 20 == 0 then
@@ -822,6 +826,7 @@ P._once.events = true
822826mhfu .on_quest_targets_building (function (quest )
823827 if quest == 0 then return end
824828 for name , port in pairs (P .ports ) do
829+ port ._hit_last = nil -- the quest's first hit apply logs as first contact
825830 for _ , victim in ipairs (port .replace ) do
826831 if mhfu .quest_has (quest , victim ) then
827832 local ok = mhfu .quest_replace_monster (quest , victim , port .species )
0 commit comments