Lost_Edge/Source/Lost_Edge/Private/PlayerBase.cpp

366 lines
9.2 KiB
C++

// Oleg Petruny proprietary.
#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 "Interactable/Activators/InteractableActivator.h"
#include "Interactable/Interactable.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "MainGameModeBase.h"
#include "Widgets/WidgetsManager.h"
namespace
{
const FVector cameraLocation = { 10, 0, 70 };
}
APlayerBase::APlayerBase()
: ACharacter()
{
PrimaryActorTick.bCanEverTick = true;
camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
camera->SetRelativeLocation(cameraLocation);
camera->SetRelativeScale3D(FVector{ 0.25, 0.25, 0.25 });
camera->bUsePawnControlRotation = true;
camera->SetupAttachment(RootComponent);
itemDropSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("ItemDropSpringArm"));
itemDropSpringArm->TargetArmLength = -200;
itemDropSpringArm->SetupAttachment(camera);
}
void APlayerBase::Tick(float DeltaTime)
{
ACharacter::Tick(DeltaTime);
// stabilize move speed by fps
AddActorLocalOffset(ConsumeMovementInputVector() * DeltaTime);
// update isMoving flag
auto loc = GetActorLocation();
bIsMoving = (loc != oldLocation);
oldLocation = std::move(loc);
rotationInput = FRotator::ZeroRotator;
}
void APlayerBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
ACharacter::SetupPlayerInputComponent(PlayerInputComponent);
}
void APlayerBase::BeginPlay()
{
ACharacter::BeginPlay();
auto world = GetWorld();
oldLocation = GetActorLocation();
GetCharacterMovement()->MaxWalkSpeed = moveSpeed;
cameraManager = UGameplayStatics::GetPlayerCameraManager(world, 0);
if(cameraManager)
{
cameraManager->ViewPitchMin = minPitch;
cameraManager->ViewPitchMax = maxPitch;
}
auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings();
if(camera)
{
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
playerController = Cast<APlayerController>(GetController());
if(playerController)
{
inputComponent = Cast<UEnhancedInputComponent>(playerController->InputComponent);;
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(playerController->GetLocalPlayer()))
{
if(auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()))
{
inputSubsystem->ClearAllMappings();
for(auto& inputContext : GI->inputContexts)
{
inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0);
}
}
}
}
LoadInteractablesActivators();
}
bool APlayerBase::IsMoving()
{
return bIsMoving;
}
bool APlayerBase::IsRunning()
{
return GetCharacterMovement()->MaxWalkSpeed > moveSpeed;
}
void APlayerBase::LockPlayer(FPlayerLock lock)
{
walkLocked += lock.walk;
jumpLocked += lock.jump;
runLocked += lock.run;
interactionLocked += lock.interaction;
cameraLocked += lock.camera;
inventoryLocked += lock.inventory;
}
void APlayerBase::UnlockPlayer(FPlayerLock lock)
{
walkLocked -= lock.walk;
jumpLocked -= lock.jump;
runLocked -= lock.run;
interactionLocked -= lock.interaction;
cameraLocked -= lock.camera;
inventoryLocked -= lock.inventory;
}
void APlayerBase::FlyMode(bool on)
{
GetCharacterMovement()->GravityScale = on ? 0.0f : 1.0f;
}
FVector APlayerBase::GetCameraDirection()
{
return camera->GetForwardVector();
}
FVector APlayerBase::GetCameraLocation()
{
return camera->GetComponentLocation();
}
void APlayerBase::SwitchToCameraPawn()
{
if(auto gamemode_base = UGameplayStatics::GetGameMode(GetWorld()))
{
if(auto gamemode = Cast<AMainGameModeBase>(gamemode_base))
{
gamemode->SwitchCameraMode();
}
}
}
void APlayerBase::SwitchToView(AActor* target)
{
((APlayerController*)Controller)->SetViewTargetWithBlend(target, 0.3f);
}
void APlayerBase::ReturnPlayerView()
{
((APlayerController*)Controller)->SetViewTargetWithBlend(this, 0.3f);
}
void APlayerBase::MoveCamera(FVector2D value)
{
if(cameraLocked)
return;
AddControllerYawInput(value.X);
rotationInput.Yaw = value.X;
AddControllerPitchInput(value.Y);
rotationInput.Pitch = value.Y;
}
void APlayerBase::MoveCharacter(FVector2D value)
{
if(walkLocked)
return;
moveVector = GetActorRightVector() * value.X;
moveVector += GetActorForwardVector() * value.Y;
moveVector.Normalize(UE_KINDA_SMALL_NUMBER);
AddMovementInput(moveVector);
}
void APlayerBase::Jump()
{
if(jumpLocked)
return;
ACharacter::Jump();
}
void APlayerBase::SwitchRun(bool run)
{
if(runLocked)
return;
if(run)
GetCharacterMovement()->MaxWalkSpeed = moveSpeed * runSpeedMultiplier;
else
GetCharacterMovement()->MaxWalkSpeed = moveSpeed;
}
void APlayerBase::UpdatePitch(float min, float max)
{
minPitch = min;
maxPitch = max;
if(cameraManager)
{
cameraManager->ViewPitchMin = minPitch;
cameraManager->ViewPitchMax = maxPitch;
}
}
void APlayerBase::LoadInteractablesActivators()
{
if(auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()))
{
TSet<UClass*> instancedActivators;
for(auto& act : GI->interactionsActivators)
{
if(instancedActivators.Contains(act))
continue;
instancedActivators.Add(act);
auto component = NewObject<UInteractableActivator>(this, act);
component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated);
component->interactableDeactivatedDelegate.BindUObject(this, &APlayerBase::InteractableDeactivated);
component->SetupAttachment(camera);
component->RegisterComponent();
}
}
}
void APlayerBase::InteractableActivated(AInteractable* interactable, EActivatorType type)
{
if(!interactable)
return;
if(interactionLocked)
return;
interactable->_Activate(type);
if(interactable != lastInteractable)
lastInteractable = interactable;
}
void APlayerBase::InteractableDeactivated(AInteractable* interactable, EActivatorType type)
{
if(!interactable)
return;
if(interactionLocked)
return;
interactable->_Deactivate(type);
if(interactable->GetActivatedFlags() == 0)
lastInteractable = nullptr;
}
bool APlayerBase::IsInInventory(const AActor* actor)
{
return (actor == leftPocketItem) || (actor == rightPocketItem);
}
void APlayerBase::TakeToInventory(AActor* actor)
{
actor->SetActorHiddenInGame(true);
actor->SetActorEnableCollision(false);
actor->SetActorTickEnabled(false);
actor->AttachToComponent(itemDropSpringArm, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
}
void APlayerBase::TakeItemToLeftHand(AActor* actor)
{
if(inventoryLocked || itemDropLocked)
return;
TakeToInventory(actor);
itemDropSpringArm->TickComponent(0, ELevelTick::LEVELTICK_All, nullptr);
DropLeftHandItem();
leftPocketItem = actor;
itemDropLocked = true;
GetWorld()->GetTimerManager().SetTimer(itemDropLockTimer, [&]() { itemDropLocked = false; }, 0.25f, false);
}
void APlayerBase::TakeItemToRightHand(AActor* actor)
{
if(inventoryLocked || itemDropLocked)
return;
TakeToInventory(actor);
itemDropSpringArm->TickComponent(0, ELevelTick::LEVELTICK_All, nullptr);
DropRightHandItem();
rightPocketItem = actor;
itemDropLocked = true;
GetWorld()->GetTimerManager().SetTimer(itemDropLockTimer, [&]() { itemDropLocked = false; }, 0.25f, false);
}
void APlayerBase::DropItem(AActor* actor)
{
actor->DetachFromActor(FDetachmentTransformRules::KeepWorldTransform);
actor->SetActorHiddenInGame(false);
actor->SetActorEnableCollision(true);
actor->SetActorTickEnabled(true);
}
void APlayerBase::DropLeftHandItem()
{
if(!leftPocketItem || itemDropLocked)
return;
DropItem(leftPocketItem);
leftPocketItem = nullptr;
if(auto WM = AMainGameModeBase::GetWidgetsManager())
WM->SetInventoryFirstItem(FText::GetEmpty());
}
void APlayerBase::DropRightHandItem()
{
if(!rightPocketItem || itemDropLocked)
return;
DropItem(rightPocketItem);
rightPocketItem = nullptr;
if(auto WM = AMainGameModeBase::GetWidgetsManager())
WM->SetInventorySecondItem(FText::GetEmpty());
}
void APlayerBase::ShowInventory()
{
if(inventoryLocked)
return;
if(auto WM = AMainGameModeBase::GetWidgetsManager())
WM->ShowInventory();
}
void APlayerBase::ShowJournal()
{
if(auto WM = AMainGameModeBase::GetWidgetsManager())
WM->ShowJournal();
}
FPlayerLock FPlayerLock::All()
{
FPlayerLock lock;
std::memset(&lock, 0xFF, sizeof(FPlayerLock));
return std::move(lock);
}