Skip to main content

Ravenmark Bow

Marks enemies for a short duration.

Marked enemies take additional damage whenever they are hit.

When a marked enemy dies, the mark spreads to nearby enemies.

Implementation​

Ravenmark Bow is one of the more complex implementations because we need to track arrows and which Actors they are currently attached to, while also keeping the ammo count consistent.

There are three scenarios for spending and reclaiming an arrow.

The first scenario is when we fire an arrow at the ground. In this case, we use a custom script to move the arrow back to its source and restore the ammo when the arrow reaches the source.

RavenmarkBow › SkillExtension_MoveToSource — Prefab component
SkillExtension_MoveToSource: RavenmarkBow
Delay:2.5
Duration:0.18
Effect Pack → on reach:ReclaimArrow

We use a SourceSeparated Int Stat for AmmoCount, while the inner Stats track the decrease amounts associated with each actor.

As shown below, the parent Stat has a range of 0 to 2, while the inner Stat has a range of -2 to 0. Modifiers are added to both the inner Stat and the SourceSeparated parent Stat. This allows the system to track both the remaining ammo count and the decrease amounts associated with arrows for each Actor.

AmmoCount(SrcSep) — Stat (SrcSep Clamped Int)
Stat (SrcSep Clamped Int): AmmoCount(SrcSep)
Stat Key:RavenmarkBow / Int_SrcSep / AmmoCount
Default:2
Inner Stat Definition:AmmoCount(SrcSep-Inner)
Max:2

When an arrow is fired, its decrease amount is initially added to the source Actor's SourceSeparated Stat. If the arrow does not hit any target, this decrease amount remains assigned to the source Actor.

If the arrow hits a target, we remove the decrease amount from the source Actor and assign the same decrease amount to the target Actor. This allows the SourceSeparated Stat to track how many arrows are currently attached to each Actor.

RavenmarkBow › Effector_OnCollide — Prefab component
Effector_OnCollide: RavenmarkBow
Trigger Actors:Enemy
Hit Limitation Type:By Count
Hit Limit:1
Team From:Source
Limit Exceeded Behaviour:Passivate
Effect Pack (target Source, source Source):UnbindAmmoFromSource
Effect Pack (target Source, source Trigger Actor):BindAmmoToTarget
Effect Pack (target Trigger Actor, source Source):RavenmarkBow_Attack

Although this setup is somewhat complex, it works reliably and allows us to keep track of both the fired arrows and the remaining ammo.

To apply additional damage to marked targets, we use a CounterEffect that checks for the mark. After applying the damage, we add a cooldown to prevent the effect from triggering again immediately.

RavenmarkBowCounterDamage — Stat (CounterEffect Signed)
Stat (CounterEffect Signed): RavenmarkBowCounterDamage
Stat Key:RavenmarkBow / CounterEffect_Signed / RavenmarksBowCounterDamage
Redirection Target:Target
Redirected Effect Source:Modifier Source
State Check:true
Multi Stat Check:true
Single Stat Checker › Stat › Actor:Target
Single Stat Checker › Condition:Is1(Int)
Multi Stat Checker › Stats [0] › Actor:Target
Multi Stat Checker › Stats [1] › Actor:Target
Multi Stat Checker › Condition:RavenmarkBowDamageCounter
Targeting Environment Id:Default
Trigger On:Applied
Incoming Effect Sign:Negative
Default: RavenmarkBowCounterDamage
Int Stat Effect (BS): MarkCounterDamageCd
Target Stat:RavenmarkBow / IntClamped / RavenmarksBowCounterDamageCd
Value:1
Processor:Add_Int
Apply Type:Temporary
Float Stat Effect (BS): MarkCounterDamage
Target Stat:Default / FloatClamped / Health
Value:-1.5
Processor:Standard_Float

To spread the mark when a marked enemy dies, we use a StateBasedEffect. We also use a SourceSeparated Stat to ensure that the mark's source is correctly preserved when it spreads.

SpreadMarkOnDeadTrigger(SrcSep) — Stat (SrcSep EffectPack)
Stat (SrcSep EffectPack): SpreadMarkOnDeadTrigger(SrcSep)
Stat Key:RavenmarkBow / StateBasedEffect_SrcSep / SpreadMarkOnDeadTrigger
Inner Stat Definition:SpreadMarkOnDeadTrigger(SrcSep-Inner)
Default: RavenmarkBowBundle(Default)

Finally, we use a CustomTargeter to find team members within the required range and apply the mark to them.

TeamMembersInRange — Custom Targeter By Relation State Filtered
Custom Targeter By Relation State Filtered: TeamMembersInRange
Relate To:Target
Relation State:Team
Filter:InRange