Enhanced Delay
Enhanced Delay - edelay in legacy engine builds, is a model- and entity-level transform for animation timing. It can scale, offset, filter, and cap the delay of each indexed animation member without requiring creators to rewrite the member's own delay value.
Enhanced Delay does not create a second timer. When an entity enters an actively animating position, OpenBOR reads that member's stored delay, applies the model or entity's Enhanced Delay configuration, and uses the result to schedule the next position.
This makes the feature useful for broad timing changes such as:
- Fast and slow character variants using the same animation data.
- Haste, slow, weight, transformation, or equipment effects applied to an individual entity.
- Global animation-pacing adjustments for a model.
- Protecting short, deliberately timed animation members while scaling longer ones.
- Enforcing a minimum or maximum duration after scaling.
- Combining proportional timing changes with a fixed adjustment.
Commands
Enhanced Delay commands expose each part of the calculation independently:
enhanced_delay_multiplier {multiplier}
enhanced_delay_modifier {modifier}
enhanced_delay_cap_min {minimum}
enhanced_delay_cap_max {maximum}
enhanced_delay_range_min {minimum}
enhanced_delay_range_max {maximum}
All six commands belong in a model definition. They may be supplied in any order because each command writes one configuration value.
| Command | Type | Default | Purpose |
|---|---|---|---|
enhanced_delay_multiplier
|
Decimal or percentage | 1.0
|
Multiplies an eligible original delay. Values such as 0.8 and 80% are equivalent.
|
enhanced_delay_modifier
|
Signed integer | 0
|
Adds a fixed number of logical clock ticks after multiplication. |
enhanced_delay_cap_min
|
Signed integer | 0
|
Lowest calculated result permitted before final finite-delay bounds are applied. |
enhanced_delay_cap_max
|
Signed integer | 2147483647
|
Highest calculated result permitted before final finite-delay bounds are applied. |
enhanced_delay_range_min
|
Signed integer | 0
|
Lowest original delay eligible for adjustment. Values of zero or less impose no lower exclusion. |
enhanced_delay_range_max
|
Signed integer | 2147483647
|
Highest original delay eligible for adjustment. Negative values disable Enhanced Delay processing. |
Default values leave ordinary delays unchanged. The default cap and range maximum use the signed integer maximum, 2147483647. OpenBOR's finite animation-delay representation extends to 4294967295, so an original value above the default range maximum bypasses Enhanced Delay and remains unchanged.
Basic Example
This configuration reduces eligible animation delays to 80 percent of their original duration:
enhanced_delay_multiplier 80%
This configuration combines scaling with a fixed addition and protects the result with minimum and maximum caps:
enhanced_delay_multiplier 0.75
enhanced_delay_modifier 2
enhanced_delay_cap_min 4
enhanced_delay_cap_max 20
Calculation Order
OpenBOR processes an animation member's delay in this order:
- The member's declared
delayis converted to logical clock ticks when the animation data is loaded. - The entity enters an actively animating position.
- OpenBOR compares the original logical-tick delay with the Enhanced Delay eligibility range.
- An in-range value is multiplied by
enhanced_delay_multiplier. enhanced_delay_modifieris added to the product.enhanced_delay_cap_minis applied.enhanced_delay_cap_maxis applied.- Fractional remainder is discarded and the result is limited to the finite delay range.
- OpenBOR converts the resulting relative delay into the absolute time for the next animation position.
The central formula is:
calculated_delay = original_delay * multiplier + modifier
Caps then constrain calculated_delay. The eligibility range is not part of the formula and does not clamp the original value. An out-of-range original delay bypasses the complete calculation and is returned unchanged.
Worked Example
Consider this configuration:
enhanced_delay_multiplier 0.75
enhanced_delay_modifier 2
enhanced_delay_cap_min 4
enhanced_delay_cap_max 20
enhanced_delay_range_min 6
enhanced_delay_range_max 30
| Original delay | Processing | Final delay |
|---|---|---|
5
|
Below the eligibility range - no calculation. | 5
|
6
|
6 * 0.75 + 2 = 6.5, then fractional remainder is discarded.
|
6
|
20
|
20 * 0.75 + 2 = 17.
|
17
|
30
|
30 * 0.75 + 2 = 24.5, then maximum cap applies.
|
20
|
31
|
Above the eligibility range - no calculation. | 31
|
Eligibility Range
Range tests use the original converted delay, before multiplication, addition, or caps.
- Both positive boundaries are inclusive. Values equal to
range_minorrange_maxare eligible. range_minonly excludes lower values when it is greater than zero. Zero or a negative value means there is no effective lower threshold.- Negative
range_maxvalues disable Enhanced Delay entirely. They do not mean "no upper limit." - Use
4294967295as the maximum when every possible finite animation delay should be eligible.
The range knows only the stored duration. It does not know the animation name, member position, attack state, collision content, or creator intent. Projects can preserve short attack-active positions by assigning them short delays and placing the range minimum above those values, though Enhanced Delay is selecting by duration rather than by gameplay role.
Scale Only Longer Delays
This example leaves original values below 6 logical ticks unchanged and halves values from 6 through 30:
enhanced_delay_multiplier 0.5
enhanced_delay_range_min 6
enhanced_delay_range_max 30
Original delays above 30 are also unchanged. This can be useful when a project's short active positions and long recovery or idle positions already occupy distinct duration ranges.
Caps
Caps apply only after an eligible delay has been multiplied and modified.
cap_minraises a calculated value below the minimum.cap_maxlowers a calculated value above the maximum.- Keep
cap_minless than or equal tocap_maxfor predictable configuration. - Final finite values cannot be below
0or above4294967295, regardless of configured caps. - Negative calculated results become
0after cap processing unless a positive minimum cap raises them first. - Results at or above
4294967295become4294967295.
Fractional results are truncated toward zero after caps. Enhanced Delay does not retain sub-tick timing. For example, 9 * 0.75 = 6.75 becomes 6 when no cap changes it.
Units
The animation member's own delay command supports declared units such as global, centisecond, millisecond, second, minute, and direct. OpenBOR converts that value to logical clock ticks while loading the animation.
Enhanced Delay runs after this conversion:
- Multiplier is dimensionless.
- Modifier is a count of logical clock ticks.
- Both caps are logical-tick values.
- Both eligibility boundaries are logical-tick values.
This distinction matters when a model uses time-based delay input. For example, with a game speed of 200 logical ticks per second, delay 10 centisecond is stored as 20 logical ticks. Enhanced Delay range values of 10 through 20 include that member because the comparison sees 20, not the source token 10. Modifier value 2 adds two logical ticks, not two centiseconds.
Projects using direct delay input already supply logical ticks, so the source and Enhanced Delay numbers share the same scale.
Runtime Timing
Enhanced Delay is evaluated when OpenBOR schedules the duration of an actively animating position. The relevant order is:
- OpenBOR assigns the new indexed animation position.
- Enhanced Delay calculates the relative duration.
- OpenBOR stores the absolute next-animation timestamp.
- Animationscript executes for the entered position.
- Later logical updates advance the animation when the stored timestamp is due.
Changing Enhanced Delay settings does not ordinarily rewrite an absolute timestamp that was already scheduled for the current position. Changes made by Animationscript are therefore normally too late to alter the duration of the position that invoked it, though they affect later position entries. If script immediately enters another animation or indexed position, that new entry follows the normal scheduling path and uses the current configuration.
Paused, frozen, or otherwise deferred time may affect when the stored timestamp is reached, but Enhanced Delay itself is not a per-tick callback. Its calculation runs when the relevant animation position is scheduled.
Per-Entity Script Control
Each entity carries a model-data copy used by the calculation. Modern property functions expose every Enhanced Delay field, allowing script to apply timing changes to one entity without editing its animation definitions.
void set_entity_animation_multiplier(void entity, void multiplier)
{
void model_data = get_entity_property(
entity,
ENTITY_PROPERTY_MODEL_DATA
);
set_model_property(
model_data,
MODEL_PROPERTY_ENHANCED_DELAY_MULTIPLIER,
multiplier
);
}
Calling this helper with 0.75 accelerates eligible future position durations for that entity, 1.5 slows them, and 1.0 restores the neutral multiplier. The existing modifier, caps, and range continue to participate.
Corresponding model-property constants are:
MODEL_PROPERTY_ENHANCED_DELAY_MULTIPLIERMODEL_PROPERTY_ENHANCED_DELAY_MODIFIERMODEL_PROPERTY_ENHANCED_DELAY_CAP_MINMODEL_PROPERTY_ENHANCED_DELAY_CAP_MAXMODEL_PROPERTY_ENHANCED_DELAY_RANGE_MINMODEL_PROPERTY_ENHANCED_DELAY_RANGE_MAX
Use ENTITY_PROPERTY_MODEL_DATA when the adjustment should belong to the current entity copy. Mutating the shared cached model instead may affect other entities or later spawns according to which model object was changed.
Remember that changing a property does not ordinarily reschedule the current position's existing timestamp. Apply a temporary status before entering the positions it should affect, or explicitly enter the desired animation state after updating the configuration.
Infinite Delays
OpenBOR encodes infinite animation delay as a behavior flag separate from the finite value bits. Enhanced Delay preserves all behavior flags while operating on the finite portion.
An infinite delay therefore remains infinite regardless of multiplier, modifier, range, or caps. Enhanced Delay cannot convert it into a finite duration. The animation needs an outside state or animation change to leave a position whose delay is infinite.
Practical Patterns
| Pattern | Configuration idea |
|---|---|
| Faster model variant | Use a multiplier below 1.0 to shorten eligible durations throughout the model.
|
| Slower or heavier variant | Use a multiplier above 1.0, with a maximum cap to prevent unusually long members from growing without bound.
|
| Haste or slow status | Change the multiplier on the entity's model-data copy, then restore 1.0 when the status ends.
|
| Fixed startup tax | Use a positive modifier to add the same logical-tick amount to every eligible duration. |
| Recovery reduction | Use a negative modifier or multiplier below 1.0, with a minimum cap to keep eligible members from collapsing to zero.
|
| Preserve short active positions | Put the range minimum above the deliberately short values, provided duration reliably identifies those positions in the project's animation design. |
| Timing normalization | Use minimum and maximum caps to keep transformed results inside a desired band. |
| Combined curve | Use both multiplier and modifier to provide proportional scaling plus a fixed offset. |
Common Mistakes
- Treating Enhanced Delay values as centiseconds or milliseconds instead of logical ticks.
- Expecting the eligibility range to clamp results rather than filter original delays.
- Testing range boundaries against the calculated result instead of the original stored delay.
- Assuming range boundaries are exclusive.
- Using a negative
range_maxto mean unlimited when it actually disables Enhanced Delay. - Forgetting that the default cap and range maximum are
2147483647, below the full finite-delay maximum. - Expecting fractional logical ticks to survive the calculation.
- Configuring
cap_minabovecap_max. - Omitting arguments from the legacy
edelayline. - Assuming legacy mode is stored and selects a different runtime formula.
- Mixing legacy and modern commands without accounting for source-order overwrites.
- Changing the configuration after the current position's timestamp is already scheduled and expecting retroactive timing.
- Expecting Enhanced Delay to make an infinite delay finite.
- Assuming the range identifies animation purpose rather than only original duration.
Comparison with Related Features
| Feature | Scope | Role |
|---|---|---|
delay
|
One indexed animation member. | Supplies that member's original duration and input unit. |
Enhanced Delay / edelay
|
Model or individual entity model-data copy. | Transforms eligible original durations when animation positions are scheduled. |
| Animationscript | One entity entering an indexed animation position. | Executes creator code after the position's normal next-animation timestamp has been scheduled. |
| Updateentityscript | One entity during each eligible logical update. | Can manage dynamic timing state before later animation processing in the same logical tick. |