Initial Commit - Lesson 31 (Commit #1)
This commit is contained in:
224
Source/FPSTemplate/Private/Player/MatchPlayerState.cpp
Normal file
224
Source/FPSTemplate/Private/Player/MatchPlayerState.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Player/MatchPlayerState.h"
|
||||
|
||||
#include "ShooterTypes/ShooterTypes.h"
|
||||
#include "UI/Elims/SpecialElimWidget.h"
|
||||
|
||||
AMatchPlayerState::AMatchPlayerState()
|
||||
{
|
||||
SetNetUpdateFrequency(100.f); // let's not be sluggish, alright?
|
||||
|
||||
ScoredElims = 0;
|
||||
Defeats = 0;
|
||||
Hits = 0;
|
||||
Misses = 0;
|
||||
bOnStreak = false;
|
||||
HeadShotElims = 0;
|
||||
SequentialElims = TMap<int32, int32>();
|
||||
HighestStreak = 0;
|
||||
RevengeElims = 0;
|
||||
DethroneElims = 0;
|
||||
ShowStopperElims = 0;
|
||||
bFirstBlood = false;
|
||||
bWinner = false;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddScoredElim()
|
||||
{
|
||||
++ScoredElims;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddDefeat()
|
||||
{
|
||||
++Defeats;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddHit()
|
||||
{
|
||||
++Hits;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddMiss()
|
||||
{
|
||||
++Misses;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddHeadShotElim()
|
||||
{
|
||||
++HeadShotElims;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddSequentialElim(int32 SequenceCount)
|
||||
{
|
||||
if (SequentialElims.Contains(SequenceCount))
|
||||
{
|
||||
SequentialElims[SequenceCount]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
SequentialElims.Add(SequenceCount, 1);
|
||||
}
|
||||
|
||||
// Reduce the count for all lower sequence counts
|
||||
// This is because a triple elim means a double was scored first,
|
||||
// But we want to count this as just a triple, i.e:
|
||||
// elim 1, elim 2, elim 3 = just a triple, not a double and a triple.
|
||||
for (auto& Elem : SequentialElims)
|
||||
{
|
||||
if (Elem.Key < SequenceCount && Elem.Value > 0)
|
||||
{
|
||||
Elem.Value--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AMatchPlayerState::UpdateHighestStreak(int32 StreakCount)
|
||||
{
|
||||
if (StreakCount > HighestStreak)
|
||||
{
|
||||
HighestStreak = StreakCount;
|
||||
}
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddRevengeElim()
|
||||
{
|
||||
++RevengeElims;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddDethroneElim()
|
||||
{
|
||||
++DethroneElims;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::AddShowStopperElim()
|
||||
{
|
||||
++ShowStopperElims;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::GotFirstBlood()
|
||||
{
|
||||
bFirstBlood = true;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::IsTheWinner()
|
||||
{
|
||||
bWinner = true;
|
||||
}
|
||||
|
||||
TArray<ESpecialElimType> AMatchPlayerState::DecodeElimBitmask(ESpecialElimType ElimTypeBitmask)
|
||||
{
|
||||
TArray<ESpecialElimType> ValidElims;
|
||||
uint8 BitmaskValue = static_cast<uint8>(ElimTypeBitmask);
|
||||
|
||||
for(uint8 i = 0; i < 16; i++) // Assuming 8 bits since ESpecialElimType is a uint16
|
||||
{
|
||||
if (BitmaskValue & (1 << i))
|
||||
{
|
||||
ESpecialElimType EnumValue = static_cast<ESpecialElimType>(1 << i);
|
||||
ValidElims.Add(EnumValue);
|
||||
}
|
||||
}
|
||||
|
||||
return ValidElims;
|
||||
}
|
||||
|
||||
void AMatchPlayerState::ProcessNextSpecialElim()
|
||||
{
|
||||
FSpecialElimInfo ElimInfo;
|
||||
if (SpecialElimQueue.Dequeue(ElimInfo))
|
||||
{
|
||||
bIsProcessingQueue = true;
|
||||
ShowSpecialElim(ElimInfo);
|
||||
|
||||
// Schedule the next elimination processing after a delay
|
||||
GetWorldTimerManager().SetTimerForNextTick([this]()
|
||||
{
|
||||
constexpr float ElimDisplayTime = 0.5f; // Adjust the time in seconds as needed
|
||||
FTimerHandle TimerHandle;
|
||||
GetWorldTimerManager().SetTimer(TimerHandle, this, &AMatchPlayerState::ProcessNextSpecialElim, ElimDisplayTime, false);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
bIsProcessingQueue = false;
|
||||
}
|
||||
}
|
||||
|
||||
void AMatchPlayerState::ShowSpecialElim(const FSpecialElimInfo& ElimMessageInfo)
|
||||
{
|
||||
FString ElimMessageString = ElimMessageInfo.ElimMessage;
|
||||
if (ElimMessageInfo.ElimType == ESpecialElimType::Sequential)
|
||||
{
|
||||
FString Msg = ElimMessageInfo.ElimMessage;
|
||||
|
||||
int32 Seq = ElimMessageInfo.SequentialElimCount;
|
||||
int32 Streak = ElimMessageInfo.StreakCount;
|
||||
|
||||
if (ElimMessageInfo.SequentialElimCount == 2) ElimMessageString = FString("Double Elim!");
|
||||
else if (ElimMessageInfo.SequentialElimCount == 3) ElimMessageString = FString("Triple Elim!");
|
||||
else if (ElimMessageInfo.SequentialElimCount == 4) ElimMessageString = FString("Quad Elim!");
|
||||
else if (ElimMessageInfo.SequentialElimCount > 4) ElimMessageString = FString::Printf(TEXT("Rampage x%d!"), ElimMessageInfo.SequentialElimCount);
|
||||
}
|
||||
if (ElimMessageInfo.ElimType == ESpecialElimType::Streak) ElimMessageString = FString::Printf(TEXT("Streak x%d!"), ElimMessageInfo.StreakCount);
|
||||
|
||||
if (SpecialElimWidgetClass)
|
||||
{
|
||||
USpecialElimWidget* ElimWidget = CreateWidget<USpecialElimWidget>(GetWorld(), SpecialElimWidgetClass);
|
||||
if (IsValid(ElimWidget))
|
||||
{
|
||||
ElimWidget->InitializeWidget(ElimMessageString, ElimMessageInfo.ElimIcon);
|
||||
ElimWidget->AddToViewport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AMatchPlayerState::Client_ScoredElim_Implementation(int32 ElimScore)
|
||||
{
|
||||
OnScoreChanged.Broadcast(ElimScore);
|
||||
}
|
||||
|
||||
void AMatchPlayerState::Client_SpecialElim_Implementation(const ESpecialElimType& SpecialElim, int32 SequentialElimCount, int32 StreakCount, int32 ElimScore)
|
||||
{
|
||||
OnScoreChanged.Broadcast(ElimScore);
|
||||
|
||||
if (!IsValid(SpecialElimData)) return;
|
||||
|
||||
TArray<ESpecialElimType> ElimTypes = DecodeElimBitmask(SpecialElim);
|
||||
for (ESpecialElimType ElimType : ElimTypes)
|
||||
{
|
||||
FSpecialElimInfo& ElimInfo = SpecialElimData->SpecialElimInfo.FindChecked(ElimType);
|
||||
if (ElimType == ESpecialElimType::Sequential)
|
||||
{
|
||||
ElimInfo.SequentialElimCount = SequentialElimCount;
|
||||
}
|
||||
if (ElimType == ESpecialElimType::Streak)
|
||||
{
|
||||
ElimInfo.StreakCount = StreakCount;
|
||||
}
|
||||
ElimInfo.ElimType = ElimType;
|
||||
SpecialElimQueue.Enqueue(ElimInfo);
|
||||
}
|
||||
if (!bIsProcessingQueue)
|
||||
{
|
||||
ProcessNextSpecialElim();
|
||||
}
|
||||
}
|
||||
|
||||
void AMatchPlayerState::Client_LostTheLead_Implementation()
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("%s Lost the Lead"), *GetName());
|
||||
if (!IsValid(SpecialElimData)) return;
|
||||
auto& ElimMessageInfo = SpecialElimData->SpecialElimInfo.FindChecked(ESpecialElimType::LostTheLead);
|
||||
|
||||
if (SpecialElimWidgetClass)
|
||||
{
|
||||
USpecialElimWidget* ElimWidget = CreateWidget<USpecialElimWidget>(GetWorld(), SpecialElimWidgetClass);
|
||||
if (IsValid(ElimWidget))
|
||||
{
|
||||
ElimWidget->InitializeWidget(ElimMessageInfo.ElimMessage, ElimMessageInfo.ElimIcon);
|
||||
ElimWidget->AddToViewport();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Player/ShooterPlayerController.h"
|
||||
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "InputMappingContext.h"
|
||||
#include "Interfaces/PlayerInterface.h"
|
||||
|
||||
AShooterPlayerController::AShooterPlayerController()
|
||||
{
|
||||
bReplicates = true;
|
||||
bPawnAlive = true;
|
||||
}
|
||||
|
||||
void AShooterPlayerController::OnPossess(APawn* InPawn)
|
||||
{
|
||||
Super::OnPossess(InPawn);
|
||||
bPawnAlive = true;
|
||||
}
|
||||
|
||||
void AShooterPlayerController::OnRep_PlayerState()
|
||||
{
|
||||
Super::OnRep_PlayerState();
|
||||
OnPlayerStateReplicated.Broadcast();
|
||||
}
|
||||
|
||||
void AShooterPlayerController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
||||
if (Subsystem)
|
||||
{
|
||||
Subsystem->AddMappingContext(ShooterIMC, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void AShooterPlayerController::SetupInputComponent()
|
||||
{
|
||||
Super::SetupInputComponent();
|
||||
|
||||
UEnhancedInputComponent* ShooterInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent);
|
||||
ShooterInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AShooterPlayerController::Input_Move);
|
||||
ShooterInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AShooterPlayerController::Input_Look);
|
||||
ShooterInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AShooterPlayerController::Input_Crouch);
|
||||
ShooterInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &AShooterPlayerController::Input_Jump);
|
||||
|
||||
}
|
||||
|
||||
void AShooterPlayerController::Input_Move(const FInputActionValue& InputActionValue)
|
||||
{
|
||||
if (!bPawnAlive) return;
|
||||
const FVector2D InputAxisVector = InputActionValue.Get<FVector2D>();
|
||||
const FRotator Rotation = GetControlRotation();
|
||||
const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);
|
||||
|
||||
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
|
||||
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
|
||||
|
||||
if (APawn* ControlledPawn = GetPawn<APawn>())
|
||||
{
|
||||
ControlledPawn->AddMovementInput(ForwardDirection, InputAxisVector.Y);
|
||||
ControlledPawn->AddMovementInput(RightDirection, InputAxisVector.X);
|
||||
}
|
||||
}
|
||||
|
||||
void AShooterPlayerController::Input_Look(const FInputActionValue& InputActionValue)
|
||||
{
|
||||
const FVector2D InputAxisVector = InputActionValue.Get<FVector2D>();
|
||||
AddYawInput(InputAxisVector.X);
|
||||
AddPitchInput(InputAxisVector.Y);
|
||||
}
|
||||
|
||||
void AShooterPlayerController::Input_Crouch()
|
||||
{
|
||||
if (!bPawnAlive) return;
|
||||
if (GetPawn() == nullptr || !GetPawn()->Implements<UPlayerInterface>()) return;
|
||||
IPlayerInterface::Execute_Initiate_Crouch(GetPawn());
|
||||
}
|
||||
|
||||
void AShooterPlayerController::Input_Jump()
|
||||
{
|
||||
if (!bPawnAlive) return;
|
||||
if (GetPawn() == nullptr || !GetPawn()->Implements<UPlayerInterface>()) return;
|
||||
IPlayerInterface::Execute_Initiate_Jump(GetPawn());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user