#GAS PR Kaos Part 1 - Convenience methods
1 messages ยท Page 1 of 1 (latest)
and ...
maybe instance structs on the context could be useful too
@shell crypt
I do have the code with a custom struct, which would be very easy to move to a PR
not sure they would do that
yeah me neither
but that scalable float one seems good
we have similar one
not as fancy but
static float GetScalableFloatValue(const FScalableFloat& InScalableFloat, int32 Level);```
does the job haha
yeah
this is missing too
static AActor* GetInstigatorFromGameplayEffectSpec(const FGameplayEffectSpec& Spec);`
AActor* UCustomAbilitySystemBlueprintLibrary::GetInstigatorFromGameplayEffectSpec(const FGameplayEffectSpec& Spec)
{
return Spec.GetEffectContext().GetInstigator();
}```
hmm
wouldnt that be a spec handle?
MMC is using spec IIRC
almost MMC BP only
but pretty much can't do withtout it
CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec)
We got a BP Exec too ๐
MMC in BP seems very lack luster
like, the method is const, and the attribute evaluate method wasn't xD
sec
most of the calcs are very simple anyway
and bp ?
this is an exec proxy for BPs
tbf, i really think it should call a native func
i hate that fact its BlueprintNativeEvent
cause that has a cost overhead
mhhhhhhhhhh
float CalculateBaseMagnitude(const FGameplayEffectSpec& Spec) const;```
this should be a normal func
that calls say K2_CalculateBaseMagnitude()
so if you do this in c++ you dont incur the findfunction shit
where is that ?
no relation with our bp exec then
well your one just calls a specific func for bp
with some extra stuff
oh
this is EffectExecutionCalc
not mod mag
but meh bp handling for Executions should be better
yeah
the way you did it feels meh
well it's non existent right now
i know
though i prefer to do these in c++ anyway
but i understand it should be bp accessible
that's the thing yeah
that's not for me anyway, I do mine in c++ too
one of our user created it, and I refined it and included it in narxim's
ie throught some statics ofc
that's why we created a proxy struct
or well just functions
in the execution
/** Struct representing the output of a custom gameplay effect execution. */
USTRUCT(BlueprintType)
struct GAMEPLAYABILITIES_API FGameplayEffectCustomExecutionOutput
{
cause these are marked as bp types
you can literally pass these out
and make wrapper funcs
unlike what was done in your example
oh, I didn't see the output was
I assumed it wasn't as the in param wasn't
yeah, good point
yeah
let me actually think about it
and have a play
maybe engine can have a BPExecutionWrapper
class
to avoid bloating the original EffectExecution
bit like how Behaviour tree does it
like UBTDecorator_BlueprintBase
is a wrapper for BP based bt decorators
same can be applied for EffectExecutions without touching any of the original
could
/**
* Base class for blueprint based decorator nodes. Do NOT use it for creating native c++ classes!
*
* Unlike task and services, decorator have two execution chains:
* ExecutionStart-ExecutionFinish and ObserverActivated-ObserverDeactivated
* which makes automatic latent action cleanup impossible. Keep in mind, that
* you HAVE TO verify is given chain is still active after resuming from any
* latent action (like Delay, Timelines, etc).
*
* Helper functions:
* - IsDecoratorExecutionActive (true after ExecutionStart, until ExecutionFinish)
* - IsDecoratorObserverActive (true after ObserverActivated, until ObserverDeactivated)
*/
like this is what the BP version has
it specificialy says for BP use only
do not make native from it
let me come up with a proof of concept for it
cause i feel that maybe a useful PR
I'll need to create convenience methods to be able to add anything to this struct in bp though
ofc
we can't do anything with it stock
thats the idea of making a bp wrapper class
you shouldnt really be modifiying stuff directly like this
talkling about /** Struct representing the output of a custom gameplay effect execution. */ USTRUCT(BlueprintType) struct FGameplayEffectCustomExecutionOutput
that's why we had a map before, which was parsed and moved over to OutExecutionOutput
void UBPGameplayEffectExecutionCalculation::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, OUT FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
FBP_ExecutionParams BlueprintParams{};
ConvertExecutionParams(ExecutionParams, BlueprintParams);
if (!BlueprintParams.SourceAbilitySystemComponent || !BlueprintParams.TargetAbilitySystemComponent)
{
return;
}
const FGameplayEffectSpec& Spec = ExecutionParams.GetOwningSpec();
TMap<FGameplayAttribute, FBP_ModifierInfo> BlueprintModifiers{};
BPExecute(
ExecutionParams,
BlueprintParams,
Spec,
Spec.GetEffectContext(),
*Spec.CapturedSourceTags.GetAggregatedTags(), // Always valid
*Spec.CapturedSourceTags.GetAggregatedTags(), // Always valid
BlueprintModifiers
);
if (BlueprintModifiers.IsEmpty())
{
return;
}
for (const auto& BpMod : BlueprintModifiers)
{
if (!BpMod.Key.IsValid())
{
UE_LOG(LogAbilitySystemComponent, Warning, TEXT("%s::Execute_Implementation - Attr %s: Invalid attribute, ignore"), *this->GetName(), *BpMod.Key.GetName());
continue;
}
// Validate Magnitude
if (!FMath::IsFinite(BpMod.Value.Magnitude))
{
UE_LOG(LogAbilitySystemComponent, Warning, TEXT("%s::Execute_Implementation - Attr %s: Magnitude is not finite, ignore"), *this->GetName(), *BpMod.Key.GetName());
continue;
}
// Output values
OutExecutionOutput.AddOutputModifier(
FGameplayModifierEvaluatedData(
BpMod.Key,
BpMod.Value.ModifierOp,
BpMod.Value.Magnitude
)
);
}
}```
const FGameplayEffectCustomExecutionParameters& ExecutionParams,
const FBP_ExecutionParams& InParams,
const FGameplayEffectSpec& Spec,
const FGameplayEffectContextHandle& EffectContextHandle,
const FGameplayTagContainer& SourceTags,
const FGameplayTagContainer& TargetTags,
UPARAM(ref) TMap<FGameplayAttribute, FBP_ModifierInfo>& OutModifiers) const
{
}```
I'll leave it as is for now until i'll have time to come up with a better solution
right but again not sure we have to be this specific about it
I kinda hate to have to create more convenience just to accomodate structs being so locked in bp
cause the way i see it, the function should be overridable
and should return some values also like ShouldTriggerCues, etc
cause there is a bit more to it
also
it is right now in the current Exec. The only thing is both output and the execution parameters can't be handled in BP
yeah, there is a bit more
although, I kinda noticed them rn ๐
basically ... make every method under FGameplayEffectCustomExecutionOutput as static convenience functions
o/
Hate a bit that the output is an array too
UE_API const TArray<FGameplayModifierEvaluatedData>& GetOutputModifiers() const;
I mean, it's not a big deal, but it also sucks if you ever want to find a value in there.
Which is probably never happening ... ๐
@shell crypt
void BPExecute(
const FGameplayEffectCustomExecutionParameters& ExecutionParams,
const FBP_ExecutionParams& BPExecutionParams,
const FGameplayEffectSpec& Spec,
const FGameplayEffectContextHandle& EffectContextHandle,
const FGameplayTagContainer& SourceTags,
const FGameplayTagContainer& TargetTags,
UPARAM(ref) FGameplayEffectCustomExecutionOutput& OutExecutionOutput
) const;
UFUNCTION(BlueprintCallable, Category = "ExecutionCalculation")
static void AddOutputModifier(
UPARAM(ref) FGameplayEffectCustomExecutionOutput& ExecutionOutput,
FGameplayAttribute Attribute,
TEnumAsByte<EGameplayModOp::Type> ModifierOp,
float Magnitude
);```
Not commited yet, but seems to be working
no more proxy bp structure
those should be BP exposed
and not private ... ๐
/** Mark that the execution has manually handled the stack count and the GE system should not attempt to automatically act upon it for emitted modifiers */
void MarkStackCountHandledManually();
or one that is BP exposed, and just set the values
you just call this from your helper funcs
I'll do that later on
this is commited, if you wanna have a look
assuming Epic never does it, at least, we have one version that works ๐
take care !
thanks for the feedback btw
ill show you what i kinda was working on but like i said needs to be more fleshed out
if your interested
that's cool too !
Yeah, I see what you meant by Wrapper
that would work too. probably a bit more complex to handle but all in all, similar
I was gonna let people use the evaluate from the target / source asc with the tags if they want to
which is similar, except for the capture
some of those could be pure imo