Jump to content

Ondeathscript

From OpenBOR
Revision as of 17:28, 17 August 2026 by Dcurrent (talk | contribs) (Created page with "<code>ondeathscript</code> is OpenBOR's lethal-damage response hook. It runs when HP remains at or below <code>0</code> after Takedamagescript, before the engine commits the entity to its dead state, awards ordinary defeat credit, drops death items, updates boss completion, or selects the final death reaction. The event marks entry into a lethal damage branch rather than guaranteed removal. Ondeath scripts may restore HP and prevent final death, transform the entity...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

ondeathscript is OpenBOR's lethal-damage response hook. It runs when HP remains at or below 0 after Takedamagescript, before the engine commits the entity to its dead state, awards ordinary defeat credit, drops death items, updates boss completion, or selects the final death reaction.

The event marks entry into a lethal damage branch rather than guaranteed removal. Ondeath scripts may restore HP and prevent final death, transform the entity into another phase, require a particular finishing attack, substitute capture or surrender behavior, or prepare effects and encounter logic for a death that will continue.

Direct removal is a separate operation. Onkillscript runs when OpenBOR actually removes an entity, including removal paths that never pass through damage or Ondeath.

Syntax

ondeathscript {path}

# Default
# No Ondeath 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_character
type enemy

ondeathscript data/scripts/example_ondeath.c

Event code may also be embedded directly in the model:

ondeathscript @script
void main()
{
    void self        = getlocalvar("self");
    void attacker    = getlocalvar("attacker");
    int damage       = getlocalvar("damage");
    int attack_type  = getlocalvar("attacktype");
    int tag          = getlocalvar("tag");
}
@end_script

Event Timing

For ordinary lethal damage, OpenBOR performs the relevant operations in this order:

  1. Accepts the hit after Ondoattack, block, and counter processing.
  2. Applies knockdown, weapon-loss, status-effect, direction, MP-recovery, score, offense, and defense behavior.
  3. Changes the recipient's HP and applies the attack's no-kill floor when applicable.
  4. Runs the recipient's Takedamagescript.
  5. Tests the HP left by Takedamage.
  6. Continues into the lethal branch only when HP is still at or below 0.
  7. Applies HP-minimum or HP-reset invincibility corrections for qualifying normal damage.
  8. Runs the recipient's ondeathscript.
  9. Calls the native death check, which commits death only when HP is still at or below 0.
  10. Continues unlinking, fall, pain, death-sequence, and other reaction handling.
  11. Runs the conferrer's Didhitscript after recipient take-damage handling returns successfully.

Takedamage gets the first opportunity to redirect a lethal result. Ondeath runs only if Takedamage leaves HP at or below zero. Ondeath then gets the final scripted opportunity to restore HP before the native death check.

HP inside Ondeath is not guaranteed to be zero. HP-minimum and HP-reset invincibility corrections occur after the lethal-branch decision but before the callback. Ondeath still runs because the engine already entered the branch, even when those corrections have restored HP to 1 or maximum health.

Practical Combat Patterns

The event provides the lethal attack, credited attacker, and still-active recipient before native death commitment.

Pattern Use of ondeathscript
Required finishing attack Inspect attacktype or tag. Restore HP when the lethal attack does not meet the defeat condition, or allow death to continue when it does.
Boss phase transformation Consume the current phase, restore or replace health, change behavior state, and launch the next form without spawning a separate encounter controller.
Revival or extra life Consume a limited revival resource, restore HP, and trigger resurrection feedback before native death commitment.
Capture, surrender, or mercy Recognize a qualifying attacker or attack tag, prevent death, and transfer the entity into a scripted nonlethal outcome.
Attack-specific death presentation Select disintegration, freezing, shattering, burning, banishment, dialogue, camera, music, or other presentation from attack type, tag, attacker, and recipient state.
Encounter branching Record how the lethal threshold was reached, set progression state, notify controllers, or choose rewards and follow-up events.
Final retaliation or inheritance Trigger a last attack, pass state to a summon or replacement entity, release stored resources, or activate a surviving encounter component.

Required Finishing Attack

The following compact example allows only a burn attack to finish the entity. Project-specific helper play_regeneration_effect() supplies the desired feedback when another attack reaches the lethal threshold.

void main()
{
    void self = getlocalvar("self");
    int attack_type = getlocalvar("attacktype");

    if(attack_type != openborconstant("ATK_BURN"))
    {
        setentityproperty(self, "health", 1);
        play_regeneration_effect(self);
    }
}

Restoring health above 0 causes the following native death check to return without marking the entity dead. Earlier consequences of the hit may remain, including knockdown, status effects, weapon loss, direction changes, and score handling.

Local Variables

Local variable Type Value
self Entity pointer Entity whose lethal damage branch invoked Ondeath.
attacker Entity pointer Entity credited as the damage source. Projectiles remain the source entity; OpenBOR does not automatically substitute their owner. Some special or environmental paths use self as the attacker.
damage Integer Attack's attack.damage.force value supplied to the damage path. This is normally raw force, not the actual HP removed after offense and defense.
drop Integer Raw attack.reaction.fall.force - the attack's knockdown force.
attacktype Integer Internal attack-type identifier. Compare it with named ATK_* constants from openborconstant().
noblock Integer Raw attack.block.penetrate value. The local retains its legacy name.
guardcost Integer Raw attack.block.cost value.
jugglecost Integer Attack's juggle-point cost.
pauseadd Integer Raw attack.reaction.pause.time in logical clock ticks.
tag Integer Creator-defined attack.tag metadata.

The event does not provide blocked, which, attack_id, or a final-damage local. Numeric locals are copied from the current attack. Assigning new values to them does not change the attack or alter death processing.

Use entity, attack, or last-hit property interfaces when native objects must be changed. Health is the decisive entity property for allowing or preventing the immediately following native death check.

Trigger Condition

Ondeath runs when all of the following are true in the ordinary HP damage helper:

  1. Damage processing reaches the recipient's HP calculation path.
  2. Takedamage finishes with recipient HP at or below 0.

The trigger decision is made before HP-minimum and HP-reset invincibility corrections. Consequently, Ondeath may run with positive current HP when one of those corrections activated.

The attack's no-kill property normally prevents Ondeath by flooring HP at 1 before Takedamage. Takedamage may still set HP back to 0, which deliberately enters Ondeath processing.

The script's return value has no effect. Returning 0 does not prevent death, and returning 1 does not confirm it. Current HP after the callback controls the following native death check.

Changing lasthitc during Ondeath is too late to cancel the hit. Collision, effects, and HP processing have already occurred.

Event Scope

Path Ondeath event Notes
Lethal accepted attack Yes Runs after Takedamage when HP remains at or below 0.
Nonlethal accepted attack No Takedamage may run, but Ondeath does not.
No-kill attack Normally no The no-kill floor sets HP to 1 before Takedamage.
Lethal native block chip When routed through HP damage processing Ordinary nonlethal chip is applied directly and does not invoke Takedamage or Ondeath.
Lethal landing damage Yes Runs when landing damage reaches the HP helper and leaves HP at or below 0 after Takedamage.
Recursive HP effect On a lethal finishing tick Quiet ticks do not enter Ondeath. Lethal ticks routed through normal take-damage may invoke it.
Special engine damage When routed through HP damage processing Applicable types include pit, lifespan, time-over, lose, boss-death, and sub-entity cleanup damage. Specialized entity handlers may bypass the ordinary helper.
damageentity() When routed through target take-damage Targets without a take-damage handler are removed directly instead.
Direct health assignment or killentity() No Neither operation automatically synthesizes a lethal damage event.

Ondeath is therefore a damage-pipeline event rather than a universal death or removal observer.

Preventing Final Death

Setting self health above 0 before Ondeath returns prevents the immediately following checkdeath() call from marking the entity dead. This supports conditional immortality, multiple life bars, scripted revival, transformation, and nonlethal defeat.

Native hit consequences applied before Ondeath are not automatically reversed. Depending on the attack, a surviving entity may still fall, retain a status effect, lose a weapon, or continue another selected reaction. Projects may use that behavior or explicitly replace it.

State used to prevent death should normally be guarded against repeated activation. Entities that survive can enter Ondeath again on later lethal damage.

Ondeath and Onkill

Ondeath and Onkill represent different stages.

Event Meaning Can prevent the outcome
ondeathscript Damage processing entered its lethal branch before native death commitment. Yes. Restore HP above 0.
onkillscript OpenBOR is removing the entity from the active entity list. No. The removal operation has already begun.

Native death may include a fall, lie state, death animation, corpse, blink, or delayed removal. Ondeath occurs near the beginning of that process. Onkill occurs at actual removal and also covers non-damage causes such as lifespan cleanup, out-of-bounds removal, animation completion, script removal, or level shutdown.

Use Ondeath for lethal-hit decisions and death prevention. Use Onkill for final cleanup that must accompany actual entity removal.

Attacker Identity

For an ordinary hit, attacker is the entity whose attack entered damage processing. Projectiles therefore appear as themselves rather than their owner. Scripts that award credit to a controlling character may follow owner or parent relationships.

Environmental and cleanup damage may supply the recipient itself as attacker. Attack type is the reliable way to distinguish sources such as ATK_PIT, ATK_LIFESPAN, ATK_TIMEOVER, ATK_LOSE, or related internal attacks.

Global Model

ondeathscript is not automatically forwarded through a model named global_model. Only the script belonging to the recipient entity runs. Shared project-wide behavior should be placed in a common script included by participating models or called from their individual Ondeath scripts.

Event Entity Relative purpose
Ondoattackscript Recipient first, then conferrer Runs before native hit resolution and may cancel the candidate through lasthitc.
Takedamagescript Recipient Runs after HP processing and can prevent entry into Ondeath by restoring HP above 0.
Ondeathscript Recipient Runs after Takedamage when the damage pipeline enters its lethal branch, before native death commitment.
Didhitscript Conferrer Runs after accepted recipient take-damage handling, including any Ondeath processing.
Onkillscript Entity being removed Runs when OpenBOR removes the entity, regardless of whether damage or Ondeath caused the removal.

See Also