Skip to content

Instantly share code, notes, and snippets.

@TTSKarlsson
Created June 24, 2026 10:28
Show Gist options
  • Select an option

  • Save TTSKarlsson/bd3e37ca5f10d0aa0f53002cb9ef463d to your computer and use it in GitHub Desktop.

Select an option

Save TTSKarlsson/bd3e37ca5f10d0aa0f53002cb9ef463d to your computer and use it in GitHub Desktop.
G1R Compass UI Patched 1.1.12
local MOD_NAME = "[G1R_CompassUI]"
local VERSION = "1.0.12"
local SCRIPT_DIR = (debug.getinfo(1, "S").source or ""):match("^@?(.*[\\/])") or ""
local SCRIPT_SEP = string.find(SCRIPT_DIR, "\\", 1, true) and "\\" or "/"
local DEBUG_LOG = SCRIPT_DIR .. ".." .. SCRIPT_SEP .. "compass_debug.log"
local CONFIG = {
startupDelayMs = 12000,
retryDelayMs = 3000,
postLoadDelayMs = 3000,
updateDelayMs = 100,
usePlayerTickHook = false,
useClientRestartHook = false,
x = 0,
markerY = 1,
labelY = 16,
width = 96,
height = 28,
markerFontSize = 12,
labelFontSize = 13,
textColor = { R = 0.78, G = 0.72, B = 0.58, A = 0.78 },
labelSpacing = 92,
markerRange = 92,
yawOffsetDegrees = -90,
useCenterAnchor = true,
maxDebugLines = 300,
tag = "G1R_COMPASS_UI",
}
local state = {
marker = nil,
labelWidgets = {},
labelSlots = {},
createdWidgets = {},
markerSlot = nil,
centerX = nil,
ready = false,
loopStarted = false,
nextCreateMs = 0,
lastText = nil,
lastLogMs = 0,
lastMoveLogMs = 0,
loopSerial = 0,
lastYaw = nil,
lastYawSource = "none",
tickHooked = false,
parentName = nil,
mainMapContext = nil,
suspendedUntilMs = 0,
creating = false,
loadGeneration = 0,
centerAnchorSupported = nil,
debugLineCount = 0,
}
local labels = {
"N", "NNE", "NE", "ENE",
"E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW",
"W", "WNW", "NW", "NNW",
}
local function reset_log()
pcall(function()
local file = io.open(DEBUG_LOG, "w")
if file then
file:write(os.date("%Y-%m-%d %H:%M:%S ") .. MOD_NAME .. " debug log reset v" .. VERSION .. "\n")
file:close()
state.debugLineCount = 1
end
end)
end
local function log(message)
if state.debugLineCount >= CONFIG.maxDebugLines then
return
end
local ok, file = pcall(function()
return io.open(DEBUG_LOG, "a")
end)
if ok and file then
file:write(os.date("%Y-%m-%d %H:%M:%S ") .. MOD_NAME .. " " .. tostring(message) .. "\n")
file:close()
state.debugLineCount = state.debugLineCount + 1
end
end
local function is_valid(object)
if not object then
return false
end
local ok, value = pcall(function()
return object:IsValid()
end)
if ok then
return value == true
end
return pcall(function()
object:GetFullName()
end)
end
local function safe_get_property(object, name)
if not is_valid(object) then
return nil
end
local ok, value = pcall(function()
return object[name]
end)
if ok then
return value
end
return nil
end
local function full_name(object)
if not is_valid(object) then
return "<invalid>"
end
local ok, name = pcall(function()
return object:GetFullName()
end)
if ok and name then
return tostring(name)
end
return "<unnamed>"
end
local function safe_static_find(path)
local ok, object = pcall(function()
return StaticFindObject(path)
end)
if ok and is_valid(object) then
return object
end
return nil
end
local function safe_find_first(class_name)
local ok, object = pcall(function()
return FindFirstOf(class_name)
end)
if ok and is_valid(object) then
return object
end
return nil
end
local function safe_find_all(class_name)
local ok, objects = pcall(function()
return FindAllOf(class_name)
end)
if ok and type(objects) == "table" then
return objects
end
return {}
end
local function vec2(x, y)
return { X = x, Y = y }
end
local function anchors(minX, minY, maxX, maxY)
return {
Minimum = vec2(minX, minY),
Maximum = vec2(maxX, maxY),
}
end
local function now_ms()
return math.floor(os.clock() * 1000)
end
local function get_controller()
local preferred = safe_find_first("GothicPlayerControllerBaseBP_C")
or safe_find_first("PlayerController")
if is_valid(preferred) and is_valid(safe_get_property(preferred, "Pawn")) then
return preferred
end
for _, class_name in ipairs({ "GothicPlayerControllerBaseBP_C", "PlayerController" }) do
for _, controller in ipairs(safe_find_all(class_name)) do
if is_valid(controller) and is_valid(safe_get_property(controller, "Pawn")) then
return controller
end
end
end
return preferred
end
local function in_main_map()
local controller = get_controller()
local controllerName = full_name(controller)
if string.find(controllerName, "None.None", 1, true) then
return false, controllerName
end
if string.find(controllerName, "MainMap", 1, true) then
return true, controllerName
end
return false, controllerName
end
local function read_number_field(value, names)
if value == nil then
return nil
end
for _, name in ipairs(names) do
local ok, number = pcall(function()
return value[name]
end)
if ok and type(number) == "number" then
return number
end
end
return nil
end
local function get_compass_center_x()
if CONFIG.useCenterAnchor and state.centerAnchorSupported == true then
return 0
end
local controller = get_controller()
if is_valid(controller) then
local ok, width = pcall(function()
return controller:GetViewportSize()
end)
if ok and type(width) == "number" and width > 100 then
return math.floor(width / 2)
end
if ok then
local x = read_number_field(width, { "X", "x", "Width", "width" })
if x and x > 100 then
return math.floor(x / 2)
end
end
end
local layoutLibrary = safe_static_find("/Script/UMG.Default__WidgetLayoutLibrary")
if is_valid(layoutLibrary) and is_valid(controller) then
local ok, size = pcall(function()
return layoutLibrary:GetViewportSize(controller)
end)
if ok then
local x = read_number_field(size, { "X", "x", "Width", "width" })
if x and x > 100 then
return math.floor(x / 2)
end
end
end
return CONFIG.x
end
local function read_yaw_from_rotator(rotator)
if not rotator then
return nil
end
for _, field in ipairs({ "Yaw", "yaw", "Z", "z" }) do
local ok, value = pcall(function()
return rotator[field]
end)
if ok and type(value) == "number" then
return value
end
end
return nil
end
local function read_yaw_from_vector(vector)
if not vector then
return nil
end
local okX, x = pcall(function()
return vector.X or vector.x
end)
local okY, y = pcall(function()
return vector.Y or vector.y
end)
if okX and okY and type(x) == "number" and type(y) == "number" then
return math.deg(math.atan(y, x))
end
return nil
end
local function read_xy_from_vector(vector)
if not vector then
return nil, nil
end
local okX, x = pcall(function()
return vector.X or vector.x
end)
local okY, y = pcall(function()
return vector.Y or vector.y
end)
if okX and okY and type(x) == "number" and type(y) == "number" then
return x, y
end
return nil, nil
end
local function read_actor_location_xy(object)
if not is_valid(object) then
return nil, nil
end
local okLocation, location = pcall(function()
return object:GetActorLocation()
end)
if okLocation then
return read_xy_from_vector(location)
end
return nil, nil
end
local function read_camera_look_yaw(manager)
if not is_valid(manager) then
return nil
end
local okCameraLocation, cameraLocation = pcall(function()
return manager:GetCameraLocation()
end)
if not okCameraLocation then
return nil
end
local cameraX, cameraY = read_xy_from_vector(cameraLocation)
if not cameraX or not cameraY then
return nil
end
local character = safe_find_first("PlayerCharacterBP_C") or safe_find_first("Character")
local targetX, targetY = read_actor_location_xy(character)
if not targetX or not targetY then
return nil
end
local dx = targetX - cameraX
local dy = targetY - cameraY
if math.abs(dx) < 0.001 and math.abs(dy) < 0.001 then
return nil
end
return math.deg(math.atan(dy, dx))
end
local function read_camera_cache_yaw(manager)
local cache = safe_get_property(manager, "CameraCachePrivate")
local pov = safe_get_property(cache, "POV")
local rotation = safe_get_property(pov, "Rotation")
return read_yaw_from_rotator(rotation)
end
local function read_actor_yaw(object, source)
if not is_valid(object) then
return nil, nil
end
local okRot, rot = pcall(function()
return object:GetActorRotation()
end)
local yaw = okRot and read_yaw_from_rotator(rot) or nil
if yaw then
return yaw, source .. ":actorRotation"
end
local okForward, forward = pcall(function()
return object:GetActorForwardVector()
end)
yaw = okForward and read_yaw_from_vector(forward) or nil
if yaw then
return yaw, source .. ":actorForward"
end
return nil, nil
end
local function read_yaw()
local controller = get_controller()
if controller then
local okManager, manager = pcall(function()
return controller.PlayerCameraManager
end)
if okManager and is_valid(manager) then
local cacheYaw = read_camera_cache_yaw(manager)
if cacheYaw then
return cacheYaw, "cameraCache"
end
local okRot, rot = pcall(function()
return manager:GetCameraRotation()
end)
local yaw = okRot and read_yaw_from_rotator(rot) or nil
if yaw then
return yaw, "camera"
end
local lookYaw = read_camera_look_yaw(manager)
if lookYaw then
return lookYaw, "cameraLook"
end
local managerYaw, managerSource = read_actor_yaw(manager, "cameraManager")
if managerYaw then
return managerYaw, managerSource
end
end
end
if controller then
local okControl, controlRot = pcall(function()
return controller:GetControlRotation()
end)
local controlYaw = okControl and read_yaw_from_rotator(controlRot) or nil
if controlYaw and math.abs(controlYaw) > 0.001 then
return controlYaw, "control"
end
local controllerYaw, controllerSource = read_actor_yaw(controller, "controller")
if controllerYaw and math.abs(controllerYaw) > 0.001 then
return controllerYaw, controllerSource
end
end
return nil, "none"
end
local function yaw_to_index(yaw)
local normalized = yaw % 360
if normalized < 0 then
normalized = normalized + 360
end
return math.floor((normalized / 22.5) + 0.5) % 16
end
local function compass_text(yaw)
local center = yaw_to_index(yaw)
local parts = {}
for offset = -2, 2 do
local index = ((center + offset) % 16) + 1
local label = labels[index]
parts[#parts + 1] = label
end
return table.concat(parts, " ")
end
local function cardinal_center(yaw)
local normalized = yaw % 360
if normalized < 0 then
normalized = normalized + 360
end
local cardinals = {
{ label = "N", yaw = 0 },
{ label = "E", yaw = 90 },
{ label = "S", yaw = 180 },
{ label = "W", yaw = 270 },
}
local index = math.floor((normalized / 90) + 0.5) % 4 + 1
return index, cardinals
end
local function yaw_delta(a, b)
local delta = (a - b + 180) % 360 - 180
return delta
end
local function find_text_class()
local candidates = {
"Class /Script/UMG.TextBlock",
"/Script/UMG.TextBlock",
}
for _, path in ipairs(candidates) do
local object = safe_static_find(path)
if object then
log("TextBlock class found: " .. full_name(object))
return object
end
end
log("TextBlock class not found")
return nil
end
local function find_text_library()
local candidates = {
"KismetTextLibrary /Script/Engine.Default__KismetTextLibrary",
"/Script/Engine.Default__KismetTextLibrary",
"Default__KismetTextLibrary",
}
for _, path in ipairs(candidates) do
local object = safe_static_find(path)
if object then
log("KismetTextLibrary found: " .. full_name(object))
return object
end
end
local object = safe_find_first("KismetTextLibrary")
if object then
log("KismetTextLibrary found by class: " .. full_name(object))
return object
end
log("KismetTextLibrary not found")
return nil
end
local textLibrary = nil
local function to_ftext(text)
if not textLibrary or not is_valid(textLibrary) then
textLibrary = find_text_library()
end
if textLibrary then
local ok, value = pcall(function()
return textLibrary:Conv_StringToText(text)
end)
if ok and value then
return value
end
log("Conv_StringToText failed: " .. tostring(value))
end
if type(FText) == "function" then
local ok, value = pcall(function()
return FText(text)
end)
if ok and value then
return value
end
end
return nil
end
local function set_text(widget, text)
if not is_valid(widget) then
return false
end
local ftext = to_ftext(text)
if not ftext then
log("cannot convert text: " .. tostring(text))
return false
end
local ok, err = pcall(function()
widget:SetText(ftext)
end)
if not ok then
log("SetText failed: " .. tostring(err))
return false
end
return true
end
local function get_text_string(widget)
if not is_valid(widget) then
return nil
end
local okText, ftext = pcall(function()
return widget:GetText()
end)
if okText and ftext then
local okString, value = pcall(function()
return tostring(ftext)
end)
if okString and value then
return value
end
end
return nil
end
local function looks_like_compass_text(text)
if not text then
return false
end
text = tostring(text)
return text == "v"
or text == "N"
or text == "E"
or text == "S"
or text == "W"
or string.find(text, "COMPASS", 1, true) ~= nil
or string.find(text, "NW", 1, true) ~= nil
or string.find(text, "NE", 1, true) ~= nil
or string.find(text, "SW", 1, true) ~= nil
or string.find(text, "SE", 1, true) ~= nil
end
local function find_player_canvas()
local best = nil
local bestScore = -10000
local candidates = {}
for _, panel in ipairs(safe_find_all("CanvasPanel")) do
if is_valid(panel) then
local name = full_name(panel)
local score = 0
local isLivePlayerUi = string.find(name, "/Engine/Transient", 1, true)
and string.find(name, "GameEngine", 1, true)
and string.find(name, "GothicGameInstance", 1, true)
and string.find(name, "Player_UI", 1, true)
and string.find(name, "CanvasPanel_793", 1, true)
if string.find(name, "Player_UI", 1, true) then
score = score + 500
end
if string.find(name, "Player_Widget", 1, true) then
score = score + 350
end
if string.find(name, "CanvasPanel_793", 1, true) then
score = score + 200
end
if isLivePlayerUi then
score = score + 1000
end
if string.find(name, "MainMenu", 1, true)
or string.find(name, "FrontEnd", 1, true)
or string.find(name, "Dialogue", 1, true)
or string.find(name, "Dialog", 1, true)
or string.find(name, "PlayerSpeak", 1, true)
or string.find(name, "BorderWarning", 1, true)
or string.find(name, "Transition", 1, true)
or string.find(name, "Loot", 1, true)
or string.find(name, "Inventory", 1, true) then
score = score - 1000
end
if string.find(name, "/Game/UI/Player/Player_Widget", 1, true) then
score = score - 2000
end
if string.find(name, "/Engine/Transient.Player_UI:", 1, true) then
score = score - 2000
end
candidates[#candidates + 1] = { object = panel, name = name, score = score }
if score > bestScore then
best = panel
bestScore = score
end
end
end
table.sort(candidates, function(a, b)
return a.score > b.score
end)
for index = 1, math.min(6, #candidates) do
log("canvas candidate " .. tostring(index) .. " score=" .. tostring(candidates[index].score) .. ": " .. candidates[index].name)
end
if best and bestScore > 1000 then
log("canvas selected score=" .. tostring(bestScore) .. ": " .. full_name(best))
return best
end
log("player canvas not found")
return nil
end
local function construct_text_block(parent, text, x, y, fontSize)
local textClass = find_text_class()
if not textClass then
return nil
end
local outer = parent
local okOuter, parentOuter = pcall(function()
return parent:GetOuter()
end)
if okOuter and is_valid(parentOuter) then
outer = parentOuter
end
local ok, widget = pcall(function()
return StaticConstructObject(textClass, outer)
end)
if not ok or not is_valid(widget) then
log("StaticConstructObject TextBlock failed: " .. tostring(widget))
return nil
end
log("TextBlock constructed: " .. full_name(widget) .. "; outer=" .. full_name(outer))
if not set_text(widget, text) then
return nil
end
pcall(function()
widget:SetToolTipText(to_ftext(CONFIG.tag))
end)
pcall(function()
widget:SetVisibility(2)
end)
pcall(function()
local font = widget.Font
if font then
font.Size = fontSize
widget:SetFont(font)
end
end)
pcall(function()
widget:SetColorAndOpacity({ SpecifiedColor = CONFIG.textColor, ColorUseRule = 0 })
end)
pcall(function()
widget:SetRenderOpacity(1.0)
end)
pcall(function()
widget:SetJustification(1)
end)
local okAdd, slot = pcall(function()
return parent:AddChildToCanvas(widget)
end)
if not okAdd or not is_valid(slot) then
log("AddChildToCanvas failed: " .. tostring(slot))
return nil
end
local positionX = x
if CONFIG.useCenterAnchor then
local okAnchor = pcall(function()
slot:SetAnchors(anchors(0.5, 0.0, 0.5, 0.0))
end)
state.centerAnchorSupported = okAnchor == true
if not okAnchor then
positionX = get_compass_center_x() + x
log("center anchor failed; using absolute x=" .. tostring(positionX))
end
end
pcall(function()
slot:SetAutoSize(true)
end)
pcall(function()
slot:SetAlignment(vec2(0.5, 0.0))
end)
pcall(function()
slot:SetPosition(vec2(positionX, y))
end)
pcall(function()
slot:SetSize(vec2(CONFIG.width, CONFIG.height))
end)
pcall(function()
slot:SetZOrder(9999)
end)
state.createdWidgets[#state.createdWidgets + 1] = widget
log("TextBlock added at x=" .. tostring(positionX) .. " y=" .. tostring(y) .. "; centerAnchor=" .. tostring(state.centerAnchorSupported))
return widget, slot
end
local function set_compass_visibility(visible)
local visibility = visible and 0 or 2
if is_valid(state.marker) then
pcall(function()
state.marker:SetVisibility(visibility)
end)
end
for _, widget in ipairs(state.labelWidgets) do
if is_valid(widget) then
pcall(function()
widget:SetVisibility(visibility)
end)
end
end
end
local function remove_widget(widget)
if is_valid(widget) then
pcall(function()
widget:SetText(to_ftext(""))
end)
pcall(function()
widget:SetRenderOpacity(0.0)
end)
pcall(function()
widget:SetVisibility(2)
end)
pcall(function()
widget:RemoveFromParent()
end)
end
end
local function destroy_compass()
for _, widget in ipairs(state.createdWidgets) do
remove_widget(widget)
end
state.createdWidgets = {}
remove_widget(state.marker)
for _, widget in ipairs(state.labelWidgets) do
remove_widget(widget)
end
state.marker = nil
state.markerSlot = nil
state.labelWidgets = {}
state.labelSlots = {}
state.ready = false
state.lastText = nil
state.parentName = nil
state.mainMapContext = nil
state.centerX = nil
state.centerAnchorSupported = nil
end
local function forget_compass(reason)
state.createdWidgets = {}
state.marker = nil
state.markerSlot = nil
state.labelWidgets = {}
state.labelSlots = {}
state.ready = false
state.lastText = nil
state.parentName = nil
state.mainMapContext = nil
state.centerX = nil
state.centerAnchorSupported = nil
state.creating = false
log("compass references cleared: " .. tostring(reason))
end
local function create_compass()
if state.creating then
return false
end
if state.ready and is_valid(state.marker) then
local labelsReady = true
for index = 1, 3 do
labelsReady = labelsReady and is_valid(state.labelWidgets[index])
end
if labelsReady then
return true
end
end
local currentMs = now_ms()
if currentMs < state.nextCreateMs then
return false
end
state.nextCreateMs = currentMs + CONFIG.retryDelayMs
local ready, context = in_main_map()
if not ready then
log("create delayed: not MainMap; " .. tostring(context))
return false
end
local parent = find_player_canvas()
if not parent then
return false
end
state.creating = true
destroy_compass()
state.parentName = full_name(parent)
state.centerX = 0
state.centerAnchorSupported = nil
log("creating native TextBlock compass")
local marker, markerSlot = construct_text_block(parent, "v", state.centerX, CONFIG.markerY, CONFIG.markerFontSize)
state.marker = marker
state.markerSlot = markerSlot
state.labelWidgets = {}
state.labelSlots = {}
local fixedLabels = { "W", "N", "E" }
for index = 1, 3 do
local offset = (index - 2) * CONFIG.labelSpacing
local widget, slot = construct_text_block(parent, fixedLabels[index], offset, CONFIG.labelY, CONFIG.labelFontSize)
state.labelWidgets[index] = widget
state.labelSlots[index] = slot
end
state.ready = is_valid(state.marker)
for index = 1, 3 do
state.ready = state.ready and is_valid(state.labelWidgets[index])
end
if state.ready then
set_compass_visibility(true)
end
state.creating = false
log("compass ready=" .. tostring(state.ready))
return state.ready
end
local function update_compass()
local currentMs = now_ms()
if currentMs < state.suspendedUntilMs then
return
end
local mainMapReady, mainMapContext = in_main_map()
if not mainMapReady then
if state.ready or state.mainMapContext ~= mainMapContext then
forget_compass("not MainMap; " .. tostring(mainMapContext))
state.mainMapContext = mainMapContext
end
state.nextCreateMs = currentMs + CONFIG.retryDelayMs
if currentMs - state.lastLogMs > 1000 then
state.lastLogMs = currentMs
log("state suspended: not MainMap; " .. tostring(mainMapContext))
end
return
end
state.mainMapContext = mainMapContext
local yaw, source = read_yaw()
if yaw then
state.lastYaw = yaw
state.lastYawSource = source
else
yaw = state.lastYaw
source = state.lastYawSource .. ":cached"
end
if currentMs - state.lastLogMs > 1000 then
state.lastLogMs = currentMs
log("state yaw=" .. tostring(yaw) .. "; source=" .. tostring(source) .. "; controller=" .. full_name(get_controller()))
end
if not create_compass() then
return
end
if not yaw then
return
end
local normalized = (yaw + CONFIG.yawOffsetDegrees) % 360
if normalized < 0 then
normalized = normalized + 360
end
local centerIndex, cardinals = cardinal_center(normalized)
local center = cardinals[centerIndex]
local left = cardinals[((centerIndex - 2) % 4) + 1]
local right = cardinals[(centerIndex % 4) + 1]
local currentLabels = { left.label, center.label, right.label }
local labelsKey = table.concat(currentLabels, "|")
if labelsKey ~= state.lastText then
state.lastText = labelsKey
for index = 1, 3 do
set_text(state.labelWidgets[index], currentLabels[index])
end
end
local delta = yaw_delta(normalized, center.yaw)
local centerX = 0
if state.centerAnchorSupported == false then
centerX = get_compass_center_x()
end
local markerX = centerX + (delta / 90) * CONFIG.markerRange
if is_valid(state.markerSlot) then
pcall(function()
state.markerSlot:SetPosition(vec2(markerX, CONFIG.markerY))
end)
end
if currentMs - state.lastMoveLogMs > 1000 then
state.lastMoveLogMs = currentMs
log("marker moved yaw=" .. tostring(yaw) .. "; displayYaw=" .. tostring(normalized) .. "; center=" .. center.label .. "; x=" .. tostring(markerX))
end
end
local loop
loop = function(serial)
if serial ~= state.loopSerial then
return
end
local ok, err = pcall(update_compass)
if not ok then
log("update error: " .. tostring(err))
end
if ExecuteWithDelay then
ExecuteWithDelay(CONFIG.updateDelayMs, function()
loop(serial)
end)
elseif ExecuteInGameThreadWithDelay then
ExecuteInGameThreadWithDelay(CONFIG.updateDelayMs, function()
loop(serial)
end)
end
end
local function tick_update()
local ok, err = pcall(update_compass)
if not ok then
log("tick update error: " .. tostring(err))
end
end
local function start_loop(delay)
if state.loopStarted then
return
end
state.loopStarted = true
state.loopSerial = state.loopSerial + 1
local serial = state.loopSerial
if ExecuteWithDelay then
ExecuteWithDelay(delay, function()
loop(serial)
end)
elseif ExecuteInGameThreadWithDelay then
ExecuteInGameThreadWithDelay(delay, function()
loop(serial)
end)
else
loop(serial)
end
end
local function restart_loop(delay)
state.loopStarted = false
start_loop(delay)
end
reset_log()
log("loaded version=" .. VERSION)
if RegisterHook then
pcall(function()
if CONFIG.usePlayerTickHook then
RegisterHook("/Script/Engine.PlayerController:PlayerTick", function()
tick_update()
end, nil)
state.tickHooked = true
log("PlayerTick hook registered")
else
log("PlayerTick hook disabled; using delayed loop")
end
end)
pcall(function()
if CONFIG.useClientRestartHook then
RegisterHook("/Script/Engine.PlayerController:ClientRestart", nil, function()
log("ClientRestart hook")
forget_compass("ClientRestart")
local currentMs = now_ms()
state.suspendedUntilMs = currentMs + CONFIG.postLoadDelayMs
state.nextCreateMs = state.suspendedUntilMs
if not state.tickHooked then
restart_loop(1000)
end
end)
else
log("ClientRestart hook disabled")
end
end)
end
if RegisterLoadMapPostHook then
pcall(function()
RegisterLoadMapPostHook(function()
log("LoadMapPostHook")
local currentMs = now_ms()
state.suspendedUntilMs = currentMs + CONFIG.postLoadDelayMs
state.nextCreateMs = state.suspendedUntilMs
end)
end)
end
if RegisterLoadMapPreHook then
pcall(function()
RegisterLoadMapPreHook(function()
log("LoadMapPreHook")
forget_compass("LoadMapPreHook")
local currentMs = now_ms()
state.suspendedUntilMs = currentMs + CONFIG.postLoadDelayMs
state.nextCreateMs = state.suspendedUntilMs
end)
end)
end
start_loop(CONFIG.startupDelayMs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment