So there is this code that I downloaded from nexus mods:
local IDA, IDB
local LightComponent
function HookNewLight(ContextParam)
local Context = ContextParam:get()
LightComponent = Context:GetPropertyValue("PointLight")
LightComponent:SetHiddenInGame(true, true)
end
RegisterHook("/Script/Engine.PlayerController:ClientRestart", function(Context, NewPawn)
if IDA == nil then
IDA, IDB = RegisterHook("/Game/Core/Characters/Player/AnathemaPlayerCharacter_BP.AnathemaPlayerCharacter_BP_C:Re ceiveBeginPlay", HookNewLight)
end
end)
function ToggleVisibility()
if(LightComponent and LightComponent:IsValid()) then
local NewState = LightComponent:IsVisible()
LightComponent:SetHiddenInGame(NewState, true)
end
end
RegisterKeyBind(Key.F3, ToggleVisibility)
It's in lua, getting loaded into an unreal engine 5 game using UE4SS, I was trying to make the ToggleVisibility() function repeat for the script to work properly, using timermanager:
function CheckVisibility()
if (LightComponent and LightComponent:IsValid() and LightComponent:IsVisible()) then
ToggleVisibility()
end
-- Schedule the function to be called again after 0.1 seconds
TimerManager:SetTimer(function() CheckVisibility() end, 0.1, false)
end
hooking into the actor ticks:
RegisterHook("/Script/Engine.Actor:Tick", CheckVisibility)
,etc but none of them seems to work, usually it gives "attempt to index a nil value" error. I wonder if anyone knows how to make it repeat and could help.
I have no experience with Unreal Engine, but I see a couple things.
"attempt to index a nil value"
should be interpreted as, in simplified form, you tried to do this: nil[1]
or nil:foo()
. The wording tends to trip some people up. In this case, it makes the most sense that TimerManager
does not actually exist in your script because I see no declaration or require, and from the docs on UE4SS, it does not appear under the global-functions section of the API; but it's hard to tell without more details.LoopAsync
global function for setting up asynchronous loops. This should resolve your issue by foregoing the TimerManager completely, but if you still want to use that class specifically, you can look through to see if there's any global function that will create an Unreal class. From my read-through, it seems like you can only access ones already existing in memory, though.https://github.com/UE4SS-RE/RE-UE4SS/tree/main/docs/lua-api/global-functions
local IDA, IDB
local LightComponent
function HookNewLight(ContextParam)
local Context = ContextParam:get()
LightComponent = Context:GetPropertyValue("PointLight")
LightComponent:SetHiddenInGame(true, true)
end
RegisterHook("/Script/Engine.PlayerController:ClientRestart", function(Context, NewPawn)
if IDA == nil then
IDA, IDB = RegisterHook("/Game/Core/Characters/Player/AnathemaPlayerCharacter_BP.AnathemaPlayerCharacter_BP_C:Re ceiveBeginPlay", HookNewLight)
end
end)
function ToggleVisibility()
if(LightComponent and LightComponent:IsValid()) then
local NewState = LightComponent:IsVisible()
LightComponent:SetHiddenInGame(NewState, true)
end
end
RegisterKeyBind(Key.F3, function()
-- call every 100 milliseconds / 0.1 seconds
LoopAsync(100, function()
ToggleVisibility()
-- if you need to disable it, you can set up a flag or condition for
-- this function to return true; otherwise it will loop forever
return false
end)
end)