280 lines
7.9 KiB
C++
280 lines
7.9 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "Player/LMPlayer.h"
|
|
|
|
#include "KismetTraceUtils.h"
|
|
#include "LMUserSettings.h"
|
|
#include "LMUtils.h"
|
|
#include "Camera/CameraComponent.h"
|
|
#include "Ammo/LMAmmo.h"
|
|
#include "Player/LMBulletInfo.h"
|
|
#include "Player/LMHealthComponent.h"
|
|
#include "Player/LMHitBox.h"
|
|
#include "Player/LMMovementComponent.h"
|
|
#include "Weapon/LMWeaponManager.h"
|
|
|
|
|
|
ALMPlayer::ALMPlayer(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer.SetDefaultSubobjectClass<ULMMovementComponent>(CharacterMovementComponentName))
|
|
{
|
|
LegumixMovementComponent = Cast<ULMMovementComponent>(GetCharacterMovement());
|
|
LedgeGrabOrigin = CreateDefaultSubobject<USceneComponent>("LedgeGrabOrigin");
|
|
LedgeGrabOrigin->SetupAttachment(RootComponent);
|
|
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
|
|
SpreadStream = FRandomStream(FMath::Rand());
|
|
HealthComponent = CreateDefaultSubobject<ULMHealthComponent>(TEXT("HealthComponent"));
|
|
|
|
HitPeriodLengthInSeconds = 15.f;
|
|
bHitPeriodInProgress = false;
|
|
TimeOfTheLastDamage = 0.f;
|
|
HealthAtTheCurrentHitPeriodBeginning = 100.f;
|
|
CumulatedDamagesOnCurrentHitPeriod = 0.f;
|
|
PlayerViewOcclusionPercent = 0.f;
|
|
NextPlayerViewOcclusionPercent = 0.f;
|
|
PlayerViewOcclusionPercent = 0.f;
|
|
AlphaLerpForPlayerViewOcclusionPercent = 0.f;
|
|
}
|
|
|
|
void ALMPlayer::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
WeaponManager->WeaponFired.AddUniqueDynamic(this, &ALMPlayer::WeaponFired);
|
|
WeaponManager->WeaponSwitched.AddUniqueDynamic(this, &ALMPlayer::WeaponSwitched);
|
|
|
|
GetCamera()->SetFieldOfView(ULMUserSettings::GetLegumixUserSettings()->FieldOfView);
|
|
|
|
// HealthComponent->OnHealthChanged.AddDynamic(this, &ALMPlayer::SetDisplayDamageParameters);
|
|
|
|
MovementModeChangedDelegate.AddUniqueDynamic(this, &ALMPlayer::MovementChanged);
|
|
}
|
|
|
|
void ALMPlayer::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
|
|
if(bHitPeriodInProgress == true)
|
|
{
|
|
double TimeElapsedSinceLastDamage = GetWorld()->GetTimeSeconds() - TimeOfTheLastDamage;
|
|
if(TimeElapsedSinceLastDamage > HitPeriodLengthInSeconds)
|
|
{
|
|
if(bHitPeriodInProgress == true)
|
|
{
|
|
bHitPeriodInProgress = false;
|
|
PlayerViewOcclusionPercent = NextPlayerViewOcclusionPercent;
|
|
NextPlayerViewOcclusionPercent = 0.f;
|
|
AlphaLerpForPlayerViewOcclusionPercent = 0.f;
|
|
TimeOfTheLastDamage = 0.f;
|
|
CumulatedDamagesOnCurrentHitPeriod = 0.f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(PlayerViewOcclusionPercent != NextPlayerViewOcclusionPercent)
|
|
{
|
|
AlphaLerpForPlayerViewOcclusionPercent = FMath::Clamp(AlphaLerpForPlayerViewOcclusionPercent + DeltaTime, 0, 1);
|
|
PlayerViewOcclusionPercent = FMath::Lerp(PlayerViewOcclusionPercent, NextPlayerViewOcclusionPercent, AlphaLerpForPlayerViewOcclusionPercent);
|
|
DamageDynamicMaterialInstance->SetScalarParameterValue("PlayerViewOcclusionPercent", PlayerViewOcclusionPercent);
|
|
}
|
|
else if(PlayerViewOcclusionPercent == NextPlayerViewOcclusionPercent)
|
|
{
|
|
AlphaLerpForPlayerViewOcclusionPercent = 0;
|
|
}
|
|
}
|
|
|
|
|
|
bool ALMPlayer::PickUpAmmo(ALMAmmo* Ammo)
|
|
{
|
|
if (GEngine)
|
|
{
|
|
const FString AmmoAmount = FString::Printf(TEXT("Quantité de munition : %i"), Ammo->GetAmmoAmount());
|
|
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 30.f, FColor::Red, AmmoAmount);
|
|
}
|
|
|
|
if (WeaponManager->AddAmmoType(Ammo->GetAmmoType(), Ammo->GetAmmoAmount()))
|
|
{
|
|
OnAmmoPickup();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int ALMPlayer::GetAmmoCount(const EAmmoType AmmoType) const
|
|
{
|
|
return WeaponManager->GetAmmoCount(AmmoType);
|
|
}
|
|
|
|
int ALMPlayer::RemoveAmmo(const EAmmoType AmmoType, const int Count) const
|
|
{
|
|
return WeaponManager->RemoveAmmo(AmmoType, Count);
|
|
}
|
|
|
|
bool ALMPlayer::CanJumpInternal_Implementation() const
|
|
{
|
|
return JumpIsAllowedInternal();
|
|
}
|
|
|
|
void ALMPlayer::SetWeaponManager(ULMWeaponManager* Manager)
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("Set weapon manager"))
|
|
if (!Manager)
|
|
{
|
|
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 10.f, FColor::Red, TEXT("No Weapon Manager was given to the player !"));
|
|
return;
|
|
}
|
|
|
|
WeaponManager = Manager;
|
|
WeaponManager->Initialize(GetArms());
|
|
}
|
|
|
|
void ALMPlayer::PlayAnimation(UAnimMontage* Animation)
|
|
{
|
|
UAnimInstance* AnimInstance = GetArms()->GetAnimInstance();
|
|
if (AnimInstance && Animation)
|
|
{
|
|
AnimInstance->Montage_Play(Animation);
|
|
}
|
|
}
|
|
|
|
void ALMPlayer::FireBullets(const FLMBulletInfo Settings)
|
|
{
|
|
FVector EndLocation;
|
|
FVector ShotVector;
|
|
FHitResult OutHit = FHitResult();
|
|
bool HitSomething = false;
|
|
|
|
OnFire();
|
|
|
|
#if WITH_EDITOR
|
|
if (bDrawBulletDebug)
|
|
DrawDebugLine(GetWorld(), Settings.Origin, Settings.Origin + (Settings.Direction * Settings.MaxDistance), FColor::Blue, false, 2.f);
|
|
#endif
|
|
|
|
for (int Shots = 0; Shots < Settings.BulletCount; Shots++)
|
|
{
|
|
ShotVector = UKismetMathLibrary::RandomUnitVectorInConeInDegreesFromStream(SpreadStream, Settings.Direction, Settings.Spread);
|
|
EndLocation = Settings.Origin + (ShotVector * Settings.MaxDistance);
|
|
|
|
const bool HasHit = GetWorld()->LineTraceSingleByChannel(OutHit, Settings.Origin, EndLocation, TRACE_BULLET);
|
|
|
|
#if WITH_EDITOR
|
|
if (bDrawBulletDebug)
|
|
DrawDebugLineTraceSingle(GetWorld(), Settings.Origin, EndLocation, EDrawDebugTrace::ForDuration, HasHit, OutHit, FColor::Green, FColor::Red, 2.f);
|
|
#endif
|
|
|
|
WeaponManager->CreateTracer(Settings.AmmoType, HasHit ? OutHit.Location : EndLocation, ShotVector.Rotation());
|
|
|
|
if (!HasHit)
|
|
continue;
|
|
|
|
if (ULMHitBox* HitBox = Cast<ULMHitBox>(OutHit.Component))
|
|
{
|
|
if (!HitBox->CanBeHitByTeam(Team))
|
|
continue;
|
|
|
|
HitSomething = true;
|
|
HitBox->OnHit(Settings, OutHit);
|
|
}
|
|
}
|
|
|
|
if (HitSomething)
|
|
{
|
|
OnEnnemyHit();
|
|
}
|
|
}
|
|
|
|
FVector ALMPlayer::GetWeaponFiringOrigin()
|
|
{
|
|
if (!GetCam())
|
|
{
|
|
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 10.f, FColor::Silver, TEXT("No camera ???"));
|
|
return FVector::ZeroVector;
|
|
}
|
|
return GetCam()->GetComponentTransform().GetLocation();
|
|
}
|
|
|
|
FVector ALMPlayer::GetAimVector() { return GetCam()->GetForwardVector(); }
|
|
|
|
void ALMPlayer::OnPause_Implementation(bool Paused)
|
|
{
|
|
}
|
|
|
|
UCameraComponent* ALMPlayer::GetCam()
|
|
{
|
|
if (!Camera)
|
|
Camera = GetCamera();
|
|
|
|
return Camera;
|
|
}
|
|
|
|
USkeletalMeshComponent* ALMPlayer::GetArms()
|
|
{
|
|
if (!ArmsMesh)
|
|
ArmsMesh = GetArmsBP();
|
|
|
|
return ArmsMesh;
|
|
}
|
|
|
|
void ALMPlayer::SetDisplayDamageParameters(float Health, float Damage)
|
|
{
|
|
if (bHitPeriodInProgress == false)
|
|
{
|
|
HealthAtTheCurrentHitPeriodBeginning = Health;
|
|
bHitPeriodInProgress = true;
|
|
}
|
|
TimeOfTheLastDamage = GetWorld()->GetTimeSeconds();
|
|
CumulatedDamagesOnCurrentHitPeriod += Damage;
|
|
SetPlayerViewOcclusionPercent();
|
|
}
|
|
|
|
|
|
void ALMPlayer::SetPlayerViewOcclusionPercent()
|
|
{
|
|
AlphaLerpForPlayerViewOcclusionPercent = 0;
|
|
PlayerViewOcclusionPercent = NextPlayerViewOcclusionPercent;
|
|
NextPlayerViewOcclusionPercent = CumulatedDamagesOnCurrentHitPeriod / HealthAtTheCurrentHitPeriodBeginning;
|
|
}
|
|
|
|
void ALMPlayer::MovementChanged(ACharacter* Character, EMovementMode PrevMovementMode, uint8 PreviousCustomMode)
|
|
{
|
|
if (GetCharacterMovement()->MovementMode == MOVE_Falling)
|
|
{
|
|
GetWorldTimerManager().SetTimer(LedgeGrabCheckTimer, this, &ALMPlayer::DoLedgeGrabCheck, LedgeGrabPollTime, true);
|
|
}
|
|
else if (PrevMovementMode == MOVE_Falling)
|
|
{
|
|
GetWorldTimerManager().ClearTimer(LedgeGrabCheckTimer);
|
|
}
|
|
}
|
|
|
|
void ALMPlayer::DoLedgeGrabCheck()
|
|
{
|
|
FVector Origin = LedgeGrabOrigin->GetComponentLocation();
|
|
FVector Dir = LedgeGrabOrigin->GetUpVector() * FVector(0, 0, -LedgeGrabTraceLength);
|
|
FVector Ray = Origin + Dir;
|
|
|
|
FHitResult Hit;
|
|
const bool Results = UKismetSystemLibrary::LineTraceSingleByProfile(GetWorld(), Origin, Ray, TEXT("BlockAll"), false
|
|
, {}, EDrawDebugTrace::None, Hit, true, FLinearColor::Red, FLinearColor::Green, 0.2f);
|
|
if (Results)
|
|
{
|
|
FVector TeleportLocation = FVector(Hit.Location.X, Hit.Location.Y, Hit.Location.Z + GetCapsuleComponent()->GetScaledCapsuleHalfHeight());
|
|
SetActorLocation(TeleportLocation, false, nullptr, ETeleportType::ResetPhysics);
|
|
}
|
|
}
|
|
|
|
FCollisionQueryParams ALMPlayer::GetIgnoreCharacterParams()
|
|
{
|
|
FCollisionQueryParams Params;
|
|
|
|
TArray<AActor*> ChildrenActors;
|
|
GetAllChildActors(ChildrenActors);
|
|
Params.AddIgnoredActors(ChildrenActors);
|
|
Params.AddIgnoredActor(this);
|
|
|
|
return Params;
|
|
}
|
|
|