Didblockscript
didblockscript is a model event script that executes on the defending entity whenever OpenBOR accepts an incoming attack as blocked. The event supplies references to both participants together with the principal attack values, making it a powerful point for building mechanics that react to a successful block.
Despite its name, didblockscript does not decide whether the attack will be blocked. OpenBOR has already accepted the block when the script executes. The hook instead allows the defender to respond during the same attack-processing sequence.
Usage
Add the command to a model definition and provide the path to the script file:
didblockscript data/scripts/didblock.c
Like most event scripts, the script uses a main() entry point. OpenBOR populates the event's local variables immediately before calling it.
void main()
{
void self = getlocalvar("self");
void attacker = getlocalvar("attacker");
int damage = getlocalvar("damage");
int drop = getlocalvar("drop");
int attack_type = getlocalvar("attacktype");
int no_block = getlocalvar("noblock");
int guard_cost = getlocalvar("guardcost");
int juggle_cost = getlocalvar("jugglecost");
int pause_add = getlocalvar("pauseadd");
int tag = getlocalvar("tag");
// Respond to the successful block here.
}
Execution
didblockscript executes once for each accepted block, whether the block was initiated by OpenBOR's native blocking system or placed under script control. Script-controlled blocks preserve the action chosen by the creator, while native blocks apply their usual animation, movement, state, and guard behavior.
The immediate event order is:
- OpenBOR accepts the attack as blocked.
- For native blocking, OpenBOR selects the appropriate BLOCK or BLOCKPAIN animation.
- OpenBOR spawns the configured block flash.
- The attacker's didhitscript executes with
blockedset to1. - For native blocking, OpenBOR applies the blocking state and action, stops X and Z velocity, and deducts the attack's guard cost when applicable.
- OpenBOR increments the hit counter of the attacker's current animation.
- The defender's didblockscript executes.
The larger attack-processing sequence continues afterward. Follow-up animation selection, attack identification, next-hit timing, and applicable energy-cost handling have not necessarily finished when didblockscript runs. Changes made to either entity can therefore influence systems that inspect their state later in the same sequence.
Event Data
| Variable | Type | Description |
|---|---|---|
self
|
Object pointer | Defending entity whose model contains the script. |
attacker
|
Object pointer | Entity whose attack was blocked. |
damage
|
Integer | Unmodified force value of the incoming attack. This is attack data, not damage taken by the defender. |
drop
|
Integer | Knockdown force of the incoming attack. |
attacktype
|
Integer | Attack type identifier. |
noblock
|
Integer | Block penetration value of the incoming attack. |
guardcost
|
Integer | Guard-point cost assigned to the incoming attack. |
jugglecost
|
Integer | Juggle-point cost assigned to the incoming attack. |
pauseadd
|
Integer | Pause value assigned to the incoming attack. |
tag
|
Integer | Metadata tag assigned to the incoming attack. |
The numeric values are local copies of the attack data. Assigning a new value to damage, guardcost, or another numeric event variable does not rewrite the attack. Use the appropriate entity, model, animation, or attack APIs when persistent changes are required.
Return Value
OpenBOR does not inspect the return value of didblockscript. Returning 0, 1, or another value does not change the result of the block.
Use ondoattackscript when the current collision must be cancelled or replaced before native blocking and damage handling. Use didblockscript when the block has already succeeded and the defender should react to that result.
Example: Perfect Guard
The following compact example assumes an input or update script opens a short perfect-guard window by setting perfect_guard. When a block succeeds during that window, didblockscript refunds the native guard cost and leaves a success flag for the model's other scripts to consume.
void main()
{
void self = getlocalvar("self");
void attacker = getlocalvar("attacker");
int guard_cost = getlocalvar("guardcost");
int block_state_property =
openborconstant("ENTITY_PROPERTY_BLOCK_STATE");
int guard_points_property =
openborconstant("ENTITY_PROPERTY_GUARD_POINTS");
int native_block = openborconstant("BLOCK_STATE_NATIVE");
int block_state = get_entity_property(
self,
block_state_property
);
if (getentityvar(self, "perfect_guard")
&& (block_state & native_block))
{
int guard_points = get_entity_property(
self,
guard_points_property
);
set_entity_property(
self,
guard_points_property,
guard_points + guard_cost
);
setentityvar(self, "perfect_guard", 0);
setentityvar(self, "perfect_guard_success", 1);
setentityvar(self, "perfect_guard_target", attacker);
}
}
The model's animation, update, or think script can consume perfect_guard_success to play an alternate flash, start a counterattack, freeze the attacker, award meter, or trigger any other desired response. This division keeps the block event concise without limiting the complexity of the resulting mechanic.
Other Uses
Quick applications include:
- Guard effects - Select sounds, flashes, camera movement, or screen effects from attack force, type, or tag.
- Resource conversion - Convert blocked damage or guard cost into MP, score, ammunition, charge, or another custom resource.
- Attacker reactions - Mark the attacker for recoil, stagger, weapon deflection, reflected projectiles, or counterattack targeting.
- Adaptive defense - Record recently blocked attack types and adjust later defensive behavior.
- Training and statistics - Count successful blocks, identify timing windows, display feedback, or record challenge progress.
- Conditional follow-ups - Choose a response according to attack force, knockdown power, metadata tag, attacker identity, or the defender's current state.
Related Scripts
| Script | Relationship |
|---|---|
| ondoattackscript | Executes on the target and attacker before native hit handling. It can cancel or replace the current collision. |
| didhitscript | Executes on the attacker when the attack is accepted. Its blocked variable reports whether the hit was blocked.
|
| 'didblockscript | Executes on the defender after the immediate block presentation and native block bookkeeping. |
| takedamagescript | Executes when an entity receives damage. Normally blocked attacks follow the block path instead. |
The similarly named onblock...script family concerns movement obstruction by level geometry. Those scripts are unrelated to defending against attacks.