fix: install spoof hook lazily from a live extension instance (getmetatable/__index) — CLASS-registry scan at mod load found nothing because extension classes register later; failure path now dumps class keys for next diagnosis

This commit is contained in:
2026-10-03 15:21:13 -04:00
parent e62d6dc6e8
commit ac79578c19
@@ -32,23 +32,49 @@ local CANCEL_INTERVAL = 0.5
-- set_tag() for off-LOS units is silently rejected because the game re-validates the tag -- set_tag() for off-LOS units is silently rejected because the game re-validates the tag
-- through the target extension's forward-LOS _contextual_tag_template_name(); flag the single -- through the target extension's forward-LOS _contextual_tag_template_name(); flag the single
-- auto-hack target on its extension so the game's own validation accepts the order. -- auto-hack target on its extension so the game's own validation accepts the order.
if not mod.omni_hack_spoof_hooked then -- the owning class is discovered lazily from a LIVE extension instance (the CLASS registry
local spoof_class, spoof_class_name -- scan at load time found nothing - extension classes aren't in it yet at that point).
for name, cls in pairs(CLASS) do local function ensure_automark_spoof_hook()
if type(cls) == "table" and rawget(cls, "_contextual_tag_template_name") ~= nil then if mod.omni_hack_spoof_hooked then
spoof_class, spoof_class_name = cls, name return
break
end end
local smart_tag_system = context.smart_tag_system
local unit_extension_data = smart_tag_system and smart_tag_system._unit_extension_data
local _, any_ext = unit_extension_data and next(unit_extension_data)
if not any_ext then
return
end end
if spoof_class then local mt = getmetatable(any_ext)
mod.omni_hack_spoof_hooked = true local cls = mt
mod.omni_hack_spoof_class = spoof_class_name if cls and type(cls) == "table" and cls._contextual_tag_template_name == nil then
mod:hook(spoof_class, "_contextual_tag_template_name", function(previous_hook, self, player_unit, tag_name) cls = rawget(cls, "__index")
end
if type(cls) == "table" and cls._contextual_tag_template_name ~= nil then
mod:hook(cls, "_contextual_tag_template_name", function(previous_hook, self, player_unit, tag_name)
if tag_name == "companion_order" and self._automark_hack_order then if tag_name == "companion_order" and self._automark_hack_order then
return HACK_TAG_NAME return HACK_TAG_NAME
end end
return previous_hook(self, player_unit, tag_name) return previous_hook(self, player_unit, tag_name)
end) end)
mod.omni_hack_spoof_hooked = true
mod.omni_hack_spoof_class = "lazy_class"
if mod_settings.debug_mode then
mod:diag("OMNI-HACK-DIAG spoof hook INSTALLED")
end
elseif mod_settings.debug_mode and not mod.omni_hack_spoof_fail_logged then
mod.omni_hack_spoof_fail_logged = true
local method_keys = {}
if type(cls) == "table" then
local seen = 0
for k, v in pairs(cls) do
if type(k) == "string" and seen < 40 then
method_keys[#method_keys + 1] = k .. ":" .. type(v)
seen = seen + 1
end
end
table.sort(method_keys)
end
mod:diag("OMNI-HACK-DIAG spoof HOOK FAILED mt=", tostring(mt), " cls=", tostring(cls), " instance_has_method=", tostring(any_ext._contextual_tag_template_name ~= nil), " cls_keys=", table.concat(method_keys, ","))
end end
end end
@@ -256,6 +282,7 @@ local function find_hackable_target_unit_omni()
if not smart_tag_system or not player_unit then if not smart_tag_system or not player_unit then
return return
end end
ensure_automark_spoof_hook()
local player_position = Unit_world_position(player_unit, 1) local player_position = Unit_world_position(player_unit, 1)
local selected_unit, selected_distance, selected_name, selected_extension local selected_unit, selected_distance, selected_name, selected_extension