Initialize Git with LFS for binary assets and add standard Unreal Engine .gitignore/.gitattributes. Co-authored-by: Cursor <cursoragent@cursor.com>
165 lines
4.6 KiB
C++
165 lines
4.6 KiB
C++
// REALMS IN RUIN. Copyright (c) 2025 Trevor Edwards. All rights reserved.
|
||
|
||
#include "Player/RIRPlayerController.h"
|
||
#include "EnhancedInputComponent.h"
|
||
#include "EnhancedInputSubsystems.h"
|
||
#include "GameFramework/Pawn.h"
|
||
#include "GameFramework/PlayerController.h"
|
||
#include "Interfaces/TargetInterface.h"
|
||
|
||
ARIRPlayerController::ARIRPlayerController()
|
||
{
|
||
bReplicates = true;
|
||
}
|
||
|
||
void ARIRPlayerController::PlayerTick(float DeltaTime)
|
||
{
|
||
Super::PlayerTick(DeltaTime);
|
||
|
||
CursorTrace();
|
||
}
|
||
|
||
void ARIRPlayerController::BindCallbacksToDependencies()
|
||
{
|
||
|
||
}
|
||
|
||
void ARIRPlayerController::CursorTrace()
|
||
{
|
||
// TODO: Modify this to be controller-compatible
|
||
// Additionally, create separate function to handle Gauntlet-style directional target line
|
||
// Cleanup unnecessary comments as needed
|
||
|
||
FHitResult CursorHit;
|
||
|
||
// Perform a visibility trace from the mouse cursor position
|
||
GetHitResultUnderCursor(ECC_Visibility, false, CursorHit);
|
||
|
||
// Exit early if the trace didn't hit anything
|
||
if (!CursorHit.bBlockingHit)
|
||
{
|
||
LastActor = ThisActor;
|
||
ThisActor = nullptr;
|
||
return;
|
||
}
|
||
|
||
// Cache the actor under the cursor
|
||
AActor* HitActor = CursorHit.GetActor();
|
||
|
||
// Store the previous targeted actor
|
||
LastActor = ThisActor;
|
||
|
||
// Validate that the hit actor exists and implements ITargetInterface
|
||
if (HitActor && HitActor->GetClass()->ImplementsInterface(UTargetInterface::StaticClass()))
|
||
{
|
||
// Wrap in TScriptInterface safely
|
||
ThisActor = TScriptInterface<ITargetInterface>(HitActor);
|
||
}
|
||
else
|
||
{
|
||
ThisActor = nullptr;
|
||
}
|
||
|
||
/**
|
||
* Line trace from cursor. There are several scenarios:
|
||
* A. LastActor is null && ThisActor is null
|
||
* - Do nothing
|
||
* B. LastActor is null && ThisActor is valid
|
||
* - Highlight ThisActor
|
||
* C. LastActor is valid && ThisActor is null
|
||
* - UnHighlight LastActor
|
||
* D. Both actors are valid, but LastActor != ThisActor
|
||
* - UnHighlight LastActor and Highlight ThisActor
|
||
* E. Both actors are valid, and are the same actor
|
||
* - Do nothing
|
||
*/
|
||
|
||
if (!LastActor) // LastActor is null
|
||
{
|
||
if (ThisActor)
|
||
{
|
||
// Case B: highlight newly found actor
|
||
ThisActor->HighlightActor();
|
||
}
|
||
// Case A: both are null – do nothing
|
||
}
|
||
else // LastActor is valid
|
||
{
|
||
if (!ThisActor)
|
||
{
|
||
// Case C: Unhighlight the old actor, nothing to highlight now
|
||
LastActor->UnHighlightActor();
|
||
}
|
||
else if (LastActor != ThisActor)
|
||
{
|
||
// Case D: new target is different – update both visuals
|
||
LastActor->UnHighlightActor();
|
||
ThisActor->HighlightActor();
|
||
}
|
||
// Case E: same actor – do nothing
|
||
}
|
||
}
|
||
|
||
void ARIRPlayerController::BeginPlay()
|
||
{
|
||
Super::BeginPlay();
|
||
check(PlayerMappingContext);
|
||
|
||
// Set up Enhanced Input system for this player
|
||
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
||
if (Subsystem)
|
||
{
|
||
Subsystem->AddMappingContext(PlayerMappingContext, 0); // Add the player input mapping context with priority 0 (highest)
|
||
}
|
||
|
||
// Configure the mouse cursor to be visible and use the default style
|
||
bShowMouseCursor = true;
|
||
DefaultMouseCursor = EMouseCursor::Default;
|
||
|
||
// Set input mode to allow both game and UI interaction
|
||
FInputModeGameAndUI InputModeData;
|
||
InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock); // Don't lock mouse to viewport
|
||
InputModeData.SetHideCursorDuringCapture(false); // Don't hide the cursor when capturing input
|
||
SetInputMode(InputModeData); // Apply input mode settings to this controller
|
||
}
|
||
|
||
void ARIRPlayerController::SetupInputComponent()
|
||
{
|
||
Super::SetupInputComponent();
|
||
|
||
// Cast InputComponent to EnhancedInputComponent to access enhanced input features
|
||
UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent);
|
||
|
||
// Bind the MoveAction input to the HandleMoveInput function when the action is triggered
|
||
EnhancedInputComponent->BindAction(MovementInput, ETriggerEvent::Triggered, this, &ARIRPlayerController::HandleMovementInput);
|
||
}
|
||
|
||
void ARIRPlayerController::HandleMovementInput(const FInputActionValue& InputActionValue)
|
||
{
|
||
if (!GetPawn())
|
||
{
|
||
return;
|
||
}
|
||
|
||
FVector2D InputVector = InputActionValue.Get<FVector2D>();
|
||
if (InputVector.IsNearlyZero())
|
||
{
|
||
return;
|
||
}
|
||
|
||
// Get the control rotation
|
||
FRotator ControlRot = GetControlRotation();
|
||
FRotator YawRot(0.f, ControlRot.Yaw, 0.f);
|
||
|
||
// Get forward and right vectors
|
||
const FVector ForwardVector = FRotationMatrix(YawRot).GetUnitAxis(EAxis::X);
|
||
const FVector RightVector = FRotationMatrix(YawRot).GetUnitAxis(EAxis::Y);
|
||
|
||
if (APawn* ControlledPlayer = GetPawn<APawn>())
|
||
{
|
||
// Apply movement input
|
||
GetPawn()->AddMovementInput(ForwardVector, InputVector.Y);
|
||
GetPawn()->AddMovementInput(RightVector, InputVector.X);
|
||
}
|
||
}
|