In this lesson, you will learn how to move beyond simple flat-value attribute changes by using UGameplayEffectExecutionCalculation to perform complex, logic-driven math during a Gameplay Effect's application.
The Problem with Simple Modifiers
Usually, when you define a Gameplay Effect, you use a simple "Additive" or "Multiplicative" operation on an attribute (like Health). However, game logic is rarely that simple. For example, damage calculation often requires looking at the attacker's Strength attribute, the defender's Armor attribute, and perhaps a random critical hit multiplier. You cannot do this with a static Gameplay Effect; you need custom code.
The Execution Calculation Approach
A GameplayEffectExecutionCalculation allows you to write C++ logic that runs the moment a Gameplay Effect is applied. It acts as a bridge where you can safely pull data from both the source (the attacker) and the target (the defender).
To implement this, you override the Execute_Implementation function. Within this function, you define Capture Definitions, which tell the system which attributes you intend to read.
// Example: Capturing Attributes
struct FMyDamageStatics {
DECLARE_ATTRIBUTE_CAPTUREDEF(Armor);
DECLARE_ATTRIBUTE_CAPTUREDEF(AttackPower);
FMyDamageStatics() {
DEFINE_ATTRIBUTE_CAPTUREDEF(UMyAttributeSet, Armor, Target, false);
DEFINE_ATTRIBUTE_CAPTUREDEF(UMyAttributeSet, AttackPower, Source, true);
}
};
Once the attributes are captured using an FGameplayEffectCustomExecutionParameters object, you can perform your math:
void UMyDamageExecution::Execute_Implementation(...) const {
float AttackPower = 0.0f;
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(Statics().AttackPowerDef, EvaluateParameters, AttackPower);
float Armor = 0.0f;
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(Statics().ArmorDef, EvaluateParameters, Armor);
// Perform custom logic: Damage = Power - (Armor * 0.5)
float FinalDamage = FMath::Max(0.0f, AttackPower - (Armor * 0.5f));
// Apply the output to the target
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(UMyAttributeSet::GetHealthAttribute(), EGameplayModOp::Additive, -FinalDamage));
}
By decoupling the math from the Gameplay Effect data asset, you create a modular system where you can swap out formulas (like different damage types) without changing the underlying attributes.
Key Takeaway: Use Execution Calculations to perform dynamic, multi-attribute arithmetic that goes beyond simple static modifiers, allowing for complex game rules like armor penetration or scaling damage.