-
Notifications
You must be signed in to change notification settings - Fork 0
Hooks.md
Hooks let a mod run code before, after, deferred after, or instead of selected vanilla script methods.
Use hooks when you want to add behavior without replacing an entire vanilla script. They are usually more compatible than full resource replacement or script overrides.
OrcKit generates a temporary hook pack. For selected vanilla methods, it renames the original method internally and inserts a wrapper method with the original name.
The wrapper can:
- Dispatch
-precallbacks. - Run a replace hook or the vanilla method.
- Dispatch
-postcallbacks. - Dispatch
-callbackcallbacks deferred.
Only non-static functions are hookable.
Declare target scripts and methods in mod.txt:
[hooks]
res://scripts/player.gd="_ready,_process"This tells OrcKit which vanilla scripts need wrappers.
Wrap all methods:
[hooks]
res://scripts/player.gd="*"Prefer specific method names. * is convenient while investigating, but it creates a larger hook pack and can affect compatibility.
extends Node
func _ready() -> void:
var modlib = Engine.get_meta("OrcmodLib")
if modlib._is_ready:
_register_hooks(modlib)
else:
modlib.frameworks_ready.connect(func(): _register_hooks(modlib))
func _register_hooks(modlib) -> void:
modlib.hook("player-_ready-pre", Callable(self, "_before_player_ready"), 100)
func _before_player_ready() -> void:
print("Player is about to run _ready")<script-stem>-<method-name>-<phase>
Example vanilla path:
res://scripts/player.gd
Script stem:
player
Method:
_ready
Hook names:
player-_ready-pre
player-_ready-post
player-_ready-callback
player-_ready
Hook names are lowercase for the script stem and method name.
Runs before vanilla behavior.
modlib.hook("player-_process-pre", Callable(self, "_before_process"))
func _before_process(delta: float) -> void:
passRuns after vanilla behavior.
modlib.hook("player-_process-post", Callable(self, "_after_process"))
func _after_process(delta: float) -> void:
passFor methods with return values, a post hook can accept the current result as its last argument. If it returns a non-null value, that value becomes the new result.
func _after_get_damage(amount: int, current_result: int) -> int:
return current_result + 5Runs deferred after the wrapper.
modlib.hook("player-_ready-callback", Callable(self, "_after_ready_deferred"))Use callback hooks when you want work to happen after the current call stack.
modlib.hook("player-_process", Callable(self, "_replace_process"))
func _replace_process(delta: float) -> void:
var modlib = Engine.get_meta("OrcmodLib")
modlib.skip_super()
# Vanilla _process will not run.Only one replace hook can own a hook name. If another replace hook already exists, hook() returns -1.
Lower priority callbacks run earlier.
modlib.hook("player-_ready-pre", Callable(self, "_first"), 10)
modlib.hook("player-_ready-pre", Callable(self, "_second"), 100)Use priority only when order matters. Most mods can use the default 100.
add_hook() builds the hook name for you:
modlib.add_hook("res://scripts/player.gd", "_ready", Callable(self, "_before_ready"), true)
modlib.add_hook("res://scripts/player.gd", "_ready", Callable(self, "_after_ready"), false)The last argument means:
-
true: pre hook -
false: post hook
var result = modlib.hook_many({
"player-_ready-pre": Callable(self, "_before_ready"),
"player-_ready-post": Callable(self, "_after_ready"),
}, 100)
if not result["ok"]:
push_warning("Some hooks failed to register")var hook_id := -1
func _install(modlib) -> void:
hook_id = modlib.hook("player-_ready-pre", Callable(self, "_before_ready"))
func _exit_tree() -> void:
if hook_id != -1 and Engine.has_meta("OrcmodLib"):
Engine.get_meta("OrcmodLib").unhook(hook_id)Most mods register once and never unhook, but unhooking is useful for temporary systems.
Register after frameworks_ready.
Direct .hook() calls are scanned and OrcKit tries to infer the target script, but explicit [hooks] declarations are more reliable.
For res://scripts/player_controller.gd, the stem is:
player_controller
not:
PlayerController
Static methods are skipped by the wrapper generator.
Replace hooks are powerful but conflict-prone. Prefer -pre or -post unless you need to suppress vanilla behavior.
- Declare hook targets in
mod.txt. - Register hooks from one autoload script.
- Wait for
frameworks_ready. - Keep hook callbacks small.
- Avoid heavy work in
_processand_physics_processhooks. - Use
-postfor result mutation. - Use replace hooks sparingly.
- Document hook names in your mod release notes for compatibility authors.
OrcKit developer wiki for Sir, We Have an Orc Problem Playtest mods. These pages document OrcKit 1.0.0.