// Fill out your copyright notice in the Description page of Project Settings. #include "SurvivalStatsComponent.h" #include "Engine/World.h" #include "TimerManager.h" USurvivalStatsComponent::USurvivalStatsComponent() { // Pas de Tick : tout passe par un timer a basse frequence. PrimaryComponentTick.bCanEverTick = false; } void USurvivalStatsComponent::BeginPlay() { Super::BeginPlay(); Health = MaxHealth; Hunger = MaxHunger; Thirst = MaxThirst; bDead = false; if (UWorld* World = GetWorld()) { World->GetTimerManager().SetTimer( UpdateTimerHandle, this, &USurvivalStatsComponent::UpdateStats, FMath::Max(UpdateInterval, 0.05f), /*bLoop=*/true); } OnStatsChanged.Broadcast(); } void USurvivalStatsComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) { // Un timer laisse en vie apres la destruction du composant rappellerait // une methode sur un objet mort. if (UWorld* World = GetWorld()) { World->GetTimerManager().ClearTimer(UpdateTimerHandle); } Super::EndPlay(EndPlayReason); } void USurvivalStatsComponent::UpdateStats() { if (bDead) { return; } // Les vitesses sont par minute, l'intervalle en secondes. const float Minutes = FMath::Max(UpdateInterval, 0.05f) / 60.f; Hunger = FMath::Max(0.f, Hunger - HungerDecayPerMinute * Minutes); Thirst = FMath::Max(0.f, Thirst - ThirstDecayPerMinute * Minutes); // Faim ET soif a zero cumulent leurs degats : mourir de soif pendant // qu'on meurt de faim doit aller plus vite. float Damage = 0.f; if (Hunger <= 0.f) { Damage += StarvationDamagePerMinute * Minutes; } if (Thirst <= 0.f) { Damage += DehydrationDamagePerMinute * Minutes; } if (Damage > 0.f) { Health = FMath::Max(0.f, Health - Damage); } OnStatsChanged.Broadcast(); if (Health <= 0.f && !bDead) { bDead = true; if (UWorld* World = GetWorld()) { World->GetTimerManager().ClearTimer(UpdateTimerHandle); } UE_LOG(LogTemp, Log, TEXT("USurvivalStatsComponent : %s est mort."), *GetNameSafe(GetOwner())); OnDied.Broadcast(); } } void USurvivalStatsComponent::ApplyRestore(float HealthAmount, float HungerAmount, float ThirstAmount) { if (bDead) { return; } Health = FMath::Clamp(Health + HealthAmount, 0.f, MaxHealth); Hunger = FMath::Clamp(Hunger + HungerAmount, 0.f, MaxHunger); Thirst = FMath::Clamp(Thirst + ThirstAmount, 0.f, MaxThirst); OnStatsChanged.Broadcast(); } void USurvivalStatsComponent::ApplyDamage(float Amount) { if (bDead || Amount <= 0.f) { return; } Health = FMath::Max(0.f, Health - Amount); OnStatsChanged.Broadcast(); if (Health <= 0.f) { bDead = true; if (UWorld* World = GetWorld()) { World->GetTimerManager().ClearTimer(UpdateTimerHandle); } OnDied.Broadcast(); } }