ed7c7fd991
Boucle de jeu complète : récolte, inventaire, consommation, stats de survie, mort et respawn. Gameplay en C++, Blueprints réservés au câblage d'assets. Assets binaires (.uasset, .umap, textures, audio) suivis via Git LFS. Binaries/, Intermediate/, Saved/ et DerivedDataCache/ sont ignorés : régénérés au build, ils pèsent 3 Go pour 1,3 Go de contenu utile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
128 lines
2.7 KiB
C++
128 lines
2.7 KiB
C++
// 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();
|
|
}
|
|
}
|