518 lines
17 KiB
C++
518 lines
17 KiB
C++
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
||
|
#include "LyraCharacter.h"
|
||
|
#include "LyraCharacterMovementComponent.h"
|
||
|
#include "LyraLogChannels.h"
|
||
|
#include "LyraGameplayTags.h"
|
||
|
#include "Character/LyraPawnExtensionComponent.h"
|
||
|
#include "Components/CapsuleComponent.h"
|
||
|
#include "Components/SkeletalMeshComponent.h"
|
||
|
#include "Components/InputComponent.h"
|
||
|
#include "Camera/LyraCameraComponent.h"
|
||
|
#include "AbilitySystem/LyraAbilitySystemComponent.h"
|
||
|
#include "Character/LyraHealthComponent.h"
|
||
|
#include "Player/LyraPlayerController.h"
|
||
|
#include "Player/LyraPlayerState.h"
|
||
|
#include "System/LyraSignificanceManager.h"
|
||
|
#include "Net/UnrealNetwork.h"
|
||
|
#include "TimerManager.h"
|
||
|
|
||
|
static FName NAME_LyraCharacterCollisionProfile_Capsule(TEXT("LyraPawnCapsule"));
|
||
|
static FName NAME_LyraCharacterCollisionProfile_Mesh(TEXT("LyraPawnMesh"));
|
||
|
|
||
|
ALyraCharacter::ALyraCharacter(const FObjectInitializer& ObjectInitializer)
|
||
|
: Super(ObjectInitializer.SetDefaultSubobjectClass<ULyraCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
|
||
|
{
|
||
|
// Avoid ticking characters if possible.
|
||
|
PrimaryActorTick.bCanEverTick = false;
|
||
|
PrimaryActorTick.bStartWithTickEnabled = false;
|
||
|
|
||
|
NetCullDistanceSquared = 900000000.0f;
|
||
|
|
||
|
UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
|
||
|
check(CapsuleComp);
|
||
|
CapsuleComp->InitCapsuleSize(40.0f, 90.0f);
|
||
|
CapsuleComp->SetCollisionProfileName(NAME_LyraCharacterCollisionProfile_Capsule);
|
||
|
|
||
|
USkeletalMeshComponent* MeshComp = GetMesh();
|
||
|
check(MeshComp);
|
||
|
MeshComp->SetRelativeRotation(FRotator(0.0f, -90.0f, 0.0f)); // Rotate mesh to be X forward since it is exported as Y forward.
|
||
|
MeshComp->SetCollisionProfileName(NAME_LyraCharacterCollisionProfile_Mesh);
|
||
|
|
||
|
ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
|
||
|
LyraMoveComp->GravityScale = 1.0f;
|
||
|
LyraMoveComp->MaxAcceleration = 2400.0f;
|
||
|
LyraMoveComp->BrakingFrictionFactor = 1.0f;
|
||
|
LyraMoveComp->BrakingFriction = 6.0f;
|
||
|
LyraMoveComp->GroundFriction = 8.0f;
|
||
|
LyraMoveComp->BrakingDecelerationWalking = 1400.0f;
|
||
|
LyraMoveComp->bUseControllerDesiredRotation = false;
|
||
|
LyraMoveComp->bOrientRotationToMovement = false;
|
||
|
LyraMoveComp->RotationRate = FRotator(0.0f, 720.0f, 0.0f);
|
||
|
LyraMoveComp->bAllowPhysicsRotationDuringAnimRootMotion = false;
|
||
|
LyraMoveComp->GetNavAgentPropertiesRef().bCanCrouch = true;
|
||
|
LyraMoveComp->bCanWalkOffLedgesWhenCrouching = true;
|
||
|
LyraMoveComp->SetCrouchedHalfHeight(65.0f);
|
||
|
|
||
|
PawnExtComponent = CreateDefaultSubobject<ULyraPawnExtensionComponent>(TEXT("PawnExtensionComponent"));
|
||
|
PawnExtComponent->OnAbilitySystemInitialized_RegisterAndCall(FSimpleMulticastDelegate::FDelegate::CreateUObject(this, &ThisClass::OnAbilitySystemInitialized));
|
||
|
PawnExtComponent->OnAbilitySystemUninitialized_Register(FSimpleMulticastDelegate::FDelegate::CreateUObject(this, &ThisClass::OnAbilitySystemUninitialized));
|
||
|
|
||
|
HealthComponent = CreateDefaultSubobject<ULyraHealthComponent>(TEXT("HealthComponent"));
|
||
|
HealthComponent->OnDeathStarted.AddDynamic(this, &ThisClass::OnDeathStarted);
|
||
|
HealthComponent->OnDeathFinished.AddDynamic(this, &ThisClass::OnDeathFinished);
|
||
|
|
||
|
CameraComponent = CreateDefaultSubobject<ULyraCameraComponent>(TEXT("CameraComponent"));
|
||
|
CameraComponent->SetRelativeLocation(FVector(-300.0f, 0.0f, 75.0f));
|
||
|
|
||
|
bUseControllerRotationPitch = false;
|
||
|
bUseControllerRotationYaw = true;
|
||
|
bUseControllerRotationRoll = false;
|
||
|
|
||
|
BaseEyeHeight = 80.0f;
|
||
|
CrouchedEyeHeight = 50.0f;
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::PreInitializeComponents()
|
||
|
{
|
||
|
Super::PreInitializeComponents();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::BeginPlay()
|
||
|
{
|
||
|
Super::BeginPlay();
|
||
|
|
||
|
UWorld* World = GetWorld();
|
||
|
|
||
|
const bool bRegisterWithSignificanceManager = !IsNetMode(NM_DedicatedServer);
|
||
|
if (bRegisterWithSignificanceManager)
|
||
|
{
|
||
|
if (ULyraSignificanceManager* SignificanceManager = USignificanceManager::Get<ULyraSignificanceManager>(World))
|
||
|
{
|
||
|
//@TODO: SignificanceManager->RegisterObject(this, (EFortSignificanceType)SignificanceType);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||
|
{
|
||
|
Super::EndPlay(EndPlayReason);
|
||
|
|
||
|
UWorld* World = GetWorld();
|
||
|
|
||
|
const bool bRegisterWithSignificanceManager = !IsNetMode(NM_DedicatedServer);
|
||
|
if (bRegisterWithSignificanceManager)
|
||
|
{
|
||
|
if (ULyraSignificanceManager* SignificanceManager = USignificanceManager::Get<ULyraSignificanceManager>(World))
|
||
|
{
|
||
|
SignificanceManager->UnregisterObject(this);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::Reset()
|
||
|
{
|
||
|
DisableMovementAndCollision();
|
||
|
|
||
|
K2_OnReset();
|
||
|
|
||
|
UninitAndDestroy();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
|
||
|
{
|
||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||
|
|
||
|
DOREPLIFETIME_CONDITION(ThisClass, ReplicatedAcceleration, COND_SimulatedOnly);
|
||
|
DOREPLIFETIME(ThisClass, MyTeamID)
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::PreReplication(IRepChangedPropertyTracker& ChangedPropertyTracker)
|
||
|
{
|
||
|
Super::PreReplication(ChangedPropertyTracker);
|
||
|
|
||
|
if (UCharacterMovementComponent* MovementComponent = GetCharacterMovement())
|
||
|
{
|
||
|
// Compress Acceleration: XY components as direction + magnitude, Z component as direct value
|
||
|
const double MaxAccel = MovementComponent->MaxAcceleration;
|
||
|
const FVector CurrentAccel = MovementComponent->GetCurrentAcceleration();
|
||
|
double AccelXYRadians, AccelXYMagnitude;
|
||
|
FMath::CartesianToPolar(CurrentAccel.X, CurrentAccel.Y, AccelXYMagnitude, AccelXYRadians);
|
||
|
|
||
|
ReplicatedAcceleration.AccelXYRadians = FMath::FloorToInt((AccelXYRadians / TWO_PI) * 255.0); // [0, 2PI] -> [0, 255]
|
||
|
ReplicatedAcceleration.AccelXYMagnitude = FMath::FloorToInt((AccelXYMagnitude / MaxAccel) * 255.0); // [0, MaxAccel] -> [0, 255]
|
||
|
ReplicatedAcceleration.AccelZ = FMath::FloorToInt((CurrentAccel.Z / MaxAccel) * 127.0); // [-MaxAccel, MaxAccel] -> [-127, 127]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::NotifyControllerChanged()
|
||
|
{
|
||
|
const FGenericTeamId OldTeamId = GetGenericTeamId();
|
||
|
|
||
|
Super::NotifyControllerChanged();
|
||
|
|
||
|
// Update our team ID based on the controller
|
||
|
if (HasAuthority() && (Controller != nullptr))
|
||
|
{
|
||
|
if (ILyraTeamAgentInterface* ControllerWithTeam = Cast<ILyraTeamAgentInterface>(Controller))
|
||
|
{
|
||
|
MyTeamID = ControllerWithTeam->GetGenericTeamId();
|
||
|
ConditionalBroadcastTeamChanged(this, OldTeamId, MyTeamID);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ALyraPlayerController* ALyraCharacter::GetLyraPlayerController() const
|
||
|
{
|
||
|
return CastChecked<ALyraPlayerController>(Controller, ECastCheckedType::NullAllowed);
|
||
|
}
|
||
|
|
||
|
ALyraPlayerState* ALyraCharacter::GetLyraPlayerState() const
|
||
|
{
|
||
|
return CastChecked<ALyraPlayerState>(GetPlayerState(), ECastCheckedType::NullAllowed);
|
||
|
}
|
||
|
|
||
|
ULyraAbilitySystemComponent* ALyraCharacter::GetLyraAbilitySystemComponent() const
|
||
|
{
|
||
|
return Cast<ULyraAbilitySystemComponent>(GetAbilitySystemComponent());
|
||
|
}
|
||
|
|
||
|
UAbilitySystemComponent* ALyraCharacter::GetAbilitySystemComponent() const
|
||
|
{
|
||
|
return PawnExtComponent->GetLyraAbilitySystemComponent();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnAbilitySystemInitialized()
|
||
|
{
|
||
|
ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent();
|
||
|
check(LyraASC);
|
||
|
|
||
|
HealthComponent->InitializeWithAbilitySystem(LyraASC);
|
||
|
|
||
|
InitializeGameplayTags();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnAbilitySystemUninitialized()
|
||
|
{
|
||
|
HealthComponent->UninitializeFromAbilitySystem();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::PossessedBy(AController* NewController)
|
||
|
{
|
||
|
const FGenericTeamId OldTeamID = MyTeamID;
|
||
|
|
||
|
Super::PossessedBy(NewController);
|
||
|
|
||
|
PawnExtComponent->HandleControllerChanged();
|
||
|
|
||
|
// Grab the current team ID and listen for future changes
|
||
|
if (ILyraTeamAgentInterface* ControllerAsTeamProvider = Cast<ILyraTeamAgentInterface>(NewController))
|
||
|
{
|
||
|
MyTeamID = ControllerAsTeamProvider->GetGenericTeamId();
|
||
|
ControllerAsTeamProvider->GetTeamChangedDelegateChecked().AddDynamic(this, &ThisClass::OnControllerChangedTeam);
|
||
|
}
|
||
|
ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::UnPossessed()
|
||
|
{
|
||
|
AController* const OldController = Controller;
|
||
|
|
||
|
// Stop listening for changes from the old controller
|
||
|
const FGenericTeamId OldTeamID = MyTeamID;
|
||
|
if (ILyraTeamAgentInterface* ControllerAsTeamProvider = Cast<ILyraTeamAgentInterface>(OldController))
|
||
|
{
|
||
|
ControllerAsTeamProvider->GetTeamChangedDelegateChecked().RemoveAll(this);
|
||
|
}
|
||
|
|
||
|
Super::UnPossessed();
|
||
|
|
||
|
PawnExtComponent->HandleControllerChanged();
|
||
|
|
||
|
// Determine what the new team ID should be afterwards
|
||
|
MyTeamID = DetermineNewTeamAfterPossessionEnds(OldTeamID);
|
||
|
ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnRep_Controller()
|
||
|
{
|
||
|
Super::OnRep_Controller();
|
||
|
|
||
|
PawnExtComponent->HandleControllerChanged();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnRep_PlayerState()
|
||
|
{
|
||
|
Super::OnRep_PlayerState();
|
||
|
|
||
|
PawnExtComponent->HandlePlayerStateReplicated();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||
|
{
|
||
|
Super::SetupPlayerInputComponent(PlayerInputComponent);
|
||
|
|
||
|
PawnExtComponent->SetupPlayerInputComponent();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::InitializeGameplayTags()
|
||
|
{
|
||
|
// Clear tags that may be lingering on the ability system from the previous pawn.
|
||
|
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
const FLyraGameplayTags& GameplayTags = FLyraGameplayTags::Get();
|
||
|
|
||
|
for (const TPair<uint8, FGameplayTag>& TagMapping : GameplayTags.MovementModeTagMap)
|
||
|
{
|
||
|
if (TagMapping.Value.IsValid())
|
||
|
{
|
||
|
LyraASC->SetLooseGameplayTagCount(TagMapping.Value, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (const TPair<uint8, FGameplayTag>& TagMapping : GameplayTags.CustomMovementModeTagMap)
|
||
|
{
|
||
|
if (TagMapping.Value.IsValid())
|
||
|
{
|
||
|
LyraASC->SetLooseGameplayTagCount(TagMapping.Value, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
|
||
|
SetMovementModeTag(LyraMoveComp->MovementMode, LyraMoveComp->CustomMovementMode, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const
|
||
|
{
|
||
|
if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
LyraASC->GetOwnedGameplayTags(TagContainer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool ALyraCharacter::HasMatchingGameplayTag(FGameplayTag TagToCheck) const
|
||
|
{
|
||
|
if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
return LyraASC->HasMatchingGameplayTag(TagToCheck);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool ALyraCharacter::HasAllMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const
|
||
|
{
|
||
|
if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
return LyraASC->HasAllMatchingGameplayTags(TagContainer);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool ALyraCharacter::HasAnyMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const
|
||
|
{
|
||
|
if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
return LyraASC->HasAnyMatchingGameplayTags(TagContainer);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::FellOutOfWorld(const class UDamageType& dmgType)
|
||
|
{
|
||
|
HealthComponent->DamageSelfDestruct(/*bFellOutOfWorld=*/ true);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnDeathStarted(AActor*)
|
||
|
{
|
||
|
DisableMovementAndCollision();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnDeathFinished(AActor*)
|
||
|
{
|
||
|
GetWorld()->GetTimerManager().SetTimerForNextTick(this, &ThisClass::DestroyDueToDeath);
|
||
|
}
|
||
|
|
||
|
|
||
|
void ALyraCharacter::DisableMovementAndCollision()
|
||
|
{
|
||
|
if (Controller)
|
||
|
{
|
||
|
Controller->SetIgnoreMoveInput(true);
|
||
|
}
|
||
|
|
||
|
UCapsuleComponent* CapsuleComp = GetCapsuleComponent();
|
||
|
check(CapsuleComp);
|
||
|
CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||
|
CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||
|
|
||
|
ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
|
||
|
LyraMoveComp->StopMovementImmediately();
|
||
|
LyraMoveComp->DisableMovement();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::DestroyDueToDeath()
|
||
|
{
|
||
|
K2_OnDeathFinished();
|
||
|
|
||
|
UninitAndDestroy();
|
||
|
}
|
||
|
|
||
|
|
||
|
void ALyraCharacter::UninitAndDestroy()
|
||
|
{
|
||
|
if (GetLocalRole() == ROLE_Authority)
|
||
|
{
|
||
|
DetachFromControllerPendingDestroy();
|
||
|
SetLifeSpan(0.1f);
|
||
|
}
|
||
|
|
||
|
// Uninitialize the ASC if we're still the avatar actor (otherwise another pawn already did it when they became the avatar actor)
|
||
|
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
if (LyraASC->GetAvatarActor() == this)
|
||
|
{
|
||
|
PawnExtComponent->UninitializeAbilitySystem();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetActorHiddenInGame(true);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode)
|
||
|
{
|
||
|
Super::OnMovementModeChanged(PrevMovementMode, PreviousCustomMode);
|
||
|
|
||
|
ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
|
||
|
|
||
|
SetMovementModeTag(PrevMovementMode, PreviousCustomMode, false);
|
||
|
SetMovementModeTag(LyraMoveComp->MovementMode, LyraMoveComp->CustomMovementMode, true);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::SetMovementModeTag(EMovementMode MovementMode, uint8 CustomMovementMode, bool bTagEnabled)
|
||
|
{
|
||
|
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
const FLyraGameplayTags& GameplayTags = FLyraGameplayTags::Get();
|
||
|
const FGameplayTag* MovementModeTag = nullptr;
|
||
|
|
||
|
if (MovementMode == MOVE_Custom)
|
||
|
{
|
||
|
MovementModeTag = GameplayTags.CustomMovementModeTagMap.Find(CustomMovementMode);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MovementModeTag = GameplayTags.MovementModeTagMap.Find(MovementMode);
|
||
|
}
|
||
|
|
||
|
if (MovementModeTag && MovementModeTag->IsValid())
|
||
|
{
|
||
|
LyraASC->SetLooseGameplayTagCount(*MovementModeTag, (bTagEnabled ? 1 : 0));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::ToggleCrouch()
|
||
|
{
|
||
|
const ULyraCharacterMovementComponent* LyraMoveComp = CastChecked<ULyraCharacterMovementComponent>(GetCharacterMovement());
|
||
|
|
||
|
if (bIsCrouched || LyraMoveComp->bWantsToCrouch)
|
||
|
{
|
||
|
UnCrouch();
|
||
|
}
|
||
|
else if (LyraMoveComp->IsMovingOnGround())
|
||
|
{
|
||
|
Crouch();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnStartCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust)
|
||
|
{
|
||
|
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
LyraASC->SetLooseGameplayTagCount(FLyraGameplayTags::Get().Status_Crouching, 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
Super::OnStartCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnEndCrouch(float HalfHeightAdjust, float ScaledHalfHeightAdjust)
|
||
|
{
|
||
|
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
|
||
|
{
|
||
|
LyraASC->SetLooseGameplayTagCount(FLyraGameplayTags::Get().Status_Crouching, 0);
|
||
|
}
|
||
|
|
||
|
Super::OnEndCrouch(HalfHeightAdjust, ScaledHalfHeightAdjust);
|
||
|
}
|
||
|
|
||
|
bool ALyraCharacter::CanJumpInternal_Implementation() const
|
||
|
{
|
||
|
// same as ACharacter's implementation but without the crouch check
|
||
|
return JumpIsAllowedInternal();
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnRep_ReplicatedAcceleration()
|
||
|
{
|
||
|
if (ULyraCharacterMovementComponent* LyraMovementComponent = Cast<ULyraCharacterMovementComponent>(GetCharacterMovement()))
|
||
|
{
|
||
|
// Decompress Acceleration
|
||
|
const double MaxAccel = LyraMovementComponent->MaxAcceleration;
|
||
|
const double AccelXYMagnitude = double(ReplicatedAcceleration.AccelXYMagnitude) * MaxAccel / 255.0; // [0, 255] -> [0, MaxAccel]
|
||
|
const double AccelXYRadians = double(ReplicatedAcceleration.AccelXYRadians) * TWO_PI / 255.0; // [0, 255] -> [0, 2PI]
|
||
|
|
||
|
FVector UnpackedAcceleration(FVector::ZeroVector);
|
||
|
FMath::PolarToCartesian(AccelXYMagnitude, AccelXYRadians, UnpackedAcceleration.X, UnpackedAcceleration.Y);
|
||
|
UnpackedAcceleration.Z = double(ReplicatedAcceleration.AccelZ) * MaxAccel / 127.0; // [-127, 127] -> [-MaxAccel, MaxAccel]
|
||
|
|
||
|
LyraMovementComponent->SetReplicatedAcceleration(UnpackedAcceleration);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::SetGenericTeamId(const FGenericTeamId& NewTeamID)
|
||
|
{
|
||
|
if (GetController() == nullptr)
|
||
|
{
|
||
|
if (HasAuthority())
|
||
|
{
|
||
|
const FGenericTeamId OldTeamID = MyTeamID;
|
||
|
MyTeamID = NewTeamID;
|
||
|
ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UE_LOG(LogLyraTeams, Error, TEXT("You can't set the team ID on a character (%s) except on the authority"), *GetPathNameSafe(this));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UE_LOG(LogLyraTeams, Error, TEXT("You can't set the team ID on a possessed character (%s); it's driven by the associated controller"), *GetPathNameSafe(this));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FGenericTeamId ALyraCharacter::GetGenericTeamId() const
|
||
|
{
|
||
|
return MyTeamID;
|
||
|
}
|
||
|
|
||
|
FOnLyraTeamIndexChangedDelegate* ALyraCharacter::GetOnTeamIndexChangedDelegate()
|
||
|
{
|
||
|
return &OnTeamChangedDelegate;
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnControllerChangedTeam(UObject* TeamAgent, int32 OldTeam, int32 NewTeam)
|
||
|
{
|
||
|
const FGenericTeamId MyOldTeamID = MyTeamID;
|
||
|
MyTeamID = IntegerToGenericTeamId(NewTeam);
|
||
|
ConditionalBroadcastTeamChanged(this, MyOldTeamID, MyTeamID);
|
||
|
}
|
||
|
|
||
|
void ALyraCharacter::OnRep_MyTeamID(FGenericTeamId OldTeamID)
|
||
|
{
|
||
|
ConditionalBroadcastTeamChanged(this, OldTeamID, MyTeamID);
|
||
|
}
|