Jump to content

Onkillscript

From OpenBOR

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:

  1. Confirms that the target entity exists.
  2. Runs the entity's onkillscript with the removal trigger.
  3. Frees active recursive effects.
  4. Breaks grab and link relationships.
  5. Clears weapon attachment, sets HP to 0, marks the entity nonexistent, and reduces the active entity count.
  6. Clears the entity's scripts.
  7. Detaches parent and sub-entity relationships and applies configured summon-kill behavior.
  8. Clears or transfers owner, opponent, binding, platform, hit-head, and last-hit references held by other entities.
  9. 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

KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_1
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_2
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_3
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_4
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_5
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_6
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_7
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_8
KILL_ENTITY_TRIGGER_SCRIPT_KILLENTITY_USER_9

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.

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.

See Also