Flexweave
Runtime Patterns

Run Temporary Buffs and Debuffs

Use duration effects for finite runtime modifiers.

Duration effects create active instances with remaining clock units. They are a good fit for buffs, debuffs, cooldowns, temporary immunities, and temporary state flags.

In the RPG example:

  • Quickened Strikes is a ten-second attack-speed buff.
  • Fortify is a ten-second max-health buff.
  • Cooldowns are ten-second effects tagged by ability.

Derived attributes inspect active buff effects rather than letting the effect pipeline mutate stats directly. When a buff expires, refresh the relevant derived attributes.

Apply temporary stat modifiers as duration effects:

EffectApply::definition(
    &EffectDefinition::duration(
        "effect/quickened-strikes",
        TEN_SECONDS,
        "AttackSpeedBuffPayload",
    ),
    EffectApplicationInput::accept(
        Some(active.source_id()),
        active.owner_id,
        tag_set([effect_buff_tag(), effect_attack_speed_tag()]),
        EffectPayload::AttackSpeedBonus {
            amount: attack_speed_bonus,
        },
    ),
)
.run(&mut effects)?;

The effect payload describes what the buff means to your runtime. The tags make the active instance discoverable by broad categories such as all buffs, all attack-speed modifiers, or all effects from a particular ability.

After ticking the effect pipeline, refresh any derived values that read active buffs:

EffectTick::new(10_000).run(&mut effects)?;
DerivedAttributeRefresh::new(player).run(&mut attack_speed);

Do not make the duration effect mutate the stat on apply and then try to undo the mutation on expiration. That approach makes stacking, cancellation, cleanup, save/load, and reconnect flows harder. Let active effect state be the source for derived calculations instead.

Use this with: