Onkillscript
onkillscript is OpenBOR's entity-removal hook. It runs when the engine begins removing an entity from active play, regardless of whether the cause was combat death, script removal, lifespan expiration, out-of-bounds cleanup, animation completion, ownership cleanup, or level shutdown.
The callback executes while self is still valid and its properties, variables, links, ownership, and other state remain available for inspection. Removal continues immediately after the script returns and cannot be cancelled.
This makes Onkill the definitive place for final cleanup, state transfer, controller notification, replacement spawning, cause-specific effects, and project systems that must react to actual removal rather than a merely lethal hit.
Syntax
onkillscript {path}
# Default
# No Onkill script
{path}- Path to an OpenBOR Script source file.- The command belongs in a model definition.
- OpenBOR loads and compiles the script with the model.
- The script's return value is ignored.
Example model definition:
name example_entity
type none
onkillscript data/scripts/example_onkill.c
Event code may also be embedded directly in the model:
onkillscript @script
void main()
{
void self = getlocalvar("self");
int trigger = getlocalvar("trigger");
}
@end_script
Event Timing
For ordinary entity removal, OpenBOR performs the relevant operations in this order:
- Confirms that the target entity exists.
- Runs the entity's
onkillscriptwith the removal trigger. - Frees active recursive effects.
- Breaks grab and link relationships.
- Clears weapon attachment, sets HP to
0, marks the entity nonexistent, and reduces the active entity count. - Clears the entity's scripts.
- Detaches parent and sub-entity relationships and applies configured summon-kill behavior.
- Clears or transfers owner, opponent, binding, platform, hit-head, and last-hit references held by other entities.
- Clears special engine registrations when the entity occupied one.
The callback is therefore the last scripted point at which the complete entity remains available. Health may still be positive, and self still reports as existing during the callback. Neither condition means removal can be prevented.
Mass entity cleanup follows a shortened path but still runs Onkill with KILL_ENTITY_TRIGGER_ALL before clearing links, scripts, and the active entity collection.
Practical Uses
| Pattern | Use of onkillscript
|
|---|---|
| Final resource cleanup | Release project-managed handles, unregister controllers, stop entity-specific processes, and clear global or indexed references that point to self.
|
| Replacement or inheritance | Spawn a successor entity, transfer stored variables or resources, pass ownership, or notify a surviving controller before the original entity becomes invalid. |
| Cause-specific removal effects | Use trigger to distinguish combat removal, lifespan cleanup, unsummoning, out-of-bounds removal, scripted removal, or shutdown and choose suitable effects.
|
| Summon and owner bookkeeping | Update creator-defined summon counts, release reserved slots, transfer shared state, or repair project-level ownership registries. |
| Encounter state | Notify waves, objectives, spawn managers, boss controllers, or scripted encounters that an entity is no longer active. |
| Persistent statistics | Record actual removals separately from lethal hits, revivals, phase transitions, and entities that entered Ondeath but survived. |
| Script-defined removal channels | Pass one of ten user trigger constants through killentity() so the removed entity can distinguish project-specific reasons without extra global state.
|
Local Variables
| Local variable | Type | Value |
|---|---|---|
self
|
Entity pointer | Entity being removed. The pointer is valid during the callback and becomes unsafe to retain after the callback returns. |
trigger
|
Integer | KILL_ENTITY_TRIGGER_* constant identifying the engine path or script-defined reason that initiated removal.
|
Onkill does not provide an attacker, attack, damage, attack type, tag, or hit-confirmation local. Removal may have no combat source. Projects that need earlier combat context should save it during Ondeathscript, Takedamagescript, or another combat event before removal begins.
Compare trigger with named constants from openborconstant(). Raw numeric values expose implementation order and should not be used as persistent project identifiers.
Trigger Constants
General and Scripted Removal
| Constant | Meaning |
|---|---|
KILL_ENTITY_TRIGGER_NONE
|
No classified removal reason. |
KILL_ENTITY_TRIGGER_ALL
|
Mass entity cleanup, such as clearing the active entity collection. |
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_UNDEFINED
|
killentity() was called without an explicit trigger.
|
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_0
|
Ten project-defined trigger channels supplied explicitly to killentity().
|
KILL_ENTITY_TRIGGER_SCRIPT_DAMAGEENTITY
|
damageentity() directly removed a target that had no take-damage handler.
|
Damage and Death Removal
| Constant | Meaning |
|---|---|
KILL_ENTITY_TRIGGER_DAMAGE_ON_LANDING
|
Landing-death handling removed an entity without a usable take-damage path. |
KILL_ENTITY_TRIGGER_DROP_NO_HEALTH
|
Drop handling removed an entity with no remaining health. |
KILL_ENTITY_TRIGGER_RECURSIVE_EFFECT
|
Lethal recursive damage removed an entity without a take-damage handler. |
KILL_ENTITY_TRIGGER_PIT
|
Pit handling removed an entity through the direct removal path. |
KILL_ENTITY_TRIGGER_PLAYER_DEATH
|
Player death handling completed and removed the player entity. |
KILL_ENTITY_TRIGGER_SMARTBOMB
|
Smart-bomb processing directly removed an entity. |
KILL_ENTITY_TRIGGER_TAKE_DAMAGE_BIKER_PIT
|
Biker take-damage handling removed an entity in a pit. |
KILL_ENTITY_TRIGGER_TAKE_DAMAGE_COMMON_FALL
|
Common take-damage fall handling removed an entity when no usable fall sequence was available. |
KILL_ENTITY_TRIGGER_TAKE_DAMAGE_COMMON_PIT
|
Common take-damage handling removed a dead entity below pit depth. |
KILL_ENTITY_TRIGGER_TAKE_DAMAGE_OBSTACLE_PIT
|
Obstacle take-damage handling removed an entity in a pit. |
Ownership and Lifecycle Removal
| Constant | Meaning |
|---|---|
KILL_ENTITY_TRIGGER_LIFESPAN
|
Entity lifespan expired and direct cleanup was required. |
KILL_ENTITY_TRIGGER_PARENT_KILL_SUMMON
|
Parent removal also removed its configured summoned sub-entity. |
KILL_ENTITY_TRIGGER_PARENT_KILL_ALL
|
Parent removal also removed all configured child entities. |
KILL_ENTITY_TRIGGER_UNSUMMON
|
Sub-entity unsummon processing removed the entity. |
KILL_ENTITY_TRIGGER_SPAWN_OVERRIDE
|
Spawn replacement or override processing removed an existing entity. |
KILL_ENTITY_TRIGGER_LEVEL_GAME_OVER
|
Game-over cleanup removed a player entity. |
Automatic and Boundary Removal
| Constant | Meaning |
|---|---|
KILL_ENTITY_TRIGGER_AUTOKILL_ATTACK_HIT
|
Attack-hit autokill removed the attacking entity. |
KILL_ENTITY_TRIGGER_AUTOKILL_ANIMATION_COMPLETE_DEFINED_LOOP_MAX
|
Animation autokill reached an explicitly defined loop maximum. |
KILL_ENTITY_TRIGGER_AUTOKILL_ANIMATION_COMPLETE_UNDEFINED_LOOP_MAX
|
Animation autokill reached its completion rule without a defined loop maximum. |
KILL_ENTITY_TRIGGER_BOMB_EXPLODE_ANIMATION_COMPLETE
|
Bomb explosion animation completed. |
KILL_ENTITY_TRIGGER_BOMB_EXPLODE_ANIMATION_UNAVAILABLE
|
Bomb removal occurred because its explosion animation was unavailable. |
KILL_ENTITY_TRIGGER_BIND_ANIMATION_MATCH
|
Binding cleanup removed an entity when the configured animation condition matched. |
KILL_ENTITY_TRIGGER_BIND_FRAME_MATCH
|
Binding cleanup removed an entity when the configured frame condition matched. |
KILL_ENTITY_TRIGGER_ANIMAL_RUN_OUT_OF_BOUNDS
|
Animal movement carried the entity out of bounds. |
KILL_ENTITY_TRIGGER_OUT_OF_BOUNDS
|
General extreme out-of-bounds handling removed the entity. |
KILL_ENTITY_TRIGGER_WALK_OUT_OF_BOUNDS
|
Generic walk behavior removed the entity outside its permitted range. |
KILL_ENTITY_TRIGGER_STAR_OUT_OF_BOUNDS
|
Star projectile behavior removed the projectile out of bounds. |
KILL_ENTITY_TRIGGER_OBSTACLE_FALL_NO_DEATH_ANIMATION
|
Falling obstacle cleanup removed an entity with no usable death animation. |
KILL_ENTITY_TRIGGER_OBSTACLE_FLY_OUT_OF_BOUNDS
|
Flying obstacle behavior carried the entity out of bounds. |
KILL_ENTITY_TRIGGER_STEAM_ANIMATION_COMPLETE
|
Steam effect animation completed. |
KILL_ENTITY_TRIGGER_TEXT_ANIMATION_COMPLETE
|
Text entity animation completed. |
KILL_ENTITY_TRIGGER_SUICIDE
|
The entity's assigned suicide action removed it. |
The trigger describes the removal route, not necessarily an attacker, attack type, or narrative cause. Several routes may represent similar visible outcomes while remaining distinct for diagnostics and project logic.
Script-Defined Triggers
killentity() accepts an optional removal trigger. Omitting it produces KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_UNDEFINED. Projects may instead pass one of the ten USER_* constants.
void remove_as_replacement(void target)
{
killentity(
target,
openborconstant("KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_0")
);
}
The target's Onkill script can compare trigger with the same constant and perform replacement-specific cleanup or effects. Additional user constants allow separate channels for despawning, pooling, transformation, encounter cleanup, or other project-defined meanings.
Once killentity() returns, the target has completed removal and must not be accessed again through the old pointer.
Entity State During Onkill
During the callback, self still exists. Its current HP, entity variables, model, animation, position, owner, parent, sub-entity, opponent, links, and other properties remain available unless an earlier system already changed them.
OpenBOR forces health to 0 and marks the entity nonexistent only after the callback. Consequently, health is not a reliable indicator of why Onkill ran. Lifespan, boundary, autokill, and scripted removal may begin while health is still positive.
Copy any state needed by a replacement or external system during the callback. Retaining self in a global variable, entity variable, array, or another long-lived reference after return leaves a stale entity pointer.
Calling killentity(self) inside Onkill must be avoided. The entity is still marked as existing until the callback returns, so killing it again re-enters the same removal callback recursively.
Removing another entity from Onkill is permitted, but that entity runs its own Onkill callback immediately. Projects should guard against circular removal chains.
Removal Cannot Be Cancelled
The script return value is ignored. Returning 0 does not cancel removal, and returning 1 does not confirm it.
Restoring health, changing invincibility, clearing a death flag, or modifying lasthitc also does not stop removal. The engine does not perform another eligibility check after Onkill returns.
Use Takedamagescript or Ondeathscript when a combat death should be prevented. Onkill is intentionally the point for consequences and cleanup after the decision to remove the entity is final.
Onkill and Ondeath
| Event | Meaning | Typical state |
|---|---|---|
ondeathscript
|
Damage processing entered a lethal branch before native death commitment. | Entity can restore HP and survive. Removal may occur much later or not at all. |
onkillscript
|
OpenBOR began actual entity removal. | Entity is still readable during the callback, but removal cannot be prevented. |
Native death may include falling, lying, death animation, blinking, corpse behavior, or delayed removal. Onkill does not run merely because HP reached 0; it runs when that process finally removes the entity.
Many non-damage causes invoke Onkill without invoking Ondeath. Examples include script removal, lifespan cleanup without take-damage, out-of-bounds cleanup, autokill, effect animation completion, unsummoning, and mass entity cleanup.
Global Model
onkillscript is not automatically forwarded through a model named global_model. Only the script belonging to the entity being removed runs. Shared project-wide behavior should be placed in a common script included by participating models or called from their individual Onkill scripts.
Related Events
| Event | Entity | Relative purpose |
|---|---|---|
| Takedamagescript | Damage recipient | Runs after HP processing and may prevent entry into lethal handling. |
| Ondeathscript | Damage recipient | Runs when damage enters its lethal branch and may still prevent native death commitment. |
| Onkillscript | Entity being removed | Runs at the beginning of actual entity removal and cannot cancel it. |
| Didhitscript | Conferrer | Runs after accepted hit handling, well before delayed death removal in most ordinary cases. |