CustomGameInstance, CustomPlayerController

This commit is contained in:
Oleg Petruny 2024-12-13 00:20:57 +01:00
parent 39ab5e17a8
commit bb5ae58b06
33 changed files with 354 additions and 324 deletions

View File

@ -10,8 +10,8 @@
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameUserSettings.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
ACameraModeBase::ACameraModeBase()
@ -25,30 +25,12 @@ void ACameraModeBase::BeginPlay()
auto world = GetWorld();
//GetMovementComponent()->speed
// GetCharacterMovement()->MaxWalkSpeed = moveSpeed;
auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings();
if(auto camera = FindComponentByClass<UCameraComponent>())
{
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
if(auto PC = Cast<APlayerController>(GetController()))
{
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
{
inputSubsystem->ClearAllMappings();
for(auto& inputContext : GI->inputContexts)
{
inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0);
}
}
}
}
}
void ACameraModeBase::Tick(float DeltaTime)

View File

@ -7,7 +7,7 @@
#include "Kismet/GameplayStatics.h"
#include "UObject/Object.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameInstance.h"
#include "Levels/LevelBase.h"
#include "PlayerBase.h"
@ -86,7 +86,7 @@ void UCommonFunctions::EnterSlowMotion(float duration)
SlowMotion::targetDilation = SlowMotion::slowDilation;
auto GI = UCustomGameInstanceBase::GetGameInstance();
auto GI = UCustomGameInstance::GetGameInstance();
if(!GI)
return;
@ -101,7 +101,7 @@ void UCommonFunctions::ExitSlowMotion(float duration)
SlowMotion::targetDilation = SlowMotion::normalDilation;
auto GI = UCustomGameInstanceBase::GetGameInstance();
auto GI = UCustomGameInstance::GetGameInstance();
if(!GI)
return;
@ -116,7 +116,7 @@ FWorldDilationChangedDelegate& UCommonFunctions::GetWorldDilationChangedDelegate
void UCommonFunctions::SlowMotionTick()
{
const UWorld* world = UCustomGameInstanceBase::GetGameInstance()->GetWorld();
const UWorld* world = UCustomGameInstance::GetGameInstance()->GetWorld();
const float currentDilation = UGameplayStatics::GetGlobalTimeDilation(world);
float newDilation = FMath::FInterpTo(currentDilation, SlowMotion::targetDilation, 1, SlowMotion::interpolationSpeed);

View File

@ -0,0 +1,74 @@
// Oleg Petruny proprietary.
#include "CustomGameInstance.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "CommonFunctions.h"
#include "ContentLoader.h"
#include "Levels/LevelBase.h"
#include "PlayerBase.h"
#include "SaveData.h"
UCustomGameInstance* UCustomGameInstance::instance = nullptr;
void UCustomGameInstance::Init()
{
UGameInstance::Init();
instance = this;
contentLoader = NewObject<UContentLoader>(this);
saveData = Cast<USaveData>(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass()));
}
UCustomGameInstance* UCustomGameInstance::GetGameInstance()
{
return instance;
}
UContentLoader* UCustomGameInstance::GetContentLoader()
{
if(auto GI = GetGameInstance())
return GI->contentLoader;
return nullptr;
}
void UCustomGameInstance::SaveGame(FName checkpointName)
{
auto levelScript = UCommonFunctions::GetCurrentLevelScript(this);
if(!levelScript)
return;
auto player = UCommonFunctions::GetPlayer(this);
if(!player)
return;
saveData->level = GetWorld()->GetFName();
saveData->state = levelScript->GetState();
saveData->checkpoint = checkpointName;
if(player->leftPocketItem)
saveData->playerLeftPocketItem = player->leftPocketItem->GetFName();
else
saveData->playerLeftPocketItem = FName(TEXT(""));
if(player->rightPocketItem)
saveData->playerRightPocketItem = player->rightPocketItem->GetFName();
else
saveData->playerRightPocketItem = FName(TEXT(""));
UGameplayStatics::SaveGameToSlot(saveData, TEXT("Save"), 0);
}
void UCustomGameInstance::LoadGame()
{
saveData = Cast<USaveData>(UGameplayStatics::LoadGameFromSlot(TEXT("Save"), 0));
if(!saveData)
return;
UGameplayStatics::OpenLevel(this, saveData->level);
}
void UCustomGameInstance::ExitGame()
{
UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, true);
}

View File

@ -4,29 +4,29 @@
#include "Engine/GameInstance.h"
#include "CustomGameInstanceBase.generated.h"
#include "CustomGameInstance.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLevelBeginnedDelegate, FName, levelName);
/**
* Expands basic UE game instance.
* Manages saves, handles content loader and can shutdown the game.
*/
UCLASS()
class UCustomGameInstanceBase : public UGameInstance
class UCustomGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
/** Instantiates content loader, dummy save data and applies settings */
virtual void Init() override;
UFUNCTION(BlueprintPure)
static UCustomGameInstanceBase* GetGameInstance();
static UCustomGameInstance* GetGameInstance();
UFUNCTION(BlueprintPure)
static class UContentLoader* GetContentLoader();
UFUNCTION(BlueprintCallable, Category = Settings)
void ApplyMouseSettings();
void AppendInteractableModificatorClass(TSubclassOf<class UInteractableModificator> modificator);
UFUNCTION(BlueprintCallable, Category = Save)
void SaveGame(FName checkpointName);
UFUNCTION(BlueprintCallable, Category = Save)
@ -34,17 +34,11 @@ public:
UFUNCTION(BlueprintCallable)
void ExitGame();
static UCustomGameInstanceBase* instance;
static UCustomGameInstance* instance;
/** Public delegate called by ALevelBase instance on instantiation */
FLevelBeginnedDelegate OnLevelBeginned;
UPROPERTY(EditDefaultsOnly)
TSet<TSubclassOf<class UInteractableActivator>> interactionsActivators;
TSet<TSubclassOf<class UInteractableModificator>> interactionsModificators;
UPROPERTY(EditDefaultsOnly)
TSet<TSoftObjectPtr<class UInputMappingContext>> inputContexts;
UPROPERTY(VisibleAnywhere)
class USaveData* saveData = nullptr;

View File

@ -1,148 +0,0 @@
// Oleg Petruny proprietary.
#include "CustomGameInstanceBase.h"
#include "EnhancedInputLibrary.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "CommonFunctions.h"
#include "ContentLoader.h"
#include "CustomGameUserSettings.h"
#include "Interactable/Activators/InCameraInteractableActivator.h"
#include "Interactable/Activators/RaycastInteractableActivator.h"
#include "Interactable/Modificators/ActivateInteractableModificator.h"
#include "Interactable/Modificators/SawInteractableModificator.h"
#include "Levels/LevelBase.h"
#include "PlayerBase.h"
#include "SaveData.h"
UCustomGameInstanceBase* UCustomGameInstanceBase::instance = nullptr;
void UCustomGameInstanceBase::Init()
{
UGameInstance::Init();
instance = this;
contentLoader = NewObject<UContentLoader>(this);
interactionsActivators.Add(URaycastInteractableActivator::StaticClass());
interactionsActivators.Add(UInCameraInteractableActivator::StaticClass());
for(auto& modificator : interactionsModificators)
{
if(modificator.GetDefaultObject()->GetMappingContext())
{
inputContexts.Add(modificator.GetDefaultObject()->GetMappingContext());
}
}
ApplyMouseSettings();
saveData = Cast<USaveData>(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass()));
}
UCustomGameInstanceBase* UCustomGameInstanceBase::GetGameInstance()
{
return instance;
}
UContentLoader* UCustomGameInstanceBase::GetContentLoader()
{
if(auto GI = GetGameInstance())
return GI->contentLoader;
return nullptr;
}
void UCustomGameInstanceBase::ApplyMouseSettings()
{
if(auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings())
{
for(auto& context : inputContexts)
{
if(!context.LoadSynchronous())
continue;
for(auto& mapping : context.LoadSynchronous()->GetMappings())
{
if(mapping.Key == EKeys::Mouse2D)
{
for(auto& modifier : mapping.Modifiers)
{
if(auto negate_modifier = Cast<UInputModifierNegate>(modifier))
{
negate_modifier->bY = !gameSettings->bMouseInverted;
}
if(auto scalar_modifier = Cast<UInputModifierScalar>(modifier))
{
scalar_modifier->Scalar = FVector{ gameSettings->GetMouseSensetivity() * 0.5 };
}
}
}
}
UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext(context.LoadSynchronous());
}
}
}
void UCustomGameInstanceBase::AppendInteractableModificatorClass(TSubclassOf<class UInteractableModificator> modificator)
{
bool alreadyPresent = false;
interactionsModificators.Add(modificator, &alreadyPresent);
if(!alreadyPresent)
{
if(auto IC = modificator.GetDefaultObject()->GetMappingContext())
{
inputContexts.Add(IC);
if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
inputSubsystem->AddMappingContext(IC, 0);
}
}
}
}
}
void UCustomGameInstanceBase::SaveGame(FName checkpointName)
{
auto levelScript = UCommonFunctions::GetCurrentLevelScript(this);
if(!levelScript)
return;
auto player = UCommonFunctions::GetPlayer(this);
if(!player)
return;
saveData->level = GetWorld()->GetFName();
saveData->state = levelScript->GetState();
saveData->checkpoint = checkpointName;
if(player->leftPocketItem)
saveData->playerLeftPocketItem = player->leftPocketItem->GetFName();
else
saveData->playerLeftPocketItem = FName(TEXT(""));
if(player->rightPocketItem)
saveData->playerRightPocketItem = player->rightPocketItem->GetFName();
else
saveData->playerRightPocketItem = FName(TEXT(""));
UGameplayStatics::SaveGameToSlot(saveData, TEXT("Save"), 0);
}
void UCustomGameInstanceBase::LoadGame()
{
saveData = Cast<USaveData>(UGameplayStatics::LoadGameFromSlot(TEXT("Save"), 0));
if(!saveData)
return;
UGameplayStatics::OpenLevel(this, saveData->level);
}
void UCustomGameInstanceBase::ExitGame()
{
UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, true);
}

View File

@ -0,0 +1,90 @@
// Oleg Petruny proprietary.
#include "CustomPlayerController.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputLibrary.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "CustomGameUserSettings.h"
ACustomPlayerController* ACustomPlayerController::instance = nullptr;
UEnhancedInputLocalPlayerSubsystem* ACustomPlayerController::subsystem = nullptr;
UEnhancedInputComponent* ACustomPlayerController::input = nullptr;
TSet<TSoftObjectPtr<UInputMappingContext>> ACustomPlayerController::contexts = {};
void ACustomPlayerController::AppendInputContext(TSoftObjectPtr<class UInputMappingContext> context)
{
if(!context.IsValid())
return;
ApplyMouseSettings(context);
contexts.Add(context);
if(subsystem)
subsystem->AddMappingContext(context.LoadSynchronous(), 0);
}
void ACustomPlayerController::BeginPlay()
{
instance = this;
subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(instance->GetLocalPlayer());
if(subsystem)
{
subsystem->ClearAllMappings();
for(auto& inputContext : contexts)
subsystem->AddMappingContext(inputContext.LoadSynchronous(), 0);
}
input = Cast<UEnhancedInputComponent>(InputComponent);
if(input)
{
((UInputComponent*)input)->BindAction(TEXT("AnyKey"), IE_Pressed, this, &ACustomPlayerController::OnAnyKeyPressed);
((UInputComponent*)input)->BindAction(TEXT("AnyKey"), IE_Released, this, &ACustomPlayerController::OnAnyKeyReleased);
}
}
void ACustomPlayerController::ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context)
{
auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings();
if(!gameSettings)
return;
if(!context.LoadSynchronous())
return;
for(auto& mapping : context.LoadSynchronous()->GetMappings())
{
if(mapping.Key != EKeys::Mouse2D)
continue;
for(auto& modifier : mapping.Modifiers)
{
if(gameSettings->bMouseInverted)
{
if(auto negate_modifier = Cast<UInputModifierNegate>(modifier))
{
negate_modifier->bY = !negate_modifier->bY;
continue;
}
}
if(auto scalar_modifier = Cast<UInputModifierScalar>(modifier))
scalar_modifier->Scalar = FVector{ gameSettings->GetMouseSensetivity() * 0.5 };
}
}
UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext(context.LoadSynchronous());
}
void ACustomPlayerController::OnAnyKeyPressed(FKey key)
{
if(onAnyKeyPressed.IsBound())
onAnyKeyPressed.Broadcast(key);
}
void ACustomPlayerController::OnAnyKeyReleased(FKey key)
{
if(onAnyKeyReleased.IsBound())
onAnyKeyReleased.Broadcast(key);
}

View File

@ -0,0 +1,49 @@
// Oleg Petruny proprietary.
#pragma once
#include "GameFramework/PlayerController.h"
#include "CustomPlayerController.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyPressedDelegate, FKey, key);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyReleasedDelegate, FKey, key);
/**
* De-facto wrapper/interface of all usefull shortcuts and automatization around input system.
* Append new input context here for auto init on BeginPlay and apply user input settings.
* Also, has delegates onAnyKeyPressed/Released.
*/
UCLASS()
class ACustomPlayerController : public APlayerController
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintPure, meta = (DisplayName = "GetCustomPlayerController"))
static ACustomPlayerController* Get() { return instance; }
UFUNCTION(BlueprintPure)
static class UEnhancedInputComponent* GetInput() { return input; }
UFUNCTION(BlueprintPure)
static class UEnhancedInputLocalPlayerSubsystem* GetInputSubsystem() { return subsystem; }
UFUNCTION(BlueprintCallable)
static void AppendInputContext(TSoftObjectPtr<class UInputMappingContext> context);
FPlayerAnyKeyPressedDelegate onAnyKeyPressed;
FPlayerAnyKeyReleasedDelegate onAnyKeyReleased;
protected:
virtual void BeginPlay() override;
private:
static void ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context);
void OnAnyKeyPressed(FKey key);
void OnAnyKeyReleased(FKey key);
static ACustomPlayerController* instance;
static class UEnhancedInputLocalPlayerSubsystem* subsystem;
static class UEnhancedInputComponent* input;
static TSet<TSoftObjectPtr<class UInputMappingContext>> contexts;
};

View File

@ -9,7 +9,7 @@
#include "LevelSequence.h"
#include "LevelSequencePlayer.h"
#include "CustomGameInstanceBase.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "Widgets/CutsceneSkipWidget.h"
@ -20,10 +20,7 @@ UCutsceneManager::UCutsceneManager()
{
static ConstructorHelpers::FObjectFinder<UInputMappingContext> asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Cutscene.IMC_Cutscene'") };
_inputContext = asset.Object;
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
{
GI->inputContexts.Add(_inputContext);
}
ACustomPlayerController::AppendInputContext(_inputContext);
}
void UCutsceneManager::EnqueueSequence(ULevelSequence* sequence, FCutsceneEndCallback endCallback)
@ -44,8 +41,9 @@ void UCutsceneManager::EnqueueSequence(ULevelSequence* sequence, FCutsceneEndCal
_lastPlayer->LockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true });
auto& mapping = _inputContext.LoadSynchronous()->GetMapping(0);
int32 handler1 = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Started, this, &UCutsceneManager::OnInputHold).GetHandle();
int32 handler2 = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UCutsceneManager::OnInputUnhold).GetHandle();
auto input = ACustomPlayerController::GetInput();
int32 handler1 = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &UCutsceneManager::OnInputHold).GetHandle();
int32 handler2 = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UCutsceneManager::OnInputUnhold).GetHandle();
_handlers = { handler1, handler2 };
if(auto WM = AMainGameModeBase::GetWidgetsManager())
@ -148,8 +146,9 @@ void UCutsceneManager::OnSequenceEnd()
{
_lastPlayer->UnlockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true });
_lastPlayer->inputComponent->RemoveBindingByHandle(_handlers.Key);
_lastPlayer->inputComponent->RemoveBindingByHandle(_handlers.Value);
auto input = ACustomPlayerController::GetInput();
input->RemoveBindingByHandle(_handlers.Key);
input->RemoveBindingByHandle(_handlers.Value);
_lastPlayer = nullptr;
}

View File

@ -11,7 +11,7 @@
#include "Kismet/KismetMathLibrary.h"
#include "Sound/SoundWave.h"
#include "CustomGameInstanceBase.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "Widgets/DialogueSkipWidget.h"
@ -22,10 +22,7 @@ UDialogueManager::UDialogueManager()
{
static ConstructorHelpers::FObjectFinder<UInputMappingContext> asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Dialogue.IMC_Dialogue'") };
_inputContext = asset.Object;
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
{
GI->inputContexts.Add(_inputContext);
}
ACustomPlayerController::AppendInputContext(_inputContext);
}
void UDialogueManager::PlayDialogue(FDialogueEnqueProperties properties, FDialogueEndCallback endCallback)
@ -96,7 +93,7 @@ void UDialogueManager::EnqueDialogue(FDialogueEnqueProperties properties, FDialo
if(_lastPlayer)
{
auto& mapping = _inputContext.LoadSynchronous()->GetMapping(0);
_inputHandler = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UDialogueManager::OnInputPress).GetHandle();
_inputHandler = ACustomPlayerController::GetInput()->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UDialogueManager::OnInputPress).GetHandle();
if(auto WM = AMainGameModeBase::GetWidgetsManager())
{
@ -258,7 +255,7 @@ void UDialogueManager::OnDialogueEnd()
_dialoguesLock.Lock();
if(_endCallbacks.IsEmpty() && _lastPlayer)
{
_lastPlayer->inputComponent->RemoveBindingByHandle(_inputHandler);
ACustomPlayerController::GetInput()->RemoveBindingByHandle(_inputHandler);
_lastPlayer = nullptr;
}
_dialoguesLock.Unlock();

View File

@ -30,7 +30,7 @@ UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInit
void UInCameraInteractableActivator::OnRegister()
{
UInteractableActivator::OnRegister();
Super::OnRegister();
capturer->RegisterComponent();
capturer->Activate();
}

View File

@ -20,6 +20,8 @@ public:
protected:
virtual void OnRegister() override;
virtual bool AutoInstantiateInPlayer() override { return true; }
/**
* Scan is performed independently by _capturer member object.
* This implementation just activates interactables in the game thread.

View File

@ -4,8 +4,16 @@
#include "Engine/CollisionProfile.h"
#include "Interactable/Interactable.h"
#include "PlayerBase.h"
void UInteractableActivator::OnRegister()
{
Super::OnRegister();
AInteractable::AppendInteractableActivatorClass(GetClass());
}
UInteractableActivator::UInteractableActivator(const FObjectInitializer& ObjectInitializer)
: USceneComponent(ObjectInitializer)
{

View File

@ -20,9 +20,14 @@ class UInteractableActivator : public USceneComponent
GENERATED_BODY()
public:
/** Append itself to CustomGameInstance modificators registry */
virtual void OnRegister() override;
UInteractableActivator(const FObjectInitializer& ObjectInitializer);
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
virtual bool AutoInstantiateInPlayer() { return false; }
/** Resets activator state forcing to rescan */
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
LOST_EDGE_API void Rescan();

View File

@ -17,6 +17,8 @@ class URaycastInteractableActivator : public UInteractableActivator
public:
URaycastInteractableActivator(const FObjectInitializer& ObjectInitializer);
virtual bool AutoInstantiateInPlayer() override { return true; }
virtual void Rescan_Implementation() override;
protected:

View File

@ -4,11 +4,32 @@
#include "Kismet/GameplayStatics.h"
#include "Activators/InteractableActivator.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "Modificators/InteractableModificator.h"
#include "PlayerBase.h"
#include "Widgets/WidgetsManager.h"
TSet<TSubclassOf<class UInteractableActivator>> AInteractable::interactionActivators = {};
TSet<TSubclassOf<class UInteractableModificator>> AInteractable::interactionModificators = {};
void AInteractable::AppendInteractableActivatorClass(TSubclassOf<class UInteractableActivator> activator)
{
interactionActivators.Add(activator);
}
void AInteractable::AppendInteractableModificatorClass(TSubclassOf<class UInteractableModificator> modificator)
{
bool alreadyPresent = false;
interactionModificators.Add(modificator, &alreadyPresent);
if(alreadyPresent)
return;
auto IC = modificator.GetDefaultObject()->GetMappingContext();
ACustomPlayerController::AppendInputContext(IC);
}
int32 AInteractable::GetActivatedFlags()
{
return activated;
@ -112,7 +133,7 @@ void AInteractable::Activate(EActivatorType type)
if(static_cast<uint8>(modificator.Value->GetActivatorTypes()) & static_cast<uint8>(type))
{
WM->ShowInteractionHints(modificator.Value);
modificator.Value->Bind(player->inputComponent);
modificator.Value->Bind(ACustomPlayerController::GetInput());
}
}
}

View File

@ -40,6 +40,15 @@ class AInteractable : public AActor
GENERATED_BODY()
public:
static void AppendInteractableActivatorClass(TSubclassOf<class UInteractableActivator> activator);
static void AppendInteractableModificatorClass(TSubclassOf<class UInteractableModificator> modificator);
/** Interactables shared cache */
static TSet<TSubclassOf<class UInteractableActivator>> interactionActivators;
static TSet<TSubclassOf<class UInteractableModificator>> interactionModificators;
public:
/** Returns flags mask of activated types */
int32 GetActivatedFlags();

View File

@ -2,24 +2,19 @@
#include "InteractableModificator.h"
#include "InputMappingContext.h"
#include "CustomGameInstanceBase.h"
#include "Interactable/Interactable.h"
#include "Widgets/InteractableHintWidget.h"
void UInteractableModificator::OnRegister()
{
UActorComponent::OnRegister();
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
{
GI->AppendInteractableModificatorClass(this->GetClass());
}
AInteractable::AppendInteractableModificatorClass(GetClass());
}
const UInputMappingContext* UInteractableModificator::GetMappingContext() const
const TSoftObjectPtr<class UInputMappingContext> UInteractableModificator::GetMappingContext() const
{
return inputMapping.LoadSynchronous();
return inputMapping;
}
EActivatorType UInteractableModificator::GetActivatorTypes() const

View File

@ -18,11 +18,11 @@ class UInteractableModificator : public UActorComponent
public:
/** Append itself to CustomGameInstance modificators registry */
void OnRegister() override;
virtual void OnRegister() override;
/** Returns input mappings assigned in constructor */
UFUNCTION(BlueprintCallable)
const class UInputMappingContext* GetMappingContext() const;
const TSoftObjectPtr<class UInputMappingContext> GetMappingContext() const;
/** Filters activation type in interractable */
UFUNCTION(BlueprintCallable)

View File

@ -2,10 +2,10 @@
#include "Checkpoint.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameInstance.h"
void ACheckpoint::SaveGame()
{
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
if(auto GI = UCustomGameInstance::GetGameInstance())
GI->SaveGame(GetFName());
}

View File

@ -10,7 +10,8 @@
#include "LevelSequencePlayer.h"
#include "CommonFunctions.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameInstance.h"
#include "CustomPlayerController.h"
#include "Interactable/Interactable.h"
#include "Levels/Checkpoint.h"
#include "MainGameModeBase.h"
@ -22,13 +23,8 @@ void ALevelBase::BeginPlay()
{
AMainGameModeBase::leadLevel = TStrongObjectPtr<ALevelBase>{ this };
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
{
for(TActorIterator<AMinigame> it(GetWorld()); it; ++it)
{
GI->inputContexts.Add(it->GetInputMappings());
}
}
ACustomPlayerController::AppendInputContext(it->GetInputMappings());
ALevelScriptActor::BeginPlay();
@ -58,7 +54,7 @@ void ALevelBase::IterateToState(int32 to)
void ALevelBase::BroadcastNewLevelBeginPlay()
{
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
if(auto GI = UCustomGameInstance::GetGameInstance())
GI->OnLevelBeginned.Broadcast(GetFName());
}
@ -79,7 +75,7 @@ void ALevelBase::StartLevelAnimations()
void ALevelBase::ApplySaveData()
{
auto GI = UCustomGameInstanceBase::GetGameInstance();
auto GI = UCustomGameInstance::GetGameInstance();
if(!GI || !GI->saveData || GI->saveData->level != GetWorld()->GetFName())
return;

View File

@ -8,7 +8,7 @@
#include "Kismet/GameplayStatics.h"
#include "UObject/ScriptInterface.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameInstance.h"
#include "CutsceneManager.h"
#include "DialogueManager.h"
#include "Levels/LevelBase.h"

View File

@ -10,7 +10,7 @@
#include "InputMappingContext.h"
#include "CrossyRoadObstacle.h"
#include "CustomGameInstanceBase.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "Widgets/WidgetsManager.h"
@ -19,7 +19,7 @@ ACrossyRoadManager::ACrossyRoadManager()
: AMinigame()
{
static ConstructorHelpers::FObjectFinder<UInputMappingContext> asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_Minigame_CrossyRoad.IMC_Minigame_CrossyRoad'") };
input = asset.Object;
context = asset.Object;
auto root = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
@ -43,16 +43,17 @@ void ACrossyRoadManager::Start(APlayerBase* playerPawn, FMinigameEndCallback del
player->LockPlayer(FPlayerLock::All());
player->SwitchToView(this);
for(auto& mapping : input.LoadSynchronous()->GetMappings())
auto input = ACustomPlayerController::GetInput();
for(auto& mapping : context.LoadSynchronous()->GetMappings())
{
if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Up"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Up).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Up).GetHandle());
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Down"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Down).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Down).GetHandle());
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Left"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Left).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Left).GetHandle());
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Right"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Right).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Right).GetHandle());
}
playerPos->SetWorldLocation(lines[0]->GetLocationAtTime(lines[0]->Duration * playerLineTime, ESplineCoordinateSpace::World));
@ -70,7 +71,7 @@ void ACrossyRoadManager::End()
PrimaryActorTick.SetTickFunctionEnable(false);
for(int32 handler : inputHandlers)
player->inputComponent->RemoveBindingByHandle(handler);
ACustomPlayerController::GetInput()->RemoveBindingByHandle(handler);
player->UnlockPlayer(FPlayerLock::All());
player->ReturnPlayerView();

View File

@ -6,13 +6,14 @@
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
AFishingManager::AFishingManager()
{
static ConstructorHelpers::FObjectFinder<UInputMappingContext> asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_Minigame_Fishing.IMC_Minigame_Fishing'") };
input = asset.Object;
context = asset.Object;
}
void AFishingManager::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate)
@ -24,15 +25,17 @@ void AFishingManager::Start(APlayerBase* playerPawn, FMinigameEndCallback delega
player->LockPlayer(FPlayerLock::All());
auto& mapping = input.LoadSynchronous()->GetMapping(0);
handler1 = player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Started, this, &AFishingManager::OnInputHold).GetHandle();
handler2 = player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Completed, this, &AFishingManager::OnInputUnhold).GetHandle();
auto input = ACustomPlayerController::GetInput();
auto& mapping = context.LoadSynchronous()->GetMapping(0);
handler1 = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &AFishingManager::OnInputHold).GetHandle();
handler2 = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &AFishingManager::OnInputUnhold).GetHandle();
}
void AFishingManager::End()
{
player->inputComponent->RemoveBindingByHandle(handler1);
player->inputComponent->RemoveBindingByHandle(handler2);
auto input = ACustomPlayerController::GetInput();
input->RemoveBindingByHandle(handler1);
input->RemoveBindingByHandle(handler2);
player->UnlockPlayer(FPlayerLock::All());

View File

@ -27,7 +27,7 @@ void AMinigame::Restart()
UInputMappingContext* AMinigame::GetInputMappings()
{
return input.LoadSynchronous();
return context.LoadSynchronous();
}
void AMinigame::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate)
@ -35,10 +35,10 @@ void AMinigame::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate)
player = playerPawn;
callback = delegate;
if(input)
if(context)
if(auto PC = Cast<APlayerController>(playerPawn->GetController()))
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
inputSubsystem->AddMappingContext(input.LoadSynchronous(), 0);
inputSubsystem->AddMappingContext(context.LoadSynchronous(), 0);
OnStart();
}

View File

@ -55,6 +55,6 @@ protected:
bool ended = false;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TSoftObjectPtr<class UInputMappingContext> input = nullptr;
TSoftObjectPtr<class UInputMappingContext> context = nullptr;
};

View File

@ -9,7 +9,7 @@
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "CustomGameInstanceBase.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "SubwaySurfObstacle.h"
@ -19,7 +19,7 @@ ASubwaySurfManager::ASubwaySurfManager()
: AMinigame()
{
static ConstructorHelpers::FObjectFinder<UInputMappingContext> asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_Minigame_SubwaySurf.IMC_Minigame_SubwaySurf'") };
input = asset.Object;
context = asset.Object;
auto root = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
@ -43,16 +43,17 @@ void ASubwaySurfManager::Start(APlayerBase* playerPawn, FMinigameEndCallback del
player->LockPlayer(FPlayerLock::All());
player->SwitchToView(this);
for(auto& mapping : input.LoadSynchronous()->GetMappings())
auto input = ACustomPlayerController::GetInput();
for(auto& mapping : context.LoadSynchronous()->GetMappings())
{
if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Up"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Up).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Up).GetHandle());
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Down"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Down).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Down).GetHandle());
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Left"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Left).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Left).GetHandle());
else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Right"))))
inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Right).GetHandle());
inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Right).GetHandle());
}
playerPos->SetRelativeLocation(lines[1]->GetLocationAtTime(lines[1]->Duration * 0.01f, ESplineCoordinateSpace::Local));
@ -66,7 +67,7 @@ void ASubwaySurfManager::End()
PrimaryActorTick.SetTickFunctionEnable(false);
for(int32 handler : inputHandlers)
player->inputComponent->RemoveBindingByHandle(handler);
ACustomPlayerController::GetInput()->RemoveBindingByHandle(handler);
player->UnlockPlayer(FPlayerLock::All());
player->ReturnPlayerView();

View File

@ -4,16 +4,14 @@
#include "PlayerBase.h"
#include "Camera/CameraComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetMathLibrary.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameUserSettings.h"
#include "CustomPlayerController.h"
#include "Interactable/Activators/InteractableActivator.h"
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
@ -84,44 +82,9 @@ void APlayerBase::BeginPlay()
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
playerController = Cast<APlayerController>(GetController());
if(playerController)
{
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(playerController->GetLocalPlayer()))
{
if(auto GI = UCustomGameInstanceBase::GetGameInstance())
{
inputSubsystem->ClearAllMappings();
for(auto& inputContext : GI->inputContexts)
{
inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0);
}
}
}
inputComponent = Cast<UEnhancedInputComponent>(playerController->InputComponent);
if(inputComponent)
{
((UInputComponent*)inputComponent)->BindAction(TEXT("AnyKey"), IE_Pressed, this, &APlayerBase::OnAnyKeyPressed);
((UInputComponent*)inputComponent)->BindAction(TEXT("AnyKey"), IE_Released, this, &APlayerBase::OnAnyKeyReleased);
}
}
LoadInteractablesActivators();
}
void APlayerBase::OnAnyKeyPressed(FKey key)
{
if(onAnyKeyPressedDelegate.IsBound())
onAnyKeyPressedDelegate.Broadcast(key);
}
void APlayerBase::OnAnyKeyReleased(FKey key)
{
if(onAnyKeyReleasedDelegate.IsBound())
onAnyKeyReleasedDelegate.Broadcast(key);
}
bool APlayerBase::IsMoving()
{
return bIsMoving;
@ -257,12 +220,8 @@ void APlayerBase::UpdatePitch(float min, float max)
void APlayerBase::LoadInteractablesActivators()
{
auto GI = UCustomGameInstanceBase::GetGameInstance();
if(!GI)
return;
TSet<UClass*> instancedActivators;
for(auto& act : GI->interactionsActivators)
for(auto& act : AInteractable::interactionActivators)
{
if(instancedActivators.Contains(act))
continue;

View File

@ -8,8 +8,6 @@
enum class EActivatorType : uint8;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyPressedDelegate, FKey, key);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyReleasedDelegate, FKey, key);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPlayerMovedDelegate);
USTRUCT(BlueprintType)
@ -66,20 +64,12 @@ public:
FPlayerMovedDelegate OnPlayerMoved;
FVector moveVector;
FPlayerAnyKeyPressedDelegate onAnyKeyPressedDelegate;
FPlayerAnyKeyReleasedDelegate onAnyKeyReleasedDelegate;
class UEnhancedInputComponent* inputComponent = nullptr;
class AActor* leftPocketItem = nullptr;
class AActor* rightPocketItem = nullptr;
protected:
virtual void BeginPlay() override;
void OnAnyKeyPressed(FKey key);
void OnAnyKeyReleased(FKey key);
UFUNCTION(BlueprintCallable, Category = CameraMode)
void SwitchToCameraPawn();

View File

@ -6,6 +6,7 @@
#include "Kismet/GameplayStatics.h"
#include "CommonFunctions.h"
#include "CustomPlayerController.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "Widgets/WidgetsManager.h"
@ -84,10 +85,10 @@ void UQuickTimeEventManager::OnEventEnd(int32 id, EQuickTimeEventResult result)
if(_events.IsEmpty())
{
if(auto player = UCommonFunctions::GetPlayer(this))
if(auto PC = ACustomPlayerController::Get())
{
player->onAnyKeyPressedDelegate.RemoveDynamic(this, &UQuickTimeEventManager::OnInputPressed);
player->onAnyKeyReleasedDelegate.RemoveDynamic(this, &UQuickTimeEventManager::OnInputReleased);
PC->onAnyKeyPressed.RemoveDynamic(this, &UQuickTimeEventManager::OnInputPressed);
PC->onAnyKeyReleased.RemoveDynamic(this, &UQuickTimeEventManager::OnInputReleased);
}
UCommonFunctions::ExitSlowMotion();
}
@ -153,12 +154,12 @@ void UQuickTimeEventManager::OnFirstEventInit()
{
if(_events.IsEmpty())
{
if(auto player = UCommonFunctions::GetPlayer(this))
if(auto PC = ACustomPlayerController::Get())
{
GetWorld()->GetTimerManager().SetTimerForNextTick([manager = this, player = player]()
GetWorld()->GetTimerManager().SetTimerForNextTick([=, this]()
{
player->onAnyKeyPressedDelegate.AddDynamic(manager, &UQuickTimeEventManager::OnInputPressed);
player->onAnyKeyReleasedDelegate.AddDynamic(manager, &UQuickTimeEventManager::OnInputReleased);
PC->onAnyKeyPressed.AddDynamic(this, &UQuickTimeEventManager::OnInputPressed);
PC->onAnyKeyReleased.AddDynamic(this, &UQuickTimeEventManager::OnInputReleased);
});
}
UCommonFunctions::EnterSlowMotion();
@ -168,12 +169,12 @@ void UQuickTimeEventManager::OnFirstEventInit()
void UQuickTimeEventManager::CreateEvent(FQuickTimeEventEnqueProperties& properties, bool sequence)
{
Event event{ properties.type, properties.key, properties.callback, sequence };
GetWorld()->GetTimerManager().SetTimer(event.timer, [id = event.GetId(), manager = this]()
GetWorld()->GetTimerManager().SetTimer(event.timer, [id = event.GetId(), this]()
{
EQuickTimeEventResult result = EQuickTimeEventResult::FailedTime;
if(auto WM = AMainGameModeBase::GetWidgetsManager())
result = WM->RemoveQuickTimeEvent(id);
manager->OnEventEnd(id, result);
this->OnEventEnd(id, result);
}, properties.duration, false);
_events.Add(event.GetId(), event);

View File

@ -23,10 +23,10 @@ void UInteractableHintWidgetManager::Append(const UInteractableModificator* modi
return;
}
if(hintsMap.Contains(modificator) || !modificator->GetMappingContext())
if(hintsMap.Contains(modificator) || !modificator->GetMappingContext().IsValid())
return;
const auto& mappings = modificator->GetMappingContext()->GetMappings();
const auto& mappings = modificator->GetMappingContext().LoadSynchronous()->GetMappings();
for(int32 i = hints->GetChildrenCount() - count - mappings.Num(); i < 0; ++i)
{

View File

@ -5,7 +5,7 @@
#include "Animation/WidgetAnimation.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameInstance.h"
#include "MainGameModeBase.h"
#include "MainMenuButtonWidget.h"
#include "Widgets/WidgetsManager.h"
@ -14,7 +14,7 @@ bool UMainMenuWidget::Initialize()
{
if(ButtonLoadLastSave)
{
auto GI = UCustomGameInstanceBase::GetGameInstance();
auto GI = UCustomGameInstance::GetGameInstance();
if(GI && GI->saveData)
{
ButtonLoadLastSave->SetIsEnabled(true);

View File

@ -10,7 +10,7 @@
#include "Kismet/GameplayStatics.h"
#include "UObject/ScriptInterface.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameInstance.h"
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "Interactable/Modificators/InventoryInteractableModificator.h"