diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 8fa97e0..9971466 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -73,3 +73,61 @@ ConnectionType=USBOnly bUseManualIPAddress=False ManualIPAddress= +[/Script/Engine.CollisionProfile] +-Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False) +-Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ",bCanModify=False) +-Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ",bCanModify=False) +-Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic",Response=ECR_Block),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False) +-Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors",bCanModify=False) +-Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors",bCanModify=False) +-Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False) +-Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False) +-Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) ++Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision") ++Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.") ++Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ") ++Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ") ++Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.") ++Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.") ++Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors") ++Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors") ++Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.") ++Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.") ++Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.") ++Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.") ++Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.") ++Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="Interactable",CollisionEnabled=QueryAndPhysics,bCanModify=True,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Interactable")),HelpMessage="WorldDynamic objects derived from AInteractable.") ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Interactable") +-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") +-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") +-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") +-ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") +-ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") ++ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") ++ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") ++ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") ++ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") ++ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") +-CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") +-CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") +-CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") +-CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") ++CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") ++CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") ++CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") ++CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") + diff --git a/Content/Blueprints/GameModes/BP_MainGameMode.uasset b/Content/Blueprints/GameModes/BP_MainGameMode.uasset index 9135344..9a721f6 100644 Binary files a/Content/Blueprints/GameModes/BP_MainGameMode.uasset and b/Content/Blueprints/GameModes/BP_MainGameMode.uasset differ diff --git a/Content/Blueprints/Other/BP_CustomGameInstance.uasset b/Content/Blueprints/Other/BP_CustomGameInstance.uasset index e20fab3..9a1d396 100644 Binary files a/Content/Blueprints/Other/BP_CustomGameInstance.uasset and b/Content/Blueprints/Other/BP_CustomGameInstance.uasset differ diff --git a/Content/Blueprints/Other/BP_MainWidgetManager.uasset b/Content/Blueprints/Other/BP_MainWidgetManager.uasset new file mode 100644 index 0000000..cce8750 Binary files /dev/null and b/Content/Blueprints/Other/BP_MainWidgetManager.uasset differ diff --git a/Source/Lost_Edge/Private/CameraModeBase.cpp b/Source/Lost_Edge/Private/CameraModeBase.cpp index fb0f45d..6ef3bfe 100644 --- a/Source/Lost_Edge/Private/CameraModeBase.cpp +++ b/Source/Lost_Edge/Private/CameraModeBase.cpp @@ -4,17 +4,18 @@ #include "CameraModeBase.h" #include "Camera/CameraComponent.h" -#include "CustomGameUserSettings.h" #include "EnhancedInputSubsystems.h" #include "GameFramework/Character.h" #include "GameFramework/PawnMovementComponent.h" +#include "InputMappingContext.h" #include "Kismet/GameplayStatics.h" + +#include "CustomGameUserSettings.h" #include "MainGameModeBase.h" ACameraModeBase::ACameraModeBase() { PrimaryActorTick.bCanEverTick = true; - } void ACameraModeBase::BeginPlay() diff --git a/Source/Lost_Edge/Private/CameraModeBase.h b/Source/Lost_Edge/Private/CameraModeBase.h index 71d61da..4986a61 100644 --- a/Source/Lost_Edge/Private/CameraModeBase.h +++ b/Source/Lost_Edge/Private/CameraModeBase.h @@ -4,7 +4,6 @@ #include "CoreMinimal.h" #include "GameFramework/SpectatorPawn.h" -#include "InputMappingContext.h" #include "CameraModeBase.generated.h" @@ -31,7 +30,7 @@ protected: void SwitchRun(bool run); UPROPERTY(EditDefaultsOnly) - TSoftObjectPtr inputMapping; + TSoftObjectPtr inputMapping; UPROPERTY(EditDefaultsOnly) float moveSpeed = 200; diff --git a/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp b/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp index b339581..0236018 100644 --- a/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp +++ b/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp @@ -3,11 +3,17 @@ #include "CustomGameInstanceBase.h" -#include "CustomGameUserSettings.h" #include "EnhancedInputLibrary.h" +#include "InputMappingContext.h" + +#include "CustomGameUserSettings.h" +#include "Interactable/UsableInteractable.h" void UCustomGameInstanceBase::Init() { + // IN FUTURE ASSIGN FROM CONTENT LOADER MEMBER + interactionsCollection = { {UUsableInteractable::StaticClass()} }; + UGameInstance::Init(); ApplyMouseSettings(); diff --git a/Source/Lost_Edge/Private/CustomGameInstanceBase.h b/Source/Lost_Edge/Private/CustomGameInstanceBase.h index 6884b4f..e4ff7bc 100644 --- a/Source/Lost_Edge/Private/CustomGameInstanceBase.h +++ b/Source/Lost_Edge/Private/CustomGameInstanceBase.h @@ -4,7 +4,6 @@ #include "CoreMinimal.h" #include "Engine/GameInstance.h" -#include "InputMappingContext.h" #include "CustomGameInstanceBase.generated.h" @@ -19,7 +18,9 @@ public: UFUNCTION(BlueprintCallable, Category = Settings) void ApplyMouseSettings(); + TArray> interactionsCollection; + protected: UPROPERTY(EditDefaultsOnly) - TArray> defaultInputContexts; + TArray> defaultInputContexts; }; diff --git a/Source/Lost_Edge/Private/CustomGameUserSettings.cpp b/Source/Lost_Edge/Private/CustomGameUserSettings.cpp index 8192440..5afcd0c 100644 --- a/Source/Lost_Edge/Private/CustomGameUserSettings.cpp +++ b/Source/Lost_Edge/Private/CustomGameUserSettings.cpp @@ -3,7 +3,6 @@ #include "CustomGameUserSettings.h" -#include "CustomGameInstanceBase.h" #include "Kismet/GameplayStatics.h" UCustomGameUserSettings::UCustomGameUserSettings(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer) diff --git a/Source/Lost_Edge/Private/Interactable/Interactable.cpp b/Source/Lost_Edge/Private/Interactable/Interactable.cpp new file mode 100644 index 0000000..7ff6710 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/Interactable.cpp @@ -0,0 +1,6 @@ +// Oleg Petruny proprietary. + + +#include "Interactable.h" + + diff --git a/Source/Lost_Edge/Private/Interactable/Interactable.h b/Source/Lost_Edge/Private/Interactable/Interactable.h new file mode 100644 index 0000000..4bbcc71 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/Interactable.h @@ -0,0 +1,22 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "UObject/ScriptInterface.h" + +#include "Interactable.generated.h" + +UCLASS(Abstract, MinimalAPI, Blueprintable, BlueprintType) +class AInteractable : public AActor +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + TArray> GetInteractableComponents(); + virtual TArray> GetInteractableComponents_Implementation() + PURE_VIRTUAL(AInteractable::GetInteractableComponents_Implementation, return {};); +}; + diff --git a/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp b/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp new file mode 100644 index 0000000..79387a3 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableActivator.cpp @@ -0,0 +1,59 @@ +// Oleg Petruny proprietary. + + +#include "InteractableActivator.h" + +#include "Engine/CollisionProfile.h" + +#include "PlayerBase.h" + +UInteractableActivator::UInteractableActivator(const FObjectInitializer& ObjectInitializer) + : USceneComponent(ObjectInitializer) +{ + if(HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) + { + return; + } + world = GetWorld(); + player = Cast(GetOwner()); + + collisionChannel = ECC_GameTraceChannel1; + if(auto collisions = UCollisionProfile::Get()) + { + for(int32 i = 0; i < ECC_MAX; ++i) + { + if(collisions->ReturnChannelNameFromContainerIndex(i) == FName{ TEXT("Interactable") }) + { + collisionChannel = (ECollisionChannel)i; + break; + } + } + } + + if(!world || !player || collisionChannel == ECC_MAX) + { + DestroyComponent(); + return; + } + + PrimaryComponentTick.TickInterval = 0.05f; + PrimaryComponentTick.bCanEverTick = true; + PrimaryComponentTick.bStartWithTickEnabled = true; + RegisterComponent(); +} + +void UInteractableActivator::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + USceneComponent::TickComponent(DeltaTime, TickType, ThisTickFunction); + + switch(TickType) + { + case ELevelTick::LEVELTICK_TimeOnly: + case ELevelTick::LEVELTICK_ViewportsOnly: + case ELevelTick::LEVELTICK_All: + Scan_Implementation(); + break; + default: + break; + } +} diff --git a/Source/Lost_Edge/Private/Interactable/InteractableActivator.h b/Source/Lost_Edge/Private/Interactable/InteractableActivator.h new file mode 100644 index 0000000..be3a19f --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableActivator.h @@ -0,0 +1,34 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "Components/SceneComponent.h" +#include "CoreMinimal.h" + +#include "InteractableActivator.generated.h" + +DECLARE_DELEGATE(FInteractableActivated); + +UCLASS(Blueprintable, BlueprintType) +class UInteractableActivator : public USceneComponent +{ + GENERATED_BODY() + +public: + UInteractableActivator(const FObjectInitializer& ObjectInitializer); + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + +protected: + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + inline void Scan(); + inline virtual void Scan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, ); + + UPROPERTY(EditDefaultsOnly) + float scanDistance = 200; + + class UWorld* world; + class APlayerBase* player; + bool isTrace = true; + enum ECollisionChannel collisionChannel; + FInteractableActivated interactableActivatedDelegate; +}; diff --git a/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp b/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp new file mode 100644 index 0000000..c520bfd --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableCaller.cpp @@ -0,0 +1,6 @@ +// Oleg Petruny proprietary. + + +#include "InteractableCaller.h" + + diff --git a/Source/Lost_Edge/Private/Interactable/InteractableCaller.h b/Source/Lost_Edge/Private/Interactable/InteractableCaller.h new file mode 100644 index 0000000..656415c --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableCaller.h @@ -0,0 +1,17 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "Components/ActorComponent.h" +#include "CoreMinimal.h" + +#include "InteractableCaller.generated.h" + +UCLASS(Abstract, MinimalAPI, Blueprintable, BlueprintType) +class UInteractableCaller : public UActorComponent +{ + GENERATED_BODY() + +public: + +}; \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp b/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp new file mode 100644 index 0000000..8906d63 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableComponent.cpp @@ -0,0 +1,6 @@ +// Oleg Petruny proprietary. + + +#include "InteractableComponent.h" + +// Add default functionality here for any IInteractableInterface functions that are not pure virtual. diff --git a/Source/Lost_Edge/Private/Interactable/InteractableComponent.h b/Source/Lost_Edge/Private/Interactable/InteractableComponent.h new file mode 100644 index 0000000..0dc7a31 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/InteractableComponent.h @@ -0,0 +1,54 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" +#include "InputMappingContext.h" +#include "UObject/Interface.h" + +#include "InteractableActivator.h" +#include "InteractableCaller.h" + +#include "InteractableComponent.generated.h" + +USTRUCT(BlueprintType) +struct FActivatorCallerPair +{ + GENERATED_BODY() + +public: + FActivatorCallerPair() {} + + FActivatorCallerPair(TSubclassOf a, TSubclassOf c) + : activator(a), caller(c) + {} + + UPROPERTY(EditAnywhere) + TSubclassOf activator; + + UPROPERTY(EditAnywhere) + TSubclassOf caller; +}; + +UCLASS() +class UInteractableComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + const FString GetName(); + virtual const FString GetName_Implementation() + PURE_VIRTUAL(UInteractableComponent::GetInteractionName_Implementation, return "NONE";); + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + const UInputMappingContext* GetInputMapping(); + virtual const UInputMappingContext* GetInputMapping_Implementation() + PURE_VIRTUAL(UInteractableComponent::GetInputMapping_Implementation, static UInputMappingContext _inputMapping{}; return &_inputMapping;); + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + const TArray GetActivatorsAndCallers(); + virtual const TArray GetActivatorsAndCallers_Implementation() + PURE_VIRTUAL(UInteractableComponent::GetActivatorsAndCallers_Implementation, + TArray _activatorsAndCallers{}; return _activatorsAndCallers;); +}; diff --git a/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp b/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp new file mode 100644 index 0000000..a00633a --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.cpp @@ -0,0 +1,26 @@ +// Oleg Petruny proprietary. + + +#include "RaycastInteractableActivator.h" + +#include "DrawDebugHelpers.h" +#include "Engine/World.h" + +void URaycastInteractableActivator::Scan_Implementation() +{ + FHitResult result{}; + FVector startLocation = GetComponentLocation(); + FVector endLocation = startLocation + (GetComponentRotation().Vector() * scanDistance); + + world->LineTraceSingleByChannel( + result, + startLocation, + endLocation, + collisionChannel + ); + + if(result.bBlockingHit) + DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, 0.5f, 0, 1.0f); + else + DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, 0.5f, 10, 1.0f); +} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.h b/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.h new file mode 100644 index 0000000..2519571 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/RaycastInteractableActivator.h @@ -0,0 +1,18 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" +#include "InteractableActivator.h" + +#include "RaycastInteractableActivator.generated.h" + +UCLASS(Blueprintable, BlueprintType) +class URaycastInteractableActivator : public UInteractableActivator +{ + GENERATED_BODY() + +protected: + void Scan(); + virtual void Scan_Implementation() override; +}; diff --git a/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp b/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp new file mode 100644 index 0000000..361cd95 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/UsableInteractable.cpp @@ -0,0 +1,27 @@ +// Oleg Petruny proprietary. + + +#include "UsableInteractable.h" + +#include "InteractableCaller.h" +#include "RaycastInteractableActivator.h" + +const FString UUsableInteractable::GetName_Implementation() +{ + static auto _name = TEXT("Use"); + return _name; +} + +const UInputMappingContext* UUsableInteractable::GetInputMapping_Implementation() +{ + static auto _mapping = UInputMappingContext{}; + return &_mapping; +} + +const TArray UUsableInteractable::GetActivatorsAndCallers_Implementation() +{ + static TArray _array = { + {{URaycastInteractableActivator::StaticClass()}, {UInteractableCaller::StaticClass()}} + }; + return _array; +} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/Interactable/UsableInteractable.h b/Source/Lost_Edge/Private/Interactable/UsableInteractable.h new file mode 100644 index 0000000..b39b388 --- /dev/null +++ b/Source/Lost_Edge/Private/Interactable/UsableInteractable.h @@ -0,0 +1,26 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" + +#include "InteractableComponent.h" + +#include "UsableInteractable.generated.h" + + +UCLASS() +class UUsableInteractable : public UInteractableComponent +{ + GENERATED_BODY() + +public: + const FString GetName(); + virtual const FString GetName_Implementation() override; + + const UInputMappingContext* GetInputMapping(); + virtual const UInputMappingContext* GetInputMapping_Implementation() override; + + const TArray GetActivatorsAndCallers(); + virtual const TArray GetActivatorsAndCallers_Implementation() override; +}; \ No newline at end of file diff --git a/Source/Lost_Edge/Private/MainGameModeBase.cpp b/Source/Lost_Edge/Private/MainGameModeBase.cpp index 4c2750d..4a6439f 100644 --- a/Source/Lost_Edge/Private/MainGameModeBase.cpp +++ b/Source/Lost_Edge/Private/MainGameModeBase.cpp @@ -6,23 +6,32 @@ #include "Engine/World.h" #include "GameFramework/SpectatorPawn.h" #include "Kismet/GameplayStatics.h" +#include "UObject/ScriptInterface.h" + +#include "CustomGameInstanceBase.h" +#include "Interactable/InteractableComponent.h" +#include "WidgetsManager.h" void AMainGameModeBase::StartPlay() { AGameModeBase::StartPlay(); - InstantiateOverlayWidgets(); + _widgetsManager = NewObject(this, widgetManagerClass); + _widgetsManager->Init(); } bool AMainGameModeBase::SetPause(APlayerController* PC, FCanUnpause CanUnpauseDelegate) { - if(IsPaused()) + if(_widgetsManager) { - HideOverlayWidgets(); - } - else - { - ShowOverlayWidgets(); + if(IsPaused()) + { + _widgetsManager->HideOverlayWidgets(); + } + else + { + _widgetsManager->ShowOverlayWidgets(); + } } return AGameModeBase::SetPause(PC, CanUnpauseDelegate); @@ -36,7 +45,7 @@ void AMainGameModeBase::SwitchCameraMode() { if(auto pawn = PC->GetPawn()) { - if(_playerPawn.IsValid()) + if(!_playerPawn.IsValid()) { auto spawnLoc = pawn->GetActorLocation(); auto spawnRot = pawn->GetActorRotation(); @@ -55,71 +64,8 @@ void AMainGameModeBase::SwitchCameraMode() } } - UpdateOverlayWidgetsOwner(); -} - -void AMainGameModeBase::InstantiateOverlayWidgets() -{ - if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) + if(_widgetsManager) { - for(auto widget : permaOverlayWidgets) - { - if(auto instance = CreateWidget(PC, widget)) - { - permaOverlayWidgetsInstances.Add(instance); - instance->AddToViewport(); - } - } - for(auto widget : overlayWidgets) - { - if(auto instance = CreateWidget(PC, widget)) - { - overlayWidgetsInstances.Add(instance); - instance->AddToViewport(); - } - } + _widgetsManager->UpdateOverlayWidgetsOwner(); } } - -void AMainGameModeBase::HideOverlayWidgets() -{ - for(auto widget : overlayWidgetsInstances) - { - if(widget.IsValid()) - { - widget->SetVisibility(ESlateVisibility::Hidden); - } - } -} - -void AMainGameModeBase::ShowOverlayWidgets() -{ - for(auto widget : overlayWidgetsInstances) - { - if(widget.IsValid()) - { - widget->SetVisibility(ESlateVisibility::Visible); - } - } -} - -void AMainGameModeBase::UpdateOverlayWidgetsOwner() -{ - if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) - { - for(auto widget : permaOverlayWidgetsInstances) - { - if(widget.IsValid()) - { - widget->SetOwningPlayer(PC); - } - } - for(auto widget : overlayWidgetsInstances) - { - if(widget.IsValid()) - { - widget->SetOwningPlayer(PC); - } - } - } -} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/MainGameModeBase.h b/Source/Lost_Edge/Private/MainGameModeBase.h index 4aadc7c..d9a9563 100644 --- a/Source/Lost_Edge/Private/MainGameModeBase.h +++ b/Source/Lost_Edge/Private/MainGameModeBase.h @@ -2,10 +2,8 @@ #pragma once -#include "Blueprint/UserWidget.h" #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" -#include "GameFramework/Pawn.h" #include "MainGameModeBase.generated.h" @@ -20,21 +18,10 @@ public: void SwitchCameraMode(); - protected: UPROPERTY(EditDefaultsOnly) - TArray> permaOverlayWidgets; // never hidden - TArray> permaOverlayWidgetsInstances; - - UPROPERTY(EditDefaultsOnly) - TArray> overlayWidgets; // hidden in pause - TArray> overlayWidgetsInstances; - + TSubclassOf widgetManagerClass; private: - inline void InstantiateOverlayWidgets(); - - void HideOverlayWidgets(); - void ShowOverlayWidgets(); - void UpdateOverlayWidgetsOwner(); + class UWidgetsManager* _widgetsManager; }; diff --git a/Source/Lost_Edge/Private/APlayerBase.cpp b/Source/Lost_Edge/Private/PlayerBase.cpp similarity index 56% rename from Source/Lost_Edge/Private/APlayerBase.cpp rename to Source/Lost_Edge/Private/PlayerBase.cpp index 2e05e59..05a9732 100644 --- a/Source/Lost_Edge/Private/APlayerBase.cpp +++ b/Source/Lost_Edge/Private/PlayerBase.cpp @@ -1,37 +1,61 @@ // Oleg Petruny proprietary. -#include "APlayerBase.h" +#include "PlayerBase.h" #include "Camera/CameraComponent.h" -#include "CustomGameUserSettings.h" #include "EnhancedInputSubsystems.h" #include "GameFramework/CharacterMovementComponent.h" +#include "InputMappingContext.h" #include "Kismet/GameplayStatics.h" #include "Kismet/KismetMathLibrary.h" + +#include "CustomGameInstanceBase.h" +#include "Interactable/InteractableActivator.h" +#include "Interactable/InteractableCaller.h" +#include "Interactable/InteractableComponent.h" +#include "Interactable/UsableInteractable.h" + +#include "CustomGameUserSettings.h" #include "MainGameModeBase.h" APlayerBase::APlayerBase() { PrimaryActorTick.bCanEverTick = true; +} +void APlayerBase::Tick(float DeltaTime) +{ + ACharacter::Tick(DeltaTime); + + // stabilize move speed by fps + AddActorLocalOffset(ConsumeMovementInputVector() * DeltaTime); +} + +void APlayerBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + ACharacter::SetupPlayerInputComponent(PlayerInputComponent); } void APlayerBase::BeginPlay() { - Super::BeginPlay(); + ACharacter::BeginPlay(); auto world = GetWorld(); GetCharacterMovement()->MaxWalkSpeed = moveSpeed; - auto cameraManager = UGameplayStatics::GetPlayerCameraManager(world, 0); - cameraManager->ViewPitchMin = minPitch; - cameraManager->ViewPitchMax = maxPitch; + cameraManager = UGameplayStatics::GetPlayerCameraManager(world, 0); + if(cameraManager) + { + cameraManager->ViewPitchMin = minPitch; + cameraManager->ViewPitchMax = maxPitch; + } auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings(); - if(auto camera = FindComponentByClass()) + camera = FindComponentByClass(); + if(camera) { camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f; } @@ -48,19 +72,7 @@ void APlayerBase::BeginPlay() } } -} - -void APlayerBase::Tick(float DeltaTime) -{ - Super::Tick(DeltaTime); - - // stabilize move speed by fps - AddActorLocalOffset(ConsumeMovementInputVector() * DeltaTime); -} - -void APlayerBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) -{ - Super::SetupPlayerInputComponent(PlayerInputComponent); + LoadInteractable(); } void APlayerBase::SwitchToCameraPawn() @@ -97,7 +109,7 @@ void APlayerBase::Jump() if(jumpLocked) return; - Super::Jump(); + ACharacter::Jump(); } void APlayerBase::SwitchRun(bool run) @@ -109,4 +121,41 @@ void APlayerBase::SwitchRun(bool run) GetCharacterMovement()->MaxWalkSpeed = moveSpeed * runSpeedMultiplier; else GetCharacterMovement()->MaxWalkSpeed = moveSpeed; -} \ No newline at end of file +} + +void APlayerBase::UpdatePitch(float min, float max) +{ + minPitch = min; + maxPitch = max; + + if(cameraManager) + { + cameraManager->ViewPitchMin = minPitch; + cameraManager->ViewPitchMax = maxPitch; + } +} + +void APlayerBase::LoadInteractable() +{ + auto GI = Cast(GetWorld()->GetGameInstance()); + if(!GI) + { + return; + } + + TSet> activators; + for(auto& interaction : GI->interactionsCollection) + { + auto actAndCallArray = interaction->GetDefaultObject()->GetActivatorsAndCallers_Implementation(); + for(auto& actAndCall : actAndCallArray) + { + activators.Add(actAndCall.activator); + } + } + + for(auto& activator : activators) + { + auto component = NewObject(this, activator); + component->AttachToComponent(camera, FAttachmentTransformRules::SnapToTargetIncludingScale); + } +} diff --git a/Source/Lost_Edge/Private/APlayerBase.h b/Source/Lost_Edge/Private/PlayerBase.h similarity index 75% rename from Source/Lost_Edge/Private/APlayerBase.h rename to Source/Lost_Edge/Private/PlayerBase.h index 7fe2179..194b3fb 100644 --- a/Source/Lost_Edge/Private/APlayerBase.h +++ b/Source/Lost_Edge/Private/PlayerBase.h @@ -4,9 +4,8 @@ #include "CoreMinimal.h" #include "GameFramework/Character.h" -#include "InputMappingContext.h" -#include "APlayerBase.generated.h" +#include "PlayerBase.generated.h" UCLASS() class APlayerBase : public ACharacter @@ -33,8 +32,11 @@ protected: UFUNCTION(BlueprintCallable, Category = Character) void SwitchRun(bool run); + UFUNCTION(BlueprintCallable, Category = Character) + void UpdatePitch(float min, float max); + UPROPERTY(EditDefaultsOnly) - TSoftObjectPtr inputMapping; + TSoftObjectPtr inputMapping; UPROPERTY(EditAnywhere) float moveSpeed = 200; @@ -48,17 +50,15 @@ protected: UPROPERTY(EditAnywhere) bool runLocked = false; - UPROPERTY(EditAnywhere) - float minPitch = -80; - UPROPERTY(EditAnywhere) - float maxPitch = 65; - - // not visible :( - //UPROPERTY(EditDefaultsOnly) - //UCameraComponent* camera; + APlayerCameraManager* cameraManager; + class UCameraComponent* camera; UPROPERTY(EditAnywhere) bool cameraLocked = false; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + float minPitch = -80; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + float maxPitch = 65; private: - + void LoadInteractable(); }; diff --git a/Source/Lost_Edge/Private/WidgetsManager.cpp b/Source/Lost_Edge/Private/WidgetsManager.cpp new file mode 100644 index 0000000..6ee7e38 --- /dev/null +++ b/Source/Lost_Edge/Private/WidgetsManager.cpp @@ -0,0 +1,85 @@ +// Oleg Petruny proprietary. + + +#include "WidgetsManager.h" + +#include "Blueprint/UserWidget.h" +#include "Engine/World.h" +#include "Kismet/GameplayStatics.h" +#include "UObject/ScriptInterface.h" + +#include "CustomGameInstanceBase.h" +#include "Interactable/Interactable.h" +#include "Interactable/InteractableComponent.h" + +void UWidgetsManager::Init() +{ + if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) + { + for(auto& widget : permaOverlayWidgets) + { + if(auto instance = CreateWidget(PC, widget)) + { + permaOverlayWidgetsInstances.Add(instance); + instance->AddToViewport(); + } + } + for(auto& widget : overlayWidgets) + { + if(auto instance = CreateWidget(PC, widget)) + { + overlayWidgetsInstances.Add(instance); + instance->AddToViewport(); + } + } + } +} + +void UWidgetsManager::HideOverlayWidgets() +{ + for(auto& widget : overlayWidgetsInstances) + { + if(widget.IsValid()) + { + widget->SetVisibility(ESlateVisibility::Hidden); + } + } +} + +void UWidgetsManager::ShowOverlayWidgets() +{ + for(auto& widget : overlayWidgetsInstances) + { + if(widget.IsValid()) + { + widget->SetVisibility(ESlateVisibility::Visible); + } + } +} + +void UWidgetsManager::UpdateOverlayWidgetsOwner() +{ + if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) + { + for(auto& widget : permaOverlayWidgetsInstances) + { + if(widget.IsValid()) + { + widget->SetOwningPlayer(PC); + } + } + for(auto& widget : overlayWidgetsInstances) + { + if(widget.IsValid()) + { + widget->SetOwningPlayer(PC); + } + } + } +} + +void UWidgetsManager::ShowInteractionHints(AInteractable* interactable) +{ + GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Interaction Hint")); + //interactable->GetInterfa +} \ No newline at end of file diff --git a/Source/Lost_Edge/Private/WidgetsManager.h b/Source/Lost_Edge/Private/WidgetsManager.h new file mode 100644 index 0000000..f521bf1 --- /dev/null +++ b/Source/Lost_Edge/Private/WidgetsManager.h @@ -0,0 +1,34 @@ +#pragma once + +// Oleg Petruny proprietary. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" + +#include "WidgetsManager.generated.h" + +UCLASS(Blueprintable) +class UWidgetsManager : public UObject +{ + GENERATED_BODY() + +public: + void Init(); + + void HideOverlayWidgets(); + void ShowOverlayWidgets(); + void UpdateOverlayWidgetsOwner(); + + void ShowInteractionHints(class AInteractable* interactable); + +protected: + UPROPERTY(EditDefaultsOnly) + TArray> permaOverlayWidgets; // never hidden + TArray> permaOverlayWidgetsInstances; + + UPROPERTY(EditDefaultsOnly) + TArray> overlayWidgets; // hidden in pause + TArray> overlayWidgetsInstances; +};