diff --git a/AutoMark/scripts/mods/AutoMark/AutoMark.lua b/AutoMark/scripts/mods/AutoMark/AutoMark.lua index 9a40af1..d2f2f56 100644 --- a/AutoMark/scripts/mods/AutoMark/AutoMark.lua +++ b/AutoMark/scripts/mods/AutoMark/AutoMark.lua @@ -330,6 +330,7 @@ mod:io_dofile("AutoMark/scripts/mods/AutoMark/mark/base_mark") mod:io_dofile("AutoMark/scripts/mods/AutoMark/mark/companion_mark") mod:io_dofile("AutoMark/scripts/mods/AutoMark/mark/focus_target_mark") mod:io_dofile("AutoMark/scripts/mods/AutoMark/mark/servo_skull_mark") +mod:io_dofile("AutoMark/scripts/mods/AutoMark/ui/debug_hud") -- Mod Enabled mod.on_enabled = function(initial_call) diff --git a/AutoMark/scripts/mods/AutoMark/AutoMark_data.lua b/AutoMark/scripts/mods/AutoMark/AutoMark_data.lua index 2d680fc..3d5ce9a 100644 --- a/AutoMark/scripts/mods/AutoMark/AutoMark_data.lua +++ b/AutoMark/scripts/mods/AutoMark/AutoMark_data.lua @@ -174,6 +174,11 @@ local widgets = { type = "checkbox", default_value = false, }, + { + setting_id = "debug_hud", + type = "checkbox", + default_value = false, + }, }, }, { diff --git a/AutoMark/scripts/mods/AutoMark/AutoMark_localization.lua b/AutoMark/scripts/mods/AutoMark/AutoMark_localization.lua index 3984c5d..f38ed52 100644 --- a/AutoMark/scripts/mods/AutoMark/AutoMark_localization.lua +++ b/AutoMark/scripts/mods/AutoMark/AutoMark_localization.lua @@ -67,6 +67,16 @@ local localization = { ["zh-cn"] = "在聊天窗口中打印调试消息。关闭可保持游戏界面安静;后台诊断不受影响。", ["zh-tw"] = "在聊天視窗中打印除錯訊息。關閉可保持遊戲介面安靜;背景診斷不受影響。", }, + debug_hud = { + en = "Debug HUD Overlay", + ["zh-cn"] = "调试HUD面板", + ["zh-tw"] = "除錯HUD面板", + }, + debug_hud_tooltip = { + en = "Shows a live text panel (left side of the screen) with current mark targets, cooldowns, skull/dog state and server accept results. Applied at the next mission start.", + ["zh-cn"] = "在屏幕左侧显示实时文本面板:当前标记目标、冷却、骷髅/狗状态及服务器接受结果。下个任务开始时生效。", + ["zh-tw"] = "在螢幕左側顯示即時文字面板:目前標記目標、冷卻、骷髏/狗狀態及伺服器接受結果。下個任務開始時生效。", + }, omni_mark = { en = "360° Marking", ["zh-cn"] = "全向标记", diff --git a/AutoMark/scripts/mods/AutoMark/mark/servo_skull_mark.lua b/AutoMark/scripts/mods/AutoMark/mark/servo_skull_mark.lua index 752853a..0871649 100644 --- a/AutoMark/scripts/mods/AutoMark/mark/servo_skull_mark.lua +++ b/AutoMark/scripts/mods/AutoMark/mark/servo_skull_mark.lua @@ -449,6 +449,7 @@ function mod:auto_hack(dt, t, fixed_frame) local smart_tag_system = context.smart_tag_system local tag = smart_tag_system and smart_tag_system:unit_tag(skull_mark_check.unit) local accepted = tag and tag._template and tag._template.name == TAG_NAMES.SERVO_SKULL_TAG + mod.last_skull_confirm = { n = skull_mark_check.n, accepted = accepted == true } mod:diag(string.format("OMNI-CONFIRM skull-mark %s accepted=%s alive=%s state=%s", skull_mark_check.n, tostring(accepted == true), tostring(HEALTH_ALIVE[skull_mark_check.unit] == true), mod:debug_servo_skull_state())) skull_mark_check = nil end diff --git a/AutoMark/scripts/mods/AutoMark/targeting/custom_targeting.lua b/AutoMark/scripts/mods/AutoMark/targeting/custom_targeting.lua index ba7139d..586ee2f 100644 --- a/AutoMark/scripts/mods/AutoMark/targeting/custom_targeting.lua +++ b/AutoMark/scripts/mods/AutoMark/targeting/custom_targeting.lua @@ -864,9 +864,12 @@ elseif tag_name == TAG_NAMES.SERVO_SKULL_TAG then end table.sort(parts) mod:diag(string.format("OMNI-DIAG pass[%s] best=%s rejects=[%s]", tostring(tag_name), tostring(best_unit_breed_name), table.concat(parts, ","))) + mod.omni_last_rejects = table.concat(parts, ",") omni_rejects = nil end + mod.omni_last = { tag_name = tag_name, best = best_unit_breed_name, cands = num_hits } + if best_unit ~= marked_unit then return best_unit, best_unit_tag, best_unit_is_dormant_daemonhost end diff --git a/AutoMark/scripts/mods/AutoMark/ui/debug_hud.lua b/AutoMark/scripts/mods/AutoMark/ui/debug_hud.lua new file mode 100644 index 0000000..25b4dc5 --- /dev/null +++ b/AutoMark/scripts/mods/AutoMark/ui/debug_hud.lua @@ -0,0 +1,123 @@ +-- AutoMark debug HUD (mod side): injects the HUD element definition at mission +-- HUD creation and feeds it a rebuilt status line buffer at 5 Hz. +local mod = get_mod("AutoMark") +local mod_settings = mod.settings +local TAG_NAMES = mod.TAG_NAMES +local Managers = Managers +local ScriptUnit_extension = ScriptUnit.extension + +mod.debug_hud_last = {} + +local ELEMENT_CLASS_NAME = "HudElementAutoMarkDebug" + +mod:hook(CLASS.UIManager, "create_player_hud", + function(func, self, peer_id, local_player_id, elements, visibility_groups) + if mod_settings.debug_hud and elements then + local already = false + for i = 1, #elements do + if elements[i].class_name == ELEMENT_CLASS_NAME then + already = true + break + end + end + if not already then + elements[#elements + 1] = { + class_name = ELEMENT_CLASS_NAME, + filename = "AutoMark/scripts/mods/AutoMark/ui/hud_element_debug", + use_hud_scale = true, + visibility_groups = { "alive", "dead" }, + } + end + end + return func(self, peer_id, local_player_id, elements, visibility_groups) + end) + +local function unit_breed_name(unit) + if not unit then + return "-" + end + + local ok, name = pcall(function() + local unit_data_extension = ScriptUnit_extension(unit, "unit_data_system") + local breed = unit_data_extension and unit_data_extension._breed + return breed and breed.name or "?" + end) + return ok and name or "?" +end + +local function tag_line(label, tag_name) + local mark_context = mod.mark_context + local tag_context = mark_context and mark_context[tag_name] + local tag = tag_context and tag_context.tag + local target = tag and tag._target_unit + local class_settings = mod:get_class_settings(tag_name) + return string.format("%-5s | %-22s | cd %4.1f sw %4.1f | %s", + label, + unit_breed_name(target), + tag_context and tag_context.cooldown or 0, + tag_context and tag_context.priority_switch_cooldown or 0, + class_settings and class_settings.toggle_class and "ON" or "OFF") +end + +function mod:build_debug_hud_lines() + local buf = mod.debug_hud_last + for i = 1, #buf do + buf[i] = nil + end + + if not mod_settings.debug_hud or not mod_settings.toggle_mod then + return buf + end + + local context = mod.context + local game_mode_manager = Managers.state.game_mode + buf[#buf + 1] = "AUTOMARK " .. tostring(context.class_name) .. " " .. (game_mode_manager and tostring(game_mode_manager:game_mode_name()) or "?") + + local has_skull = context.class_name == "cryptic" and context.has_servo_skull + local has_dog = context.class_name == "adamant" and context.has_companion + + if has_skull then + buf[#buf + 1] = tag_line("SKULL", TAG_NAMES.SERVO_SKULL_TAG) + buf[#buf + 1] = "skull state: " .. tostring(mod:debug_servo_skull_state()) .. (mod:is_servo_skull_hacking() and " HACKING" or "") + end + if has_dog then + buf[#buf + 1] = tag_line("DOG", TAG_NAMES.COMPANION_TAG) + end + buf[#buf + 1] = tag_line("PING", TAG_NAMES.ENEMY_TAG) + + local last = mod.omni_last + if last then + buf[#buf + 1] = string.format("PICK[%s] best=%s cands=%s", tostring(last.tag_name), tostring(last.best), tostring(last.cands)) + if mod.omni_last_rejects then + buf[#buf + 1] = " rejects: " .. mod.omni_last_rejects + end + end + + local confirm = mod.last_skull_confirm + if confirm then + buf[#buf + 1] = "SERVER last " .. tostring(confirm.n) .. ": " .. (confirm.accepted and "ACCEPTED" or "REJECTED") + end + + return buf +end + +local hud_build_timer = 0 +mod:hook_safe(CLASS.PlayerUnitSmartTargetingExtension, "fixed_update", + function(self, unit, dt, t, fixed_frame) + if not mod_settings.debug_hud or not mod_settings.toggle_mod then + return + end + if self._player.viewport_name ~= "player1" then + return + end + + hud_build_timer = hud_build_timer - dt + if hud_build_timer <= 0 then + hud_build_timer = 0.2 + local ok, err = pcall(mod.build_debug_hud_lines, mod) + if not ok and mod_settings.debug_mode and not mod.debug_hud_err_logged then + mod.debug_hud_err_logged = true + mod:diag("OMNI-HUD builder error:", tostring(err)) + end + end + end) diff --git a/AutoMark/scripts/mods/AutoMark/ui/hud_element_debug.lua b/AutoMark/scripts/mods/AutoMark/ui/hud_element_debug.lua new file mode 100644 index 0000000..2b7af73 --- /dev/null +++ b/AutoMark/scripts/mods/AutoMark/ui/hud_element_debug.lua @@ -0,0 +1,92 @@ +-- AutoMark debug HUD element: plain-text live status panel (fork feature). +-- Instantiated by the game HUD pipeline (UIHud._add_element requires this file +-- by definition.filename). Content is produced by AutoMark mod side +-- (ui/debug_hud.lua -> mod.debug_hud_last) so this file stays dumb. +local UIWorkspaceSettings = require("scripts/settings/ui/ui_workspace_settings") +local UIWidget = require("scripts/managers/ui/ui_widget") + +require("scripts/foundation/utilities/color") + +local mod = get_mod("AutoMark") + +local HudElementAutoMarkDebug = class("HudElementAutoMarkDebug", "HudElementBase") + +local panel_size = { 860, 800 } + +local scenegraph_definition = { + screen = UIWorkspaceSettings.screen, + panel = { + horizontal_alignment = "left", + parent = "screen", + vertical_alignment = "middle", + size = panel_size, + position = { + 25, + 0, + 10, + }, + }, +} + +local widget_definitions = { + automark_debug = UIWidget.create_definition({ + { + pass_type = "text", + style_id = "debug_text", + value_id = "debug_text", + style = { + drop_shadow = true, + font_size = 19, + font_type = "proxima_nova_bold", + horizontal_alignment = "left", + vertical_alignment = "top", + text_horizontal_alignment = "left", + text_vertical_alignment = "top", + line_spacing = 1.2, + size = panel_size, + offset = { + 0, + 0, + 0, + }, + text_color = { + 240, + 235, + 180, + 255, + }, + }, + }, + }, "panel"), +} + +HudElementAutoMarkDebug.init = function (self, parent, draw_layer, start_scale) + HudElementAutoMarkDebug.super.init(self, parent, draw_layer, start_scale, { + scenegraph_definition = scenegraph_definition, + widget_definitions = widget_definitions, + }) + self._rebuild_time = 0 + self._last_text = nil +end + +HudElementAutoMarkDebug.update = function (self, dt, t, ui_renderer, render_settings, input_service) + self._rebuild_time = self._rebuild_time - dt + if self._rebuild_time > 0 then + return + end + self._rebuild_time = 0.2 + + local buf = mod.debug_hud_last + local text = table.concat(buf, "\n") + + if text ~= self._last_text then + self._last_text = text + local widget = self._widgets_by_name.automark_debug + if widget then + widget.content.debug_text = text + widget.dirty = true + end + end +end + +return HudElementAutoMarkDebug