Global Update Hook Examples¶
Pack-level hooks run around every active entity update. They are powerful because they can change universal combat rules, but they are also expensive and easy to over-apply. Keep them small, guard by context, and return quickly for entities that do not need the rule.
Configure Global Hooks¶
Add hooks to config.json with the same script shape used by animation scripts:
{
"preEntityUpdateScripts": [
{
"packName": "My Pack",
"scriptName": "Global entities pre-update"
}
],
"postEntityUpdateScripts": [
{
"packName": "My Pack",
"scriptName": "Global entities post-update"
}
]
}
Pre-entity hooks run before the entity controller. Returning false from a pre hook cancels that entity update for the frame. Post-entity hooks run after the entity controller and are best for cleanup or reactions to what just happened.
Pre-Update: Thrown Bodies Break Containers¶
Use a pre hook when you need to adjust vulnerability before normal collision and physics run.
return function()
local character = game.this_character
if character == nil then
return true
end
-- Object mode 10 and 6 are the example knocked/thrown modes.
-- Use the modes that mean airborne damage state in your data.
if character.object_mode == 10 or character.object_mode == 6 then
-- Prevent normal hits from interrupting this thrown-body rule before the
-- post hook decides whether the body can be juggled.
character.is_vulnerable = false
if character.check_body_breaking_containers() then
-- If the body breaks a container, bounce it away. is_being_thrown
-- identifies active throw releases; those already own X velocity.
if not character.is_being_thrown then
character.velocity_x = -character.velocity_x / 3
end
character.auxiliar_velocity_x = -character.auxiliar_velocity_x / 3
character.impulse_y = -120
end
end
return true
end
Post-Update: Juggle And Multi-Hit Limiter¶
This post hook creates a global juggle rule. It lets knocked-down characters be hit in the air, applies diminishing damage, changes the hit reaction, and stops the rule after a limit.
return function()
local character = game.this_character
if character == nil then
return true
end
-- Let hit pause finish. During hit pause, the entity should not be re-tested
-- for another global juggle hit every frame.
if character.hit_pause_timer ~= 0 then
return true
end
local juggle_limit = 15
local divider_limit = 8
local increment = 1
if character.is_player then
-- Players reach the limit faster than enemies in this example.
increment = 3
end
if character.object_mode == 10 or character.object_mode == 6 then
if character.is_pressing_against_walls(true) then
character.is_facing_right = not character.is_facing_right
if not character.is_being_thrown then
character.velocity_x = -character.velocity_x / 2
end
character.auxiliar_velocity_x = (character.auxiliar_velocity_x * 3) / 4
character.impulse_y = character.impulse_y - 10
character.hit_pause_timer = 6
end
-- current_animation_id 12 is treated as non-juggleable in this example.
character.is_vulnerable =
character.current_animation_id ~= 12 and
character.custom_value_5 < juggle_limit
if not character.is_vulnerable then
character.is_knocked_down = false
return true
end
character.is_knocked_down = true
-- Later hits do less damage. Guard the first two hits so division does not
-- over-reduce the opening juggle hits.
if character.custom_value_5 > 1 then
character.damage_taken = character.damage_taken / character.custom_value_5
end
if character.check_being_hit() then
character.set_animation(10)
character.custom_value_5 = character.custom_value_5 + increment
if character.custom_value_5 < divider_limit then
character.impulse_y = character.impulse_y / character.custom_value_5
else
-- After the divider limit, force the body downward so the juggle
-- naturally ends.
character.impulse_y =
(character.custom_value_5 - divider_limit) * 20
end
end
else
-- Reset the per-character juggle counter outside knocked/thrown modes.
character.custom_value_5 = 0
end
return true
end
Post-Update: Air Recovery Escape¶
This hook lets players recover out of a knockdown on the first airborne hit-reaction frame by holding up plus jump.
return function()
local character = game.this_character
if character == nil or not character.is_player then
return true
end
local can_air_recover =
character.object_mode == 10 and
character.current_animation_id == 11 and
character.current_animation_frame == 0 and
character.is_holding_up and
character.is_holding_button_c
if can_air_recover then
-- Clear the global juggle counter and mark the character as recovered.
character.custom_value_5 = 0
character.is_knocked_down = false
-- safe_land returns the player to a valid grounded state if the engine
-- considers the character close enough to land safely.
character.safe_land()
end
return true
end
Global Hit Aura With Per-Target Cooldown¶
Use a post hook for effects that should damage targets near a special owner or spawned field. The example below assumes another script sets custom_value_7 on characters inside the aura.
return function()
local character = game.this_character
if character == nil or not character.is_enemy then
return true
end
-- custom_value_8 is this target's local cooldown. Without it, a global aura
-- would hit every frame and drain health instantly.
if character.custom_value_8 > 0 then
character.custom_value_8 = character.custom_value_8 - 1
return true
end
if character.custom_value_7 == 1 then
character.damage_taken = 2
character.is_being_hit = true
-- check_being_hit applies the normal hit reaction fields and links.
character.check_being_hit()
character.custom_value_8 = 12
end
return true
end
Hook Performance Checklist¶
- Guard with
game.this_character,game.this_player,game.this_enemy, orgame.this_itemimmediately. - Use object modes and animation IDs to avoid running logic on unrelated states.
- Prefer
custom_value_*cooldowns over scanning every entity every frame. - Avoid
requireinside hot hook bodies unless you intentionally load shared helper modules once. - Keep projectiles and effects in animation scripts when the rule only affects that one move.