// 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(CharacterMovementComponentName)) { LegumixMovementComponent = Cast(GetCharacterMovement()); LedgeGrabOrigin = CreateDefaultSubobject("LedgeGrabOrigin"); LedgeGrabOrigin->SetupAttachment(RootComponent); PrimaryActorTick.bCanEverTick = true; SpreadStream = FRandomStream(FMath::Rand()); HealthComponent = CreateDefaultSubobject(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(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 ChildrenActors; GetAllChildActors(ChildrenActors); Params.AddIgnoredActors(ChildrenActors); Params.AddIgnoredActor(this); return Params; }