Update AA synchronization, CW progression and diagnostics

This commit is contained in:
CAtlas0784 committed 2026-10-30 19:19:05 +07:00
1 parent 67a819a4d3
commit 30bee81fe9
30 files changed
+1143 -55

No files matched your search

+252
View File
@@ -0,0 +1,252 @@
do
local VERSION = 7
local MODULE_NAMES = {
'Logic.SettingModule.SettingEnum',
'Logic/SettingModule/SettingEnum',
'@BakedLua/Logic/SettingModule/SettingEnum',
'SettingEnum',
}
local state = _G.__GAC_FPS_SETTINGS_120_STATE
local Unity = CS.UnityEngine
local function remove_callback(callback)
if not callback then return end
for _, event in ipairs({
{Unity.Application, 'onBeforeRender'},
{Unity.Camera, 'onPreCull'},
}) do
pcall(function() event[1][event[2]]('-', callback) end)
pcall(function() event[1][event[2]] = event[1][event[2]] - callback end)
end
end
local function add_callback(callback)
for _, event in ipairs({
{Unity.Application, 'onBeforeRender'},
{Unity.Camera, 'onPreCull'},
}) do
local ok = pcall(function() event[1][event[2]]('+', callback) end)
if not ok then
ok = pcall(function()
event[1][event[2]] = event[1][event[2]] + callback
end)
end
if ok then return true, event[1], event[2] end
end
return false
end
if state and state.version ~= VERSION then
remove_callback(state.callback)
if state.module and state.original_getter then
pcall(function()
state.module.get_graphics_data_by_type = state.original_getter
end)
end
state = nil
end
state = state or {version = VERSION, next_check = 0}
_G.__GAC_FPS_SETTINGS_120_STATE = state
local function log(message)
Unity.Debug.Log('[GaC 120 FPS Settings] ' .. message)
end
if not state.load_logged then
state.load_logged = true
log('script loaded; checking the native Graphics settings module')
end
local function add_native_option(list, text_id)
if type(list) ~= 'table' then return false end
local next_key = 1
local has_30_fps = false
local has_60_fps = false
for _, option in ipairs(list) do
if type(option) == 'table' then
if option.setting == 120 then return true, false end
if option.setting == 30 and option.text_id == 'UIText_Setting_Level_30FPS' then
has_30_fps = true
elseif option.setting == 60 and option.text_id == 'UIText_Setting_Level_60FPS' then
has_60_fps = true
end
if type(option.key) == 'number' and option.key >= next_key then
next_key = option.key + 1
end
end
end
if not has_30_fps or not has_60_fps then return false, false end
table.insert(list, {
key = next_key,
text_id = text_id,
setting = 120,
})
return true, true
end
local function patch_native_data(module)
local graphics_data = rawget(module, '_graphics_data')
if type(graphics_data) ~= 'table' then
if not state.data_probe_logged then
state.data_probe_logged = true
log('native _graphics_data is not available on the settings module')
end
return false
end
local found_fps_list = false
local added = false
for setting_type, list in pairs(graphics_data) do
local ok, matched, inserted = pcall(add_native_option, list, 'UIText_Setting_Level_120FPS')
if ok and matched then
found_fps_list = true
if inserted then added = true end
if not state.data_probe_logged then
state.data_probe_logged = true
log('found native FPS rows in _graphics_data[' .. tostring(setting_type) .. ']')
end
elseif not ok and not state.data_probe_logged then
state.data_probe_logged = true
log('_graphics_data probe failed: ' .. tostring(matched))
end
end
if added and not state.row_added then
state.row_added = true
log('added the 120 FPS option to the native Graphics data')
elseif not found_fps_list and not state.data_probe_logged then
state.data_probe_logged = true
log('native _graphics_data is present but contains no matching 30/60 FPS rows')
end
return found_fps_list
end
local function find_setting_module()
for _, name in ipairs(MODULE_NAMES) do
local loaded = package.loaded[name]
if type(loaded) == 'table' and type(loaded.get_graphics_data_by_type) == 'function' then
state.module_alias = name
return loaded
end
end
if not state.require_attempted then
state.require_attempted = true
local outcomes = {}
for _, name in ipairs(MODULE_NAMES) do
local ok, result = pcall(require, name)
if ok and type(result) == 'table' and type(result.get_graphics_data_by_type) == 'function' then
state.module_alias = name
return result
end
local loaded = package.loaded[name]
if type(loaded) == 'table' and type(loaded.get_graphics_data_by_type) == 'function' then
state.module_alias = name
return loaded
end
outcomes[#outcomes + 1] = name .. '=' .. (ok and (type(result) .. ':' .. tostring(result)) or tostring(result))
end
state.require_error = table.concat(outcomes, '; ')
end
local global_registry = rawget(_G, 'G')
for _, entry in ipairs({
{value = rawget(_G, 'SettingModule'), name = '_G.SettingModule'},
{value = rawget(_G, 'SettingEnum'), name = '_G.SettingEnum'},
{value = type(global_registry) == 'table' and rawget(global_registry, 'SettingModule') or nil, name = 'G.SettingModule'},
{value = type(global_registry) == 'table' and rawget(global_registry, 'SettingEnum') or nil, name = 'G.SettingEnum'},
}) do
local candidate = entry.value
if type(candidate) == 'table' and type(candidate.get_graphics_data_by_type) == 'function' then
state.module_alias = entry.name
return candidate
end
end
return nil
end
local function install()
local module = find_setting_module()
if type(module) ~= 'table' then
if not state.module_wait_logged then
state.module_wait_logged = true
log('SettingEnum lookup failed; ' .. tostring(state.require_error))
end
return false
end
local getter = module.get_graphics_data_by_type
if type(getter) ~= 'function' then
if not state.getter_wait_logged then
state.getter_wait_logged = true
log('Settings module loaded, but its graphics-data getter is unavailable')
end
return false
end
if state.module == module then return true end
local fps_text = 'UIText_Setting_Level_120FPS'
local original = getter
module.get_graphics_data_by_type = function(...)
local list = original(...)
local ok, result, inserted = pcall(add_native_option, list, fps_text)
if not ok and state.last_error ~= tostring(result) then
state.last_error = tostring(result)
log('could not add the native 120 FPS option: ' .. state.last_error)
elseif ok and result and inserted and not state.row_added then
state.row_added = true
log('added the 120 FPS option to the native Graphics list')
elseif not state.getter_probe_logged then
state.getter_probe_logged = true
local count = type(list) == 'table' and #list or -1
log('Graphics getter called; returned ' .. type(list) .. ' with ' .. tostring(count) .. ' rows')
end
return list
end
state.module = module
state.original_getter = original
log('ready; patched ' .. tostring(state.module_alias))
patch_native_data(module)
return true
end
local function tick()
local now = Unity.Time.unscaledTime
if now < state.next_check then return end
state.next_check = now + 0.5
local ok, result = pcall(install)
if not ok then
if state.last_error ~= tostring(result) then
state.last_error = tostring(result)
log('waiting for the native Graphics settings: ' .. state.last_error)
end
return
end
if result then
remove_callback(state.callback)
state.callback = nil
end
end
if not state.module and not state.callback then
state.callback = tick
local ok = add_callback(state.callback)
if not ok then
state.callback = nil
log('could not register the Graphics settings hook')
end
end
if not state.module then
tick()
end
end
+30
View File
@@ -124,6 +124,35 @@ local function current_facecam_target()
return nil, nil, nil, true
end
-- Log only changes, so diagnostics stay useful during long battles.
local function log_facecam_target(ok, head, root, id, tracked)
local success, detail = pcall(function()
if not ok then return 'resolve_error=' .. tostring(head) end
return 'tracked=' .. tostring(tracked) .. ' entity=' .. tostring(id)
.. ' model=' .. tostring(root and root.name)
.. ' head=' .. tostring(head and head.name)
.. ' head_parent=' .. tostring(head and head.parent and head.parent.name)
.. ' head_active=' .. tostring(head and head.gameObject.activeInHierarchy)
end)
if not success then detail = 'diagnostic_error=' .. tostring(detail) end
if _G.__FC_FACE_LAST_DIAGNOSTIC ~= detail then
_G.__FC_FACE_LAST_DIAGNOSTIC = detail
local message = '[GaC FaceCam] ' .. detail
CS.UnityEngine.Debug.Log(message)
local written, err = pcall(function()
local dir = _G.__GAC_DIAGNOSTICS_DIR
if not dir or dir == '' then error('server diagnostics directory unavailable') end
CS.System.IO.Directory.CreateDirectory(dir)
local path = CS.System.IO.Path.Combine(dir, 'facecam.log')
CS.System.IO.File.AppendAllText(path, tostring(CS.System.DateTime.Now) .. ' ' .. message .. '\n')
end)
if not written and _G.__FC_FACE_FILE_ERROR ~= tostring(err) then
_G.__FC_FACE_FILE_ERROR = tostring(err)
CS.UnityEngine.Debug.Log('[GaC FaceCam] file log error: ' .. tostring(err))
end
end
end
local function facecam_target(cam)
local ok, head, root = pcall(function()
local battleHead, battleRoot, id, tracked = current_facecam_target()
@@ -152,6 +181,7 @@ local function update_facecam(cam, settings)
if now >= (_G.__FC_FACE_NEXT or 0) then
_G.__FC_FACE_NEXT = now + 0.15
local ok, head, root, id, tracked = pcall(current_facecam_target)
log_facecam_target(ok, head, root, id, tracked)
if ok and tracked and head and root then
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT, _G.__FC_FACE_ENTITY = head, root, id
end
+61 -6
View File
@@ -6,6 +6,22 @@ local GameObject = CS.UnityEngine.GameObject
local CanvasGroup = CS.UnityEngine.CanvasGroup
local Camera = CS.UnityEngine.Camera
-- The server supplies its installation's log directory in the heartbeat.
local function diagnostic(message)
CS.UnityEngine.Debug.Log(message)
local ok, err = pcall(function()
local dir = _G.__GAC_DIAGNOSTICS_DIR
if not dir or dir == '' then error('server diagnostics directory unavailable') end
CS.System.IO.Directory.CreateDirectory(dir)
local path = CS.System.IO.Path.Combine(dir, 'hide-ui.log')
CS.System.IO.File.AppendAllText(path, tostring(CS.System.DateTime.Now) .. ' ' .. message .. '\n')
end)
if not ok and _G.__HIDE_UI_FILE_ERROR ~= tostring(err) then
_G.__HIDE_UI_FILE_ERROR = tostring(err)
CS.UnityEngine.Debug.Log('[GaC HideUI] file log error: ' .. tostring(err))
end
end
-- Names observed under UIRoot in this Client, plus the existing battle HUD.
-- Never target an ancestor shared by HUD and character/reward dialogs.
local HUD_PATHS = {
@@ -58,8 +74,9 @@ _G.__HIDE_UI_ENABLED = _G.__HIDE_UI_ENABLED or false
_G.__HIDE_UI_TARGETS = _G.__HIDE_UI_TARGETS or {}
local function restore_hud()
local count, errors = 0, 0
for id, state in pairs(_G.__HIDE_UI_TARGETS) do
pcall(function()
local ok = pcall(function()
if state.group then
if state.added then
CS.UnityEngine.Object.Destroy(state.group)
@@ -70,8 +87,11 @@ local function restore_hud()
end
end
end)
count = count + 1
if not ok then errors = errors + 1 end
_G.__HIDE_UI_TARGETS[id] = nil
end
diagnostic('[GaC HideUI] restored=' .. count .. ' errors=' .. errors)
end
local function protected_name(name)
@@ -91,6 +111,9 @@ local function hide_object(obj)
state = {group=group, added=added, alpha=group.alpha,
raycast=group.blocksRaycasts, interactable=group.interactable}
_G.__HIDE_UI_TARGETS[id] = state
if _G.__HIDE_UI_SCAN_DIAG then
_G.__HIDE_UI_SCAN_DIAG.added = _G.__HIDE_UI_SCAN_DIAG.added + 1
end
end
state.group.alpha = 0
state.group.blocksRaycasts = false
@@ -166,7 +189,14 @@ end
local function hide_hud()
for _, path in ipairs(HUD_PATHS) do
pcall(function() hide_hud_tree(GameObject.Find(path)) end)
local ok, err = pcall(function()
local obj = GameObject.Find(path)
if obj and obj.activeInHierarchy then
table.insert(_G.__HIDE_UI_SCAN_DIAG.paths, path)
end
hide_hud_tree(obj)
end)
if not ok then table.insert(_G.__HIDE_UI_SCAN_DIAG.errors, path .. ': ' .. tostring(err)) end
end
local ok, err = pcall(function()
local flags = CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags), 60)
@@ -176,6 +206,7 @@ local function hide_hud()
or typeof(CS.RPG.Client.BattleGamePhase):GetField("_HudPage", flags)
local manager = CS.RPG.Client.GlobalVars.s_GamePhaseManager
local phase = manager and _G.__HIDE_UI_PHASE_FIELD:GetValue(manager)
_G.__HIDE_UI_SCAN_DIAG.phase = phase and tostring(phase:GetType().Name) or 'none'
if phase and typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase) then
local hud = _G.__HIDE_UI_BATTLE_HUD_FIELD:GetValue(phase)
if hud and hud.Trans then hide_hud_tree(hud.Trans.gameObject) end
@@ -189,13 +220,14 @@ local function hide_hud()
end)
if not ok and _G.__HIDE_UI_LAST_ERROR ~= tostring(err) then
_G.__HIDE_UI_LAST_ERROR = tostring(err)
CS.UnityEngine.Debug.Log("[GaC HideUI] Battle HUD: " .. tostring(err))
diagnostic("[GaC HideUI] Battle HUD: " .. tostring(err))
end
pcall(function()
local pagesOK, pagesErr = pcall(function()
local ui = CS.RPG.Client.GlobalVars.s_UIManager
local pages = ui:GetAllPageNames()
for i = 0, pages.Count - 1 do
local name = tostring(pages[i]); local lower = string.lower(name)
table.insert(_G.__HIDE_UI_SCAN_DIAG.pages, name)
local page = ui:GetPageByName(name)
if page and page.ChildDialogs then
for j = 0, page.ChildDialogs.Count - 1 do
@@ -219,16 +251,18 @@ local function hide_hud()
end
hide_rank_controls(GameObject.Find("UIRoot/Page/AvatarMainPage(Clone)/Root/AvatarRankPanel"))
end)
if not pagesOK then table.insert(_G.__HIDE_UI_SCAN_DIAG.errors, 'pages: ' .. tostring(pagesErr)) end
end
function _G.__HIDE_UI_TICK()
pcall(function()
local ok, err = pcall(function()
local frame = Time.frameCount
if _G.__HIDE_UI_LAST_FRAME == frame then return end
_G.__HIDE_UI_LAST_FRAME = frame
local toggled = Input.GetKeyDown(KeyCode.Backslash)
if toggled then
_G.__HIDE_UI_ENABLED = not _G.__HIDE_UI_ENABLED
diagnostic('[GaC HideUI] enabled=' .. tostring(_G.__HIDE_UI_ENABLED))
if not _G.__HIDE_UI_ENABLED then restore_hud() end
end
-- The page/child scan walks Unity UI trees, so keep it to once a second.
@@ -237,10 +271,31 @@ function _G.__HIDE_UI_TICK()
local now = Time.unscaledTime
if toggled or now >= (_G.__HIDE_UI_NEXT_SCAN or 0) then
_G.__HIDE_UI_NEXT_SCAN = now + 1.0
hide_hud()
local started = Time.realtimeSinceStartup
local diag = {added=0, paths={}, pages={}, errors={}, phase='unknown'}
_G.__HIDE_UI_SCAN_DIAG = diag
local scanOK, scanErr = pcall(hide_hud)
_G.__HIDE_UI_SCAN_DIAG = nil
if not scanOK then table.insert(diag.errors, 'scan: ' .. tostring(scanErr)) end
local elapsed = (Time.realtimeSinceStartup - started) * 1000
local signature = diag.phase .. '|' .. table.concat(diag.pages, ',') .. '|'
.. table.concat(diag.paths, ',') .. '|' .. table.concat(diag.errors, ',')
if toggled or diag.added > 0 or #diag.errors > 0 or elapsed >= 20
or signature ~= _G.__HIDE_UI_DIAG_SIGNATURE
or now >= (_G.__HIDE_UI_DIAG_NEXT or 0) then
_G.__HIDE_UI_DIAG_SIGNATURE = signature
_G.__HIDE_UI_DIAG_NEXT = now + 30
diagnostic(string.format('[GaC HideUI] scan_ms=%.2f phase=%s added=%d pages=[%s] paths=[%s] errors=[%s]',
elapsed, diag.phase, diag.added, table.concat(diag.pages, ','),
table.concat(diag.paths, ','), table.concat(diag.errors, ',')))
end
end
end
end)
if not ok and _G.__HIDE_UI_TICK_ERROR ~= tostring(err) then
_G.__HIDE_UI_TICK_ERROR = tostring(err)
diagnostic('[GaC HideUI] tick error: ' .. tostring(err))
end
end
-- Restore targets from the previous policy (including VersionText) on upgrade.