Skip to content

Resource Recovery

Summary: The UResourceRecoveryComponent manages passive regeneration of Health, Stamina, and Resonance using infinite-duration GameplayEffects. This document explains the recovery architecture, configuration, and integration with combat systems.


Why GE-Based Recovery?

Using GameplayEffects for recovery provides: - GAS Integration: Recovery interacts naturally with buffs, debuffs, and tags - Attribute-Driven: Recovery rates are attributes that can be modified by equipment - Tag Blocking: Combat states can block recovery via gameplay tags - Consistent Timing: GE periodic ticks ensure predictable regeneration


Architecture

+---------------------------+
| UResourceRecoveryComponent|  On Character pawn
+---------------------------+
         |
         | Applies infinite-duration GEs
         v
+---------------------------+     +---------------------------+
| HealthRecoveryEffect      |     | StaminaRecoveryEffect     |
| (Periodic: 0.5s)          |     | (Periodic: 0.5s)          |
+---------------------------+     +---------------------------+
         |                                   |
         v                                   v
+---------------------------+     +---------------------------+
| Modifies Health by:       |     | Modifies Stamina by:      |
| HealthRecoveryRate * 0.5  |     | StaminaRecoveryRate * 0.5 |
+---------------------------+     +---------------------------+

                    +---------------------------+
                    | ResonanceRecoveryEffect   |
                    | (Periodic: 0.5s)          |
                    +---------------------------+
                              |
                              v
                    +---------------------------+
                    | Modifies Resonance by:    |
                    | ResonanceRecoveryRate*0.5 |
                    +---------------------------+

Recovery Formula

Recovery Per Tick = RecoveryRate * Period

Example:
+---------------------+--------+
| Recovery Rate       | 10/sec |
| Effect Period       | 0.5s   |
+---------------------+--------+
| Recovery Per Tick   | 5      |
| Recovery Per Second | 10     |
+---------------------+--------+

The 0.5s period provides responsive recovery while minimizing network traffic and effect evaluations.


Component API

Control Methods

Method Action
InitializeRecovery() Called on BeginPlay, starts all recovery
StartHealthRecovery() Applies health GE if not already active
StartStaminaRecovery() Applies stamina GE if not already active
StartResonanceRecovery() Applies resonance GE if not already active
StartAllRecovery() Convenience method for all three
StopHealthRecovery() Removes health recovery GE
StopStaminaRecovery() Removes stamina recovery GE
StopResonanceRecovery() Removes resonance recovery GE
StopAllRecovery() Removes all recovery effects

Duplicate Prevention

Each Start*Recovery() method checks for the corresponding tag before applying:

Stats.Effects.Resource.HealthRecovery
Stats.Effects.Resource.StaminaRecovery
Stats.Effects.Resource.ResonanceRecovery

If the tag is already present, the effect is not reapplied.


GameplayEffect Configuration

Structure

+----------------------------------+
| Recovery Effect Properties       |
+----------------------------------+
| Duration Policy: Infinite        |
| Period: 0.5 seconds              |
| Execute Periodic Effect on Apply |
+----------------------------------+

+----------------------------------+
| Modifier                         |
+----------------------------------+
| Attribute: Health (or Stamina)   |
| Modifier Op: Additive            |
| Magnitude Type: Attribute Based  |
| Backing Attribute: *RecoveryRate |
| Coefficient: 0.5 (= period)      |
+----------------------------------+

+----------------------------------+
| Granted Tags                     |
+----------------------------------+
| Stats.Effects.Resource.*Recovery |
+----------------------------------+

Recovery Rate Attributes

Definitions

Attribute Category Default Purpose
HealthRecoveryRate Recovery Rates HP regenerated per second
StaminaRecoveryRate Recovery Rates Stamina regenerated per second
ResonanceRecoveryRate Recovery Rates Mana regenerated per second

Modification Sources

Source How It Works
Equipment Items with +X HealthRecoveryRate modifier
Buffs Temporary GEs that boost recovery attributes
Character Class Base values set via class default GE
Level Scaling Secondary attribute calculation GE
Auras Persistent effects from passive skills

Combat Integration

Blocking During Stagger

Poise Broken
     |
     v
+---------------------------+
| UPoiseSystemComponent     |
| HandleBrokenState()       |
+---------------------------+
     |
     | Applies PoiseRecoveryBlockEffect
     v
+---------------------------+
| Grants Tag:               |
| Stats.Effects.Recovery    |
|   .Blocked                |
+---------------------------+
     |
     | Recovery effects have this as blocked tag
     v
+---------------------------+
| Recovery ticks skipped    |
| while tag is present      |
+---------------------------+

Ability Integration

Abilities can control recovery for gameplay purposes:

Scenario Implementation
Charge attack Stop stamina recovery during charge, resume on end
Sprint Continuous stamina drain, no recovery while active
Meditation skill Boost recovery rates via temporary GE

Ability Cost & Cooldown (Shared SetByCaller GEs)

Recovery restores resources; abilities spend them. Spending is now standardized on shared, SetByCaller-driven GameplayEffects rather than direct attribute writes — the project-wide convention every new ability follows.

One Shared Cost GE Per Resource

Resource Cost GE How it deducts
Resonance Ge_ResonanceCost_Dynamic SetByCaller magnitude (negative), multiplied by ResonanceCostMultiplier
Stamina Ge_StaminaCost_Dynamic SetByCaller magnitude (negative), multiplied by StaminaCostMultiplier

An ability sets the cost as a SetByCaller magnitude on an outgoing spec of the shared GE and applies it to self. A dual-cost ability (e.g. a body-originated AOE skill) applies both — it checks each pool up front, then deducts each via its shared GE.

Shared Cooldown GE

Cooldowns use a single GE_Cooldown_Shared for every ability:

  • Duration is passed via the SetByCaller_Cooldown magnitude, so the same GE serves any duration.
  • The per-ability cooldown tag is added to the spec's DynamicGrantedTags, so blocking is per-ability even though the GE is shared. The ability reports that tag through GetCooldownTags().

The Direct-Set Fallbacks Were Retired

Earlier abilities had a direct-set fallback (ConsumeStamina / ConsumeResonance) that wrote the resource attribute directly. Those paths were removed: on a LocalPredicted ability the direct write was a client-reachable write to a replicated attribute, and a silent no-op when misconfigured. The GE path is now mandatory — a missing cost effect class fails activation loudly, and the ability validator errors on a null cost effect class at authoring time. New abilities must use the shared cost/cooldown GEs.


Lifecycle

Initialization

1. BeginPlay()
2. Find ASC via IAbilitySystemInterface on owner
3. Cache ASC reference
4. InitializeRecovery() -> StartAllRecovery()

Effect Handles

The component maintains FActiveGameplayEffectHandle for each recovery type:

HealthRecoveryHandle    -> Active health GE instance
StaminaRecoveryHandle   -> Active stamina GE instance
ResonanceRecoveryHandle -> Active resonance GE instance

These handles enable: - Checking if recovery is active - Removing specific recovery effects - Preventing duplicate applications


Source Reference

Component Location
UResourceRecoveryComponent Source/ProjectEternal/Public/AbilitySystem/Components/ResourceRecoveryComponent.h
Recovery Rate Attributes Source/ProjectEternal/Public/AbilitySystem/EternalAttributeSet.h
Recovery GameplayEffects Content/AbilitySystem/Effects/Recovery/


Refactoring Considerations

Issue Current State Recommendation
No state queries Cannot check if recovery is active Add IsHealthRecoveryActive() etc.
No multiplier support Cannot boost recovery temporarily Add multiplier effect stacking
Immediate recovery No delay after taking damage Add configurable delay timer
No events UI cannot react to recovery state Add OnRecoveryStateChanged delegates

Recent Changes

Date Change Impact
2026-07-07 Shared SetByCaller cost/cooldown convention One shared cost GE per resource (Ge_ResonanceCost_Dynamic / Ge_StaminaCost_Dynamic) deducting via SetByCaller; dual-cost abilities apply both; GE_Cooldown_Shared with SetByCaller_Cooldown duration + per-ability tag in DynamicGrantedTags; direct-set ConsumeStamina/ConsumeResonance fallbacks retired — missing cost GE now fails loudly and the validator errors on a null cost class
2024-Q4 Tag-based duplicate prevention Prevents stacking recovery effects
2024-Q4 Poise system integration Recovery blocked during stagger/break
2024-Q3 Resonance recovery added Full mana regeneration support
2024-Q3 Component moved to Character Recovery tied to pawn lifecycle