{"id":131,"date":"2022-03-19T02:49:22","date_gmt":"2022-03-19T02:49:22","guid":{"rendered":"https:\/\/www.thegames.dev\/?p=131"},"modified":"2022-03-19T02:49:22","modified_gmt":"2022-03-19T02:49:22","slug":"adjusting-durations-cooldowns-of-active-gameplay-effects","status":"publish","type":"post","link":"https:\/\/www.thegames.dev\/?p=131","title":{"rendered":"Adjusting Durations\/Cooldowns of Active Gameplay Effects"},"content":{"rendered":"\n<p>So a common question is, how can i increase\/decrease cooldowns or duration based effects when they are active. I did some research, and came up with what i think is the nicest way to do it, and it uses GameplayEffects to achieve this. <\/p>\n\n\n\n<p>First we need to make a dummy attribute, you can put this in any attribute set you like (i recommend something like PlayerSet or CharacterSet.) <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nUPROPERTY(BlueprintReadOnly, Meta = (HideFromModifiers, AllowPrivateAccess = true))\nFKaosGameplayAttributeData ActiveEffectDuration;\nATTRIBUTE_ACCESSORS(ThisClass, ActiveEffectDuration);\n<\/pre><\/div>\n\n\n<p>This attribute will not show up in your Gameplay Effect BP&#8217;s or anywhere in the editor. (That is what HideFromModifiers does).<\/p>\n\n\n\n<p>Now we do need a few functions in your project specific ASC.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nvoid UKaosAbilitySystemComponent::MarkActiveGameplayEffectDirty(FActiveGameplayEffect* ActiveGE)\n{\n\tif (ActiveGE)\n\t{\n\t\tActiveGameplayEffects.MarkItemDirty(*ActiveGE);\n\t}\n}\n\nvoid UKaosAbilitySystemComponent::CheckActiveEffectDuration(const FActiveGameplayEffectHandle&amp; Handle)\n{\n\tActiveGameplayEffects.CheckDuration(Handle);\n}\n\nFActiveGameplayEffect* UKaosAbilitySystemComponent::GetActiveGameplayEffect_Mutable(const FActiveGameplayEffectHandle Handle)\n{\n\treturn ActiveGameplayEffects.GetActiveGameplayEffect(Handle);\n}\n\nTArray&lt;FActiveGameplayEffectHandle&gt; UKaosAbilitySystemComponent::GetAllActiveEffectHandles() const\n{\n\treturn ActiveGameplayEffects.GetAllActiveEffectHandles();\n}\n\nHeader file:\n\t\/** Return a mutable pointer to the ActiveGameplayEffect from the supplied handle. *\/\n\tFActiveGameplayEffect* GetActiveGameplayEffect_Mutable(FActiveGameplayEffectHandle Handle);\n\n\t\/** Returns all active gameplay effect handles *\/\n\tTArray&lt;FActiveGameplayEffectHandle&gt; GetAllActiveEffectHandles() const;\n\n\t\/** Marks the ActiveGameplayEffect as dirty for replication purposes *\/\n\tvoid MarkActiveGameplayEffectDirty(FActiveGameplayEffect* ActiveGE);\n\n\t\/** Checks the active effect duration and runs any logic, checks to see if the GE is expired and removes it. *\/\n\tvoid CheckActiveEffectDuration(const FActiveGameplayEffectHandle&amp; Handle);\n<\/pre><\/div>\n\n\n<p>These functions expose some things we need, first one allows us to mark a GE as dirty for replication purposes, second one checks the duration of the GE after we manipulate the value. The third one, returns a mutable pointer to the ActiveGameplayEffect, and last, returns a copy of all ActiveEffectHandles.<\/p>\n\n\n\n<p>Now we get on to the actual Gameplay Effect Execution Calculation we will be using.<br>We need to define a struct, which will capture our ActiveEffectDuration attribute.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nstruct FKaosActiveDurationStatics\n{\n\t\/\/Target\n\tFGameplayEffectAttributeCaptureDefinition TargetActiveEffectDurationDef;\n\n\tFKaosActiveDurationStatics()\n\t{\n\t\t\/\/Source captures\n\t\tTargetActiveEffectDurationDef = FGameplayEffectAttributeCaptureDefinition(UKaosPlayerSet::GetActiveEffectDurationAttribute(), EGameplayEffectAttributeCaptureSource::Target, true);\n\t}\n};\n\nstatic FKaosActiveDurationStatics&amp; KaosActiveDurationStatics()\n{\n\tstatic FKaosActiveDurationStatics Statics;\n\treturn Statics;\n}\n<\/pre><\/div>\n\n\n<p>Now we can define the rest of the calculation.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nUKaosActiveEffectDurationExecution::UKaosActiveEffectDurationExecution()\n{\n\t\/\/Source Captures\n\tRelevantAttributesToCapture.Add(KaosActiveDurationStatics().TargetActiveEffectDurationDef);\n}\n\nvoid UKaosActiveEffectDurationExecution::Execute_Implementation(const FGameplayEffectCustomExecutionParameters&amp; ExecutionParams, FGameplayEffectCustomExecutionOutput&amp; OutExecutionOutput) const\n{\n#if WITH_SERVER_CODE\n\tUKaosAbilitySystemComponent* TargetASC = Cast&lt;UKaosAbilitySystemComponent&gt;(ExecutionParams.GetTargetAbilitySystemComponent());\n\n\t\/\/Used to hold the evaluate params for the loop.\n\tFAggregatorEvaluateParameters EvaluateParameters;\n\n\t\/\/Get all active effect handles.\n\tTArray&lt;FActiveGameplayEffectHandle&gt; Handles = TargetASC-&gt;GetAllActiveEffectHandles();\n\n\t\/\/Loop over all active Effect handles.\n\tfor (const FActiveGameplayEffectHandle Handle : Handles)\n\t{\n\t\tFActiveGameplayEffect* ActiveGE = TargetASC-&gt;GetActiveGameplayEffect_Mutable(Handle);\n\n\t\t\/\/Didn&#039;t find an active GE or GE is not duration based, skip it. Only works on duration based GE&#039;s.\n\t\tif (!ActiveGE || ActiveGE-&gt;Spec.Def-&gt;DurationPolicy != EGameplayEffectDurationType::HasDuration)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t\/\/Our new duration (calculated from AttemptCalculateCapturedAttributeMagnitudeWithBase)\n\t\tfloat NewDuration = 0.f;\n\n\t\t\/\/We get the current iterated GE&#039;s asset tags and use this in the calculation\n\t\tFGameplayTagContainer Tags;\n\t\tActiveGE-&gt;Spec.GetAllAssetTags(Tags);\n\n\t\t\/\/Set the evalute params target tags to the current iterated GE&#039;s asset tags.\n\t\tEvaluateParameters.TargetTags = &amp;Tags;\n\n\t\t\/\/Here we run the calculation to get the new duration, passing in the current iterated GE&#039;s duration as a base value, before it gets manipulated.\n\t\tExecutionParams.AttemptCalculateCapturedAttributeMagnitudeWithBase(KaosActiveDurationStatics().TargetActiveEffectDurationDef, EvaluateParameters, ActiveGE-&gt;GetDuration(), NewDuration);\n\n\t\t\/\/We set the GE&#039;s new duration, but clamp it so it is never 0.\n\t\tActiveGE-&gt;Spec.Duration = FMath::Max(NewDuration, SMALL_NUMBER);\n\n\t\t\/\/Mark the GE as dirty, so it can be replicated.\n\t\tTargetASC-&gt;MarkActiveGameplayEffectDirty(ActiveGE);\n \n\t\t\/\/This will remove the GE if it has expired and update the timers if necessary\n\t\tTargetASC-&gt;CheckActiveEffectDuration(Handle);\n\t}\n#endif\n}\n<\/pre><\/div>\n\n\n<p>Most of the code is commented here, but in brief, we iterate all active GE&#8217;s, only get the ones with a duration, then we calculate the new duration, and set it dirty and then check the duration on it (to see if it should expire).<\/p>\n\n\n\n<p>Here is an example GE, that will reduce cooldown by 25% when this GE is applied<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"http:\/\/thegames.dev\/snaps\/UnrealEditor-Win64-DebugGame_DfhBtejBua.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>Hope this helps, any issues or problems, check out my Discord in About Me, or join Unreal Slackers.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>So a common question is, how can i increase\/decrease cooldowns or duration based effects when they are active. I did some research, and came up with what i think is the nicest way to do it, and it uses GameplayEffects to achieve this. First we need to make a dummy attribute, you can put this <a href=\"https:\/\/www.thegames.dev\/?p=131\" class=\"more-link\">&#8230;<span class=\"screen-reader-text\">  Adjusting Durations\/Cooldowns of Active Gameplay Effects<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,2],"tags":[],"class_list":["post-131","post","type-post","status-publish","format-standard","hentry","category-gameplay-ability-system","category-unreal-engine"],"rise-blocks_total_comments":0,"rise-blocks_categories":[{"term_id":4,"name":"Gameplay Ability System","slug":"gameplay-ability-system","term_group":0,"term_taxonomy_id":4,"taxonomy":"category","description":"Unreal Engine's Gameplay Ability System (GAS)","parent":2,"count":16,"filter":"raw","cat_ID":4,"category_count":16,"category_description":"Unreal Engine's Gameplay Ability System (GAS)","cat_name":"Gameplay Ability System","category_nicename":"gameplay-ability-system","category_parent":2},{"term_id":2,"name":"Unreal Engine","slug":"unreal-engine","term_group":0,"term_taxonomy_id":2,"taxonomy":"category","description":"All unreal engine related tutorials, tips and tricks.","parent":0,"count":5,"filter":"raw","cat_ID":2,"category_count":5,"category_description":"All unreal engine related tutorials, tips and tricks.","cat_name":"Unreal Engine","category_nicename":"unreal-engine","category_parent":0}],"rise-blocks_excerpt":"So a common question is, how can i increase\/decrease cooldowns or duration based effects when they are active. I did some research, and came up with what i think is the nicest way to do it, and it uses GameplayEffects to achieve this. First we need to make a dummy attribute, you can put this in any attribute set you..","_links":{"self":[{"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts\/131","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=131"}],"version-history":[{"count":2,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts\/131\/revisions"}],"predecessor-version":[{"id":133,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts\/131\/revisions\/133"}],"wp:attachment":[{"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}