claude-code-arcane 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +54 -6
  3. package/agents/game/ue-blueprint-specialist.md +125 -0
  4. package/agents/game/ue-gas-specialist.md +133 -0
  5. package/agents/game/ue-umg-specialist.md +131 -0
  6. package/dist/cli.js +5 -0
  7. package/docs/SKILLS-CATALOG.md +42 -3
  8. package/docs/USER-GUIDE.md +2 -2
  9. package/hooks/detect-unreal.sh +90 -0
  10. package/package.json +1 -1
  11. package/profiles/unreal-dev.yaml +97 -0
  12. package/rules/gamedev/unreal-code.md +125 -0
  13. package/skills/install-mcp/SKILL.md +135 -46
  14. package/skills/install-mcp/references/unreal-operations.md +55 -0
  15. package/skills/ue-actor-component-architecture/SKILL.md +509 -0
  16. package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
  17. package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
  18. package/skills/ue-ai-navigation/SKILL.md +526 -0
  19. package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
  20. package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
  21. package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
  22. package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
  23. package/skills/ue-animation-system/SKILL.md +521 -0
  24. package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
  25. package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
  26. package/skills/ue-async-threading/SKILL.md +433 -0
  27. package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
  28. package/skills/ue-async-threading/references/threading-patterns.md +345 -0
  29. package/skills/ue-audio-system/SKILL.md +527 -0
  30. package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
  31. package/skills/ue-blueprints/SKILL.md +134 -0
  32. package/skills/ue-blueprints/references/communication.md +82 -0
  33. package/skills/ue-character-movement/SKILL.md +475 -0
  34. package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
  35. package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
  36. package/skills/ue-cpp-foundations/SKILL.md +533 -0
  37. package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
  38. package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
  39. package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
  40. package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
  41. package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
  42. package/skills/ue-data-assets-tables/SKILL.md +527 -0
  43. package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
  44. package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
  45. package/skills/ue-editor-tools/SKILL.md +523 -0
  46. package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
  47. package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
  48. package/skills/ue-game-features/SKILL.md +477 -0
  49. package/skills/ue-game-features/references/experience-system.md +222 -0
  50. package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
  51. package/skills/ue-gameplay-abilities/SKILL.md +518 -0
  52. package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
  53. package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
  54. package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
  55. package/skills/ue-gameplay-framework/SKILL.md +466 -0
  56. package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
  57. package/skills/ue-input-system/SKILL.md +394 -0
  58. package/skills/ue-input-system/references/cpp-setup.md +131 -0
  59. package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
  60. package/skills/ue-input-system/references/input-action-reference.md +731 -0
  61. package/skills/ue-mass-entity/SKILL.md +476 -0
  62. package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
  63. package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
  64. package/skills/ue-materials-rendering/SKILL.md +526 -0
  65. package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
  66. package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
  67. package/skills/ue-module-build-system/SKILL.md +487 -0
  68. package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
  69. package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
  70. package/skills/ue-naming-conventions/SKILL.md +142 -0
  71. package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
  72. package/skills/ue-naming-conventions/references/content-structure.md +83 -0
  73. package/skills/ue-networking-replication/SKILL.md +452 -0
  74. package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
  75. package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
  76. package/skills/ue-niagara-effects/SKILL.md +531 -0
  77. package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
  78. package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
  79. package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
  80. package/skills/ue-packaging/SKILL.md +116 -0
  81. package/skills/ue-physics-collision/SKILL.md +423 -0
  82. package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
  83. package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
  84. package/skills/ue-procedural-generation/SKILL.md +505 -0
  85. package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
  86. package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
  87. package/skills/ue-project-context/SKILL.md +305 -0
  88. package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
  89. package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
  90. package/skills/ue-serialization-savegames/SKILL.md +524 -0
  91. package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
  92. package/skills/ue-state-trees/SKILL.md +489 -0
  93. package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
  94. package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
  95. package/skills/ue-testing-debugging/SKILL.md +520 -0
  96. package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
  97. package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
  98. package/skills/ue-ui-umg-slate/SKILL.md +431 -0
  99. package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
  100. package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
  101. package/skills/ue-world-level-streaming/SKILL.md +518 -0
  102. package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
  103. package/templates/gamedev/unreal-project-context.md +107 -0
@@ -0,0 +1,397 @@
1
+ # GameplayEffect Reference
2
+
3
+ Configuration guide for `UGameplayEffect`: duration policies, modifier types, stacking rules,
4
+ execution calculations, periodic effects, and conditional effects.
5
+
6
+ Source: `GameplayEffect.h` (UE5.3+, modular GE component architecture)
7
+
8
+ ---
9
+
10
+ ## Duration Policies (`EGameplayEffectDurationType`)
11
+
12
+ | Value | Behavior |
13
+ |-------|----------|
14
+ | `Instant` | Executes once, modifies base value permanently, never enters the active container |
15
+ | `HasDuration` | Active for a set time, then removed; modifies current value temporarily |
16
+ | `Infinite` | Active until `RemoveActiveGameplayEffect` is called; use for passive bonuses |
17
+
18
+ Instant effects call `PostGameplayEffectExecute` on the AttributeSet; duration/infinite effects
19
+ do not (they work through aggregators on the current value).
20
+
21
+ ---
22
+
23
+ ## Modifier Operations (`EGameplayModOp`)
24
+
25
+ The modifier equation is evaluated in this order across all active modifiers:
26
+ ```
27
+ Final = ((BaseValue + AddBase) * MultiplyAdditive / DivideAdditive * MultiplyCompound) + AddFinal
28
+ ```
29
+
30
+ | Op | Enum | Effect |
31
+ |----|------|--------|
32
+ | `Additive` | `EGameplayModOp::Additive` | Adds to the attribute (+10 hp) |
33
+ | `Multiplicative` | `EGameplayModOp::Multiplicative` | Multiplies (1.25x damage) |
34
+ | `Division` | `EGameplayModOp::Division` | Divides; applied as additive in denominator |
35
+ | `Override` | `EGameplayModOp::Override` | Replaces the attribute value entirely |
36
+
37
+ ---
38
+
39
+ ## Magnitude Calculation Types (`EGameplayEffectMagnitudeCalculation`)
40
+
41
+ ### ScalableFloat (most common)
42
+ A constant or level-scaled float. Supply a `FScalableFloat` backed optionally by a CurveTable:
43
+
44
+ ```
45
+ Modifier: Health
46
+ Operation: Additive
47
+ Magnitude Type: ScalableFloat
48
+ Scalable Float Magnitude: -50.0 (or reference a CurveTable row for level scaling)
49
+ ```
50
+
51
+ ### AttributeBased
52
+ Derives magnitude from another attribute. Formula:
53
+ ```
54
+ (Coefficient * (PreMultiplyAdditive + [Attribute Value])) + PostMultiplyAdditive
55
+ ```
56
+
57
+ ```
58
+ Magnitude Type: AttributeBased
59
+ Backing Attribute: SourceObject.AttackPower (capture from Source or Target)
60
+ Attribute Calculation Type: AttributeMagnitude (final evaluated value)
61
+ Coefficient: 1.0
62
+ ```
63
+
64
+ `EAttributeBasedFloatCalculationType` options:
65
+ - `AttributeMagnitude`: Final current value (includes active modifiers)
66
+ - `AttributeBaseValue`: Permanent base value only
67
+ - `AttributeBonusMagnitude`: Final - Base (modifier contribution only)
68
+
69
+ ### CustomCalculationClass
70
+ Runs a `UGameplayModMagnitudeCalculation` subclass for arbitrary logic:
71
+
72
+ ```cpp
73
+ UCLASS()
74
+ class UMyDamageMagnitudeCalc : public UGameplayModMagnitudeCalculation
75
+ {
76
+ GENERATED_BODY()
77
+ public:
78
+ UMyDamageMagnitudeCalc();
79
+
80
+ virtual float CalculateBaseMagnitude_Implementation(
81
+ const FGameplayEffectSpec& Spec) const override;
82
+
83
+ private:
84
+ // Declare captures in constructor
85
+ FGameplayEffectAttributeCaptureDefinition AttackPowerDef;
86
+ };
87
+
88
+ UMyDamageMagnitudeCalc::UMyDamageMagnitudeCalc()
89
+ {
90
+ // Capture AttackPower from Source at execution time (not snapshot)
91
+ AttackPowerDef = FGameplayEffectAttributeCaptureDefinition(
92
+ UMyAttackSet::GetAttackPowerAttribute(),
93
+ EGameplayEffectAttributeCaptureSource::Source,
94
+ false /*bSnapshot*/);
95
+ RelevantAttributesToCapture.Add(AttackPowerDef);
96
+ }
97
+
98
+ float UMyDamageMagnitudeCalc::CalculateBaseMagnitude_Implementation(
99
+ const FGameplayEffectSpec& Spec) const
100
+ {
101
+ FAggregatorEvaluateParameters EvalParams;
102
+ EvalParams.SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
103
+ EvalParams.TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();
104
+
105
+ float AttackPower = 0.f;
106
+ GetCapturedAttributeMagnitude(AttackPowerDef, Spec, EvalParams, AttackPower);
107
+ return AttackPower * 1.5f; // Example: 150% of attack power
108
+ }
109
+ ```
110
+
111
+ ### SetByCaller
112
+ The caller sets the magnitude at spec creation time using a tag as the key.
113
+
114
+ In the GE asset:
115
+ ```
116
+ Magnitude Type: SetByCaller
117
+ DataTag: SetByCaller.Damage
118
+ ```
119
+
120
+ In ability/code:
121
+ ```cpp
122
+ FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(DamageEffectClass, Level);
123
+ SpecHandle.Data->SetSetByCallerMagnitude(
124
+ FGameplayTag::RequestGameplayTag("SetByCaller.Damage"), 75.f);
125
+ ApplyGameplayEffectSpecToTarget(Handle, ActorInfo, ActivationInfo, SpecHandle, TargetASC);
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Execution Calculations (`UGameplayEffectExecutionCalculation`)
131
+
132
+ Executions are for complex damage formulas that modify multiple attributes at once.
133
+ They run on instant GEs and fire `PostGameplayEffectExecute` on the AttributeSet.
134
+
135
+ ```cpp
136
+ UCLASS()
137
+ class UMyDamageExecution : public UGameplayEffectExecutionCalculation
138
+ {
139
+ GENERATED_BODY()
140
+ public:
141
+ UMyDamageExecution();
142
+
143
+ virtual void Execute_Implementation(
144
+ const FGameplayEffectCustomExecutionParameters& ExecutionParams,
145
+ FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const override;
146
+
147
+ private:
148
+ FGameplayEffectAttributeCaptureDefinition AttackPowerDef;
149
+ FGameplayEffectAttributeCaptureDefinition ArmorDef;
150
+ };
151
+
152
+ UMyDamageExecution::UMyDamageExecution()
153
+ {
154
+ AttackPowerDef = FGameplayEffectAttributeCaptureDefinition(
155
+ UMyAttackSet::GetAttackPowerAttribute(),
156
+ EGameplayEffectAttributeCaptureSource::Source,
157
+ true /*bSnapshot*/);
158
+
159
+ ArmorDef = FGameplayEffectAttributeCaptureDefinition(
160
+ UMyDefenseSet::GetArmorAttribute(),
161
+ EGameplayEffectAttributeCaptureSource::Target,
162
+ false);
163
+
164
+ RelevantAttributesToCapture.Add(AttackPowerDef);
165
+ RelevantAttributesToCapture.Add(ArmorDef);
166
+ }
167
+
168
+ void UMyDamageExecution::Execute_Implementation(
169
+ const FGameplayEffectCustomExecutionParameters& ExecutionParams,
170
+ FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
171
+ {
172
+ const FGameplayEffectSpec& Spec = ExecutionParams.GetOwningSpec();
173
+
174
+ FAggregatorEvaluateParameters EvalParams;
175
+ EvalParams.SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
176
+ EvalParams.TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();
177
+
178
+ float AttackPower = 0.f;
179
+ ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(
180
+ AttackPowerDef, EvalParams, AttackPower);
181
+
182
+ float Armor = 0.f;
183
+ ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(
184
+ ArmorDef, EvalParams, Armor);
185
+
186
+ // Example formula: damage = (attack * 2) - armor, min 1
187
+ float Damage = FMath::Max(1.f, (AttackPower * 2.f) - Armor);
188
+
189
+ // Output modifier: subtract from Health on target
190
+ OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(
191
+ UMyHealthSet::GetHealthAttribute(),
192
+ EGameplayModOp::Additive,
193
+ -Damage));
194
+ }
195
+ ```
196
+
197
+ In the GE asset, add this class to `Executions` array (replaces individual Modifiers for complex
198
+ calculations).
199
+
200
+ ---
201
+
202
+ ## Stacking
203
+
204
+ ### Stacking Type (`EGameplayEffectStackingType`)
205
+
206
+ | Value | Behavior |
207
+ |-------|----------|
208
+ | `None` | No stacking; each application is a separate active effect |
209
+ | `AggregateBySource` | One stack group per source ASC applying the effect |
210
+ | `AggregateByTarget` | One stack group regardless of source; all sources share one stack |
211
+
212
+ ### Stack Limit
213
+
214
+ Set `StackLimitCount` in the GE asset. A value of 0 means unlimited.
215
+
216
+ ### Duration Policy While Stacking (`EGameplayEffectStackingDurationPolicy`)
217
+
218
+ | Value | Behavior |
219
+ |-------|----------|
220
+ | `RefreshOnSuccessfulApplication` | Duration resets on each successful stack add |
221
+ | `NeverRefresh` | Duration is set at first application, never extended |
222
+ | `ExtendDuration` | Each new stack adds the spec's full duration to remaining time |
223
+
224
+ ### Expiration Policy (`EGameplayEffectStackingExpirationPolicy`)
225
+
226
+ | Value | Behavior |
227
+ |-------|----------|
228
+ | `ClearEntireStack` | All stacks removed when the effect expires |
229
+ | `RemoveSingleStackAndRefreshDuration` | Decrement by 1 and restart duration |
230
+ | `RefreshDuration` | Duration refreshes (effectively infinite until manually removed) |
231
+
232
+ ### Reading Stack Count at Runtime
233
+
234
+ ```cpp
235
+ // By active handle:
236
+ int32 StackCount = AbilitySystemComponent->GetCurrentStackCount(ActiveHandle);
237
+
238
+ // By query:
239
+ FGameplayEffectQuery Query = FGameplayEffectQuery::MakeQuery_MatchAllOwningTags(
240
+ FGameplayTagContainer(PoisonEffectTag));
241
+ int32 TotalStacks = AbilitySystemComponent->GetAggregatedStackCount(Query);
242
+
243
+ // Update SetByCaller on active stacking effect:
244
+ AbilitySystemComponent->UpdateActiveGameplayEffectSetByCallerMagnitude(
245
+ ActiveHandle,
246
+ FGameplayTag::RequestGameplayTag("SetByCaller.StackDamage"),
247
+ NewDamageValue);
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Periodic Effects (Damage Over Time)
253
+
254
+ Set in the GE asset:
255
+ ```
256
+ Duration Policy: HasDuration
257
+ Duration Magnitude: 10.0 (total duration in seconds)
258
+ Period: 1.0 (execute every 1 second)
259
+ Execute Periodic Effect on Application: true/false
260
+ ```
261
+
262
+ `EGameplayEffectStackingPeriodPolicy` controls what happens to the period timer on stack add:
263
+ - `ResetOnSuccessfulApplication`: Timer resets to full period on each stack
264
+ - `NeverReset`: Timer continues uninterrupted
265
+
266
+ Period callbacks on the ASC:
267
+ ```cpp
268
+ // Called on server when a periodic GE executes on self:
269
+ AbilitySystemComponent->OnPeriodicGameplayEffectExecuteDelegateOnSelf.AddUObject(
270
+ this, &AMyCharacter::OnPeriodicEffectExecuted);
271
+ ```
272
+
273
+ ---
274
+
275
+ ## Conditional Effects (`FConditionalGameplayEffect`)
276
+
277
+ Apply secondary effects only when a primary execution succeeds:
278
+
279
+ ```cpp
280
+ // In GE asset, set up Executions[0].ConditionalGameplayEffects:
281
+ FConditionalGameplayEffect ConditionalEntry;
282
+ ConditionalEntry.EffectClass = UMyBurnEffect::StaticClass();
283
+ ConditionalEntry.RequiredSourceTags.AddTag(
284
+ FGameplayTag::RequestGameplayTag("Ability.FireType")); // Source must have this tag
285
+ ```
286
+
287
+ The conditional effect is applied to the same target as the parent execution.
288
+
289
+ ---
290
+
291
+ ## Immunity
292
+
293
+ Block specific GEs from applying using the `UImmunityGameplayEffectComponent` (UE 5.3+).
294
+ In the GE asset, add this component and configure its tag query to match incoming GE source tags.
295
+
296
+ `GrantedApplicationImmunityTags` (deprecated since UE 5.3) was the legacy property for this.
297
+ New code should use `UImmunityGameplayEffectComponent` in the GE component list instead.
298
+
299
+ When an ASC has this GE active, any incoming GE matching the immunity query is blocked.
300
+ The `OnImmunityBlockGameplayEffectDelegate` fires on the ASC when a block occurs:
301
+
302
+ ```cpp
303
+ AbilitySystemComponent->OnImmunityBlockGameplayEffectDelegate.AddUObject(
304
+ this, &AMyCharacter::OnImmunityBlockGE);
305
+
306
+ void AMyCharacter::OnImmunityBlockGE(
307
+ const FGameplayEffectSpec& BlockedSpec,
308
+ const FActiveGameplayEffect* ImmunityEffect)
309
+ {
310
+ // Log or trigger "immune" visual feedback
311
+ }
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Querying Active Effects
317
+
318
+ ```cpp
319
+ // Get all active effect handles matching a query:
320
+ FGameplayEffectQuery Query;
321
+ Query.EffectTagQuery = FGameplayTagQuery::MakeQuery_MatchAnyTags(
322
+ FGameplayTagContainer(FGameplayTag::RequestGameplayTag("Effect.Type.Buff")));
323
+
324
+ TArray<FActiveGameplayEffectHandle> Handles =
325
+ AbilitySystemComponent->GetActiveEffects(Query);
326
+
327
+ // Get time remaining:
328
+ TArray<float> Remaining = AbilitySystemComponent->GetActiveEffectsTimeRemaining(Query);
329
+
330
+ // Remove all matching:
331
+ AbilitySystemComponent->RemoveActiveEffects(Query);
332
+
333
+ // Remove those with specific granted tags:
334
+ AbilitySystemComponent->RemoveActiveEffectsWithGrantedTags(
335
+ FGameplayTagContainer(FGameplayTag::RequestGameplayTag("Buff.Speed")));
336
+
337
+ // Remove those with specific applied source tags:
338
+ AbilitySystemComponent->RemoveActiveEffectsWithSourceTags(
339
+ FGameplayTagContainer(FGameplayTag::RequestGameplayTag("Effect.Poison")));
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Effect Application Callbacks
345
+
346
+ ```cpp
347
+ // Any GE applied to self (server-side):
348
+ AbilitySystemComponent->OnGameplayEffectAppliedDelegateToSelf.AddUObject(
349
+ this, &AMyCharacter::OnEffectApplied);
350
+
351
+ void AMyCharacter::OnEffectApplied(
352
+ UAbilitySystemComponent* Source,
353
+ const FGameplayEffectSpec& Spec,
354
+ FActiveGameplayEffectHandle Handle)
355
+ {
356
+ // React to any applied effect
357
+ // Use Spec.Def->DurationPolicy to determine if instant/duration/infinite
358
+ UE_LOG(LogTemp, Log, TEXT("Effect applied: %s"), *GetNameSafe(Spec.Def));
359
+ }
360
+
361
+ // Duration-based GE added (client + server):
362
+ AbilitySystemComponent->OnActiveGameplayEffectAddedDelegateToSelf.AddUObject(
363
+ this, &AMyCharacter::OnActiveEffectAdded);
364
+
365
+ // GE removed — subscribe per active effect handle after applying:
366
+ FOnActiveGameplayEffectRemoved_Info* RemovalDelegate =
367
+ AbilitySystemComponent->OnGameplayEffectRemoved_InfoDelegate(ActiveHandle);
368
+ if (RemovalDelegate)
369
+ {
370
+ RemovalDelegate->AddUObject(this, &AMyCharacter::OnEffectRemoved);
371
+ }
372
+
373
+ void AMyCharacter::OnEffectRemoved(const FGameplayEffectRemovalInfo& RemovalInfo)
374
+ {
375
+ // RemovalInfo.ActiveEffect holds the effect that was removed
376
+ // RemovalInfo.bPrematureRemoval is true if removed before natural expiry
377
+ }
378
+ ```
379
+
380
+ ---
381
+
382
+ ## UE5.3+ Modular GE Components
383
+
384
+ Since UE 5.3, `UGameplayEffect` uses `UGameplayEffectComponents` instead of monolithic
385
+ properties for many behaviors. Legacy properties still work (the system auto-upgrades via
386
+ `PostCDOCompiled`), but new GEs should prefer the component approach in the editor.
387
+
388
+ Key components include:
389
+ - `UAdditionalEffectsGameplayEffectComponent` — conditional and chained GEs
390
+ - `UBlockAbilityTagsGameplayEffectComponent` — block abilities while active
391
+ - `UTargetTagsGameplayEffectComponent` — grant tags to the target actor while active
392
+ - `UImmunityGameplayEffectComponent` — immunity to incoming GEs
393
+ - `UTargetTagRequirementsGameplayEffectComponent` — required/ignored tags on target for application/continuation
394
+
395
+ These replace what was previously set directly on `UGameplayEffect` properties. When
396
+ reading older code, map properties like `GrantedTags`, `InhibitionTags`, and
397
+ `ApplicationTagRequirements` to their respective component equivalents.