Core Functions
Overviewβ
This module contains a collection of essential functions that you will probably need sooner or later in your scripts. This module includes utilities for logging, callbacks, time management, and accessing game information.
Callbacks - Brief Explanation
This is essentially the most important part of scripting, since most of your code must be ran inside a callback.What is a Callback?
A callback is a function that you write, which you then pass to the game engine or framework. The engine doesn't execute this function immediately. Instead, it "calls back" to your function at a specific time or when a particular event occurs in the game.
Think of it like leaving your phone number with a friend (the game engine) and asking them to call you (execute your function) when a certain event happens.
Why Use Callbacks?
Callbacks allow your game to respond to events without constantly checking for them. This makes your code more efficient and easier to manage. Instead of writing code that keeps asking, "Has the player pressed a button yet? Has an enemy appeared yet?" you can simply tell the game engine, "When this happens, run this function." So, all games use callbacks to run, and same with WoW.
Imagine you're waiting for a package to be delivered. You don't stand by the door all day waiting for it (which would be like constantly checking in a loop). Instead, you might continue with your day, and when the doorbell rings (the event), you go to answer it (the callback function is executed).
What was explained is what is a callback in general in the context of videogames. In our case, we have multiple events that our callbacks will be listening to. These are the following:
-
On Update β This is the callback that you will use to run your logic most of the time. The code placed inside this callback is called at a reduced speed, relative to the speed of
On Render
. It's ideal for logic that doesn't need to be executed every frame. In a game where 95% of spells have a global cooldown, 50% of spells are cast, and units move at 7 yards per second, you don't need to read all the information and check everything every frame. Doing so at 120 FPS means you're, for example, checking the position of all units 120 times per second, which is unnecessary. That's whereOn Update
comes in. -
On Render β This is a callback used only for rendering graphics, like rectangles, circles, etc. (See graphics). It is the most important and central callback, placed within the game inside DirectX in a part called
EndScene
. Every time DirectX is about to render something, this callback is called. That's why it's calledOn Render
, and it's the callback that's called the most times of allβexactly once per frame. This allows the game to draw the graphics and call your callback so that you can draw at the same speed, neither one frame more nor less, ensuring it feels natural within the game. While you could place your logic here, common sense suggests otherwise. -
On Render Menu β This is a callback used only for rendering menu elements. (See Menu Elements)
-
On Render Control Panel β This is a very specialized callback that will be used ONLY to handle the control panel elements. (See Control Panel)
-
On Spell Cast β This callback will only trigger if a spell is cast, so it might be useful to control some specific cooldowns or how your spells (or other game objects) are being cast.
-
On Legit Spell Cast β This callback will only trigger if a spell is MANUALLY cast by the player.
As you will see in the following examples, all callbacks expect you to pass a function. This function must contain all the code that will be read in the case that the event that the callback is listening to is triggered.
You can pass it anonymously:
core.register_on_render_callback(function()
-- your render code here
end)
Or you can pass a defined function:
local function all_my_render_code_function()
-- your render code here
end
core.register_on_render_callback(all_my_render_code_function)
On render callback was used just as an example, but this behaviour is the same for all available callbacks.
Callback Functions πβ
core.register_on_pre_tick_callback
β
Syntax
core.register_on_pre_tick_callback(callback: function)
Parameters
callback
:function
- The function to be called before each game tick.
Registers a callback function to be executed before each game tick.
Example Usage
core.register_on_pre_tick_callback(function()
-- Code to execute before each game tick
end)
core.register_on_update_callback
β
Syntax
core.register_on_update_callback(callback: function)
Parameters
callback
:function
- The function to be called on each frame update.
Registers a callback function to be executed on each frame update.
Example Usage
core.register_on_update_callback(function()
-- Code to execute every frame
end)
core.register_on_render_callback
β
Syntax
core.register_on_render_callback(callback: function)
Parameters
callback
:function
- The function to be called during the render phase.
Registers a callback function to be executed during the render phase.
Example Usage
local function on_render()
-- Rendering code here
end
core.register_on_render_callback(on_render)
core.register_on_render_menu_callback
β
Syntax
core.register_on_render_menu_callback(callback: function)
Parameters
callback
:function
- The function to render custom menu elements.
Registers a callback function to render custom menu elements.
Avoid calling game functions within this callback. It should be used solely for rendering menus and variables.
Example Usage
local function render_menu()
-- Menu rendering code here
end
core.register_on_render_menu_callback(render_menu)
core.register_on_render_control_panel_callback
β
Syntax
core.register_on_render_control_panel_callback(callback: function)
Parameters
callback
:function
- The function to render control panel elements.
Registers a callback function to render control panel elements.
Example Usage
local function render_control_panel()
-- Control panel rendering code here
end
core.register_on_render_control_panel_callback(render_control_panel)
core.register_on_spell_cast_callback
β
Syntax
core.register_on_spell_cast_callback(callback: function)
Parameters
callback
:function
- The function to be called when any spell is cast.
Registers a callback function that is invoked whenever any spell is cast in the game, including spells cast by the player, allies, and enemies.
Example Usage
local function on_spell_casted(data)
-- Access spell data
local spell_name = core.spell_book.get_spell_name(data.spell_id)
core.log(string.format("Spell cast detected: %s", spell_name))
end
core.register_on_spell_cast_callback(on_spell_casted)
core.register_on_legit_spell_cast_callback
β
Syntax
core.register_on_legit_spell_cast_callback(callback: function)
Parameters
callback
:function
- The function to be called when the local player casts a spell, including unsuccessful attempts.
Registers a callback function that is invoked when the local player casts a spell, including unsuccessful attempts.
Example Usage
local function on_legit_spell_cast(data)
-- Handle local player's spell cast
end
core.register_on_legit_spell_cast_callback(on_legit_spell_cast)
The "data" parameter is filled with the ID of the spell that was just casted. You can check the way this callback works by adding a core.log(tostring(data)) call inside the function called by the callback.
Logging - An Important Tool π₯β
Use Logs In Your Code!
Adding debug logs is a very powerfull tool that you should use in all your plugins. This will help you find bugs and typos very easily. One option that we recommend is that you add a debug local variable (boolean) at the top of your code. When true, the debug for your code will be enabled. For example:local debug = false
local function my_logics()
local is_check_1_ok = true
if not is_check_1_ok then
if debug then
core.log("Check 1 is not ok! .. aborting logics because of it - -")
end
return false
end
local is_check_2_ok = true
if not is_check_2_ok then
if debug then
core.log("Check 2 is not ok! .. aborting logics because of it - -")
end
return false
end
if debug then
core.log("All checks were ok! .. Running logics succesfully!")
end
return true
end
Obviously, this is a very simple example without any real logic or functionality, but it was showcased here just so you see the recommended workflow. All these prints will only work if your debug variable is true, which is something you can change in less than a second.
Logging - Functions πβ
core.log
β
Syntax
core.log(message: string)
Parameters
message
:string
- The message to log.
Logs a standard message.
Example Usage
core.log("This is a standard log message.")
Use LUA's in-built strings function to format your logs. For example, to pass from boolean or number to string, you would have to use the tostring() function. Example: Logging the cooldown of a spell:
local function print_spell_cd(spell_id)
local local_player = core.object_manager.get_local_player()
if not local_player then
return
end
local spell_cd = core.spell_book.get_spell_cooldown(spell_id)
core.log("Remaining Spell (ID: " .. tostring(spell_id) .. ") CD: " .. tostring(spell_cd) .. "s")
end
core.log_error
β
Syntax
core.log_error(message: string)
Parameters
message
:string
- The error message to log.
Logs an error message.
Example Usage
core.log_error("An error has occurred.")
core.log_warning
β
Syntax
core.log_warning(message: string)
Parameters
message
:string
- The warning message to log.
Logs a warning message.
Example Usage
core.log_warning("This is a warning message.")
core.log_file
β
Syntax
core.log_file(message: string)
Parameters
message
:string
- The message to log to a file.
Logs a message to a file.
Access to log files may be restricted due to security considerations.
Example Usage
core.log_file("Logging this message to a file.")