fix: omni auto-hack retargeted at DECODING OBJECTS (_target_type=='hack' + interactee can_interact) — per cryptic_double_tag_settings the companion hack template applies to data-interro objectives, NOT enemies (enemy double-ping = shooting tag, already covered by marking); validates the exact same way the game's own double-ping resolver does

This commit is contained in:
2026-10-03 15:50:37 -04:00
parent 1479b62a61
commit ab5ff1ee49
@@ -12,7 +12,6 @@ local SpecialRulesSettings = require("scripts/settings/ability/spec
local CompanionServoSkullSettings = require("scripts/settings/companion/companion_servo_skull_settings") local CompanionServoSkullSettings = require("scripts/settings/companion/companion_servo_skull_settings")
local Hud = require("scripts/utilities/ui/hud") local Hud = require("scripts/utilities/ui/hud")
local Health = require("scripts/utilities/health") local Health = require("scripts/utilities/health")
local Breed = require("scripts/utilities/breed")
local special_rules = SpecialRulesSettings.special_rules local special_rules = SpecialRulesSettings.special_rules
local servo_skull_states = CompanionServoSkullSettings.STATES local servo_skull_states = CompanionServoSkullSettings.STATES
@@ -288,6 +287,10 @@ mod._hack_blacklist = mod._hack_blacklist or {}
-- hackable=0 all session for all 15 nearby smart-taggable units, even under the crosshair), -- hackable=0 all session for all 15 nearby smart-taggable units, even under the crosshair),
-- so we pick the target ourselves with the same enemy filter the marking path uses and let -- so we pick the target ourselves with the same enemy filter the marking path uses and let
-- auto_hack()'s set_tag() do the actual tagging - same call in-game smart tagging performs. -- auto_hack()'s set_tag() do the actual tagging - same call in-game smart tagging performs.
-- REAL SEMANTICS (per game source cryptic_double_tag_settings): double-ping on an enemy breed =
-- shooting tag (handled by the normal marking passes); double-ping on a "hack" smart-target
-- whose interactee is decoding = hacking_over_here_companion -> skull detaches, flies over,
-- auto-decrypts. So the omni scan must look for DECODING OBJECTS, not enemies.
local function find_hackable_target_unit_omni() local function find_hackable_target_unit_omni()
local smart_tag_system = context.smart_tag_system local smart_tag_system = context.smart_tag_system
local player = context.player local player = context.player
@@ -305,23 +308,21 @@ local function find_hackable_target_unit_omni()
end end
local diag_samples = mod_settings.debug_mode and {} or nil local diag_samples = mod_settings.debug_mode and {} or nil
for unit, target_extension in pairs(smart_tag_system._unit_extension_data) do for unit, target_extension in pairs(smart_tag_system._unit_extension_data) do
if unit ~= player_unit and HEALTH_ALIVE[unit] and target_extension._target_type == "breed" and not mod._hack_blacklist[unit] then if unit ~= player_unit and target_extension._target_type == "hack" and not mod._hack_blacklist[unit] then
local unit_data_extension = ScriptUnit_extension(unit, "unit_data_system") local interactee_extension = ScriptUnit_extension(unit, "interactee_system")
local breed_data = unit_data_extension and unit_data_extension._breed local decoding = interactee_extension ~= nil and interactee_extension:interaction_type() == "decoding" and interactee_extension:can_interact(unit, "decoding")
if breed_data and Breed.is_minion(breed_data) and breed_data.unit_template_name == "minion" and breed_data.faction_name ~= "imperium" and not breed_data.is_boss then if decoding then
if diag_total then if diag_total then
diag_total = diag_total + 1 diag_total = diag_total + 1
end end
local distance = Vector3_distance(Unit_world_position(unit, 1), player_position) local distance = Vector3_distance(Unit_world_position(unit, 1), player_position)
if diag_samples and #diag_samples < 10 then if diag_samples and #diag_samples < 10 then
diag_samples[#diag_samples + 1] = breed_data.name .. "=" .. tostring(distance) diag_samples[#diag_samples + 1] = tostring(distance)
end end
if distance <= OMNI_HACK_RANGE and (not selected_distance or distance < selected_distance) then if distance <= OMNI_HACK_RANGE and (not selected_distance or distance < selected_distance) then
selected_unit, selected_distance = unit, distance selected_unit, selected_distance = unit, distance
selected_extension = target_extension selected_extension = target_extension
if diag_samples then selected_name = "hack_object"
selected_name = breed_data.name
end
end end
end end
end end
@@ -329,7 +330,7 @@ local function find_hackable_target_unit_omni()
if diag_total then if diag_total then
mod.omni_hack_diag_counter = (mod.omni_hack_diag_counter or 0) + 1 mod.omni_hack_diag_counter = (mod.omni_hack_diag_counter or 0) + 1
if mod.omni_hack_diag_counter % 10 == 1 then if mod.omni_hack_diag_counter % 10 == 1 then
mod:diag(string.format("OMNI-HACK-DIAG enemies=%d selected=%s dist=%s", diag_total, tostring(selected_unit), tostring(selected_distance))) mod:diag(string.format("OMNI-HACK-DIAG decoding_objects=%d selected=%s dist=%s", diag_total, tostring(selected_unit), tostring(selected_distance)))
end end
if not selected_unit and diag_total > 0 and mod.omni_hack_diag_counter % 50 == 1 then if not selected_unit and diag_total > 0 and mod.omni_hack_diag_counter % 50 == 1 then
mod:diag("OMNI-HACK-DIAG no-selection samples: " .. table.concat(diag_samples, " ")) mod:diag("OMNI-HACK-DIAG no-selection samples: " .. table.concat(diag_samples, " "))