Solved Is there a way to modify the pause time of an attack using code?

Question that is answered or resolved.

hechelion

Member
Hi. I have an attack system that changes based on certain variables, so I alter the amount and type of damage using a script. So far, everything is working.

The problem is that when a critical attack occurs, I'd like to increase the pause time, but I haven't been able to figure out how to do it.

I know I can read that value using the local variable "pauseadd" in the "didhit" and/or "ondoattack" events, but I can't find a way to modify it.

PS: I don't want to resort to using different "freespecial"; I'm looking for a way to change that value using a script.
 
Solution
Hi. I have an attack system that changes based on certain variables, so I alter the amount and type of damage using a script. So far, everything is working.

The problem is that when a critical attack occurs, I'd like to increase the pause time, but I haven't been able to figure out how to do it.

I know I can read that value using the local variable "pauseadd" in the "didhit" and/or "ondoattack" events, but I can't find a way to modify it.

PS: I don't want to resort to using different "freespecial"; I'm looking for a way to change that value using a script.

I wrote a 3.0 compatible system that does exactly this some time ago. One you set it up, it becomes fire and forget in that you use the pause set function the same way you...
Hi. I have an attack system that changes based on certain variables, so I alter the amount and type of damage using a script. So far, everything is working.

The problem is that when a critical attack occurs, I'd like to increase the pause time, but I haven't been able to figure out how to do it.

I know I can read that value using the local variable "pauseadd" in the "didhit" and/or "ondoattack" events, but I can't find a way to modify it.

PS: I don't want to resort to using different "freespecial"; I'm looking for a way to change that value using a script.

I wrote a 3.0 compatible system that does exactly this some time ago. One you set it up, it becomes fire and forget in that you use the pause set function the same way you would another attack property - if the attack hits, the target gets defined extra pause added, simple as that. I don't have time to write a full tutorial on how to install, but there are only three files and I think you'll find it largely self explanatory. It expects to be in a folder: data/scripts/dc_timing

master_config.h
C-like:
#ifndef DC_TIMING_CONFIG
#define DC_TIMING_CONFIG 1

#define DC_TIMING_VARKEY_PAUSE_ADJUST "dctiming0"

#endif

master_functions.c
C-like:
#include "data/scripts/dc_timing/master_config.h"

/*
 * dc_pause_adjust
 *
 * Adjusts stun-related timers on a target entity to modify how long they're paused (unable to act),
 * usually following an attack.
 *
 * Intended to be called during the `didhit` event of the attacking entity.
 *
 * Combines two sources of timing delay:
 *   1. `time_adjust_param` - An explicit value passed into the function.
 *   2. A temporary per-entity value stored in a custom entity variable
 *      (`DC_TIMING_VARKEY_PAUSE_ADJUST`) on the attacking entity.
 *
 * Once both values are added together, it extends the stun timers on the target entity,
 * then clears the temporary variable from the attacker to avoid double application.
 *
 * Note: The engine applies native attack pause **after** the `didhit` script runs.
 * This means any adjustment made here is **added on top** of the default hitpause.
 *
 * Some of Valis's armed attacks have a bit of lag compared to others to balance his reach
 * and initial execution speed. The stun times, however, are tuned for near-instant
 * combo execution. Adjusting the stun time for hit entities lets us keep his attack lag
 * while still allowing him to complete his combos reliably on a struck opponent.
 *
 * Also – you know, he's hitting them with a BFS, so let's make it *feel* like it hurt. :)
 *
 * This mechanic exists because we can't simply increase Valis's native attack stun because
 * that pause affects both him and the enemy. Doing so would make his attacks feel sluggish
 * and visually clumsy. Instead, we isolate and extend the *enemy's* pause window here
 * while leaving Valis free to recover and continue his combo.
 *
 * Parameters:
 *   - acting_entity: The attacker (must be a valid entity pointer).
 *   - acting_target: The target who receives the adjusted stun.
 *   - time_adjust_param: Additional time to add to stun timers.
 */

void dc_pause_adjust_apply(void acting_entity, void acting_target, int time_adjust_param){

    // Validate that the acting entity is a valid pointer
    if(!acting_entity || typeof(acting_entity) != openborconstant("VT_PTR")) {
        return;
    }

    // Validate that the target entity is a valid pointer
    if(!acting_target || typeof(acting_target) != openborconstant("VT_PTR")) {
        return;
    }

    // If no time adjustment parameter is passed, default to zero
    if(!time_adjust_param){
        time_adjust_param = 0;
    }

    // Retrieve current stun-related timer values from the target entity
    int next_move_time = getentityproperty(acting_target, "nextmove");
    int next_anim_time = getentityproperty(acting_target, "nextanim");
    int next_think_time = getentityproperty(acting_target, "nextthink");
    int toss_time = getentityproperty(acting_target, "tosstime");

    // Read the attacker's temporary pause adjustment value
    int time_adjust_setup = getentityvar(acting_entity, DC_TIMING_VARKEY_PAUSE_ADJUST);

    // Default to zero if the attacker has no pause adjustment value set
    if(!time_adjust_setup){
        time_adjust_setup = 0;
    }

    // 0 the temporary variable on the attacking entity so it doesn't apply again.
    // We don't NULL() it so the variable stays in placy. This is slightly
    // more optimal since we will almost certainly use the variable again and
    // so there's no reason to make engine re-initialize it over and over.
    setentityvar(acting_entity, DC_TIMING_VARKEY_PAUSE_ADJUST, 0);

    // Calculate final time adjustment by summing the param and the temp variable
    int final_adjust = time_adjust_setup + time_adjust_param;

    // If no adjustment is needed, do nothing
    if(!final_adjust) {
        return;
    }

    // Apply the final adjustment to all relevant timers on the target
    next_anim_time += final_adjust;
    next_move_time += final_adjust;
    next_think_time += final_adjust;
    toss_time += final_adjust;

    // Update the target's timers with the new adjusted values
    changeentityproperty(acting_target, "nextmove", next_move_time);
    changeentityproperty(acting_target, "nextanim", next_anim_time);
    changeentityproperty(acting_target, "nextthink", next_think_time);  
    changeentityproperty(acting_target, "tosstime", toss_time);
}

/*
 * dc_pause_adjust_setup
 *
 * Stores a temporary pause adjustment value on the acting entity. This value is picked up later
 * by the `dc_pause_adjust` function during the `didhit` event to extend the target's stun window.
 *
 * Parameters:
 *   - pause_adjustment: The number of ticks to add to the target's stun when hit.
 *                       This value is stored temporarily and cleared after use.
 *
 * Important:
 * This should be called before the attack connects—typically early in the attack animation.
 * Be sure to call this function again later in the animation with a value of 0 to turn the effect off.
 *
 * Also run this in the takedamage script to clear the value early if the attacker gets interrupted
 * before the hit connects — this avoids stale values accidentally carrying over to the next hit.
 */
void dc_pause_adjust_setup(int pause_adjustment){
    void acting_entity = getlocalvar("self");

    // Validate that 'self' is a proper entity pointer
    if(!acting_entity || typeof(acting_entity) != openborconstant("VT_PTR")) {
        return;
    }

    // Store the pause adjustment value in the attacker's entity vars
    setentityvar(acting_entity, DC_TIMING_VARKEY_PAUSE_ADJUST, pause_adjustment);
}

main.c - #include this in script files you want functionality.
C-like:
#include "data/scripts/dc_timing/master_config.h"
#import "data/scripts/dc_timing/master_functions.c"

/*
* Timing and stun-pause adjustment library.
*
* Copyright (c) 2026 Damon V. Caskey.
*
* You may use and distribute this library as part of
* your own OpenBOR projects with attribution.
*
* You may not redistribute this library as a standalone
* work, whether in original or modified form, without
* permission from the author.
*
* All other rights reserved.
*
*********************
* Usage Notes
*
* Include this file in your OpenBOR project to
* access the timing adjustment functions. See
* function documentation for usage details.
*/

Usage example (in text):
Rich (BB code):
@cmd dc_space_setup_start 0 -30 165 0 40 -15 15 0.5 0.0 0.0
    frame    data/chars/valis/december/cross_cut_1.png

    @cmd dc_pause_adjust_setup 20

    attack.position.x                 152
    attack.position.y                 158
    attack.size.x                     58
    attack.size.y                     20
    attack.size.z.background         20
    attack.size.z.foreground         20
    attack.damage.type                12
    attack.damage.force             10
    attack.reaction.pause.time         10
    attack.reaction.invincible.time 5
    attack.effect.hit.flash.model    cut
    attack.effect.hit.sound.path    ata/sounds/cut1.wav
   
    frame    data/chars/valis/december/cross_cut_2.png  
   
    bbox.position.x    152
    bbox.position.y 145
    bbox.size.x     21
    bbox.size.y     41

    frame    data/chars/valis/december/cross_cut_3.png
   
    delay 5
    attack 0
    @cmd dc_pause_adjust_setup 0
    @cmd dc_space_setup_end 0
    frame    data/chars/valis/december/cross_cut_4.png

In takedamage script:
C-like:
#include "data/scripts/dc_timing/main.c"

void main(){

    //void acting_entity = getlocalvar("self");

    // Clear any leftover pause adjustment if Valis gets interrupted
    dc_pause_adjust_setup(0);
}

In didhit script.
C-like:
#include "data/scripts/dc_timing/main.c"

void main(){

    void acting_entity = getlocalvar("self");
    void acting_target = getlocalvar("damagetaker");

    dc_pause_adjust_apply(acting_entity, acting_target, 0);
}


1782525746434.png

1782525763838.png

HTH,
DC

PS: Before anyone asks, yes, natively separate attacker and target pause values are a planed addition for upcoming releases.
 
Solution
Thank you so much for your time and response. Your code is very clean and well-documented, so it's quite self-explanatory and allows me to understand what modifications need to be made.
 
Back
Top Bottom