Hooks

Hooks are used to trigger function calls on specific events, either custom defined events or whenever a specific function is called in the game. When adding code on top of existing game logic using hooks is heavily encouraged over function overrides as the latter are way more destructive, especially when multiple mods touch the same function.

Function Hooks

These hooks trigger on specific function calls and can either execute before the target function is called or afterwards. When you add a hook to a function, SuperBLT will intercept the target function call and run your function before or immediately after it and then return to the normal program flow.

The following is an approximation on how post and pre hooks behave when hooking a specific function:

Hooks:PostHook(PlayerManager, "spawn_players", "spawn_players_my_mod_post", function()
  log("post hook")
end)

Hooks:PreHook(PlayerManager, "spawn_players", "spawn_players_my_mod_pre", function()
  log("pre hook")
end)

function PlayerManager:spawn_players(position, rotation, state)
  -- spawn_players_my_mod_pre will be executed here

  for var = 1, self._nr_players do
     self._last_id = var
  end

  self:spawned_player(self._last_id, safe_spawn_unit(self:player_unit_name(), position, rotation))

  -- spawn_players_my_mod_post will be executed here

  return self._players[1]
end

Post hooks

Adding a post hook

Hooks:PostHook(object, func, id, post_call)

Hooks a function to be called after the specified function on a specified object.
If post_call returns anything, it will override the return value(s) of the original function and other hooks coming before this one.
object Object for the hooked function to be called on.
func Name of the function on object to run post_call after.
id Unique name for this post hook.
post_call Function to be called after func on object.

Example:

Hooks:Post(PlayerManager, "init", "TestPostPlayerManagerInit", function(ply)
  log("PlayerManager Post-initialized")
end)

Removing a post hook

Hooks:RemovePostHook(id)

Removes a posthook and prevents it from being run.
id Name of the posthook to remove.

Example:

Hooks:RemovePostHook("TestPostPlayerManagerInit")

Pre hooks

Adding a pre hook

Hooks:PreHook(object, func, id, pre_call)

Hooks a function to be called before the specified function on a specified object.
If pre_call returns anything, it will be used as the final return value if neither the original function nor any hooks coming after this one return anything.
object Object for the hooked function to be called on.
func Name of the function on object to run pre_call before.
id Unique name for this pre hook.
pre_call Function to be called before func on object.

Example:

Hooks:PreCall(PlayerManager, "init", "TestPrePlayerManagerInit", function(ply)
    log("PlayerManager Pre-initialized")
end)

Removing a pre hook

Hooks:RemovePreHook(id)

Removes the pre-hook with identifier that matches id.
id The unique identifier for the pre-hook to be removed.

Example:

Hooks:RemovePreHook("TestPrePlayerManagerInit")

Overriding a function

Hooks:OverrideFunction(object, func, override)

Overrides a function completely while keeping existing hooks to it intact.
object Object of the function to override.
func Name of the function on object override.
override Function to replace the original function func with.

When pre/post hooks can't be used and a function has to be redefined completely, using OverrideFunction will make sure any hooks that might have been added to it previously will stay intact.

Example:

Hooks:OverrideFunction(LootManager, "show_small_loot_taken_hint", function()
  -- Disable loot hint
end)

Retrieving a function

Hooks:GetFunction(object, func)

Returns the current original function of an object, that is either the raw function if it hasn't been hooked or the original function without any hooks attached to it.
object Object of the function to get.
func Name of the function on object to get.
returns Original function func of object.

Can be useful to call functions without invoking hooks or in combination with OverrideFunction.

Getting return value(s)

Hooks:GetReturn()

Returns the return value(s) of the currently hooked function which are any values returned by hook functions that were executed before the active hook function.
returns Any amount of return values of the current hook.

This allows access to the function return value inside a hook without having to do a function override.

Example:

Hooks:PostHook(CopDamage, "accuracy_multiplier", "accuracy_multiplier_mymod", function(self)
  local multiplier = Hooks:GetReturn()
  if self._unit:movement():get_walk_to_pos() then
    return multiplier
  else
    return multiplier * 1.25
  end
end)

Custom Hooks

These are manually defined hooks that don't need to be called from a specific single function. They can be used to provide convenient events that can be triggered from multiple locations.

Registering a hook

Hooks:RegisterHook(hook_id)

Registers a hook so that functions can be added to it, and later called.
Can also be called as Hooks:RegisterHook(hook_id).
hook_id Unique hook name.

Example:

Hooks:RegisterHook("OnMyExampleModLoaded")

Unregistering a hook

Hooks:UnregisterHook(key)

Removes a hook, so that it will not call any functions.
Can also be called as Hooks:Unregister(key).
key Name of the hook to remove.

Example:

Hooks:UnregisterHook("OnMyExampleModLoaded")

Adding to a hook

Hooks:AddHook(key, id, func)

Adds a function call to a hook, so that it will be called when the hook is called.
Can also be called as Hooks:Add(hook_id, id, func).
key Name of the hook to be called on.
id Unique name for this specific function call.
func The function to call with the hook.

Example:

Hooks:AddHook("OnMyExampleModLoaded", "OnMyExampleModLoaded_ExampleMod2", function()
  log("OnMyExampleModLoaded was called!")
end)

Note that a hook doesn't actually have to be registered to be able to use Hooks:AddHook. Registering a hook is only relevant if you want to provide custom hooks yourself.

Removing from a hook

Hooks:Remove(id)

Removes a hooked function call with the specified id to prevent it from being called.
id Name of the function call to remove.

Example:

Hooks:Remove("OnMyExampleModLoaded_ExampleMod2")

Calling hooks

When you register a custom hook, you probably want to trigger it at some point, allowing any functions added to it to also execute.

Call

Hooks:Call(key, ...)

Calls a specified hook, executing all of its hooked functions. Any arguments can be passed into the call.
key Name of the hook to call.
... Arguments to pass to the hooked functions.

Example:

Hooks:Call("OnMyExampleModLoaded", "TestData", 1234, { 5, 6, 7, 8 })

Return Call

Hooks:ReturnCall(key, ...)

Calls a specified hook, executing all of its hooked functions, until a function returns a non nil value.
Any arguments can be passed into the call.
key Name of the hook to call.
... Arguments to pass to the hooked functions.

Example:

local r = Hooks:ReturnCall("OnMyExampleModLoaded", "TestData", 1234, { 5, 6, 7, 8 })
log(r)