Concept: Windows, Shapes and Filters
The model behind the plugin, and why it is split the way it is.
Geometry is a selection task, validity is a filter task
A UTargetingPreset holds both. A selection task contributes candidates; filter tasks remove them; a sort task orders what remains. That split is Epic's, and this plugin adopts it wholesale rather than inventing a parallel one.
Because of it, area attacks and hitscan need no geometry code here at all - the Targeting System's AOE and Trace tasks already cover them. This plugin contributes only the two shapes Epic does not ship: a multi-socket sweep for a swung weapon, and a path sweep for a moving actor.
UCrimsonHitProfile reports a Data Validation error for a preset with no selection task - the failure is otherwise completely silent.Why sweeps are interpolated
A weapon tip can travel several metres between two frames. A single overlap or trace at its new position simply misses everything it passed through, and the faster the swing or the lower the frame rate, the worse it gets. Both Crimson selection tasks sweep from where the shape was at the previous query to where it is now, sub-stepping when the distance exceeds the shape's radius.
That is also why lowering Query Hz on a profile is close to free: each sweep runs from the previous query, not the previous frame, so the swept volume still covers the whole gap. 30 Hz is a good default for melee and halves the trace cost.
Teleport Distance Threshold is skipped and the history re-baselined.Hit windows and dedup
A hit window is a period during which queries run. It is opened by an animation notify firing an armed profile, or by the Crimson Hit Window ability task, and it owns the state that makes a swing behave like one attack rather than a series of independent frames: the already-hit set, the target budget, and the previous positions the sweep interpolates from.
| Dedup policy | Behaviour | Use for |
|---|---|---|
Once Per Window | An actor is reported at most once for the life of the window | Almost every melee swing, and projectile pierces |
Once Per Interval | An actor becomes eligible again after Dedup Interval seconds | Lingering damage volumes, beams, burning ground |
Every Tick | No dedup at all | When the consumer does its own accumulation |
Default Max Window Duration) and is force-closed with a warning if nothing else closes it.For an attack that is routinely interrupted, prefer the Crimson Hit Window ability task: it is tied to the ability's lifetime and closes even when the ability is canceled.
Why the arc is measured from when the window opened
Crimson Filter: Angle measures against the facing captured at the moment the window opened, not the attacker's live rotation. An attack's arc is decided when it starts; sampling live rotation would let a player spin the camera mid-swing and retroactively sweep in targets who were behind them.
Report-only, and why
The plugin outputs a FCrimsonHitReport and stops. It never builds or applies a UGameplayEffect, and it never executes a GameplayCue - it carries the cue tag and lets you fire it.
This is deliberate. Effect specs are frequently modified between construction and application - by stat systems, augments, buffs - and applying them from inside a detection system would silently bypass all of it. It would also double-fire cues against any the caller's own effect already carries. Detection knows what was hit; your ability knows what that should mean.
Where each piece runs
| Piece | Runs on |
|---|---|
| Shape queries, filtering, dedup, target limits | Server only |
On Hit Targets Resolved, On Hit Window State Changed | Server only |
On Hit Impact Cosmetic | All machines, via an unreliable multicast |
| Ability task completion pins | All machines - empty report on clients, so a predicted graph continues |
| Projectile impact detection and pierce counting | Server only |
| Projectile visual flight | All machines, simulated locally from the replicated launch state |
_Validate surface. The cost is that hit feedback is delayed by roughly half a round trip; the cosmetic multicast exists so impact effects still land promptly on every machine that can see the fight.The server has to be able to see the pose
Because queries run on the server, the sockets a swing sweeps between are read from the server's copy of the animation. That copy is only as current as the mesh's Visibility Based Anim Tick Option allows, and Always Tick Pose And Refresh Bones is the only value that refreshes bone transforms while a mesh is not being rendered. A server renders almost nothing, and on a listen server that includes every other player's character.
It is correct in standalone - one machine, mesh on screen - and wrong for everybody else, which is what makes it look like replication. It is not: the montage replicated fine and the window opened fine.
The plugin corrects this for you.
Force Bone Refresh During Hit Windows (Project Settings > Crimson > Crimson Hit Detection, on by default) holds the attacker's mesh at Always Tick Pose And Refresh Bones while any window is open and restores the mesh's own setting the moment the last one closes, so the cost is paid only during the frames that need it.See also
- Quick Start
- How-To: Projectiles
- API Reference