From 713fcaf4f3369747718df10c3154ae02b1eb0acc Mon Sep 17 00:00:00 2001 From: Michael Delva Date: Wed, 2 Apr 2025 22:30:37 +0200 Subject: [PATCH] Moved Smart Object and Gameplay Interactions code to new plugin --- GameBaseFramework.uplugin | 45 +--- .../GameBaseFramework.Build.cs | 4 - ...FAT_WaitUseSmartObjectGameplayBehavior.cpp | 253 ------------------ ...GBFAT_WaitUseSmartObjectGameplayBehavior.h | 84 ------ 4 files changed, 14 insertions(+), 372 deletions(-) delete mode 100644 Source/GameBaseFramework/Private/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.cpp delete mode 100644 Source/GameBaseFramework/Public/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.h diff --git a/GameBaseFramework.uplugin b/GameBaseFramework.uplugin index b73b9ec3..8510f491 100644 --- a/GameBaseFramework.uplugin +++ b/GameBaseFramework.uplugin @@ -3,17 +3,17 @@ "Version": 1.1, "VersionName": "1.1", "FriendlyName": "Game Base Framework", - "Description" : "Helper classes", - "Category" : "Game Franework", - "CreatedBy" : "Michael Delva", - "CreatedByURL" : "http://www.emidee.net", - "DocsURL" : "", - "MarketplaceURL" : "", - "SupportURL" : "", - "EnabledByDefault" : false, - "CanContainContent" : true, - "IsBetaVersion" : false, - "Installed" : false, + "Description": "Helper classes", + "Category": "Game Franework", + "CreatedBy": "Michael Delva", + "CreatedByURL": "http://www.emidee.net", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "EnabledByDefault": false, + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, "Modules": [ { "Name": "GameBaseFramework", @@ -24,7 +24,7 @@ "Name": "GameBaseFrameworkEditor", "Type": "Editor", "LoadingPhase": "Default" - }, + } ], "Plugins": [ { @@ -103,22 +103,6 @@ "Name": "UIExtension", "Enabled": true }, - { - "Name": "SmartObjects", - "Enabled": true - }, - { - "Name": "GameplayBehaviors", - "Enabled": true - }, - { - "Name": "GameplayBehaviorSmartObjects", - "Enabled": true - }, - { - "Name": "GameplayInteractions", - "Enabled": true - }, { "Name": "StateTree", "Enabled": true @@ -130,6 +114,5 @@ { "Name": "ModelViewViewModel", "Enabled": true - } - ] -} + } +] } diff --git a/Source/GameBaseFramework/GameBaseFramework.Build.cs b/Source/GameBaseFramework/GameBaseFramework.Build.cs index ab9d58df..f3c68071 100644 --- a/Source/GameBaseFramework/GameBaseFramework.Build.cs +++ b/Source/GameBaseFramework/GameBaseFramework.Build.cs @@ -55,10 +55,6 @@ public GameBaseFramework( ReadOnlyTargetRules Target ) "Niagara", "PhysicsCore", "GameplayMessageRuntime", - "SmartObjectsModule", - "GameplayBehaviorsModule", - "GameplayBehaviorSmartObjectsModule", - "GameplayInteractionsModule", "StateTreeModule", "LevelSequence", "MovieScene", diff --git a/Source/GameBaseFramework/Private/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.cpp b/Source/GameBaseFramework/Private/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.cpp deleted file mode 100644 index a44eefde..00000000 --- a/Source/GameBaseFramework/Private/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.cpp +++ /dev/null @@ -1,253 +0,0 @@ -#include "GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.h" - -#include "BlueprintLibraries/CoreExtArrayBlueprintLibrary.h" - -#include -#include -#include -#include -#include -#include -#include - -void UGBFWaitUseSmartObjectProxy::SendEventToStateTree( const FGameplayTag tag ) -{ - GameplayInteractionContext.SendEvent( tag ); -} - -UGBFAT_WaitUseSmartObjectGameplayBehavior::UGBFAT_WaitUseSmartObjectGameplayBehavior( const FObjectInitializer & object_initializer ) : - Super( object_initializer ) - -{ - bInteractionCompleted = false; - bTickingTask = true; -} - -void UGBFAT_WaitUseSmartObjectGameplayBehavior::Activate() -{ - Super::Activate(); - - SetWaitingOnAvatar(); - - bool bSuccess = false; - ON_SCOPE_EXIT - { - if ( !bSuccess ) - { - EndTask(); - } - }; - - if ( !ClaimedHandle.IsValid() ) - { - return; - } - - auto * smart_object_subsystem = USmartObjectSubsystem::GetCurrent( GetAvatarActor()->GetWorld() ); - if ( !ensureMsgf( smart_object_subsystem != nullptr, TEXT( "SmartObjectSubsystem must be accessible at this point." ) ) ) - { - return; - } - - // A valid claimed handle can point to an object that is no longer part of the simulation - if ( !smart_object_subsystem->IsClaimedSmartObjectValid( ClaimedHandle ) ) - { - UE_VLOG( GetAvatarActor(), LogSmartObject, Log, TEXT( "Claim handle: %s refers to an object that is no longer available." ), *LexToString( ClaimedHandle ) ); - return; - } - - // Register a callback to be notified if the claimed slot became unavailable - smart_object_subsystem->RegisterSlotInvalidationCallback( ClaimedHandle, FOnSlotInvalidated::CreateUObject( this, &ThisClass::OnSlotInvalidated ) ); - - bSuccess = StartInteraction(); - - if ( bSuccess ) - { - OnActivated.Broadcast( SmartObjectProxy ); - } -} - -UGBFAT_WaitUseSmartObjectGameplayBehavior * UGBFAT_WaitUseSmartObjectGameplayBehavior::WaitUseSmartObjectGameplayBehaviorWithSmartObjectComponent( UGameplayAbility * owning_ability, USmartObjectComponent * smart_object_component, EGBFATSmartObjectComponentSlotSelection slot_selection, const TArray< TSubclassOf< USmartObjectBehaviorDefinition > > behavior_definition_classes, const FGameplayTagQuery activity_tags, ESmartObjectClaimPriority claim_priority ) -{ - auto * smart_object_subsystem = USmartObjectSubsystem::GetCurrent( owning_ability->GetWorld() ); - - const auto registered_handle = smart_object_component->GetRegisteredHandle(); - - FSmartObjectRequestFilter smart_object_request_filter; - owning_ability->GetAbilitySystemComponentFromActorInfo()->GetOwnedGameplayTags( smart_object_request_filter.UserTags ); - smart_object_request_filter.BehaviorDefinitionClasses = behavior_definition_classes; - smart_object_request_filter.ActivityRequirements = activity_tags; - - TArray< FSmartObjectSlotHandle > slots; - smart_object_subsystem->FindSlots( registered_handle, smart_object_request_filter, slots ); - - FSmartObjectClaimHandle claim_handle( FSmartObjectClaimHandle::InvalidHandle ); - - for ( auto ite = slots.CreateIterator(); ite; ++ite ) - { - const auto slot_handle = *ite; - - if ( !smart_object_subsystem->CanBeClaimed( slot_handle ) ) - { - ite.RemoveCurrent(); - } - } - - if ( slots.Num() > 0 ) - { - FSmartObjectSlotHandle selected_slot; - - switch ( slot_selection ) - { - case EGBFATSmartObjectComponentSlotSelection::First: - { - selected_slot = slots[ 0 ]; - } - break; - case EGBFATSmartObjectComponentSlotSelection::Closest: - { - const auto avatar_location = owning_ability->GetAvatarActorFromActorInfo()->GetActorLocation(); - auto max_distance_squared = TNumericLimits< float >::Max(); - - for ( const auto slot_handle : slots ) - { - const auto slot_location = smart_object_subsystem->GetSlotLocation( slot_handle ).GetValue(); - const auto distance_squared = ( slot_location - avatar_location ).SquaredLength(); - - if ( distance_squared < max_distance_squared ) - { - max_distance_squared = distance_squared; - selected_slot = slot_handle; - } - } - } - break; - case EGBFATSmartObjectComponentSlotSelection::Random: - { - selected_slot = UCoreExtArrayBlueprintLibrary::GetRandomArrayValue( slots ); - } - break; - default: - { - checkNoEntry(); - break; - } - } - - claim_handle = smart_object_subsystem->MarkSlotAsClaimed( selected_slot, claim_priority ); - } - - return WaitUseSmartObjectGameplayBehaviorWithClaimHandle( owning_ability, claim_handle ); -} - -UGBFAT_WaitUseSmartObjectGameplayBehavior * UGBFAT_WaitUseSmartObjectGameplayBehavior::WaitUseSmartObjectGameplayBehaviorWithSlotHandle( UGameplayAbility * owning_ability, FSmartObjectSlotHandle slot_handle, ESmartObjectClaimPriority claim_priority ) -{ - auto * smart_object_subsystem = USmartObjectSubsystem::GetCurrent( owning_ability->GetWorld() ); - const auto claim_handle = smart_object_subsystem->MarkSlotAsClaimed( slot_handle, claim_priority ); - - return WaitUseSmartObjectGameplayBehaviorWithClaimHandle( owning_ability, claim_handle ); -} - -UGBFAT_WaitUseSmartObjectGameplayBehavior * UGBFAT_WaitUseSmartObjectGameplayBehavior::WaitUseSmartObjectGameplayBehaviorWithClaimHandle( UGameplayAbility * owning_ability, FSmartObjectClaimHandle claim_handle ) -{ - auto * task = NewAbilityTask< UGBFAT_WaitUseSmartObjectGameplayBehavior >( owning_ability ); - task->ClaimedHandle = claim_handle; - return task; -} - -bool UGBFAT_WaitUseSmartObjectGameplayBehavior::StartInteraction() -{ - const auto * world = GetAvatarActor()->GetWorld(); - auto * smart_object_subsystem = USmartObjectSubsystem::GetCurrent( world ); - if ( !ensure( smart_object_subsystem ) ) - { - return false; - } - - const auto * behavior_definition = smart_object_subsystem->MarkSlotAsOccupied< UGameplayInteractionSmartObjectBehaviorDefinition >( ClaimedHandle ); - if ( behavior_definition == nullptr ) - { - UE_VLOG_UELOG( GetAvatarActor(), LogGameplayInteractions, Error, TEXT( "SmartObject was claimed for a different type of behavior definition. Expecting: %s." ), *UGameplayInteractionSmartObjectBehaviorDefinition::StaticClass()->GetName() ); - return false; - } - - const auto * smart_object_component = smart_object_subsystem->GetSmartObjectComponent( ClaimedHandle ); - - SmartObjectProxy = NewObject< UGBFWaitUseSmartObjectProxy >( this ); - - SmartObjectProxy->GameplayInteractionContext.SetContextActor( GetAvatarActor() ); - SmartObjectProxy->GameplayInteractionContext.SetSmartObjectActor( smart_object_component ? smart_object_component->GetOwner() : nullptr ); - SmartObjectProxy->GameplayInteractionContext.SetClaimedHandle( ClaimedHandle ); - - return SmartObjectProxy->GameplayInteractionContext.Activate( *behavior_definition ); -} - -void UGBFAT_WaitUseSmartObjectGameplayBehavior::Abort( const EGameplayInteractionAbortReason reason ) -{ - AbortContext.Reason = reason; - - if ( !bInteractionCompleted ) - { - SmartObjectProxy->GameplayInteractionContext.SetAbortContext( AbortContext ); - } - - EndTask(); -} - -void UGBFAT_WaitUseSmartObjectGameplayBehavior::OnDestroy( bool ability_ended ) -{ - if ( ClaimedHandle.IsValid() ) - { - auto * smart_object_subsystem = USmartObjectSubsystem::GetCurrent( GetAvatarActor()->GetWorld() ); - check( smart_object_subsystem != nullptr ); - - smart_object_subsystem->MarkSlotAsFree( ClaimedHandle ); - smart_object_subsystem->UnregisterSlotInvalidationCallback( ClaimedHandle ); - - ClaimedHandle.Invalidate(); - } - - if ( TaskState != EGameplayTaskState::Finished ) - { - if ( AbortContext.Reason == EGameplayInteractionAbortReason::Unset && bInteractionCompleted ) - { - OnSucceeded.Broadcast(); - } - else - { - OnFailed.Broadcast(); - } - } - - SmartObjectProxy = nullptr; - Super::OnDestroy( ability_ended ); -} - -void UGBFAT_WaitUseSmartObjectGameplayBehavior::TickTask( float delta_time ) -{ - Super::TickTask( delta_time ); - - const auto keep_ticking = SmartObjectProxy->GameplayInteractionContext.Tick( delta_time ); - if ( !keep_ticking ) - { - bInteractionCompleted = true; - EndTask(); - } -} - -void UGBFAT_WaitUseSmartObjectGameplayBehavior::OnSlotInvalidated( const FSmartObjectClaimHandle & /*claim_handle*/, ESmartObjectSlotState /*state*/ ) -{ - Abort( EGameplayInteractionAbortReason::InternalAbort ); -} - -void UGBFAT_WaitUseSmartObjectGameplayBehavior::OnSmartObjectBehaviorFinished( UGameplayBehavior & behavior, AActor & avatar, const bool interrupted ) -{ - // make sure we handle the right pawn - we can get this notify for a different - // Avatar if the behavior sending it out is not instanced (CDO is being used to perform actions) - if ( GetAvatarActor() == &avatar ) - { - behavior.GetOnBehaviorFinishedDelegate().Remove( OnBehaviorFinishedNotifyHandle ); - bInteractionCompleted = true; - EndTask(); - } -} diff --git a/Source/GameBaseFramework/Public/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.h b/Source/GameBaseFramework/Public/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.h deleted file mode 100644 index 8db95772..00000000 --- a/Source/GameBaseFramework/Public/GAS/Tasks/GBFAT_WaitUseSmartObjectGameplayBehavior.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "GBFAT_WaitUseSmartObjectGameplayBehavior.generated.h" - -class UGameplayBehavior; -class USmartObjectComponent; - -UENUM( BlueprintType ) -enum class EGBFATSmartObjectComponentSlotSelection : uint8 -{ - First, - Closest, - Random -}; - -UCLASS( BlueprintType ) -class UGBFWaitUseSmartObjectProxy : public UObject -{ - GENERATED_BODY() - -public: - UFUNCTION( BlueprintCallable ) - void SendEventToStateTree( const FGameplayTag tag ); - - UPROPERTY() - FGameplayInteractionContext GameplayInteractionContext; -}; - -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FOnWaitUseSmartObjectGameplayBehaviorActivated, UGBFWaitUseSmartObjectProxy *, Proxy ); - -UCLASS() -class GAMEBASEFRAMEWORK_API UGBFAT_WaitUseSmartObjectGameplayBehavior final : public UAbilityTask -{ - GENERATED_BODY() - -public: - explicit UGBFAT_WaitUseSmartObjectGameplayBehavior( const FObjectInitializer & object_initializer ); - - void Activate() override; - - UFUNCTION( BlueprintCallable, Category = "Ability|Tasks", meta = ( HidePin = "owning_ability", DefaultToSelf = "owning_ability", BlueprintInternalUseOnly = "TRUE" ) ) - static UGBFAT_WaitUseSmartObjectGameplayBehavior * WaitUseSmartObjectGameplayBehaviorWithSmartObjectComponent( UGameplayAbility * owning_ability, USmartObjectComponent * smart_object_component, EGBFATSmartObjectComponentSlotSelection slot_selection, const TArray< TSubclassOf< USmartObjectBehaviorDefinition > > behavior_definition_classes, const FGameplayTagQuery activity_tags, ESmartObjectClaimPriority claim_priority = ESmartObjectClaimPriority::Normal ); - - UFUNCTION( BlueprintCallable, Category = "Ability|Tasks", meta = ( HidePin = "owning_ability", DefaultToSelf = "owning_ability", BlueprintInternalUseOnly = "TRUE" ) ) - static UGBFAT_WaitUseSmartObjectGameplayBehavior * WaitUseSmartObjectGameplayBehaviorWithSlotHandle( UGameplayAbility * owning_ability, FSmartObjectSlotHandle slot_handle, ESmartObjectClaimPriority claim_priority = ESmartObjectClaimPriority::Normal ); - - UFUNCTION( BlueprintCallable, Category = "Ability|Tasks", meta = ( HidePin = "owning_ability", DefaultToSelf = "owning_ability", BlueprintInternalUseOnly = "TRUE" ) ) - static UGBFAT_WaitUseSmartObjectGameplayBehavior * WaitUseSmartObjectGameplayBehaviorWithClaimHandle( UGameplayAbility * owning_ability, FSmartObjectClaimHandle claim_handle ); - -private: - bool StartInteraction(); - void Abort( const EGameplayInteractionAbortReason reason ); - void OnDestroy( bool ability_ended ) override; - void TickTask( float delta_time ) override; - - void OnSlotInvalidated( const FSmartObjectClaimHandle & claim_handle, ESmartObjectSlotState state ); - void OnSmartObjectBehaviorFinished( UGameplayBehavior & behavior, AActor & avatar, const bool interrupted ); - - UPROPERTY( BlueprintAssignable ) - FOnWaitUseSmartObjectGameplayBehaviorActivated OnActivated; - - UPROPERTY( BlueprintAssignable ) - FGenericGameplayTaskDelegate OnSucceeded; - - UPROPERTY( BlueprintAssignable ) - FGenericGameplayTaskDelegate OnFailed; - - UPROPERTY() - TObjectPtr< UGBFWaitUseSmartObjectProxy > SmartObjectProxy; - - UPROPERTY() - FGameplayInteractionAbortContext AbortContext; - - FSmartObjectClaimHandle ClaimedHandle; - FDelegateHandle OnBehaviorFinishedNotifyHandle; - bool bInteractionCompleted; - ESmartObjectClaimPriority ClaimPriority; -};