195 lines
5.3 KiB
C++
195 lines
5.3 KiB
C++
#include "Level/LevelPlayerController.h"
|
|
#include "Level/Actor/BusyPlayerRole.h"
|
|
#include "EnhancedInput/Public/EnhancedInputSubsystems.h"
|
|
#include "Level/LevelPlayerState.h"
|
|
#include "EnhancedInput/Public/EnhancedInputComponent.h"
|
|
|
|
|
|
inline static void BindEnhancedInputAction(UEnhancedInputComponent* EnhancedInput, const UInputAction* Action, UObject* Target, const FName& Callback)
|
|
{
|
|
if (Action)
|
|
{
|
|
EnhancedInput->BindAction(Action, ETriggerEvent::Triggered, Target, Callback);
|
|
}
|
|
}
|
|
|
|
|
|
ALevelPlayerController::ALevelPlayerController()
|
|
{
|
|
}
|
|
|
|
void ALevelPlayerController::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
bShowMouseCursor = true;
|
|
FInputModeGameAndUI InputMode;
|
|
InputMode.SetHideCursorDuringCapture(false);
|
|
InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
|
|
SetInputMode(InputMode);
|
|
|
|
if (RoamingCameraClass)
|
|
{
|
|
RoamingCameraActor = GetWorld()->SpawnActor<AActor>(RoamingCameraClass);
|
|
}
|
|
}
|
|
|
|
void ALevelPlayerController::SetupInputComponent()
|
|
{
|
|
Super::SetupInputComponent();
|
|
// 注册输入
|
|
if (!InputMapping || !InputComponent) return;
|
|
|
|
if (const auto Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
Subsystem->AddMappingContext(InputMapping, 0);
|
|
}
|
|
|
|
UEnhancedInputComponent* EnhancedInput = CastChecked<UEnhancedInputComponent>(InputComponent);
|
|
if (!EnhancedInput) return;
|
|
|
|
BindEnhancedInputAction(EnhancedInput, MoveAction, this, "OnMove");
|
|
BindEnhancedInputAction(EnhancedInput, CameraDetachAction, this, "OnCameraDetach");
|
|
BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill");
|
|
BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill");
|
|
BindEnhancedInputAction(EnhancedInput, SwitchRoleAction, this, "OnSwitchRole");
|
|
}
|
|
|
|
void ALevelPlayerController::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
|
|
if (!bCameraDetached || !RoamingCameraActor) return;
|
|
|
|
AActor *ControlledRole = GetControlledRole();
|
|
const IBusyMovable *Movable = Cast<IBusyMovable>(GetControlledRole());
|
|
if (!Movable) return;
|
|
|
|
if (float CursorX, CursorY; GetMousePosition(CursorX, CursorY))
|
|
{
|
|
|
|
// 获取视口大小
|
|
int32 ViewportSizeX, ViewportSizeY;
|
|
GetViewportSize(ViewportSizeX, ViewportSizeY);
|
|
|
|
// 计算屏幕中心
|
|
const FVector2D ScreenCenter(ViewportSizeX / 2.0f, ViewportSizeY / 2.0f);
|
|
|
|
// 获取漫游相机位置
|
|
const FVector CurrentLocation = RoamingCameraActor->GetActorLocation();
|
|
|
|
// 计算方向向量
|
|
FVector Direction(CursorX - ScreenCenter.X, CursorY - ScreenCenter.Y, 0);
|
|
|
|
// 归一化
|
|
Direction.Normalize();
|
|
|
|
const float MoveSpeed = Movable->Execute_GetSpeed(ControlledRole);
|
|
const FVector MoveDistance = Direction * DeltaTime * MoveSpeed * RoamingSpeedFactor;
|
|
|
|
// 更新漫游相机位置
|
|
RoamingCameraActor->SetActorLocation(CurrentLocation + MoveDistance);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
bool ALevelPlayerController::GetCursorPosition(FVector2D& Position) const
|
|
{
|
|
if (float CursorX, CursorY; GetMousePosition(CursorX, CursorY))
|
|
{
|
|
FVector WorldLocation, WorldDirection;
|
|
if (DeprojectMousePositionToWorld(WorldLocation, WorldDirection))
|
|
{
|
|
Position.Set(WorldLocation.X, WorldLocation.Y);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ALevelPlayerController::GetCursorHitResult(TArray<AActor*>& Results) const
|
|
{
|
|
}
|
|
|
|
ABusyPlayerRole* ALevelPlayerController::GetControlledRole() const
|
|
{
|
|
if (const ALevelPlayerState* PS = GetPlayerState<ALevelPlayerState>())
|
|
{
|
|
return PS->GetControlledRole();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void ALevelPlayerController::SwitchControlledRole(ABusyPlayerRole* Target)
|
|
{
|
|
this->Possess(Target);
|
|
}
|
|
|
|
void ALevelPlayerController::OnMove(const FInputActionValue& Value) const
|
|
{
|
|
AActor* ControlledRole = GetControlledRole();
|
|
if (!ControlledRole) return;
|
|
|
|
IBusyControllable *Controllable = Cast<IBusyControllable>(ControlledRole);
|
|
if (!Controllable) return;
|
|
|
|
if (FVector2D Position; GetCursorPosition(Position))
|
|
{
|
|
Controllable->Execute_OnMove(ControlledRole, Position);
|
|
}
|
|
}
|
|
|
|
void ALevelPlayerController::OnPrimarySkill(const FInputActionValue& Value) const
|
|
{
|
|
AActor* ControlledRole = GetControlledRole();
|
|
if (!ControlledRole) return;
|
|
|
|
if (IBusyControllable *Controllable = Cast<IBusyControllable>(ControlledRole))
|
|
{
|
|
Controllable->Execute_OnPrimarySkill(ControlledRole);
|
|
}
|
|
}
|
|
|
|
void ALevelPlayerController::OnUltimateSkill(const FInputActionValue& Value) const
|
|
{
|
|
AActor* ControlledRole = GetControlledRole();
|
|
if (!ControlledRole) return;
|
|
if (IBusyControllable *Controllable = Cast<IBusyControllable>(ControlledRole))
|
|
{
|
|
Controllable->Execute_OnUltimateSkill(ControlledRole);
|
|
}
|
|
}
|
|
|
|
void ALevelPlayerController::OnCameraDetach(const FInputActionValue& Value)
|
|
{
|
|
if (!RoamingCameraActor) return;
|
|
|
|
AActor* ControlledRole = GetControlledRole();
|
|
if (!ControlledRole) return;
|
|
|
|
const FVector RoleLocation = ControlledRole->GetActorLocation();
|
|
RoamingCameraActor->SetActorLocation(RoleLocation);
|
|
|
|
|
|
if (Value.GetMagnitude() > 0)
|
|
{
|
|
bCameraDetached = true;
|
|
SetViewTarget(RoamingCameraActor);
|
|
}
|
|
else
|
|
{
|
|
bCameraDetached = false;
|
|
SetViewTarget(ControlledRole);
|
|
}
|
|
}
|
|
|
|
void ALevelPlayerController::OnSwitchRole(const FInputActionValue& Value)
|
|
{
|
|
const int32 Index = static_cast<int32>(Value.GetMagnitude() - 1);
|
|
if (ALevelPlayerState* PS = GetPlayerState<ALevelPlayerState>())
|
|
{
|
|
ABusyPlayerRole* ControlledRole = PS->SwitchControlledRole(Index);
|
|
SwitchControlledRole(ControlledRole);
|
|
}
|
|
}
|