This is an informational post on how to create a system for creating your own keybinds to run arbitrary LUA.
It is dynamic in that you are able to edit the files and reload them while the game is running.
I also disable Strict.
Strict is used for mainly debugging and it enforces that any global variable must be declared before use, or it will throw a violation error.
I don't like Strict, and so I kill it.
Everything from here on is what I did for my stuff, so change what you will to fit your needs.
Like the names of functions that you'll be calling.
I am vain, and so pretty much all of my stuff has the cz_ prefix.
I'd suggest changing it for the cz_reload() concommand to something you can easily remember.
File structure layout:
Klei/DoNotStarveTogether/customcommands.lua
Klei/DST_Scripts/customcommands.lua
Klei/DST_Scripts/custom_keybinds.lua
I reused customcommands.lua in the DST_Scripts folder for portability in that it could be used in the main folder, but for how it's setup here this is how it should be setup without needing to edit anything.
The two keybinds in there are examples on things to do, and to check for.
It binds 'R' to do the yawn emote should you have the sleep set, and it binds 'Z' to drop your current cursor-held item at your player's feet.
File contents:
File Klei/DoNotStarveTogether/customcommands.lua:
cz_customcommands_path = "../../DST_Scripts/" print("Reloading customcommands.lua") TheSim:GetPersistentString(cz_customcommands_path.."customcommands.lua", function(success, output) if(success==true) then xpcall(loadstring(output), debug.traceback) print("Reloaded customcommands.lua") end end )
Klei/DST_Scripts/customcommands.lua:
local OldStrict = getmetatable(_G) local NoStrict = {} setmetatable(_G, NoStrict) cz_customcommands_path = cz_customcommands_path or "./DST_Scripts/" function cz_reload_custom(filename) print("Reloading "..filename..".lua") TheSim:GetPersistentString(cz_customcommands_path..filename..".lua", function(success, output) if(success==true) then local filefn = loadstring(output) if(filefn) then local success = xpcall( filefn, function(errormsg) print("LUA Error:", errormsg) end ) if(success) then print("Reloaded "..filename..".lua") end end end end ) end function cz_reload() cz_reload_custom("customcommands") end -- Put your custom functions here, or create another file. -- Keybinds then will have access to anything here. cz_reload_custom("custom_keybinds")
File Klei/DST_Scripts/custom_keybinds.lua:
function cz_hotkey_checker() local curScreen = TheFrontEnd:GetActiveScreen() if(curScreen and curScreen.name=="HUD") then return false end return true end if(cz_hotkey_r) then TheInput.onkeyup:RemoveHandler(cz_hotkey_r) cz_hotkey_r = nil end cz_hotkey_r = TheInput:AddKeyUpHandler( KEY_R, function() if cz_hotkey_checker() then return end if TheNet:GetIsServer() and not TheNet:IsDedicated() then return end TheNet:SendSlashCmdToServer("yawn", true) end ) if(cz_hotkey_z) then TheInput.onkeyup:RemoveHandler(cz_hotkey_z) cz_hotkey_z = nil end cz_hotkey_z = TheInput:AddKeyUpHandler( KEY_Z, function() if cz_hotkey_checker() then return end if(ThePlayer and ThePlayer.replica and ThePlayer.replica.inventory) then local item = ThePlayer.replica.inventory:GetActiveItem() if(item~=nil) then local x,y,z = ThePlayer.Transform:GetWorldPosition() SendRPCToServer(RPC.LeftClick, ACTIONS.DROP.code, x, z, nil, nil, nil, nil, nil) end end end )
Note that the functions you have access to are from the core system's functionality and so you don't need to prefix 'GLOBAL.' to anything here.
Likewise you do not have direct access to the Mod API, and so creating a prefab postinit dynamically like this will take a higher level of knowledge of how a prefab hook is done etc.
Here's a freebie.
How to setup a repeating timer:
Editing Klei/DST_Scripts/customcommands.lua:
function cz_reload() cz_reload_custom("customcommands") end cz_reload_custom("custom_runloops") cz_reload_custom("custom_keybinds")
File Klei/DST_Scripts/custom_runloops.lua:
if(cz__ongameframe~=nil) then cz__ongameframe:Cancel() cz__ongameframe = nil end cz__ongameframe = scheduler:ExecutePeriodic( 0.0, function() if ThePlayer then -- Do something end end ) if(cz__on10fps~=nil) then cz__on10fps:Cancel() cz__on10fps = nil end cz__on10fps = scheduler:ExecutePeriodic( 0.1, function() if ThePlayer then -- Do something end end )
I used double underscores to denote hot variables- variables that are very caustic should they be touched without care.