{"id":109,"date":"2022-02-07T01:52:09","date_gmt":"2022-02-07T01:52:09","guid":{"rendered":"https:\/\/www.thegames.dev\/?p=109"},"modified":"2022-02-07T01:53:48","modified_gmt":"2022-02-07T01:53:48","slug":"gameplay-tag-stack-container","status":"publish","type":"post","link":"https:\/\/www.thegames.dev\/?p=109","title":{"rendered":"Gameplay Tag Stack Container"},"content":{"rendered":"\n<p>Here is a very simple container which allows you to have replicated Gameplay Tags as a Stack Count. Useful for say things like Weapon Ammo, Inventory item count, stat points, etc.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Here is the header file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nUSTRUCT(BlueprintType)\nstruct FKaosGameplayTagStack : public FFastArraySerializerItem\n{\n\tGENERATED_BODY()\n\n\tFKaosGameplayTagStack()\n\t{}\n\n\tFKaosGameplayTagStack(FGameplayTag InTag, int32 InCount)\n\t\t: Tag(InTag)\n\t{\n\t\tTag = InTag;\n\t\tCount = InCount;\n\t}\n\nprivate:\n\tfriend FKaosGameplayTagStackContainer;\n\n\tUPROPERTY()\n\tFGameplayTag Tag;\n\n\tUPROPERTY()\n\tint32 Count = 0;\n\n};\n\n\nUSTRUCT(BlueprintType)\nstruct FKaosGameplayTagStackContainer : public FFastArraySerializer\n{\n\tGENERATED_BODY()\n\n\tFKaosGameplayTagStackContainer() { }\n\npublic:\n\n\tvoid PreReplicatedRemove(const TArrayView&lt;int32&gt; RemovedIndices, int32 FinalSize);\n\tvoid PostReplicatedAdd(const TArrayView&lt;int32&gt; AddedIndices, int32 FinalSize);\n\tvoid PostReplicatedChange(const TArrayView&lt;int32&gt; ChangedIndices, int32 FinalSize);\n\t\n\tbool NetDeltaSerialize(FNetDeltaSerializeInfo&amp; DeltaParms)\n\t{\n\t\treturn FastArrayDeltaSerialize&lt;FKaosGameplayTagStack, FKaosGameplayTagStackContainer&gt;(Stacks, DeltaParms, *this);\n\t}\n\n\t\/* \n\t * Adds count to the tag&#039;s stack\n\t *\/\n\tvoid AddStackCount(FGameplayTag Tag, int32 Count);\n\n\t\/*\n\t * Removes count from the tag&#039;s stack\n\t *\/\n\tvoid RemoveStackCount(FGameplayTag Tag, int32 Count);\n\t\n\t\/* \n\t * Returns true if we have a one or more of the tag in the stack.\n\t *\/\n\tbool HasTag(FGameplayTag Tag) const\n\t{\n\t\treturn TagToCountMap.Contains(Tag);\n\t}\n\t\n\t\/*\n\t * Returns the amount of the stack we have for the supplied tag\n\t *\/\n\tint32 GetStackCount(FGameplayTag Tag) const\n\t{\n\t\treturn TagToCountMap.FindRef(Tag);\n\t}\n\t\n\nprivate:\n\t\/\/ List of gameplay tag stacks. Use the accelerated TagCountMap for checking tag count, etc.\n\tUPROPERTY()\n\tTArray&lt;FKaosGameplayTagStack&gt; Stacks;\n\t\n\t\/\/ Accelerated list for queries\n\tTMap&lt;FGameplayTag, int32&gt; TagCountMap;\n};\n\ntemplate&lt;&gt;\nstruct TStructOpsTypeTraits&lt;FKaosGameplayTagStackContainer&gt; : public TStructOpsTypeTraitsBase2&lt;FKaosGameplayTagStackContainer&gt;\n{\n\tenum\n\t{\n\t\tWithNetDeltaSerializer = true,\n\t};\n};\n<\/pre><\/div>\n\n\n<p>And the cpp file part:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nvoid FKaosGameplayTagStackContainer::AddStackCount(FGameplayTag Tag, int32 Count)\n{\n\tif (Count &gt; 0)\n\t{\n\t\tfor (FKaosGameplayTagStack&amp; Stack : Stacks)\n\t\t{\n\t\t\tif (Stack.Tag == Tag)\n\t\t\t{\n\t\t\t\tconst int32 NewCount = Stack.Count + Count;\n\t\t\t\tStack.Count = NewCount;\n\t\t\t\tTagCountMap&#x5B;Tag] = NewCount;\n\t\t\t\tMarkItemDirty(Stack);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tFKaosGameplayTagStack&amp; NewStack = Stacks.Emplace_GetRef(Tag, Count);\n\t\tMarkItemDirty(NewStack);\n\t\tTagCountMap.Add(Tag, Count);\n\t}\n}\n\nvoid FKaosGameplayTagStackContainer::RemoveStackCount(FGameplayTag Tag, int32 Count)\n{\n\tif (Count &gt; 0)\n\t{\n\t\tfor (auto It = Stacks.CreateIterator(); It; ++It)\n\t\t{\n\t\t\tFKaosGameplayTagStack&amp; Stack = *It;\n\t\t\tif (Stack.Tag == Tag)\n\t\t\t{\n\t\t\t\tif (Stack.Count &lt;= Count)\n\t\t\t\t{\n\t\t\t\t\tIt.RemoveCurrent();\n\t\t\t\t\tTagCountMap.Remove(Tag);\n\t\t\t\t\tMarkArrayDirty();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tconst int32 NewCount = Stack.Count - Count;\n\t\t\t\t\tStack.Count = NewCount;\n\t\t\t\t\tTagCountMap&#x5B;Tag] = NewCount;\n\t\t\t\t\tMarkItemDirty(Stack);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid FKaosGameplayTagStackContainer::PreReplicatedRemove(const TArrayView&lt;int32&gt; RemovedIndices, int32 FinalSize)\n{\n\tfor (const int32 Index : RemovedIndices)\n\t{\n\t\tconst FGameplayTag Tag = Stacks&#x5B;Index].Tag;\n\t\tTagCountMap.Remove(Tag);\n\t}\n}\n\nvoid FKaosGameplayTagStackContainer::PostReplicatedAdd(const TArrayView&lt;int32&gt; AddedIndices, int32 FinalSize)\n{\n\tfor (const int32 Index : AddedIndices)\n\t{\n\t\tconst FKaosGameplayTagStack&amp; Stack = Stacks&#x5B;Index];\n\t\tTagCountMap.Add(Stack.Tag, Stack.Count);\n\t}\n}\n\nvoid FKaosGameplayTagStackContainer::PostReplicatedChange(const TArrayView&lt;int32&gt; ChangedIndices, int32 FinalSize)\n{\n\tfor (const int32 Index : ChangedIndices)\n\t{\n\t\tconst FKaosGameplayTagStack&amp; Stack = Stacks&#x5B;Index];\n\t\tTagCountMap&#x5B;Stack.Tag] = Stack.Count;\n\t}\n}\n\n<\/pre><\/div>\n\n\n<p>To use it, simply add a replicated property somewhere, say for example your player<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nUPROPERTY(Replicated)\nFKaosGameplayTagStackContainer GameplayStats;\n<\/pre><\/div>\n\n\n<p>And you can use it like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Relevant Code:; notranslate\" title=\"Relevant Code:\">\nvoid AMyCharacter::AddStatTagCount(FGameplayTag Tag, int32 Count)\n{\n   GameplayStats.AddStack(Tag, Count);\n}\n\nvoid AMyCharacter::RemoveStatTagCount(FGameplayTag Tag, int32 Count)\n{\n   GameplayStats.RemoveStack(Tag, Count);\n}\n\nint32 AMyCharacter::GetStatTagStackCount(FGameplayTag Tag) const\n{\n\treturn GameplayStats.GetStackCount(Tag);\n}\n\nbool AMyCharacter::HasStatTag(FGameplayTag Tag) const\n{\n\treturn GameplayStats.ContainsTag(Tag);\n}\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Hopefully people find this helpful and useful.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here is a very simple container which allows you to have replicated Gameplay Tags as a Stack Count. Useful for say things like Weapon Ammo, Inventory item count, stat points, etc. Here is the header file: And the cpp file part: To use it, simply add a replicated property somewhere, say for example your player <a href=\"https:\/\/www.thegames.dev\/?p=109\" class=\"more-link\">&#8230;<span class=\"screen-reader-text\">  Gameplay Tag Stack Container<\/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":[3,4],"tags":[],"class_list":["post-109","post","type-post","status-publish","format-standard","hentry","category-game-framework","category-gameplay-ability-system"],"rise-blocks_total_comments":0,"rise-blocks_categories":[{"term_id":3,"name":"Game Framework","slug":"game-framework","term_group":0,"term_taxonomy_id":3,"taxonomy":"category","description":"Unreal Engine Game Framework","parent":2,"count":2,"filter":"raw","cat_ID":3,"category_count":2,"category_description":"Unreal Engine Game Framework","cat_name":"Game Framework","category_nicename":"game-framework","category_parent":2},{"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}],"rise-blocks_excerpt":"Here is a very simple container which allows you to have replicated Gameplay Tags as a Stack Count. Useful for say things like Weapon Ammo, Inventory item count, stat points, etc. Here is the header file: And the cpp file part: To use it, simply add a replicated property somewhere, say for example your player And you can use it..","_links":{"self":[{"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts\/109","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=109"}],"version-history":[{"count":2,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts\/109\/revisions"}],"predecessor-version":[{"id":111,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=\/wp\/v2\/posts\/109\/revisions\/111"}],"wp:attachment":[{"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=109"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=109"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thegames.dev\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}