Death, Downed & Respawn
Goal: turn "health reached zero" into a death that plays out, a bleed-out other players can reverse, and a respawn that puts the player back in the game.
UCrimsonHealthComponent and a granted UCrimsonHealthSet (Vitals: Shield, Barrier & Reservation), and a working interact ability if you want revives (Interaction Integration). Tick Show Plugin Content in the Content Browser's settings to see the shipped death montages.UCrimsonHealthComponent already sends GameplayEvent.Death to the owner's ability system the moment health runs out. Nothing listens to it until you grant one of two abilities - and until something does, StartDeath and FinishDeath are never reached and the character simply stands there at zero health.
| Ability | Grant it to | What the death event means |
|---|---|---|
UCrimsonCoreGameplayAbility_Death | NPCs, summons, anything that just dies | Cancel abilities -> StartDeath -> death montage -> FinishDeath -> destroyed or pooled; the owning client gets a respawn dialog |
UCrimsonCoreGameplayAbility_Downed | Players | Enter a bleed-out first; only a finisher or an expired clock reaches the flow above |
GameplayEvent.Death. Granting both to one ability system activates both on the same death, and the generic one will destroy the pawn out from under the bleed-out. Pick one per ability set.1. Create the death ability
Make a data-only asset from UCrimsonCoreGameplayAbility_Death and set its presentation. Everything about the ability's mechanics - the GameplayEvent.Death trigger, ServerInitiated execution, ReplicateYes, InstancedPerActor, the Ability.Behavior.SurvivesDeath asset tag that stops the pawn's own teardown from canceling it mid-death - is already set in the constructor. Do not change it.
| Property | Default | What it does |
|---|---|---|
DeathMontage | None | Played through the ability's montage task on every machine. MM_Death_Front_01_Montage ships in /CrimsonCore/Characters/Mannequins/Anims/Death/. |
FallbackDeathDurationSeconds | 2.0 | How long the death takes with no montage authored. Zero finishes on the next tick. Ignored while bRagdollOnDeath is on. |
bRagdollOnDeath | true | Hand the body to physics as it dies. On replaces DeathMontage / FallbackDeathDurationSeconds with the two timings below; off leaves the montage path exactly as it was. |
RagdollDelaySeconds | 0.0 | How long the death montage plays before the physics takes over. Zero skips the montage entirely and ragdolls the instant the character dies. |
RagdollDurationSeconds | 3.0 | How long the body lies there after it ragdolls, before FinishDeath. |
RagdollGameplayCueTag | GameplayCue.Crimson.Death.Ragdoll | The persistent cue that carries the ragdoll to every machine. Handled by the GCN_Crimson_Death_Ragdoll asset - see the step below. |
RespawnHeader | "You Died" | Header of the respawn dialog. |
RespawnBody | Empty | Body text. Empty is fine - the header alone reads perfectly well. |
RespawnButtonText | "Respawn" | Label on the dialog's only button. |
RespawnButtonDelaySeconds | 0.0 | Seconds before the button becomes pressable, so a mashed input cannot skip the death animation. |
Right-click in the Content Browser -> Blueprint Class -> expand All Classes -> pick CrimsonCoreGameplayAbility_Death. Name it GA_Death. Open it, and in Class Defaults set DeathMontage and the four respawn texts under the Crimson|Death category. No graph is needed.
Then add GA_Death to a UCrimsonAbilitySet's Granted Gameplay Abilities list and reference that set from UCrimsonNPCData::AbilitySets (NPCs and summons) - see Character Pipeline for where ability sets are granted.
bRagdollOnDeath is on by default, and the ability only adds the cue - the thing that actually simulates each machine's mesh is a Blueprint of UCrimsonCoreGameplayCueNotify_Ragdoll named GCN_Crimson_Death_Ragdoll, sitting in /CrimsonCore/GameplayCues. The plugin registers that folder as a cue path through an Add Gameplay Cue Path action on its game feature, and the cue manager finds handlers by scanning registered paths, not C++ classes: without the asset the corpse simply never falls over. Author it once, by hand, in the Content Browser: navigate to /CrimsonCore/GameplayCues (tick Settings -> Show Plugin Content if the folder is hidden), right-click -> Blueprint Class -> expand All Classes -> search CrimsonCoreGameplayCueNotify_Ragdoll -> Select, and name the new asset exactly GCN_Crimson_Death_Ragdoll. Save it and you are done - it needs no graph and no properties, because the cue tag comes from the parent class.GA_Death, then run VitalsDamage 9999 from the host window. With the ragdoll on, the dummy drops into physics on the host and on every client and is destroyed - or recycled into the pool when its UCrimsonNPCData has bCanBePooled - RagdollDurationSeconds later. With bRagdollOnDeath off it plays the montage on every machine and finishes when the montage ends.2. Create the downed ability for players
UCrimsonCoreGameplayAbility_Downed inherits everything above and inserts a bleed-out in front of it. Author it exactly the same way, from the subclass.
| Property | Default | What it does |
|---|---|---|
DownedMontage | None | One-shot knockdown, played on every machine. Not a loop: when it ends, the animation Blueprint holds the downed pose for as long as the ability system carries Status.Death.Downed. |
GetUpMontage | None | Optional get-up animation. With none authored the downed pose is simply stopped. |
DownedDurationSeconds | 30.0 | How long the character has before the bleed-out kills it. |
DamageBleedOutPenaltySeconds | 5.0 | Seconds taken off the remaining bleed-out by each damaging hit. Zero disables the penalty. |
ReviveHealthPercent | 0.3 | Fraction of effective maximum health (MaxHealth - HealthReserved) a revived character stands up with. |
SelfReviveEventTag | GameplayEvent.Downed.SelfRevive | Gameplay event that revives the character while it is down. |
SelfReviveBuffTags | Empty | Buff tags that revive the character automatically; the effects granting them are removed when spent. |
SelfReviveBuffDelaySeconds | 0.0 | Grace period before a buff revive fires, so the player still sees they went down. |
Same recipe as step 1, with CrimsonCoreGameplayAbility_Downed as the parent. Name it GA_Death_Downed, set the montages and the four numbers under Crimson|Downed, then add it to the ability set referenced from your UCrimsonPawnData::AbilitySets.
UCrimsonCoreDownedComponent on the pawn there is no interaction surface, no replicated bleed-out and no HUD, so a downed state would be invisible and unrecoverable. The ability logs a warning and dies normally instead - look for has no Crimson Downed Component in the Output Log.3. Add the Crimson Downed Component
The component is the interactable, replicated face of a bleeding-out character. Interaction discovery only inspects the primitive it overlapped, which is why this is a sphere on the character rather than something on the actor itself. It sits dark - NoCollision, no overlap events - until the pawn actually goes down.
| Property | Default | What it does |
|---|---|---|
ReviveText / FinishOffText | "Revive" / "Finish Off" | The two interaction prompts. |
ReviveHoldSeconds / FinishOffHoldSeconds | 3.0 / 1.5 | Hold durations. Both options are Hold, never a quick press. |
ReviveAllowedAttitudes | Friendly & Neutral (Support) | Who is offered Revive. |
FinishOffAllowedAttitudes | Hostile Only | Who is offered Finish Off. |
ReviveAbilityClass / FinishOffAbilityClass | UCrimsonCoreGameplayAbility_ReviveDowned / UCrimsonCoreGameplayAbility_FinishOffDowned | Handler abilities granted to the interacting character. Two distinct classes because nearby-interaction grants are cached per class. |
InteractionResponse | ECR_Overlap | How the sphere answers UCrimsonInteractionSettings::InteractionTraceChannel. |
DownedStatusWidgetClass | None | Bleed-out readout, shown to the downed player alone. Leave unset for no HUD. |
DownedStatusSlotTag | HUD.Slot.Downed | UI extension slot the readout is registered at. |
DownedStatusPriority | 0 | Higher displays first when the slot holds more than one widget. |
ECR_Overlap default is right. The SingleLineTrace scan only reports blocking hits: for that strategy set InteractionResponse to ECR_Block and point UCrimsonInteractionSettings::InteractionTraceChannel at the dedicated Crimson_TraceChannel_Interaction, or the sphere will block camera and visibility traces too. See Interaction Integration -> Collision channel + profiles.Open your player character Blueprint -> Components panel -> Add -> search Crimson Downed Component -> drop it under the root (not under the mesh). Set DownedStatusWidgetClass, the hold times and the prompt texts in its Details panel.
For a character you do not own the Blueprint of, add it from an experience instead: an engine UGameFeatureAction_AddComponents entry targeting your pawn class, with UCrimsonCoreDownedComponent as the component class. It attaches to the actor rather than to a named socket, which is what the sphere needs anyway.
VitalsDamage 9999 from the host window. The pawn stops moving but stays solid, showdebug abilitysystem lists Status.Death.Downed on it, and the pawn is not destroyed. Every other client sees the same pose.4. Put the bleed-out readout on the HUD
UCrimsonCoreDownedStatusWidget is registered by the component at HUD.Slot.Downed on the downed player's own client the moment the pawn goes down, and unregistered when the downed state ends. Nothing places it by hand and no other client ever sees it. All three bound widgets are optional, so a Blueprint that simply names them needs no graph at all.
| Bound widget | Type | Filled with |
|---|---|---|
Text_Title | UCommonTextBlock | TitleText ("Downed"), once on construct. |
Text_Countdown | UCommonTextBlock | CountdownFormat ("{0}") with whole seconds remaining, rounded up. |
Bar_BleedOut | UProgressBar | Remaining over DownedDurationSeconds, clamped to 0..1. |
Beyond those three, On Bleed Out Tick(RemainingSeconds, Fraction) fires on every update - and once immediately on construct - for anything else you want to drive (a pulsing vignette, a heartbeat sound), and On Downed Ended fires once as the state ends so you can play a closing animation before the component tears the widget down. The readout refreshes on a UpdateIntervalSeconds timer (default 0.1), never on tick, and refreshes immediately whenever the server moves the end time.
Create a Widget Blueprint whose parent class is CrimsonCoreDownedStatusWidget (User Interface -> Widget Blueprint -> All Classes), name it W_CrimsonDownedStatus, and add a CommonTextBlock named Text_Title, a CommonTextBlock named Text_Countdown and a ProgressBar named Bar_BleedOut. Set it as DownedStatusWidgetClass on the component from step 3.
Then place a CrimsonUIExtensionPoint in your HUD layout with ExtensionPointTag set to HUD.Slot.Downed. Without one the widget registers successfully and appears nowhere, with no error.
DamageBleedOutPenaltySeconds.5. Block abilities while dead or downed
Nothing in C++ stops a dead or downed character from firing abilities - that is content's call, and it has to be made or a corpse can still cast. Status.Death.Downed is a child of Status.Death, so one rule covers both states.
Block on Status.Death either globally, through the UCrimsonAbilityTagRelationshipMapping named by your UCrimsonPawnData, or per ability through its Activation Blocked Tags. Two deliberate exceptions:
- Leave the interact ability unblocked. A reviver is holding their interact ability while they are alive - but a downed player whose interact is blocked cannot be the one reviving anyone, and blocking it project-wide is the usual reason Revive prompts never appear.
- Anything that must work while dead or downed carries `Ability.Behavior.SurvivesDeath`. That asset tag is what exempts an ability from the death gate and from the cancel sweep the death ability runs. Both death abilities already carry it.
HUD widgets built on UCrimsonTaggedWidget can hide themselves the same way with HiddenByTags = Status.Death.
Ability.ActivateFail.IsDead reason; the interact ability still activates.6. Optional: give the player their own way back up
Two self-revive routes exist, both server-side, both ending in the same Revive. On Revived reports the instigator, and an instigator equal to the avatar identifies a self-revive.
- Active - something sends
SelfReviveEventTag(GameplayEvent.Downed.SelfRevive) to the downed character: a consumable's use ability, a Blueprint Send Gameplay Event to Actor, a cheat. - Passive - a gameplay effect grants a tag listed in
SelfReviveBuffTags. The tag is checked on the way down and again whenever one arrives while down, so an ally can buff a downed friend from across the room. The effects granting it are removed when the revive is spent.
Status.Death.Downed blocks ability activation exactly like Status.Death. A consumable's use ability that does not carry the Ability.Behavior.SurvivesDeath asset tag can never activate while its owner is down, so the event is never sent and the item does nothing.In the consumable's use ability (asset tags including Ability.Behavior.SurvivesDeath): Event ActivateAbility -> Get Avatar Actor From Actor Info -> Send Gameplay Event To Actor (Actor = the avatar, Event Tag = GameplayEvent.Downed.SelfRevive) -> End Ability.
For the passive route, author a gameplay effect granting a tag such as Status.Buff.SecondWind and list that tag in GA_Death_Downed's SelfReviveBuffTags. No graph is needed - applying the effect is enough.
7. Verify the whole loop in a networked session
Run Play As Client with two or three clients plus a listen host, and drive the cheats from the machine that owns the character - the vitals cheats on UCrimsonCheatManager are all BlueprintAuthorityOnly, so in a listen-server session run them from the host window.
| Do this | Server | The downed client | Another player nearby |
|---|---|---|---|
VitalsDamage 9999 on an NPC with GA_Death | Runs the ability, calls FinishDeath | - | Sees the montage, then the NPC destroyed or pooled |
DamageSelfDestruct on a player with GA_Death_Downed | Arms the bleed-out timer, replicates bDowned | Pose, no movement, countdown ticking, Status.Death.Downed in showdebug abilitysystem | Sees the pose; the capsule is still solid |
| Walk a party member up to the body | Re-checks the attitude condition on the handler ability | - | Sees a Revive hold prompt and nothing else |
| Complete the Revive hold | ResetForRespawn, health set to ReviveHealthPercent, spawn-activated abilities re-activated | Countdown gone, movement back, abilities work again | Sees the get-up montage |
| Walk a hostile up instead | Same re-check | - | Sees Finish Off, never Revive |
| Let the clock run out | BeginDying with no instigator to credit | Death montage, then the respawn dialog | Sees the death montage |
| Press the dialog's button | ServerRestartPlayer -> a fresh pawn at full health | New pawn, full health, and dying again works immediately | Sees the new pawn spawn |
UCrimsonHealthComponent::InitializeWithAbilitySystem calls UCrimsonHealthSet::ResetForRespawn(), so bOutOfHealth is cleared on the PlayerState-owned set and the second death fires exactly like the first. If the second kill does nothing, the health set was not reset.See also
- Concept: Death, Downed & Respawn - the state machine, who runs where, and the API tables.
- Vitals: Shield, Barrier & Reservation - where the health that reaches zero comes from.
- Interaction Integration - the scan strategies, collision channel and prompt widget the Revive option rides on.
- Character Pipeline - where ability sets are granted, and the NPC object pool a dead NPC returns to.
- GameFeatureActions - adding the downed component to a pawn class you do not own.