Takedamagescript
takedamagescript is OpenBOR's recipient-side post-damage combat hook. It runs after the engine calculates offense and defense and changes the recipient's HP, but before final death processing and most pain, fall, or death reaction selection.
This placement gives creators access to the resolved recipient state while the outcome can still be redirected. Scripts may prevent an otherwise lethal result, trigger boss phases, cap damage, convert lost health into another resource, distribute damage, activate reactive abilities, or select custom responses based on the attacker and attack metadata.
Takedamage is not a pre-hit veto. Use Ondoattackscript when native hit handling must be cancelled before HP, effects, knockdown, or other damage processing begins.
Syntax
takedamagescript {path}
# Default
# No Takedamage 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
takedamagescript data/scripts/example_takedamage.c
Event code may also be embedded directly in the model:
takedamagescript @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 an ordinary accepted, unblocked hit, OpenBOR performs the relevant operations in this order:
- Confirms collision and preliminary eligibility.
- Runs the recipient's Ondoattackscript, followed by the conferrer's Ondoattack script.
- Continues only when the shared last-hit confirmation remains enabled.
- Rejects native blocks and counters.
- Applies or selects knockdown, weapon-loss, status-effect, direction, MP-recovery, and score behavior.
- Calculates damage from attack force, offense, defense, blocking state, and applicable HP-nullification rules.
- Changes the recipient's HP and applies the attack's no-kill floor when applicable.
- Runs the recipient's
takedamagescript. - Enters zero-HP processing when HP remains at or below zero, applies remaining invincibility corrections, and runs Ondeathscript.
- Finalizes death, unlinking, pain, fall, movement, and other reaction behavior.
- Runs the conferrer's Didhitscript after the recipient's take-damage handling returns successfully.
The script therefore sees current HP after calculated damage. Lethal results have not yet been finalized, which allows the script to restore HP and prevent the pending death path. Setting HP to 0 may likewise send an otherwise nonlethal event into death processing.
Several recipient effects have already been selected or applied by this point. Takedamage should not be treated as a clean cancellation hook for knockdown, weapon loss, elemental effects, score, or similar earlier operations. Ondoattack is the appropriate event when none of the native hit consequences should occur.
Practical Combat Patterns
The event's strength comes from combining the resolved recipient state with an attack and attacker that are still in active processing.
| Pattern | Use of takedamagescript
|
|---|---|
| Last stand or extra life | Detect HP at or below zero, consume a one-use state or resource, restore HP, and trigger a survival effect before death finalizes. |
| Boss phase transition | Detect a health threshold after the hit, lock the phase change so it occurs once, restore or set phase HP when needed, and launch the next behavior package. |
| Damage cap or guts system | Compare current HP with a pre-hit value recorded by Ondoattack, restore damage beyond the permitted amount, and provide armor or resistance feedback. |
| Resource conversion | Convert part of the resolved loss into MP, guard points, a super meter, armor charge, rage, or another creator-defined resource. |
| Reactive abilities | Use attacktype, tag, the attacker, and recipient state to activate enrage, retaliation, adaptation, elemental charge, or conditional buffs.
|
| Damage sharing or redirection | Restore a chosen portion of the recipient's HP and apply the transferred amount to armor entities, summons, linked allies, or a shared encounter pool. |
| Combat feedback and telemetry | Record who caused the event, categorize it by type or tag, update recipient-owned statistics, and drive custom UI, sound, flash, dialogue, or accessibility feedback. |
Last Stand
The following compact example prevents one lethal result. Project-specific helper play_last_stand_effect() may supply animation, sound, flash, meter, or temporary invincibility behavior.
void main()
{
void self = getlocalvar("self");
int health = getentityproperty(self, "health");
int used = getentityvar(self, "last_stand_used");
if(health <= 0 && used != 1)
{
setentityvar(self, "last_stand_used", 1);
setentityproperty(self, "health", 1);
play_last_stand_effect(self);
}
}
Raising health above 0 prevents the immediately pending death checks for this damage event. The example remains intentionally small; the survival resource, animation, invincibility, and reset rules belong to the project using it.
Local Variables
| Local variable | Type | Value |
|---|---|---|
self
|
Entity pointer | Entity whose Takedamage script is running and whose HP was processed. |
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 final HP change 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, or attack_id locals. Successful native blocks normally follow a different path, and Takedamage always runs on the recipient.
Numeric locals are copied from the current attack. Assigning new values to these local variables does not change the attack or undo completed damage. Use entity, attack, or last-hit property interfaces when native objects must be changed.
Raw Force and Actual HP Change
The damage local normally contains raw attack force. Offense, defense, invincibility, healing caps, and no-kill behavior may cause the actual HP change to differ substantially. Zero or negative resolved damage can still reach the event.
Scripts that need the exact amount removed should record the recipient's HP during Ondoattack, then compare that value with current HP during Takedamage. This also captures results from dynamic offense, defense, body-specific defense, and other calculations without duplicating engine math.
Recursive HP effects are a special case. Quiet recursive ticks calculate and subtract mitigated force directly, then supply that calculated force as damage. Finishing recursive ticks that enter normal take-damage handling supply their ordinary attack force and allow the regular calculation path to run.
Event Scope
| Damage path | Takedamage event | Notes |
|---|---|---|
| Accepted unblocked attack | Yes | Runs after HP processing and before final death and reaction handling. |
| Successful native block | Usually no | Ordinary nonlethal chip damage is applied directly. Chip damage routed through take-damage to permit a KO invokes the event. |
| Damage on landing | Yes | Runs after landing HP loss and before landing death finalization. |
| Recursive HP damage | Yes | Runs for quiet HP ticks and for finishing ticks routed through normal take-damage. MP-only ticks do not invoke it. |
| Smart bomb and engine damage routes | Yes, when routed through HP damage processing | Includes applicable special attack types such as pit, lifespan, time-over, lose, boss-death, and sub-entity cleanup damage. Specialized entity handlers may use their own behavior. |
| Item collection | No | Collection is handled through the item event path rather than recipient damage. |
| Direct script HP assignment | No | Changing an entity's health property does not automatically synthesize a Takedamage event. |
The event is tied to OpenBOR paths that reach the engine's HP damage helper or explicitly execute the script for recursive HP loss. Specialized entity handlers may bypass that helper, and direct property changes do not synthesize the event. Takedamage is therefore a combat hook rather than a universal observer for every possible health change.
Death Interception
Takedamage runs before Ondeathscript in the normal damage path. Current HP determines what happens next:
- HP above
0- Normal death processing does not begin. - HP at or below
0- OpenBOR enters the zero-HP branch, applies remaining invincibility corrections, and runs Ondeath. Final death still depends on the health and state left after those operations.
This ordering supports extra lives, survival tokens, phase transformations, scripted immortality, or delayed defeat. It also allows a script to make a normally nonlethal event lethal by setting HP to 0.
The script's return value has no effect. Returning 0 does not cancel damage or death, and returning 1 does not confirm either result.
Changing lasthitc during Takedamage is too late to cancel the event. The engine has already passed the Ondoattack confirmation point and changed HP.
Attacker Identity
For an ordinary hit, attacker is the entity whose attack entered take-damage processing. Projectiles therefore appear as themselves rather than their owner. Scripts that award credit to the controlling character may follow the projectile's owner or parent relationship.
Environmental and cleanup paths may supply the recipient itself as attacker because no separate combat entity exists. Attack type is the reliable way to distinguish sources such as ATK_PIT, ATK_LIFESPAN, ATK_TIMEOVER, ATK_LOSE, or related internal damage.
Global Model
takedamagescript 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 Takedamage scripts.
Related Events
| Event | Entity | Relative purpose |
|---|---|---|
| Ondoattackscript | Recipient first, then conferrer | Runs before block, counter, HP, effects, and reaction resolution. May cancel native hit handling through lasthitc.
|
| Takedamagescript | Recipient | Runs after HP processing but before final death and most reaction handling. |
| Ondeathscript | Recipient | Runs when HP remains at or below zero after Takedamage and remaining invincibility rules. |
| Didhitscript | Conferrer | Runs after OpenBOR accepts the hit and the recipient's take-damage handling returns. |
| Didblockscript | Defender | Runs after a successful native block and applicable guard-cost handling. |