// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Components/ActorComponent.h" #include "SurvivalStatsComponent.generated.h" /** Diffuse a chaque changement de vie, faim ou soif. L'UI s'y abonne. */ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSurvivalStatsChanged); /** Diffuse une seule fois, quand la vie atteint zero. */ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSurvivalDeath); /** * Vie, faim et soif du personnage. * * Les valeurs descendent sur un timer a basse frequence et non dans Tick : * une jauge qui perd trois points par minute n'a aucune raison d'etre * recalculee 120 fois par seconde. * * Les vitesses sont exprimees PAR MINUTE, parce que c'est l'unite dans * laquelle on raisonne quand on equilibre un jeu de survie -- "cent points * de faim en trente minutes" se lit, "0.055 par seconde" non. */ UCLASS(ClassGroup = (Survival), meta = (BlueprintSpawnableComponent)) class SURVIVAL_PROJET_API USurvivalStatsComponent : public UActorComponent { GENERATED_BODY() public: USurvivalStatsComponent(); virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; /** Rend de la vie, de la faim et de la soif. Les valeurs sont bornees au max. */ UFUNCTION(BlueprintCallable, Category = "Survie") void ApplyRestore(float HealthAmount, float HungerAmount, float ThirstAmount); UFUNCTION(BlueprintCallable, Category = "Survie") void ApplyDamage(float Amount); UFUNCTION(BlueprintPure, Category = "Survie") float GetHealth() const { return Health; } UFUNCTION(BlueprintPure, Category = "Survie") float GetHunger() const { return Hunger; } UFUNCTION(BlueprintPure, Category = "Survie") float GetThirst() const { return Thirst; } /** Ratios 0-1, directement utilisables par une ProgressBar. */ UFUNCTION(BlueprintPure, Category = "Survie") float GetHealthPercent() const { return MaxHealth > 0.f ? Health / MaxHealth : 0.f; } UFUNCTION(BlueprintPure, Category = "Survie") float GetHungerPercent() const { return MaxHunger > 0.f ? Hunger / MaxHunger : 0.f; } UFUNCTION(BlueprintPure, Category = "Survie") float GetThirstPercent() const { return MaxThirst > 0.f ? Thirst / MaxThirst : 0.f; } UFUNCTION(BlueprintPure, Category = "Survie") bool IsDead() const { return bDead; } UPROPERTY(BlueprintAssignable, Category = "Survie") FOnSurvivalStatsChanged OnStatsChanged; UPROPERTY(BlueprintAssignable, Category = "Survie") FOnSurvivalDeath OnDied; protected: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Survie|Vie", meta = (ClampMin = "1")) float MaxHealth = 100.f; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Survie|Faim", meta = (ClampMin = "1")) float MaxHunger = 100.f; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Survie|Soif", meta = (ClampMin = "1")) float MaxThirst = 100.f; /** Points de faim perdus par minute. 3.3 vide une jauge pleine en ~30 min. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Survie|Faim", meta = (ClampMin = "0")) float HungerDecayPerMinute = 3.3f; /** La soif descend plus vite que la faim : c'est le besoin le plus pressant. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Survie|Soif", meta = (ClampMin = "0")) float ThirstDecayPerMinute = 5.f; /** Vie perdue par minute quand la faim est a zero. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Survie|Vie", meta = (ClampMin = "0")) float StarvationDamagePerMinute = 6.f; /** Vie perdue par minute quand la soif est a zero. Cumulable avec la faim. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Survie|Vie", meta = (ClampMin = "0")) float DehydrationDamagePerMinute = 9.f; /** * Secondes entre deux mises a jour. Une seconde suffit largement et reste * assez fin pour que les barres bougent de facon fluide a l'oeil. */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Survie", meta = (ClampMin = "0.05")) float UpdateInterval = 1.f; private: /** Appelee par le timer : fait descendre les jauges et applique les degats. */ void UpdateStats(); FTimerHandle UpdateTimerHandle; float Health = 0.f; float Hunger = 0.f; float Thirst = 0.f; bool bDead = false; };