Initial Commit - Lesson 31 (Commit #1)
This commit is contained in:
63
Source/FPSTemplate/Private/UI/Elims/ScoreWidget.cpp
Normal file
63
Source/FPSTemplate/Private/UI/Elims/ScoreWidget.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/Elims/ScoreWidget.h"
|
||||
#include "Components/TextBlock.h"
|
||||
#include "Player/MatchPlayerState.h"
|
||||
#include "Player/ShooterPlayerController.h"
|
||||
|
||||
void UScoreWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
AMatchPlayerState* PlayerState = GetPlayerState();
|
||||
if (IsValid(PlayerState))
|
||||
{
|
||||
PlayerState->OnScoreChanged.AddDynamic(this, &UScoreWidget::OnScoreChanged);
|
||||
OnScoreChanged(PlayerState->GetScoredElims());
|
||||
}
|
||||
else
|
||||
{
|
||||
AShooterPlayerController* ShooterPlayerController = Cast<AShooterPlayerController>(GetOwningPlayer());
|
||||
if (IsValid(ShooterPlayerController))
|
||||
{
|
||||
ShooterPlayerController->OnPlayerStateReplicated.AddUniqueDynamic(this, &UScoreWidget::OnPlayerStateInitialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UScoreWidget::OnScoreChanged(int32 NewScore)
|
||||
{
|
||||
if (IsValid(ScoreText))
|
||||
{
|
||||
ScoreText->SetText(FText::AsNumber(NewScore));
|
||||
}
|
||||
}
|
||||
|
||||
void UScoreWidget::OnPlayerStateInitialized()
|
||||
{
|
||||
// Get the PlayerState and bind to the score changed delegate
|
||||
AMatchPlayerState* PlayerState = GetPlayerState();
|
||||
if (IsValid(PlayerState))
|
||||
{
|
||||
PlayerState->OnScoreChanged.AddDynamic(this, &UScoreWidget::OnScoreChanged);
|
||||
OnScoreChanged(PlayerState->GetScoredElims());
|
||||
}
|
||||
|
||||
// Unsubscribe from the OnPlayerStateChanged delegate
|
||||
AShooterPlayerController* ShooterPlayerController = Cast<AShooterPlayerController>(GetOwningPlayer());
|
||||
if (IsValid(ShooterPlayerController))
|
||||
{
|
||||
ShooterPlayerController->OnPlayerStateReplicated.RemoveDynamic(this, &UScoreWidget::OnPlayerStateInitialized);
|
||||
}
|
||||
}
|
||||
|
||||
AMatchPlayerState* UScoreWidget::GetPlayerState() const
|
||||
{
|
||||
APlayerController* PlayerController = GetOwningPlayer();
|
||||
if (IsValid(PlayerController))
|
||||
{
|
||||
return PlayerController->GetPlayerState<AMatchPlayerState>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
35
Source/FPSTemplate/Private/UI/Elims/SpecialElimWidget.cpp
Normal file
35
Source/FPSTemplate/Private/UI/Elims/SpecialElimWidget.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/Elims/SpecialElimWidget.h"
|
||||
|
||||
#include "Blueprint/WidgetLayoutLibrary.h"
|
||||
#include "Components/TextBlock.h"
|
||||
#include "Components/Image.h"
|
||||
|
||||
void USpecialElimWidget::InitializeWidget(const FString& InElimMessage, UTexture2D* InElimTexture)
|
||||
{
|
||||
if (IsValid(ElimText))
|
||||
{
|
||||
ElimText->SetText(FText::FromString(InElimMessage));
|
||||
}
|
||||
|
||||
if (IsValid(ElimImage) && InElimTexture)
|
||||
{
|
||||
ElimImage->SetBrushFromTexture(InElimTexture);
|
||||
}
|
||||
}
|
||||
|
||||
void USpecialElimWidget::CenterWidget(UUserWidget* Widget, float VerticalRatio)
|
||||
{
|
||||
if (!IsValid(Widget))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FVector2D ViewportSize = UWidgetLayoutLibrary::GetViewportSize(Widget);
|
||||
const float VerticalFraction = VerticalRatio == 0.f ? 1.f : VerticalRatio * 2.f;
|
||||
FVector2D CenterPosition(ViewportSize.X / 2.0f, VerticalFraction * ViewportSize.Y / 2.0f);
|
||||
Widget->SetAlignmentInViewport(FVector2D(0.5f, 0.5f)); // Align widget center to the center of the viewport
|
||||
Widget->SetPositionInViewport(CenterPosition, true);
|
||||
}
|
||||
90
Source/FPSTemplate/Private/UI/ShooterAmmoCounter.cpp
Normal file
90
Source/FPSTemplate/Private/UI/ShooterAmmoCounter.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/ShooterAmmoCounter.h"
|
||||
|
||||
#include "Character/ShooterCharacter.h"
|
||||
#include "Combat/CombatComponent.h"
|
||||
#include "Interfaces/PlayerInterface.h"
|
||||
#include "Weapon/Weapon.h"
|
||||
#include "Components/Image.h"
|
||||
#include "Components/TextBlock.h"
|
||||
|
||||
void UShooterAmmoCounter::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
Image_WeaponIcon->SetRenderOpacity(0.f);
|
||||
Text_Ammo->SetRenderOpacity(0.f);
|
||||
|
||||
GetOwningPlayer()->OnPossessedPawnChanged.AddDynamic(this, &UShooterAmmoCounter::OnPossessedPawnChanged);
|
||||
|
||||
AShooterCharacter* ShooterCharacter = Cast<AShooterCharacter>(GetOwningPlayer()->GetPawn());
|
||||
if (!IsValid(ShooterCharacter)) return;
|
||||
|
||||
OnPossessedPawnChanged(nullptr, ShooterCharacter);
|
||||
|
||||
if (ShooterCharacter->bWeaponFirstReplicated)
|
||||
{
|
||||
AWeapon* CurrentWeapon = IPlayerInterface::Execute_GetCurrentWeapon(ShooterCharacter);
|
||||
if (IsValid(CurrentWeapon))
|
||||
{
|
||||
OnCarriedAmmoChanged(CurrentWeapon->GetAmmoCounterDynamicMaterialInstance(), IPlayerInterface::Execute_GetCarriedAmmo(ShooterCharacter), CurrentWeapon->Ammo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShooterCharacter->OnWeaponFirstReplicated.AddDynamic(this, &UShooterAmmoCounter::OnWeaponFirstReplicated);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterAmmoCounter::OnWeaponFirstReplicated(AWeapon* Weapon)
|
||||
{
|
||||
OnCarriedAmmoChanged(Weapon->GetAmmoCounterDynamicMaterialInstance(), IPlayerInterface::Execute_GetCarriedAmmo(GetOwningPlayer()->GetPawn()), Weapon->Ammo);
|
||||
}
|
||||
|
||||
void UShooterAmmoCounter::OnPossessedPawnChanged(APawn* OldPawn, APawn* NewPawn)
|
||||
{
|
||||
UCombatComponent* OldPawnCombat = UCombatComponent::FindCombatComponent(OldPawn);
|
||||
if (IsValid(OldPawnCombat))
|
||||
{
|
||||
OldPawnCombat->OnCarriedAmmoChanged.RemoveDynamic(this, &UShooterAmmoCounter::OnCarriedAmmoChanged);
|
||||
OldPawnCombat->OnRoundFired.RemoveDynamic(this, &UShooterAmmoCounter::OnRoundFired);
|
||||
}
|
||||
UCombatComponent* NewPawnCombat = UCombatComponent::FindCombatComponent(NewPawn);
|
||||
if (IsValid(NewPawnCombat))
|
||||
{
|
||||
Image_WeaponIcon->SetRenderOpacity(1.f);
|
||||
Text_Ammo->SetRenderOpacity(1.f);
|
||||
NewPawnCombat->OnCarriedAmmoChanged.AddDynamic(this, &UShooterAmmoCounter::OnCarriedAmmoChanged);
|
||||
NewPawnCombat->OnRoundFired.AddDynamic(this, &UShooterAmmoCounter::OnRoundFired);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterAmmoCounter::OnCarriedAmmoChanged(UMaterialInstanceDynamic* WeaponIconDynMatInst, int32 InCarriedAmmo, int32 RoundsInWeapon)
|
||||
{
|
||||
CurrentWeaponIcon_DynMatInst = WeaponIconDynMatInst;
|
||||
FSlateBrush Brush;
|
||||
Brush.SetResourceObject(CurrentWeaponIcon_DynMatInst);
|
||||
if (IsValid(Image_WeaponIcon))
|
||||
{
|
||||
Image_WeaponIcon->SetBrush(Brush);
|
||||
}
|
||||
TotalAmmo = InCarriedAmmo + RoundsInWeapon;
|
||||
if (IsValid(Text_Ammo))
|
||||
{
|
||||
FText AmmoText = FText::Format(NSLOCTEXT("AmmoText", "AmmoKey", "{0}"), TotalAmmo);
|
||||
Text_Ammo->SetText(AmmoText);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterAmmoCounter::OnRoundFired(int32 RoundsCurrent, int32 RoundsMax, int32 RoundsCarried)
|
||||
{
|
||||
TotalAmmo = RoundsCarried + RoundsCurrent;
|
||||
if (IsValid(Text_Ammo))
|
||||
{
|
||||
FText AmmoText = FText::Format(NSLOCTEXT("AmmoText", "AmmoKey", "{0}"), TotalAmmo);
|
||||
Text_Ammo->SetText(AmmoText);
|
||||
}
|
||||
}
|
||||
|
||||
19
Source/FPSTemplate/Private/UI/ShooterHUD.cpp
Normal file
19
Source/FPSTemplate/Private/UI/ShooterHUD.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/ShooterHUD.h"
|
||||
|
||||
#include "Blueprint/UserWidget.h"
|
||||
|
||||
|
||||
void AShooterHUD::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
APlayerController* PlayerController = GetOwningPlayerController();
|
||||
if (IsValid(PlayerController) && ShooterOverlayClass)
|
||||
{
|
||||
Overlay = CreateWidget<UUserWidget>(PlayerController, ShooterOverlayClass);
|
||||
Overlay->AddToViewport();
|
||||
}
|
||||
}
|
||||
161
Source/FPSTemplate/Private/UI/ShooterReticle.cpp
Normal file
161
Source/FPSTemplate/Private/UI/ShooterReticle.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/ShooterReticle.h"
|
||||
|
||||
#include "Character/ShooterCharacter.h"
|
||||
#include "Components/Image.h"
|
||||
#include "Combat/CombatComponent.h"
|
||||
#include "Weapon/Weapon.h"
|
||||
#include "Interfaces/PlayerInterface.h"
|
||||
|
||||
namespace Reticle
|
||||
{
|
||||
const FName Inner_RGBA = FName("Inner_RGBA");
|
||||
const FName RoundedCornerScale = FName("RoundedCornerScale");
|
||||
const FName ShapeCutThickness = FName("ShapeCutThickness");
|
||||
}
|
||||
|
||||
namespace Ammo
|
||||
{
|
||||
const FName Rounds_Current = FName("Rounds_Current");
|
||||
const FName Rounds_Max = FName("Rounds_Max");
|
||||
}
|
||||
|
||||
void UShooterReticle::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
Image_Reticle->SetRenderOpacity(0.f);
|
||||
Image_AmmoCounter->SetRenderOpacity(0.f);
|
||||
|
||||
GetOwningPlayer()->OnPossessedPawnChanged.AddDynamic(this, &UShooterReticle::OnPossessedPawnChanged);
|
||||
|
||||
AShooterCharacter* ShooterCharacter = Cast<AShooterCharacter>(GetOwningPlayer()->GetPawn());
|
||||
if (!IsValid(ShooterCharacter)) return;
|
||||
|
||||
OnPossessedPawnChanged(nullptr, ShooterCharacter);
|
||||
|
||||
if (ShooterCharacter->bWeaponFirstReplicated)
|
||||
{
|
||||
AWeapon* CurrentWeapon = IPlayerInterface::Execute_GetCurrentWeapon(ShooterCharacter);
|
||||
if (IsValid(CurrentWeapon))
|
||||
{
|
||||
OnReticleChange(CurrentWeapon->GetReticleDynamicMaterialInstance(), CurrentWeapon->ReticleParams);
|
||||
OnAmmoCounterChange(CurrentWeapon->GetAmmoCounterDynamicMaterialInstance(), CurrentWeapon->Ammo, CurrentWeapon->MagCapacity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShooterCharacter->OnWeaponFirstReplicated.AddDynamic(this, &UShooterReticle::OnWeaponFirstReplicated);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterReticle::OnWeaponFirstReplicated(AWeapon* Weapon)
|
||||
{
|
||||
OnReticleChange(Weapon->GetReticleDynamicMaterialInstance(), Weapon->ReticleParams);
|
||||
OnAmmoCounterChange(Weapon->GetAmmoCounterDynamicMaterialInstance(), Weapon->Ammo, Weapon->MagCapacity);
|
||||
}
|
||||
|
||||
void UShooterReticle::OnPossessedPawnChanged(APawn* OldPawn, APawn* NewPawn)
|
||||
{
|
||||
UCombatComponent* OldPawnCombat = UCombatComponent::FindCombatComponent(OldPawn);
|
||||
if (IsValid(OldPawnCombat))
|
||||
{
|
||||
OldPawnCombat->OnReticleChanged.RemoveDynamic(this, &UShooterReticle::OnReticleChange);
|
||||
OldPawnCombat->OnAmmoCounterChanged.RemoveDynamic(this, &UShooterReticle::OnAmmoCounterChange);
|
||||
OldPawnCombat->OnTargetingPlayerStatusChanged.RemoveDynamic(this, &UShooterReticle::OnTargetingPlayerStatusChanged);
|
||||
OldPawnCombat->OnRoundFired.RemoveDynamic(this, &UShooterReticle::OnRoundFired);
|
||||
OldPawnCombat->OnAimingStatusChanged.RemoveDynamic(this, &UShooterReticle::OnAimingStatusChanged);
|
||||
}
|
||||
UCombatComponent* NewPawnCombat = UCombatComponent::FindCombatComponent(NewPawn);
|
||||
if (IsValid(NewPawnCombat))
|
||||
{
|
||||
Image_Reticle->SetRenderOpacity(1.f);
|
||||
Image_AmmoCounter->SetRenderOpacity(1.f);
|
||||
NewPawnCombat->OnReticleChanged.AddDynamic(this, &UShooterReticle::OnReticleChange);
|
||||
NewPawnCombat->OnAmmoCounterChanged.AddDynamic(this, &UShooterReticle::OnAmmoCounterChange);
|
||||
NewPawnCombat->OnTargetingPlayerStatusChanged.AddDynamic(this, &UShooterReticle::OnTargetingPlayerStatusChanged);
|
||||
NewPawnCombat->OnRoundFired.AddDynamic(this, &UShooterReticle::OnRoundFired);
|
||||
NewPawnCombat->OnAimingStatusChanged.AddDynamic(this, &UShooterReticle::OnAimingStatusChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterReticle::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
|
||||
{
|
||||
Super::NativeTick(MyGeometry, InDeltaTime);
|
||||
|
||||
_BaseCornerScaleFactor_TargetingPlayer = FMath::FInterpTo(_BaseCornerScaleFactor_TargetingPlayer, bTargetingPlayer ? CurrentReticleParams.ScaleFactor_Targeting : CurrentReticleParams.ScaleFactor_NotTargeting, InDeltaTime, CurrentReticleParams.TargetingPlayerInterpSpeed);
|
||||
_BaseCornerScaleFactor_Aiming = FMath::FInterpTo(_BaseCornerScaleFactor_Aiming, bAiming ? CurrentReticleParams.ScaleFactor_Aiming : CurrentReticleParams.ScaleFactor_NotAiming, InDeltaTime, CurrentReticleParams.AimingInterpSpeed);
|
||||
_BaseCornerScaleFactor_RoundFired = FMath::FInterpTo(_BaseCornerScaleFactor_RoundFired, 0.f, InDeltaTime, CurrentReticleParams.RoundFiredInterpSpeed);
|
||||
|
||||
_BaseShapeCutFactor_Aiming = FMath::FInterpTo(BaseShapeCutFactor, bAiming ? CurrentReticleParams.ShapeCutFactor_Aiming : CurrentReticleParams.ShapeCutFactor_NotAiming, InDeltaTime, CurrentReticleParams.AimingInterpSpeed);
|
||||
_BaseShapeCutFactor_RoundFired = FMath::FInterpTo(_BaseShapeCutFactor_RoundFired, 0.f, InDeltaTime, CurrentReticleParams.RoundFiredInterpSpeed);
|
||||
|
||||
BaseCornerScaleFactor = _BaseCornerScaleFactor_TargetingPlayer + _BaseCornerScaleFactor_Aiming + _BaseCornerScaleFactor_RoundFired;
|
||||
BaseShapeCutFactor = _BaseShapeCutFactor_Aiming + _BaseShapeCutFactor_RoundFired;
|
||||
if (IsValid(CurrentReticle_DynMatInst))
|
||||
{
|
||||
CurrentReticle_DynMatInst->SetScalarParameterValue(Reticle::RoundedCornerScale, BaseCornerScaleFactor);
|
||||
CurrentReticle_DynMatInst->SetScalarParameterValue(Reticle::ShapeCutThickness, BaseShapeCutFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterReticle::OnReticleChange(UMaterialInstanceDynamic* ReticleDynMatInst, const FReticleParams& ReticleParams,
|
||||
bool bCurrentlyTargetingPlayer)
|
||||
{
|
||||
CurrentReticleParams = ReticleParams;
|
||||
|
||||
CurrentReticle_DynMatInst = ReticleDynMatInst;
|
||||
FSlateBrush Brush;
|
||||
Brush.SetResourceObject(ReticleDynMatInst);
|
||||
if (IsValid(Image_Reticle))
|
||||
{
|
||||
Image_Reticle->SetBrush(Brush);
|
||||
}
|
||||
|
||||
OnTargetingPlayerStatusChanged(bCurrentlyTargetingPlayer);
|
||||
}
|
||||
|
||||
void UShooterReticle::OnAmmoCounterChange(UMaterialInstanceDynamic* AmmoCounterDynMatInst, int32 RoundsCurrent,
|
||||
int32 RoundsMax)
|
||||
{
|
||||
CurrentAmmoCounter_DynMatInst = AmmoCounterDynMatInst;
|
||||
CurrentAmmoCounter_DynMatInst->SetScalarParameterValue(Ammo::Rounds_Current, RoundsCurrent);
|
||||
CurrentAmmoCounter_DynMatInst->SetScalarParameterValue(Ammo::Rounds_Max, RoundsMax);
|
||||
FSlateBrush Brush;
|
||||
Brush.SetResourceObject(CurrentAmmoCounter_DynMatInst);
|
||||
|
||||
if (IsValid(Image_AmmoCounter))
|
||||
{
|
||||
Image_AmmoCounter->SetBrush(Brush);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterReticle::OnTargetingPlayerStatusChanged(bool bIsTargetingPlayer)
|
||||
{
|
||||
if (IsValid(CurrentReticle_DynMatInst))
|
||||
{
|
||||
FLinearColor ReticleColor = bIsTargetingPlayer ? FLinearColor::Red : FLinearColor::White;
|
||||
CurrentReticle_DynMatInst->SetVectorParameterValue(Reticle::Inner_RGBA, ReticleColor);
|
||||
}
|
||||
bTargetingPlayer = bIsTargetingPlayer;
|
||||
}
|
||||
|
||||
void UShooterReticle::OnRoundFired(int32 RoundsCurrent, int32 RoundsMax, int32 RoundsCarried)
|
||||
{
|
||||
_BaseCornerScaleFactor_RoundFired += CurrentReticleParams.ScaleFactor_RoundFired;
|
||||
_BaseShapeCutFactor_RoundFired += CurrentReticleParams.ShapeCutFactor_RoundFired;
|
||||
|
||||
if (IsValid(CurrentAmmoCounter_DynMatInst))
|
||||
{
|
||||
CurrentAmmoCounter_DynMatInst->SetScalarParameterValue(Ammo::Rounds_Current, RoundsCurrent);
|
||||
CurrentAmmoCounter_DynMatInst->SetScalarParameterValue(Ammo::Rounds_Max, RoundsMax);
|
||||
}
|
||||
}
|
||||
|
||||
void UShooterReticle::OnAimingStatusChanged(bool bIsAiming)
|
||||
{
|
||||
bAiming = bIsAiming;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user