Ondoattackscript
ondoattackscript is a model event that runs when an entity's attack becomes a candidate to hit another entity. OpenBOR invokes the recipient's script first and the conferring entity's script second, before native block, counter, and damage resolution.
The event is an attack-interception hook rather than hit confirmation. Scripts may inspect the proposed attack, coordinate custom responses, or cancel native handling through the shared last-hit confirmation value. Use Didhitscript when logic should run only after OpenBOR accepts a hit.
Syntax
ondoattackscript {path}
# Default
# No Ondoattack 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
ondoattackscript data/scripts/example_ondoattack.cEvent code may also be embedded directly in the model:
ondoattackscript @script
void main()
{
void self = getlocalvar("self");
void other = getlocalvar("other");
int which = getlocalvar("which");
int attack_type = getlocalvar("attacktype");
}
@end_scriptEvent Scope
OpenBOR invokes ondoattackscript for candidate impacts that reach the attack-resolution stage. Relevant native paths include ordinary attack-box collisions, active item attack-box collisions, and configured damage on landing.
Preliminary rules are evaluated before the event. These include collision, target life state, invincibility, faction permission, next-hit timing, attack-ID duplication, ground-hit permission, juggle availability, and the presence of a take-damage handler. Rejected candidates do not invoke the event.
Passing the preliminary rules does not guarantee a hit. Native processing may still reject the candidate after both scripts run, or may resolve it as a block or counter. Consequently, this event can run without a later Didhit event.
Ordinary item pickup paths may invoke an item's collection script directly. ondoattackscript should not be treated as a universal item-collection callback.
self is always the entity whose model owns the currently executing script. For a projectile impact, the projectile is the conferring entity; OpenBOR does not automatically substitute its owner.
Execution Order
For an ordinary candidate impact, OpenBOR performs the relevant operations in this order:
- Confirms collision and preliminary attack eligibility.
- Initializes the shared last-hit context with confirmation enabled.
- Runs the recipient's
ondoattackscriptwithwhich = EXCHANGE_RECIPIENT. - Runs the conferring entity's
ondoattackscriptwithwhich = EXCHANGE_CONFERRER. - Continues only when the shared last-hit confirmation remains enabled.
- Applies remaining identity, ownership, projectile, block, counter, and take-damage rules.
- Runs later events, including Didblockscript or Didhitscript, when their conditions are met.
Both Ondoattack scripts operate on the same last-hit context. The recipient runs first, the conferrer runs second, and the value remaining after the second callback controls native continuation. Setting lasthitc to 0 in the recipient's script does not prevent the conferrer's script from running.
Exchange Roles
The which local identifies the current entity's role in the proposed exchange.
| Constant | Numeric value | Current self
|
Execution order |
|---|---|---|---|
EXCHANGE_RECIPIENT
|
1
|
Recipient or defender | First |
EXCHANGE_CONFERRER
|
0
|
Attacker, projectile, or other entity conferring the attack | Second |
Comparing which with named constants is clearer and safer than relying on raw numeric values.
Local Variables
| Local variable | Type | Value |
|---|---|---|
self
|
Entity pointer | Entity whose Ondoattack script is currently running. |
other
|
Entity pointer | Other participant in the exchange. Recipient scripts receive the conferrer; conferrer scripts receive the recipient. |
damage
|
Integer | Raw attack.damage.force at the time of the event. This is not final HP loss.
|
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.
|
which
|
Integer | Current exchange role: EXCHANGE_RECIPIENT or EXCHANGE_CONFERRER.
|
attack_id
|
Integer | Current outgoing attack ID used by native duplicate-hit control. Both callbacks receive the same value. |
attack_id is not an entity ID or collision-box index. Synthetic landing-damage events may supply 0. The local name includes the underscore; attackid is not the current event local.
Numeric attack locals are copied from the current attack when each callback begins. Assigning new values to these local variables does not write them back to native attack data. Use the last-hit interface when native context must be changed.
Cancelling Native Hit Handling
The shared OpenBOR variant lasthitc exposes the current last-hit confirmation flag. Collision setup normally initializes it to 1. Setting it to 0 during Ondoattack tells the engine to abandon native handling after both callbacks finish.
The following recipient-side example cancels native handling for freeze attacks:
void main()
{
int which = getlocalvar("which");
int attack_type = getlocalvar("attacktype");
if(which != openborconstant("EXCHANGE_RECIPIENT"))
{
return;
}
if(attack_type == openborconstant("ATK_FREEZE"))
{
changeopenborvariant("lasthitc", 0);
}
}Cancellation prevents the normal block, counter, damage, and Didhit processing for that candidate. Custom effects or responses may be performed before clearing the flag.
The conferrer's callback still runs after the example clears lasthitc. If that later callback sets the flag back to 1, native handling resumes. Projects that cancel from the recipient side should establish a clear convention for conferrer scripts.
Returning 0, 1, or another value from main() does not accept or cancel the impact. OpenBOR ignores the script return value for this event.
Shared Last-Hit Context
Ondoattack scripts may inspect the full candidate through OpenBOR's last-hit variants.
| Variant | Purpose |
|---|---|
lasthitc
|
Reads or changes candidate confirmation. |
lasthit_attack
|
Provides the current attack object for property access. |
lasthit_attacker
|
Provides the entity conferring the attack. |
lasthit_target
|
Provides the proposed recipient. |
lasthitt
|
Reads or changes the current attack type. |
lasthitx, lasthity, lasthitz
|
Provide the recorded impact coordinates. |
Read these values with openborvariant(). Writable variants may be changed with changeopenborvariant().
Since the recipient callback runs first, native context changes it makes can be visible to the conferrer's callback. For example, changing lasthitt in the recipient callback changes the attack type used to populate the later conferrer's attacktype local. Treat such changes as shared state rather than private per-entity data.
Role-Specific Example
This example shows one file shared by several models. Recipient logic may reject a tagged attack, while conferrer logic records that the candidate reached Ondoattack processing.
void main()
{
void self = getlocalvar("self");
void other = getlocalvar("other");
int which = getlocalvar("which");
int tag = getlocalvar("tag");
int attack_id = getlocalvar("attack_id");
if(which == openborconstant("EXCHANGE_RECIPIENT"))
{
if(tag == 42)
{
changeopenborvariant("lasthitc", 0);
}
return;
}
if(which == openborconstant("EXCHANGE_CONFERRER"))
{
log("Candidate attack reached Ondoattack");
}
}Unused variables are retained to demonstrate the usual event setup. Real scripts may pass self, other, and attack_id into project-specific combat, immunity, parry, statistics, or debugging systems.
Damage on Landing
Configured landing damage also passes through Ondoattack processing. OpenBOR builds a temporary attack, chooses a living opponent as the conferrer when possible, and otherwise uses the landing entity itself. The recipient callback runs before the conferrer callback, following the same confirmation rules as an ordinary candidate impact.
Landing events use a synthetic attack context. Some values, including attack_id, may therefore be 0 or differ from ordinary attack-box collisions.
Global Model
Unlike Didhit and Onspawn, ondoattackscript is not automatically forwarded through a model named global_model. Only the scripts belonging to the two participating entities run. Shared project-wide behavior should be placed in a common script included by participating models or called from their individual Ondoattack scripts.
Related Events
| Event | Entity | Relative purpose |
|---|---|---|
| Ondoattackscript | Recipient first, then conferrer | Intercepts a candidate impact before native block, counter, and damage handling. May cancel native processing through lasthitc.
|
| Takedamagescript | Recipient | Runs while native damage and reaction handling are being applied. |
| Didhitscript | Conferrer | Runs after OpenBOR accepts a normal hit, block, qualifying item event, or landing-damage event. |
| Didblockscript | Defender | Runs after a successful native block and applicable guard-cost deduction. |