# Gameplay Ability System - dynamic cooldowns

**URL:** <https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829>\
**Category:** Programming & Scripting\
**Tags:** unreal-engine\
**Created:** [April 10, 2022, 9:46am UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829 "2022-04-10T09:46:14Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![KingPenguinator](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/kingpenguinator/32/615094_2.png) [@KingPenguinator](https://forums.unrealengine.com/u/KingPenguinator)\
**Post date:** [April 10, 2022, 9:46am UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/1 "2022-04-10T09:46:14Z")

</div>

Hello,

We’ve implemented the GAS in our game with basic cooldowns; each GA has a GE\_cooldown with a fixed cooldown value.

How could we make it so the cooldowns are dynamic ?  
IE: the cooldown for a fireball ability is 10 seconds, if the player activates a “boost” the next fireball would have a 20% cooldown reduction, so would be 8 seconds.

One way we could do this would be with ability level table but I don’t think this would be flexible enough for us.

Thanks

---

<div class="post-metadata">

**Author:** ![KingPenguinator](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/kingpenguinator/32/615094_2.png) [@KingPenguinator](https://forums.unrealengine.com/u/KingPenguinator)\
**Post date:** [April 12, 2022, 10:24am UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/2 "2022-04-12T10:24:44Z")

</div>

\*bump

---

<div class="post-metadata">

**Author:** ![L.F.A](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/l.f.a/32/1194525_2.png) [@L.F.A](https://forums.unrealengine.com/u/L.F.A)\
**Post date:** [April 12, 2022, 3:18pm UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/3 "2022-04-12T15:18:18Z")

</div>

This logic requires four sources of information: a gameplay TAG associated with Boosting ability, a node inside your Gameplay Ability ‘Assign set by caller magnitude’, a ‘Data Tag’ (for instance, SetbyCaller.Cooldown), and a gameplay effect (your ability cooldown) with a calculation modifier set to use Caller Magnitude (the Lyra Demo has a blueprint GE\_Damage\_Basic\_SetByCaller already setup for this logic.)

From your GA, check if owning actor (player or even an AI) has a matching tag ‘is Boosting’. If true (player has tag), use a select node and modify the magnitude value of the node Assign set by caller magnitude. Finally set your cooldown GE to calculate magnitude using information from caller.

Take a look at this github page, at chapter 4.5.9.1 SetByCallers:

[tranek/GASDocumentation: My understanding of Unreal Engine 4’s GameplayAbilitySystem plugin with a simple multiplayer sample project. (github.com)](https://github.com/tranek/GASDocumentation#concepts-ge-spec-setbycaller)

Here is the quote:

##### 4.5.9.1 SetByCallers

`SetByCallers` allow the `GameplayEffectSpec` to carry float values associated with a `GameplayTag` or `FName` around. They are stored in their respective `TMaps`: `TMap<FGameplayTag, float>` and `TMap<FName, float>` on the `GameplayEffectSpec`. These can be used to as `Modifiers` on the `GameplayEffect` or as generic means of ferrying floats around. It is common to pass numerical data generated inside of an ability to [`GameplayEffectExecutionCalculations`](https://github.com/tranek/GASDocumentation#concepts-ge-ec) or [`ModifierMagnitudeCalculations`](https://github.com/tranek/GASDocumentation#concepts-ge-mmc) via `SetByCallers`.

| `SetByCaller` Use | Notes |
| --- | --- |
| `Modifiers` | Must be defined ahead of time in the `GameplayEffect` class. Can only use the `GameplayTag` version. If one is defined on the `GameplayEffect` class but the `GameplayEffectSpec` does not have the corresponding tag and float value pair, the game will have a runtime error on application of the `GameplayEffectSpec` and return 0. This is a potential problem for a `Divide` operation. See [`Modifiers`](https://github.com/tranek/GASDocumentation#concepts-ge-mods). |
| Elsewhere | Does not need to be defined ahead of time anywhere. Reading a `SetByCaller` that does not exist on a `GameplayEffectSpec` can return a developer defined default value with optional warnings. |

To assign `SetByCaller` values in Blueprint, use the Blueprint node for the version that you need (`GameplayTag` or `FName`):

[![Assigning SetByCaller](https://d3kjluh73b9h9o.cloudfront.net/original/4X/0/3/b/03b2e6228dae16bf624fdb757bc2ebea4e83fa32.png)](https://github.com/tranek/GASDocumentation/raw/master/Images/setbycaller.png)

To read a `SetByCaller` value in Blueprint, you will need to make custom nodes in your Blueprint Library.

To assign `SetByCaller` values in C++, use the version of the function that you need (`GameplayTag` or `FName`):

void FGameplayEffectSpec::SetSetByCallerMagnitude(FName DataName, float Magnitude);

void FGameplayEffectSpec::SetSetByCallerMagnitude(FGameplayTag DataTag, float Magnitude);

To read a `SetByCaller` value in C++, use the version of the function that you need (`GameplayTag` or `FName`):

float GetSetByCallerMagnitude(FName DataName, bool WarnIfNotFound = true, float DefaultIfNotFound = 0.f) const;

float GetSetByCallerMagnitude(FGameplayTag DataTag, bool WarnIfNotFound = true, float DefaultIfNotFound = 0.f) const;

I recommend using the `GameplayTag` version over the `FName` version. This can prevent spelling errors in Blueprint and `GameplayTags` are more efficient to send over the network when the `GameplayEffectSpec` replicates than `FNames` since the `TMaps` replicate too.

---

<div class="post-metadata">

**Author:** ![KingPenguinator](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/kingpenguinator/32/615094_2.png) [@KingPenguinator](https://forums.unrealengine.com/u/KingPenguinator)\
**Post date:** [April 13, 2022, 7:53am UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/4 "2022-04-13T07:53:45Z")

</div>

Something like this then ?

 ![bp_exec](https://d3kjluh73b9h9o.cloudfront.net/original/4X/9/4/1/941911dceddd59a7a024449e42d5456b02c03dad.png)  
(in GA\_Fireball)

How could I get the value from the GA boost, the one that gives the actor the tag and the 20% CD reduction, and plug that in to the switch ?

Is this sufficient for the GE ? In the Lyra Demo there’s an ExecCalculation, but that seems to be only for attributes, but the data I would use would only be the magnitude and the base CD from the GA

 ![ge](https://d3kjluh73b9h9o.cloudfront.net/original/4X/b/2/2/b22e415289a94df6d28dbf75ef151358c93e035b.png)  
(GE\_Fireball\_Cooldown)

Thanks

---

<div class="post-metadata">

**Author:** ![L.F.A](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/l.f.a/32/1194525_2.png) [@L.F.A](https://forums.unrealengine.com/u/L.F.A)\
**Post date:** [April 13, 2022, 8:23am UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/5 "2022-04-13T08:23:24Z")

</div>

> [@KingPenguinator](#):
>
> boost

In your picture, has matching gameplay tag should be booster effect, not cooldown. You want to give the 20% reduction if booster is still active, correct? Not during booster cooldown.

You are almost there. The booster tag can be assigned to the actor right after executing the booster ability inside Booster GA. To achieve that, you need to use the nodes Add Granted Tag or Add Granted Tags. Make sure the booster tag is removed after finishing the booster effect. For this one, you can use ‘remove gameplay tag’ inside GA or ‘add granted tag’ inside the GE Booster settings (the Action RPG game template has examples of adding granted tags inside GE. These tags will be removed after the effect finishes.)

![image](https://d3kjluh73b9h9o.cloudfront.net/original/4X/c/5/0/c50e2d3833a0e202a06f6aaab609b877e732e042.png)

 ![image](https://d3kjluh73b9h9o.cloudfront.net/original/4X/5/8/2/5822eab739fbe8c0d8dbac0fbb62ee54e9442333.png)

---

<div class="post-metadata">

**Author:** ![KingPenguinator](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/kingpenguinator/32/615094_2.png) [@KingPenguinator](https://forums.unrealengine.com/u/KingPenguinator)\
**Post date:** [April 13, 2022, 11:01am UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/6 "2022-04-13T11:01:56Z")

</div>

My bad, the name I was wasn’t explicit enough, it is indeed the cooldownReduction effect.

Like this ? Or is this too much ?

 ![ga_cooldownReduction](https://d3kjluh73b9h9o.cloudfront.net/original/4X/6/9/6/6963b9a67bbdef24d82baba904b51062f191d884.png)  
(ga\_cooldownReduction)

Does my GE make sense ?

 ![ge_cooldownReduction](https://d3kjluh73b9h9o.cloudfront.net/original/4X/e/7/0/e7083533e6c89cedefd50c401c8d99f270f19cdd.png)  
Is this where I would declare the % of reduction I wanted ?

Also regardless of the magnitude I set to my SetByCallerMagnitude, the CD is always 1 second

---

<div class="post-metadata">

**Author:** ![L.F.A](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/l.f.a/32/1194525_2.png) [@L.F.A](https://forums.unrealengine.com/u/L.F.A)\
**Post date:** [April 13, 2022, 5:41pm UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/7 "2022-04-13T17:41:13Z")

</div>

Good progress, but keep in mind if you add the node ‘add granted tag’ inside GA, there is no need to do it again inside GE. You should pick one or another. The percent reduction is going to be calculated inside the GA Fireball that checks if player has matching tag and also contains the set by caller. The select node shown in GA Fireball contains 1 and 0.8, try something more noticeable, like 10 and 5 sec, after testing you can set back to 1 and 0.8. You may want to add print string nodes to check if the tags are being added/removed timely.

To wrap-up, it is a good practice to create a workflow, or a flowchart with all steps you are envisioning. For instance:

1. Player activates booster
2. GA Booster adds tag booster.cooldownreduction to the player during the booster effect duration.  
2.1. If any other ability reads that tag, perform condition checks and move to true/ false branches.  
2.2 If player executes Fireball, GA Fireball checks if player has matching tag and selects fireball cooldown duration depending on true/false. This info is fed into Fireball GE via set by caller.
3. After 20sec, booster effect ceases and the tag booster.cooldownreduction is removed from player.

---

<div class="post-metadata">

**Author:** ![KingPenguinator](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/kingpenguinator/32/615094_2.png) [@KingPenguinator](https://forums.unrealengine.com/u/KingPenguinator)\
**Post date:** [April 13, 2022, 7:12pm UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/8 "2022-04-13T19:12:40Z")

</div>

I’m sorry I haven’t been clear enough, I say 20% as an example, but the amount of cooldown reduction would depend on the level of the GA\_boost, for example :10%, 20%, 40%, 50% (would be 0% if the tag branch is false). Could this be determined by a table in GE\_cooldown\_reduction ?

 ![GA_fireball](https://d3kjluh73b9h9o.cloudfront.net/original/4X/3/a/0/3a07e560159ac1e30fc1c566554a8d139b7f3f5e.png)  
(ga\_fireball)

I put here 30 for testing the magnitude regardless of if it’s actor has the tag or not, however the cooldown is still one second, I feel like I’m missing something in the GE\_fireball\_cooldown

 ![ge_fireball_cooldown](https://d3kjluh73b9h9o.cloudfront.net/original/4X/e/1/d/e1d5e684f3fbd88c79426d1d7fde6b11f0dc0d61.png)  
(ge\_fireball\_cooldown)

I believe these are my last issues, I think I understand the big picture  
Thank you for you help so far

---

<div class="post-metadata">

**Author:** ![L.F.A](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/l.f.a/32/1194525_2.png) [@L.F.A](https://forums.unrealengine.com/u/L.F.A)\
**Post date:** [April 13, 2022, 7:31pm UTC](https://forums.unrealengine.com/t/gameplay-ability-system-dynamic-cooldowns/522829/9 "2022-04-13T19:31:58Z")

</div>

You can use a curve table, similarly to player level in the Action RPG template. There are two nodes: get ability level, set ability level. Try to update values manually and see what happens. It seems to me these nodes are disabled by default in UE4; thus, you need to modify the source code in C++. I haven’t tested these nodes in UE5, perhaps Epic fixed the code.

It seems that the ability level, by default, is set to follow the player level. So, if you create a logic to level up your player, all abilities will level up accordingly, unless you modify the code in C++. I cannot help you on that. There is a channel that teaches GAS with C++ and also provides source code at git hub.

[UE4 Gameplay Ability System Practical Example – Part 0 Introduction - YouTube](https://www.youtube.com/watch?v=CHK62nIut24&list=PLeEXbS_TaXrAbfoPYSNROqe1fDQfQHTfo)

[UE4 Gameplay Ability System for Blueprint Programmers - Pt 0 - Introduction - YouTube](https://www.youtube.com/watch?v=axsxsFGelqE&list=PLeEXbS_TaXrDlqQv753CpKqDlpNXixFMg)
