tranek / GASDocumentation

My understanding of Unreal Engine 5's GameplayAbilitySystem plugin with a simple multiplayer sample project.
MIT License
4.41k stars 809 forks source link

Attribute Modifiers Guarded by Tags Not Testable -- Any Ideas? #63

Closed GuyPaddock closed 3 years ago

GuyPaddock commented 3 years ago

Apologies for asking this here, since it's really more of a support question that belongs in the UE4 Answer Hub, but there doesn't seem to be anyone over there answering GAS-related questions, and I think this might be something quick I'm completely missing.

I'm working on a public plug-in for UE4 that implements Pathfinder 2e on the GAS, and writing some specs as part of developing that project since we need to make sure we can keep all the math with stacking, modifiers, etc. straight before the project gets super large.

Anyway, after some initial stops and starts, testing has been going relatively smoothly until I tried to write a test for a Gameplay Effect that calculates a boost to the character's "key ability". We've implemented things such that each of the abilities of the character (Strength, Dexterity, Intelligence, etc.) and their modifiers are Attributes in the Attribute Set; so, there are 6 x 2 = 12 attributes total. image

Then, we represent the character's "key ability" using a tag on the character's ASC: image

To calculate the boost, we have an Infinite GE (GE_CalcKeyAbilityBoost) that has one modifier per attribute, invoking a custom MMC that encapsulates the boost logic (+2 if attribute is < 18, +1 thereafter). Each modifier is guarded by its corresponding key ability tag; for example, for the strength attribute: image

Then we have class-based Infinite GEs that apply the appropriate tags to the character based on the key ability of their class (e.g. warriors have Strength as a key ability, mages have Intelligence, etc). That all seems to work in the game, but getting this to work in a spec/test has been a nightmare. For whatever reason, the effect of an ability boost doesn't seem to "stick" to the attribute score -- neither the base nor current value of the attribute is boosted after the GE that applies the boost is made active on the character (I would expect the current value to increase with the boost, since it's an infinite GE).

Initially, I was adding the tag as a loose tag, but I read the part here about how that doesn't replicate, and I figured that perhaps replication was necessary for tags to be evaluated. Then I tried creating a GE on the fly with the CONSTRUCT_CLASS macro Epic uses in GameplayEffectTests.cpp, but that didn't work; so I read the part here about how GEs that are generated on-the-fly don't work on the server because it can't find the class definition. Eventually I just created a GE that I'm loading in the test that gets applied first, and that is an infinite GE that adds the tags: image

Regardless, it still doesn't work; no matter what, when the test checks the character's current and base value for the attribute, it's still the starting value set by the test. The test logic is otherwise correct -- if I remove the tag requirement on the attribute in GE_CalcKeyAbilityBoost, the MMC magnitude will stick and increment the attribute, and the test will pass. So, this seems heavily related to how the tags are getting evaluated by the GAS during the test.

I have spent several work days stepping through the GAS and the various aggregator logic to see where this is supposed to be getting evaluated, but so far the logic seems as the though the tag checks are being satisfied, yet the value is not sticking in the attribute set.

Any ideas? Is there something else I need to get tags to be evaluated? Am I somehow looking at a stale copy of the attribute set?

The test code is here: https://gist.github.com/GuyPaddock/ff8dcba1d30b5e3751c1226f24e24e56

It depends on other code from the project: https://github.com/OpenPF2/PF2Core/tree/feature/specs-and-unit-tests/Source/OpenPF2Core/Private/Tests

GuyPaddock commented 3 years ago

So, I take it back... it doesn't seem like tags are evaluated properly by an Infinite GE that has modifiers that are guarded by tags granted by another infinite GE. Even in the game, this isn't working.

image

GuyPaddock commented 3 years ago

I've posted this as an engine bug: https://answers.unrealengine.com/questions/1050416/ge-modifiers-that-require-tags-on-source-or-target.html