Instantly share code, notes, and snippets.
michaeltchapman/EffectTypes.cpp Secret
CreatedApril 8, 2020 15:16
Save michaeltchapman/e305f6468f302f52a85ca767935afb08 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| #include"EffectTypes.h" | |
| #include"maladius.h" | |
| #include"AbilitySystemGlobals.h" | |
| #include"AbilitySystemComponent.h" | |
| #include"AsyncAbilitySystemComponent.h" | |
| #include"GlobalGameStateBase.h" | |
| #include"GameplayEffect.h" | |
| #include"GameplayAbility.h" | |
| #include"BaseGameplayAbility.h" | |
| #include"BaseCharacter.h" | |
| #include"Spell.h" | |
| boolFMActorFilter::PassesFilter(UAbilitySystemComponent* Source, UAbilitySystemComponent* Target) | |
| { | |
| if (AllowSelf != EMActorFilterMatchType::Skip && ((Source == Target) != (AllowSelf == EMActorFilterMatchType::MustPass))) | |
| { | |
| returnfalse; | |
| } | |
| returntrue; | |
| } | |
| boolFMFactionFilter::PassesFilter(UAbilitySystemComponent* Source, UAbilitySystemComponent* Target) | |
| { | |
| ABaseCharacter* SourceChar = Cast<ABaseCharacter>(Source->GetAvatarActor()); | |
| ABaseCharacter* TargetChar = Cast<ABaseCharacter>(Target->GetAvatarActor()); | |
| if (SourceChar && TargetChar) | |
| { | |
| AGlobalGameStateBase *GameState = Cast<AGlobalGameStateBase>(SourceChar->GetWorld()->GetGameState()); | |
| check(GameState); | |
| EHostility Relationship = GameState->GetHostility(SourceChar->GetFactionIndex(), TargetChar->GetFactionIndex()); | |
| bool FriendlyTest =false; | |
| if (FriendlyFaction == EMFactionFilterMatchType::Skip) | |
| { | |
| FriendlyTest =true; | |
| } | |
| elseif (FriendlyFaction == EMFactionFilterMatchType::MustPass && Relationship == EHostility::E_Friendly) | |
| { | |
| FriendlyTest =true; | |
| } | |
| elseif (FriendlyFaction == EMFactionFilterMatchType::MustFail && Relationship != EHostility::E_Friendly) | |
| { | |
| FriendlyTest =true; | |
| } | |
| bool NeutralTest =false; | |
| if (NeutralFaction == EMFactionFilterMatchType::Skip) | |
| { | |
| NeutralTest =true; | |
| } | |
| elseif (NeutralFaction == EMFactionFilterMatchType::MustPass && Relationship == EHostility::E_Neutral) | |
| { | |
| NeutralTest =true; | |
| } | |
| elseif (NeutralFaction == EMFactionFilterMatchType::MustFail && Relationship != EHostility::E_Neutral) | |
| { | |
| NeutralTest =true; | |
| } | |
| bool HostileTest =false; | |
| if (HostileFaction == EMFactionFilterMatchType::Skip) | |
| { | |
| HostileTest =true; | |
| } | |
| elseif (HostileFaction == EMFactionFilterMatchType::MustPass && Relationship == EHostility::E_Hostile) | |
| { | |
| HostileTest =true; | |
| } | |
| elseif (HostileFaction == EMFactionFilterMatchType::MustFail && Relationship != EHostility::E_Hostile) | |
| { | |
| HostileTest =true; | |
| } | |
| return HostileTest && NeutralTest && FriendlyTest; | |
| } | |
| returntrue; | |
| } | |
| voidFMEffectApplicationContainer::InitialiseEffectContainer(AActor* Source,float VariableLevel,float NormalisedCharge,float VariableRatio,float NormalisedRatio, AActor* AbilityOrigin,float Period,bool bClean) | |
| { | |
| if (UAbilitySystemComponent* ASC =UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Source)) | |
| { | |
| SourceAbilitySystemComponent = ASC; | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GeneratedSpec.IsValid()) | |
| { | |
| if (bClean) | |
| { | |
| EffectItem.GeneratedSpec.Clear(); | |
| } | |
| else { | |
| UE_LOG(LogTemp, Warning,TEXT("GenerateEffectSpecs called on ApplicationContainer that already has generated specs!")); | |
| continue; | |
| } | |
| } | |
| if (*EffectItem.GameplayEffect ==nullptr) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("GenerateEffectSpecs called on ApplicationContainer with invalid GameplayEffect!")); | |
| continue; | |
| } | |
| float Level =GetLevelForEffect(EffectItem, VariableLevel, NormalisedCharge, VariableRatio, NormalisedRatio) * Period; | |
| int32 StackCount = EffectItem.StackCount; | |
| if (AbilityOrigin && Cast<ASpell>(AbilityOrigin) && Cast<ASpell>(AbilityOrigin)->OwningAbility) | |
| { | |
| UBaseGameplayAbility* SourceAbility = Cast<ASpell>(AbilityOrigin)->OwningAbility; | |
| if (SourceAbility) | |
| { | |
| EffectItem.GeneratedSpec = SourceAbility->MakeGameplayEffectSpec(EffectItem.GameplayEffect, Level); | |
| } | |
| } | |
| else { | |
| FGameplayEffectContextHandle ContextHandle = ASC->MakeEffectContext(); | |
| if (AbilityOrigin && Source->GetInstigator()) | |
| { | |
| ContextHandle.AddInstigator(Source->GetInstigator(), AbilityOrigin); | |
| } | |
| else { | |
| ContextHandle.AddInstigator(Source, Source); | |
| } | |
| EffectItem.GeneratedSpec =FGameplayEffectSpecHandle(newFGameplayEffectSpec(EffectItem.GameplayEffect.GetDefaultObject(), ContextHandle, Level)); | |
| } | |
| EffectItem.GeneratedSpec.Data->StackCount = StackCount; | |
| for (FMEffectModifier& Modifier : EffectItem.Modifiers) | |
| { | |
| EffectItem.GeneratedSpec.Data->SetSetByCallerMagnitude(Modifier.ModifierName,GetLevelForStrategy(Modifier.ModifierLevelStrategy, Modifier.ModifierMagnitude, VariableLevel, NormalisedCharge, VariableRatio, NormalisedRatio * Period)); | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("GenerateEffectSpecs called on Source %s with no ASC"), *GetNameSafe(Source)); | |
| } | |
| } | |
| floatFMEffectApplicationContainer::GetLevelForEffect(FMEffectItem &Item,float VariableLevel,float NormalisedCharge,float VariableRatio,float NormalisedRatio) | |
| { | |
| returnGetLevelForStrategy(Item.LevelStrategy, Item.Level, VariableLevel, NormalisedCharge, VariableRatio, NormalisedRatio); | |
| } | |
| floatFMEffectApplicationContainer::GetLevelForStrategy(EMEffectLevelStrategy Strategy,float Base,float VariableLevel,float NormalisedCharge,float VariableRatio,float NormalisedRatio) | |
| { | |
| switch (Strategy) | |
| { | |
| case EMEffectLevelStrategy::Base: | |
| return Base; | |
| case EMEffectLevelStrategy::BaseVarianceCharge: | |
| return Base + VariableLevel*NormalisedCharge; | |
| case EMEffectLevelStrategy::BaseVarianceInvCharge: | |
| return Base + VariableLevel*(1.0f - NormalisedCharge); | |
| case EMEffectLevelStrategy::BaseVarianceRatio: | |
| return Base + VariableRatio*NormalisedRatio; | |
| case EMEffectLevelStrategy::BaseVarianceInvRatio: | |
| return Base + VariableRatio*(1.0f - NormalisedRatio); | |
| case EMEffectLevelStrategy::BaseVarianceInvChargeInvRatio: | |
| return Base + VariableRatio*(1.f - NormalisedRatio) + VariableLevel*(1.f - NormalisedCharge); | |
| case EMEffectLevelStrategy::BaseVarianceChargeInvRatio: | |
| return Base + VariableRatio*(1.f - NormalisedRatio) + VariableLevel*NormalisedCharge; | |
| case EMEffectLevelStrategy::BaseVarianceChargeRatio: | |
| return Base + VariableRatio*NormalisedRatio + VariableLevel*NormalisedCharge; | |
| case EMEffectLevelStrategy::BaseVarianceChargeSquared: | |
| return Base + VariableLevel*NormalisedCharge*NormalisedCharge; | |
| case EMEffectLevelStrategy::BaseVarianceChargeSquaredRatioSquared: | |
| return Base + VariableLevel * NormalisedCharge*NormalisedCharge + VariableRatio * NormalisedRatio*NormalisedRatio; | |
| case EMEffectLevelStrategy::BaseVarianceChargeSquaredInvRatioSquared: | |
| return Base + VariableLevel * NormalisedCharge*NormalisedCharge + VariableRatio * (1.f-NormalisedRatio)*(1.f-NormalisedRatio); | |
| default: | |
| return Base; | |
| break; | |
| } | |
| } | |
| voidFMEffectApplicationContainer::GenerateEffectSpecs(AActor* Source,float LevelOverride, int32 StackOverride, AActor* AbilityOrigin) | |
| { | |
| if (UAbilitySystemComponent* ASC =UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Source)) | |
| { | |
| SourceAbilitySystemComponent = ASC; | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GeneratedSpec.IsValid()) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("GenerateEffectSpecs called on ApplicationContainer that already has generated specs!")); | |
| continue; | |
| } | |
| if (*EffectItem.GameplayEffect ==nullptr) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("GenerateEffectSpecs called on ApplicationContainer with invalid GameplayEffect!")); | |
| continue; | |
| } | |
| float Level = LevelOverride >0.f ? LevelOverride : EffectItem.Level; | |
| int32 StackCount = StackOverride >0 ? StackOverride : EffectItem.StackCount; | |
| if (AbilityOrigin && Cast<ASpell>(AbilityOrigin) && Cast<ASpell>(AbilityOrigin)->OwningAbility) | |
| { | |
| UBaseGameplayAbility* SourceAbility = Cast<ASpell>(AbilityOrigin)->OwningAbility; | |
| if (SourceAbility) | |
| { | |
| EffectItem.GeneratedSpec = SourceAbility->MakeGameplayEffectSpec(EffectItem.GameplayEffect, Level); | |
| } | |
| } | |
| else { | |
| FGameplayEffectContextHandle ContextHandle = ASC->MakeEffectContext(); | |
| if (AbilityOrigin && Source->GetInstigator()) | |
| { | |
| ContextHandle.AddInstigator(Source->GetInstigator(), AbilityOrigin); | |
| } | |
| else { | |
| ContextHandle.AddInstigator(Source, AbilityOrigin); | |
| } | |
| EffectItem.GeneratedSpec =FGameplayEffectSpecHandle(newFGameplayEffectSpec(EffectItem.GameplayEffect.GetDefaultObject(), ContextHandle, Level)); | |
| } | |
| EffectItem.GeneratedSpec.Data->StackCount = StackCount; | |
| for (FMEffectModifier& Modifer : EffectItem.Modifiers) | |
| { | |
| EffectItem.GeneratedSpec.Data->SetSetByCallerMagnitude(Modifer.ModifierName, Modifer.ModifierMagnitude); | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("GenerateEffectSpecs called on Source %s with no ASC"), *GetNameSafe(Source)); | |
| } | |
| } | |
| voidFMEffectApplicationContainer::SetCallerMagnitude(FName AttributeName,float Magnitude) | |
| { | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| EffectItem.GeneratedSpec.Data->SetSetByCallerMagnitude(AttributeName, Magnitude); | |
| } | |
| } | |
| } | |
| voidFMEffectApplicationContainer::SetCallerMagnitudeOnEffect(FName AttributeName,float Magnitude, TSubclassOf<UGameplayEffect> Effect) | |
| { | |
| if (Effect) | |
| { | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GameplayEffect == Effect) | |
| { | |
| EffectItem.GeneratedSpec.Data->SetSetByCallerMagnitude(AttributeName, Magnitude); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| voidFMEffectApplicationContainer::AddModifierForEffect(FName AttributeName,float Magnitude, TSubclassOf<UGameplayEffect> Effect) | |
| { | |
| if (Effect) | |
| { | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GameplayEffect == Effect) | |
| { | |
| EffectItem.Modifiers.Add(FMEffectModifier(AttributeName, Magnitude)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| voidFMEffectApplicationContainer::AddHitResult(FHitResult Result) | |
| { | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GeneratedSpec.Data.IsValid()) | |
| { | |
| EffectItem.GeneratedSpec.Data->GetContext().AddHitResult(Result,true); | |
| } | |
| } | |
| } | |
| } | |
| boolFMEffectApplicationContainer::ApplyEffectApplicationContainerToTargetASC(UAsyncAbilitySystemComponent* TargetASC, FHitResult HitResult, EMCueSimulation SimulateCue) | |
| { | |
| bool RetVal =false; | |
| if (TargetASC) | |
| { | |
| if (!SourceAbilitySystemComponent) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("ApplyEffectApplicationContainerToTarget called on container with no SourceAbilitySystemComponent. call GeneratEffectSpecs first")); | |
| returnfalse; | |
| } | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| if (Item.Filter.PassesFilter(SourceAbilitySystemComponent, TargetASC) ==false) | |
| { | |
| continue; | |
| } | |
| if (Item.FactionFilter.PassesFilter(SourceAbilitySystemComponent, TargetASC) ==false) | |
| { | |
| continue; | |
| } | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GeneratedSpec.IsValid() ==false) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("ApplyEffectApplicationContainerToTarget called on ApplicationContainer that has NO generated specs!")); | |
| continue; | |
| } | |
| if (!EffectItem.GeneratedSpec.Data->GetContext().GetHitResult()) | |
| { | |
| if (!HitResult.GetActor()) | |
| { | |
| HitResult.Actor = TargetASC->GetAvatarActor(); | |
| } | |
| AddHitResult(HitResult); | |
| } | |
| FActiveGameplayEffectHandle NewHandle; | |
| if (SourceAbilitySystemComponent->ScopedPredictionKey.IsLocalClientKey() || SourceAbilitySystemComponent->IsOwnerActorAuthoritative()) | |
| { | |
| NewHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectItem.GeneratedSpec.Data.Get(), SourceAbilitySystemComponent->ScopedPredictionKey); | |
| } | |
| else { | |
| // Execute client-side instant FX and triggers cues | |
| TargetASC->SimulateEffect(*EffectItem.GeneratedSpec.Data.Get()); | |
| } | |
| /* | |
| // Ghetto weak prediction | |
| // If we're a client, check if the spec can be applied and if so, execute its weak predicted cues immediately | |
| if (SimulateCue == EMCueSimulation::Local && TargetASC->GetNetMode() != ENetMode::NM_DedicatedServer) | |
| { | |
| }*/ | |
| if (NewHandle.WasSuccessfullyApplied()) | |
| { | |
| RetVal =true; | |
| } | |
| } | |
| } | |
| } | |
| return RetVal; | |
| } | |
| boolFMEffectApplicationContainer::ApplyEffectApplicationContainerToTarget(AActor* Target, UBaseGameplayAbility* SourceAbility, FHitResult HitResult, EMCueSimulation CueSimulation) | |
| { | |
| bool RetVal =false; | |
| if (SourceAbilitySystemComponent ==nullptr) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("ApplyEffectApplicationContainerToTarget called on container with no SourceAbilitySystemComponent. call GeneratEffectSpecs first")); | |
| returnfalse; | |
| } | |
| UAsyncAbilitySystemComponent* ASC = Cast<UAsyncAbilitySystemComponent>(UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target)); | |
| returnApplyEffectApplicationContainerToTargetASC(ASC, HitResult, CueSimulation); | |
| /* | |
| if (UAsyncAbilitySystemComponent* ASC = Cast<UAsyncAbilitySystemComponent>(UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target))) | |
| { | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| if (Item.Filter.PassesFilter(SourceAbilitySystemComponent, ASC) == false) | |
| { | |
| continue; | |
| } | |
| if (Item.FactionFilter.PassesFilter(SourceAbilitySystemComponent, ASC) == false) | |
| { | |
| continue; | |
| } | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GeneratedSpec.IsValid() == false) | |
| { | |
| UE_LOG(LogTemp, Warning, TEXT("ApplyEffectApplicationContainerToTarget called on ApplicationContainer that has NO generated specs!")); | |
| continue; | |
| } | |
| HitResult.Actor = Target; | |
| AddHitResult(HitResult); | |
| FActiveGameplayEffectHandle NewHandle; | |
| // Ghetto weak prediction | |
| // If we're a client, check if the spec can be applied and if so, execute its weak predicted cues immediately | |
| if (CueSimulation == EMCueSimulation::Local && ASC->GetNetMode() != ENetMode::NM_DedicatedServer) | |
| { | |
| // Execute client-side instant FX cues | |
| ASC->SimulateEffect(*EffectItem.GeneratedSpec.Data.Get()); | |
| } | |
| NewHandle = ASC->ApplyGameplayEffectSpecToSelf(*EffectItem.GeneratedSpec.Data.Get(), SourceAbilitySystemComponent->ScopedPredictionKey); | |
| if (NewHandle.WasSuccessfullyApplied()) | |
| { | |
| RetVal = true; | |
| } | |
| } | |
| } | |
| } | |
| return RetVal;*/ | |
| } | |
| TArray<FActiveGameplayEffectHandle>FMEffectApplicationContainer::ApplyEffectApplicationContainerToTargetWithHandles(AActor* Target, UBaseGameplayAbility* SourceAbility) | |
| { | |
| TArray<FActiveGameplayEffectHandle> Handles; | |
| if (SourceAbilitySystemComponent ==nullptr) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("ApplyEffectApplicationContainerToTarget called on container with no SourceAbilitySystemComponent. call GeneratEffectSpecs first")); | |
| return Handles; | |
| } | |
| if (UAbilitySystemComponent* ASC =UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target)) | |
| { | |
| for (FMEffectApplicationItem& Item : Items) | |
| { | |
| if (Item.Filter.PassesFilter(SourceAbilitySystemComponent, ASC) ==false) | |
| { | |
| continue; | |
| } | |
| if (Item.FactionFilter.PassesFilter(SourceAbilitySystemComponent, ASC) ==false) | |
| { | |
| continue; | |
| } | |
| for (FMEffectItem& EffectItem : Item.Effects) | |
| { | |
| if (EffectItem.GeneratedSpec.IsValid() ==false) | |
| { | |
| UE_LOG(LogTemp, Warning,TEXT("ApplyEffectApplicationContainerToTarget called on ApplicationContainer that has NO generated specs!")); | |
| continue; | |
| } | |
| //FActiveGameplayEffectHandle NewHandle = ASC->ApplyGameplayEffectSpecToSelf(*EffectItem.GeneratedSpec.Data.Get(), SourceAbilitySystemComponent->ScopedPredictionKey); | |
| FActiveGameplayEffectHandle NewHandle; | |
| if (SourceAbility) | |
| { | |
| NewHandle = SourceAbilitySystemComponent->ApplyGameplayEffectSpecToTarget(*EffectItem.GeneratedSpec.Data.Get(), ASC, SourceAbility->GetCurrentActivationInfo().GetActivationPredictionKey()); | |
| } | |
| else { | |
| NewHandle = ASC->ApplyGameplayEffectSpecToSelf(*EffectItem.GeneratedSpec.Data.Get(), ASC->ScopedPredictionKey); | |
| } | |
| if (NewHandle.IsValid()) | |
| { | |
| Handles.Add(NewHandle); | |
| } | |
| } | |
| } | |
| } | |
| return Handles; | |
| } | |
| voidFMEffectApplicationContainer::PopulateEffectContainer(FMEffectApplicationContainer &Container, | |
| TSubclassOf<UGameplayEffect> Effect, | |
| float Level, | |
| EMActorFilterMatchType SelfFilter, | |
| EMFactionFilterMatchType FriendlyFilter, | |
| EMFactionFilterMatchType NeutralFilter, | |
| EMFactionFilterMatchType HostileFilter) | |
| { | |
| FMEffectItem Item; | |
| Item.GameplayEffect = Effect; | |
| Item.Level = Level; | |
| FMEffectApplicationItem ApplicationItem; | |
| ApplicationItem.Effects.Add(Item); | |
| ApplicationItem.Filter.AllowSelf = SelfFilter; | |
| ApplicationItem.FactionFilter.FriendlyFaction = FriendlyFilter; | |
| ApplicationItem.FactionFilter.NeutralFaction = NeutralFilter; | |
| ApplicationItem.FactionFilter.HostileFaction = HostileFilter; | |
| Container.Items.Add(ApplicationItem); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| #pragma once | |
| #include"GameplayEffectTypes.h" | |
| #include"GameplayEffect.h" | |
| #include"EffectTypes.generated.h" | |
| /* | |
| Depending on the type of event occurring, we might fall into a few different categories, each requiring different replication strategies. | |
| We want to avoid having the cue fire twice, so mainly either: | |
| - cues fire locally on all clients | |
| - cue is fired replicated from server | |
| - cue is fired replicated from instigating client | |
| */ | |
| UENUM() | |
| enumclassEMCueSimulation :uint8 | |
| { | |
| /** Cues are fired locally, no replication. */ | |
| Local, | |
| /** Cue is executed from the server via ASC and replicated */ | |
| Server, | |
| /** Cue is executed from instigating client and replicated */ | |
| Instigator, | |
| }; | |
| UENUM() | |
| enumclassEMActorFilterMatchType :uint8 | |
| { | |
| /** Skip this check completely. */ | |
| Skip, | |
| /** Actor must pass this check (true) */ | |
| MustPass, | |
| /** Actor must fail this check (not true) */ | |
| MustFail, | |
| }; | |
| UENUM() | |
| enumclassEMFactionFilterMatchType :uint8 | |
| { | |
| /** Skip this check completely. */ | |
| Skip, | |
| /** Actor must pass this check (true) */ | |
| MustPass, | |
| /** Actor must fail this check (not true) */ | |
| MustFail, | |
| }; | |
| USTRUCT(BlueprintType) | |
| structFMFactionFilter | |
| { | |
| GENERATED_USTRUCT_BODY() | |
| UPROPERTY(EditAnywhere) | |
| EMFactionFilterMatchTypeFriendlyFaction; | |
| UPROPERTY(EditAnywhere) | |
| EMFactionFilterMatchTypeNeutralFaction; | |
| UPROPERTY(EditAnywhere) | |
| EMFactionFilterMatchTypeHostileFaction; | |
| boolPassesFilter(UAbilitySystemComponent*Source,UAbilitySystemComponent*Target); | |
| }; | |
| USTRUCT(BlueprintType) | |
| structFMActorFilter | |
| { | |
| GENERATED_USTRUCT_BODY() | |
| UPROPERTY(EditAnywhere) | |
| EMActorFilterMatchTypeAllowSelf; | |
| boolPassesFilter(UAbilitySystemComponent*Source,UAbilitySystemComponent*Target); | |
| }; | |
| // ---------------------------------------- | |
| /* | |
| Assume NormalisedCharge and Ratio are both 0..1.f | |
| */ | |
| UENUM() | |
| enumclassEMEffectLevelStrategy :uint8 | |
| { | |
| /** The level is always the same */ | |
| Base, | |
| /** Level is determined by BaseLevel + NormalisedCharge*VariableCharge */ | |
| BaseVarianceCharge, | |
| /** Level is determined by BaseLevel + (1.0f - NormalisedCharge)*VariableCharge */ | |
| BaseVarianceInvCharge, | |
| /** Level is determined by BaseLevel + (1.0f - Ratio)*VariableRatio */ | |
| BaseVarianceRatio, | |
| /** Level is determined by BaseLevel + Ratio*VariableRatio */ | |
| BaseVarianceInvRatio, | |
| /** Level is determined by BaseLevel + NormalisedCharge*VariableCharge + (1.0f - Ratio)*VariableRatio */ | |
| BaseVarianceChargeInvRatio, | |
| /** Level is determined by BaseLevel + (1.0f - NormalisedCharge)*VariableCharge + (1.0f - Ratio)*VariableRatio */ | |
| BaseVarianceInvChargeInvRatio, | |
| /** Level is determined by BaseLevel + NormalisedCharge*VariableCharge + Ratio*VariableRatio */ | |
| BaseVarianceChargeRatio, | |
| /** Level is determined by BaseLevel + NormalisedCharge^2*VariableCharge */ | |
| BaseVarianceChargeSquared, | |
| /** Level is determined by BaseLevel + NormalisedCharge^2*VariableCharge + Ratio^2*VariableRatio */ | |
| BaseVarianceChargeSquaredRatioSquared, | |
| /** Level is determined by BaseLevel + NormalisedCharge^2*VariableCharge + (1.f-Ratio)^2*VariableRatio */ | |
| BaseVarianceChargeSquaredInvRatioSquared, | |
| }; | |
| USTRUCT(BlueprintType) | |
| structFMEffectModifier | |
| { | |
| GENERATED_USTRUCT_BODY() | |
| UPROPERTY(EditAnywhere) | |
| FNameModifierName; | |
| UPROPERTY(EditAnywhere) | |
| floatModifierMagnitude; | |
| UPROPERTY(EditAnywhere) | |
| EMEffectLevelStrategyModifierLevelStrategy; | |
| FMEffectModifier() :ModifierName(NAME_None),ModifierMagnitude(-1.f) | |
| { | |
| } | |
| FMEffectModifier(FNameModifier,floatMagnitude) : | |
| ModifierName(Modifier), | |
| ModifierMagnitude(Magnitude), | |
| ModifierLevelStrategy(EMEffectLevelStrategy::Base) | |
| { | |
| } | |
| FMEffectModifier(FNameModifier,floatMagnitude,EMEffectLevelStrategyModifierStrategy) : | |
| ModifierName(Modifier), | |
| ModifierMagnitude(Magnitude), | |
| ModifierLevelStrategy(ModifierStrategy) | |
| { | |
| } | |
| }; | |
| USTRUCT(BlueprintType) | |
| structFMEffectItem | |
| { | |
| GENERATED_USTRUCT_BODY() | |
| FMEffectItem() :Level(1.f),StackCount(1) | |
| { | |
| } | |
| UPROPERTY(EditAnywhere) | |
| TSubclassOf<UGameplayEffect>GameplayEffect; | |
| UPROPERTY(EditAnywhere) | |
| floatLevel; | |
| UPROPERTY(EditAnywhere) | |
| int32StackCount; | |
| UPROPERTY(EditAnywhere) | |
| TArray<FMEffectModifier>Modifiers; | |
| UPROPERTY() | |
| FGameplayEffectSpecHandleGeneratedSpec; | |
| UPROPERTY(EditAnywhere) | |
| EMEffectLevelStrategyLevelStrategy; | |
| }; | |
| USTRUCT(BlueprintType) | |
| structFMEffectApplicationItem | |
| { | |
| GENERATED_USTRUCT_BODY() | |
| UPROPERTY(EditAnywhere) | |
| FMActorFilterFilter; | |
| UPROPERTY(EditAnywhere) | |
| FMFactionFilterFactionFilter; | |
| UPROPERTY(EditAnywhere) | |
| TArray<FMEffectItem>Effects; | |
| }; | |
| /** A generic utility struct that can hold a list of "Apply this GE (Spec, Level, StackCount) to actors matching this filter". */ | |
| USTRUCT(BlueprintType) | |
| structFMEffectApplicationContainer | |
| { | |
| GENERATED_USTRUCT_BODY() | |
| UPROPERTY(EditAnywhere) | |
| TArray<FMEffectApplicationItem>Items; | |
| /** Cached source when specs are generated */ | |
| UPROPERTY(BlueprintReadWrite) | |
| UAbilitySystemComponent*SourceAbilitySystemComponent; | |
| // Source is the instigator actor, AbilityOrigin is the spell actor | |
| voidInitialiseEffectContainer(AActor*Source,floatVariableLevel=0.f,floatNormalisedCharge=0.f,floatVariableRatio=0.f,floatNormalisedRatio=0.f,AActor*AbilityOrigin=nullptr,floatPeriod=1.f,boolbClean= false); | |
| floatGetLevelForEffect(FMEffectItem&Item,floatVariableLevel=0.f,floatNormalisedCharge=0.f,floatVariableRatio=0.f,floatNormalisedRatio=0.f); | |
| floatGetLevelForStrategy(EMEffectLevelStrategyStrategy,floatBase=0.f,floatVariableLevel=0.f,floatNormalisedCharge=0.f,floatVariableRatio=0.f,floatNormalisedRatio=0.f); | |
| voidGenerateEffectSpecs(AActor*Source,floatLevelOverride=0.f,int32StackOverride=0,AActor*AbilityOrigin=nullptr); | |
| voidSetCallerMagnitude(FNameAttributeName,floatMagnitude); | |
| voidSetCallerMagnitudeOnEffect(FNameAttributeName,floatMagnitude,TSubclassOf<UGameplayEffect>Effect); | |
| voidAddModifierForEffect(FNameAttributeName,floatMagnitude,TSubclassOf<UGameplayEffect>Effect); | |
| voidAddHitResult(FHitResultResult); | |
| TArray<FActiveGameplayEffectHandle>ApplyEffectApplicationContainerToTargetWithHandles(AActor*Target,classUBaseGameplayAbility*SourceAbility=nullptr); | |
| staticvoidPopulateEffectContainer(FMEffectApplicationContainer&Container, | |
| TSubclassOf<UGameplayEffect>Effect, | |
| floatLevel=0.f, | |
| EMActorFilterMatchTypeSelfFilter=EMActorFilterMatchType::Skip, | |
| EMFactionFilterMatchTypeFriendlyFilter=EMFactionFilterMatchType::Skip, | |
| EMFactionFilterMatchTypeNeutralFilter=EMFactionFilterMatchType::Skip, | |
| EMFactionFilterMatchTypeHostileFilter=EMFactionFilterMatchType::Skip); | |
| // returns true if any effect was applied successfully | |
| boolApplyEffectApplicationContainerToTarget(AActor*Target,classUBaseGameplayAbility*SourceAbility=nullptr,FHitResultHitResult=FHitResult(),EMCueSimulationSimulateCue=EMCueSimulation::Local); | |
| boolApplyEffectApplicationContainerToTargetASC(classUAsyncAbilitySystemComponent*TargetASC,FHitResultHitResult=FHitResult(),EMCueSimulationSimulateCue=EMCueSimulation::Local); | |
| }; |
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment