509 lines
19 KiB
C++
509 lines
19 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "GameFramework/Actor.h"
|
|
#include "Interactable.h"
|
|
#include "CookingStation.generated.h"
|
|
|
|
class UInventoryComponent;
|
|
class UItemDataAsset;
|
|
class UNiagaraComponent;
|
|
class UPointLightComponent;
|
|
class USoundBase;
|
|
class USphereComponent;
|
|
class UStaticMeshComponent;
|
|
|
|
/**
|
|
* Ce qu'un emplacement du grill porte a l'instant t.
|
|
*
|
|
* Uniquement de l'etat : le DataAsset dit ce que l'objet EST, cette struct dit
|
|
* ou il en est. C'est la meme separation que FInventorySlot, pour la meme raison.
|
|
*/
|
|
USTRUCT(BlueprintType)
|
|
struct FCookingSlotState
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
/** L'objet pose, ou nullptr. Un seul exemplaire par emplacement, comme dans Raft. */
|
|
UPROPERTY(BlueprintReadOnly, Category = "Cooking")
|
|
TObjectPtr<UItemDataAsset> Item = nullptr;
|
|
|
|
/**
|
|
* Charges restantes de l'exemplaire pose. -1 = plein.
|
|
* L'usure traverse la cuisson comme elle traverse le sol : ce qu'on
|
|
* recupere est le meme exemplaire, pas un neuf.
|
|
*/
|
|
UPROPERTY(BlueprintReadOnly, Category = "Cooking")
|
|
int32 RemainingUses = -1;
|
|
|
|
/**
|
|
* Compte a rebours de l'etape en cours. Pas une UPROPERTY : un FTimerHandle
|
|
* n'est qu'un index dans le gestionnaire de timers, il n'y a rien a
|
|
* collecter ni a serialiser.
|
|
*/
|
|
FTimerHandle Timer;
|
|
|
|
bool IsEmpty() const { return Item == nullptr; }
|
|
};
|
|
|
|
/**
|
|
* Une buche dans le foyer : QUEL objet a ete mis, et combien de temps il tient
|
|
* encore.
|
|
*
|
|
* C'est le coeur du modele : le carburant n'est pas une jauge de secondes mais
|
|
* une pile d'objets. Cinq buches, cinq objets -- une branche qui tient dix
|
|
* secondes occupe exactement la meme place qu'une planche qui en tient cent
|
|
* quatre-vingts. Le joueur voit donc ce qu'il a donne au feu, pas un
|
|
* pourcentage abstrait, et melanger les combustibles reste lisible.
|
|
*/
|
|
USTRUCT(BlueprintType)
|
|
struct FFuelSlotState
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY(BlueprintReadOnly, Category = "Cooking")
|
|
TObjectPtr<UItemDataAsset> Item = nullptr;
|
|
|
|
/** Secondes de combustion restantes pour CE morceau. */
|
|
UPROPERTY(BlueprintReadOnly, Category = "Cooking")
|
|
float RemainingSeconds = 0.f;
|
|
};
|
|
|
|
/** L'etat de la station a change : allumage, depot, transformation, retrait. */
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCookingStationChanged);
|
|
|
|
/**
|
|
* Ce que l'appui sur Interagir va declencher, compte tenu de ce que le joueur
|
|
* vise et de ce qu'il tient.
|
|
*
|
|
* Pas un UENUM : c'est un detail d'implementation, rien a l'exterieur n'a
|
|
* besoin de le nommer.
|
|
*/
|
|
enum class ECookingAction : uint8
|
|
{
|
|
None,
|
|
TakeItem,
|
|
PlaceItem,
|
|
AddFuel
|
|
};
|
|
|
|
/**
|
|
* Resultat complet de la decision. Calcule UNE fois, par ResolveAction(), et
|
|
* servi a la fois au texte du prompt et a l'execution : deux cascades de `if`
|
|
* separees finiraient par diverger, et le joueur lirait "Light the fire" en
|
|
* obtenant autre chose.
|
|
*
|
|
* Struct de pile a duree de vie tres courte, d'ou les pointeurs bruts : rien
|
|
* ici ne peut etre collecte entre le calcul et son usage.
|
|
*/
|
|
struct FCookingInteraction
|
|
{
|
|
ECookingAction Action = ECookingAction::None;
|
|
|
|
/** Emplacement de cuisson vise, ou INDEX_NONE si le joueur regarde le foyer. */
|
|
int32 SlotIndex = INDEX_NONE;
|
|
|
|
/** Objet actif de la barre rapide. */
|
|
UItemDataAsset* HeldItem = nullptr;
|
|
|
|
/** Slot d'inventaire d'ou sortira le bois, et l'objet correspondant. */
|
|
int32 FuelSourceSlot = INDEX_NONE;
|
|
UItemDataAsset* FuelItem = nullptr;
|
|
};
|
|
|
|
/**
|
|
* Poste de cuisson pose dans le monde : feu de camp, et plus tard fourneau ou
|
|
* sechoir en changeant simplement ses reglages.
|
|
*
|
|
* Modele Raft assume : AUCUNE interface. Le joueur tient sa viande crue dans la
|
|
* barre rapide, vise un emplacement du grill, appuie sur Interagir, et regarde
|
|
* le mesh changer.
|
|
*
|
|
* Le poste ne commente jamais son propre etat : le prompt n'affiche QUE des
|
|
* actions realisables, exactement comme un objet a ramasser. Ce qui cuit, ce
|
|
* qui manque et ce qui brule se lit sur les flammes, sur le nombre de buches
|
|
* et sur le mesh de la nourriture -- l'ecrire en plus reconstruirait une
|
|
* interface par-dessus un monde qui se suffit a lui-meme.
|
|
*
|
|
* Aucun Tick. Un timer par emplacement de cuisson, un seul pour le carburant :
|
|
* celui de la buche en train de bruler. Eteindre le feu met ces timers en
|
|
* pause, et la cuisson reprend exactement ou elle s'etait arretee sans qu'une
|
|
* ligne ne compte le temps a la main.
|
|
*
|
|
* Le feu ne s'allume PAS a la main : il part des qu'il a du bois et quelque
|
|
* chose a transformer, et s'arrete des qu'il n'a plus rien a faire. Le bois ne
|
|
* part donc jamais en fumee pour rien -- ce qui evite au joueur d'avoir a
|
|
* penser a eteindre derriere lui, une corvee qui n'apporte aucune decision
|
|
* interessante.
|
|
*/
|
|
UCLASS()
|
|
class SURVIVAL_PROJET_API ACookingStation : public AActor, public IInteractable
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
ACookingStation();
|
|
|
|
// --- IInteractable ---
|
|
virtual FText GetInteractionPrompt_Implementation(AActor* Interactor) const override;
|
|
virtual bool CanInteract_Implementation(AActor* Interactor) const override;
|
|
virtual void Interact_Implementation(AActor* Interactor) override;
|
|
virtual void OnBeginFocus_Implementation() override;
|
|
virtual void OnEndFocus_Implementation() override;
|
|
|
|
/**
|
|
* Allume le feu s'il reste du bois dans le foyer.
|
|
*
|
|
* En temps normal, personne n'appelle ceci : UpdateFireState() decide seul.
|
|
* Reste exposee pour un futur allume-feu ou un evenement scenarise.
|
|
* @return false si le foyer est vide.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Cooking")
|
|
bool Light();
|
|
|
|
/** Eteint le feu. Les cuissons en cours se figent, elles ne repartent pas de zero. */
|
|
UFUNCTION(BlueprintCallable, Category = "Cooking")
|
|
void Extinguish();
|
|
|
|
/** Vrai si au moins un emplacement porte quelque chose qui a encore une etape a franchir. */
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
bool HasPendingWork() const;
|
|
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
bool IsLit() const { return bIsLit; }
|
|
|
|
/**
|
|
* Combien de morceaux de bois le foyer peut contenir.
|
|
*
|
|
* C'est le nombre de buches taguees dans le Blueprint : la capacite est une
|
|
* decision de mise en scene, et la regler a deux endroits garantirait qu'ils
|
|
* finissent par se contredire. FallbackFuelCapacity ne sert qu'aux postes
|
|
* sans buche visible, un four ferme par exemple.
|
|
*/
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
int32 GetFuelCapacity() const { return FuelIndicators.Num() > 0 ? FuelIndicators.Num() : FallbackFuelCapacity; }
|
|
|
|
/** Morceaux de bois actuellement dans le foyer. */
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
int32 GetFuelCount() const { return Fuel.Num(); }
|
|
|
|
/** Secondes de combustion cumulees sur tout ce qui est dans le foyer. */
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
float GetFuelRemaining() const;
|
|
|
|
/** Secondes avant la prochaine transformation, ou 0 si l'emplacement n'attend rien. */
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
float GetSlotTimeRemaining(int32 SlotIndex) const;
|
|
|
|
UFUNCTION(BlueprintPure, Category = "Cooking")
|
|
const TArray<FCookingSlotState>& GetSlots() const { return Slots; }
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Cooking")
|
|
FOnCookingStationChanged OnStationChanged;
|
|
|
|
protected:
|
|
virtual void BeginPlay() override;
|
|
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
|
|
|
/**
|
|
* Nombre d'emplacements de cuisson existant dans la classe. Les composants
|
|
* sont crees au constructeur, donc ce nombre est fige a la compilation --
|
|
* c'est le prix a payer pour pouvoir les positionner A LA SOURIS dans le
|
|
* viewport du Blueprint. Des composants engendres a l'execution ne seraient
|
|
* reglables qu'en tapant des coordonnees a l'aveugle.
|
|
*/
|
|
static constexpr int32 MaxCookingSlots = 4;
|
|
|
|
// ------------------------------------------------------------------
|
|
// Composants
|
|
// ------------------------------------------------------------------
|
|
|
|
/** Le foyer lui-meme : bois, pierres, structure. */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
TObjectPtr<UStaticMeshComponent> BaseMesh;
|
|
|
|
/**
|
|
* Ce que le trace d'interaction vient toucher. Sphere dediee et non le mesh,
|
|
* pour la meme raison que sur APickupItem : rien ne garantit qu'un mesh
|
|
* d'asset pack ait une collision.
|
|
*/
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
TObjectPtr<USphereComponent> InteractionSphere;
|
|
|
|
/**
|
|
* Un mesh par emplacement de cuisson, qui porte la nourriture posee. Sa
|
|
* transform sert a la fois a l'afficher et a savoir ce que le joueur vise :
|
|
* pas besoin d'une collision par emplacement, donc pas une requete physique
|
|
* de plus.
|
|
*
|
|
* Positionne-les dans le viewport du Blueprint. Ils sont caches au demarrage
|
|
* tant qu'ils sont vides, mais restent visibles dans l'editeur pour que tu
|
|
* puisses les placer.
|
|
*/
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
TArray<TObjectPtr<UStaticMeshComponent>> SlotMeshes;
|
|
|
|
/** Flamme. Active tant que le feu brule, coupee des qu'il s'eteint. */
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
TObjectPtr<UNiagaraComponent> FireEffect;
|
|
|
|
/**
|
|
* Halo du foyer, allume en meme temps que la flamme.
|
|
*
|
|
* Regle intensite, couleur et rayon directement sur le composant dans le
|
|
* Blueprint : ce sont des proprietes natives, les redeclarer ici en
|
|
* doublon garantirait qu'un jour les deux se contredisent.
|
|
*/
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
TObjectPtr<UPointLightComponent> FireLight;
|
|
|
|
// ------------------------------------------------------------------
|
|
// Reglages
|
|
// ------------------------------------------------------------------
|
|
|
|
/** Emplacements de cuisson reellement utilises. Les autres restent caches. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking", meta = (ClampMin = "1", ClampMax = "4"))
|
|
int32 CookingSlotCount = 2;
|
|
|
|
/**
|
|
* Echelle appliquee au mesh de la nourriture posee.
|
|
* Les meshes d'objets sont dimensionnes pour etre poses au sol ; sur un
|
|
* grill ils sont souvent trop gros.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking", meta = (ClampMin = "0.01"))
|
|
float CookingMeshScale = 1.f;
|
|
|
|
/**
|
|
* Demi-angle du cone de visee autour de chaque emplacement, en degres.
|
|
*
|
|
* Au-dela, on considere que le joueur vise le foyer et pas un emplacement :
|
|
* c'est ce qui lui permet d'ajouter du bois ou d'allumer le feu sans devoir
|
|
* eviter le grill du regard.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking", meta = (ClampMin = "1", ClampMax = "89"))
|
|
float SlotAimHalfAngle = 25.f;
|
|
|
|
/** Multiplie la vitesse de cuisson. Un fourneau va plus vite que des braises. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking", meta = (ClampMin = "0.01"))
|
|
float CookSpeedMultiplier = 1.f;
|
|
|
|
/**
|
|
* Autorise a reprendre un objet qui n'a pas fini de cuire.
|
|
*
|
|
* Decoche par defaut : ce qu'on a mis a cuire est engage, on attend. Un
|
|
* objet qui a fini sa cuisson reste toujours recuperable, y compris pendant
|
|
* qu'il se dirige vers le brule -- sans quoi il serait impossible de sauver
|
|
* sa viande a temps, ce qui viderait la sur-cuisson de tout son sens.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
bool bAllowTakingRawItems = false;
|
|
|
|
/**
|
|
* Ajoute les secondes restantes aux textes du prompt.
|
|
*
|
|
* Decoche en jeu : un chiffre qui s'egrene est de l'interface deguisee, et
|
|
* le joueur doit lire l'avancement sur le mesh, pas sur un compteur. Coche
|
|
* le temps d'un reglage pour verifier tes durees.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
bool bShowRemainingTimeInPrompt = false;
|
|
|
|
/** Active le Custom Depth quand le poste est vise, comme les ramassables. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking")
|
|
bool bHighlightOnFocus = true;
|
|
|
|
// ------------------------------------------------------------------
|
|
// Reglages : carburant
|
|
// ------------------------------------------------------------------
|
|
|
|
/**
|
|
* Tag a poser sur les meshes de buches qui figurent le contenu du foyer.
|
|
* Leur NOMBRE fait la capacite du feu, et leur ordre alphabetique l'ordre
|
|
* d'apparition : la derniere posee est la premiere a bruler.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Fuel")
|
|
FName FuelIndicatorTag = TEXT("FuelLog");
|
|
|
|
/** Capacite des postes qui n'ont aucune buche visible. Ignore des qu'il y en a une. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Fuel", meta = (ClampMin = "1"))
|
|
int32 FallbackFuelCapacity = 5;
|
|
|
|
/**
|
|
* Chaque buche prend le mesh de l'objet qu'elle represente.
|
|
*
|
|
* Decoche par defaut : les buches d'un feu de camp sont posees a la main
|
|
* dans le Blueprint, avec leur orientation et leur imbrication soignees, et
|
|
* y substituer un mesh d'objet gacherait ce travail. Coche-le pour un
|
|
* support ou l'on veut distinguer d'un coup d'oeil branches et planches.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Fuel")
|
|
bool bFuelIndicatorsUseItemMesh = false;
|
|
|
|
/** Bois deja dans le foyer au demarrage. Laisse vide pour un feu a alimenter. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Fuel")
|
|
TObjectPtr<UItemDataAsset> StartingFuelItem;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Fuel", meta = (ClampMin = "0"))
|
|
int32 StartingFuelCount = 0;
|
|
|
|
// ------------------------------------------------------------------
|
|
// Sons. Tous facultatifs : un champ vide ne joue rien.
|
|
// ------------------------------------------------------------------
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Sound")
|
|
TObjectPtr<USoundBase> LightSound;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Sound")
|
|
TObjectPtr<USoundBase> ExtinguishSound;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooking|Sound")
|
|
TObjectPtr<USoundBase> PlaceItemSound;
|
|
|
|
private:
|
|
/**
|
|
* Quel emplacement de cuisson le joueur vise, ou INDEX_NONE s'il regarde le
|
|
* foyer. Se base sur le point de vue reel du pawn, donc sur ce qu'il voit a
|
|
* l'ecran, et non sur la position de son corps.
|
|
*/
|
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
|
|
|
int32 ResolveAimedSlot(const AActor* Interactor) const;
|
|
|
|
/** Decide ce que ferait un appui sur Interagir, sans rien modifier. */
|
|
FCookingInteraction ResolveAction(AActor* Interactor) const;
|
|
|
|
/** Depose l'objet actif de la barre rapide sur l'emplacement de cuisson. */
|
|
bool PlaceItemFromHand(int32 SlotIndex, AActor* Interactor);
|
|
|
|
/** Rend l'objet a l'inventaire. Refuse et laisse tout en place si c'est plein. */
|
|
bool TakeItemToInventory(int32 SlotIndex, AActor* Interactor);
|
|
|
|
/**
|
|
* Met UN morceau de bois dans le foyer, pris dans un slot d'inventaire.
|
|
*
|
|
* Un exemplaire par appui, jamais la pile entiere : donner du bois est un
|
|
* geste irreversible, et vider vingt branches d'un coup sur un feu qui n'en
|
|
* demandait qu'une ne se rattrape pas. Le joueur dose lui-meme.
|
|
*/
|
|
bool AddFuelFrom(int32 InventorySlotIndex, AActor* Interactor);
|
|
|
|
/**
|
|
* Ou prendre du bois : la main d'abord, sinon le premier slot qui en
|
|
* contient. La main est prioritaire parce que c'est le seul moyen pour le
|
|
* joueur de CHOISIR ce qu'il brule.
|
|
*/
|
|
static int32 FindFuelSource(const UInventoryComponent* Inventory, UItemDataAsset*& OutItem);
|
|
|
|
/** Peut-on retirer ce qui se trouve sur cet emplacement de cuisson. */
|
|
bool CanTakeFromSlot(int32 SlotIndex) const;
|
|
|
|
/** Arme le compte a rebours de l'etape courante de l'emplacement. */
|
|
void StartSlotTimer(int32 SlotIndex);
|
|
|
|
/** Fin d'etape : l'objet devient son resultat, et on enchaine s'il y a une suite. */
|
|
void HandleSlotFinished(int32 SlotIndex);
|
|
|
|
/** Recopie le WorldMesh de l'objet pose, ou cache le composant si l'emplacement est vide. */
|
|
void RefreshSlotMesh(int32 SlotIndex);
|
|
|
|
/**
|
|
* Allume ou eteint selon qu'il y ait, ou non, du bois ET du travail.
|
|
*
|
|
* Point de decision UNIQUE : toutes les actions qui changent le contenu du
|
|
* foyer ou du grill finissent ici. Laisser chaque action decider elle-meme
|
|
* d'allumer aurait fini par oublier un cas -- typiquement le dernier objet
|
|
* retire, qui laisserait le feu bruler dans le vide.
|
|
*/
|
|
void UpdateFireState();
|
|
|
|
/** La buche du dessus a fini de bruler : on passe a la suivante. */
|
|
void HandleFuelConsumed();
|
|
|
|
/** Arme le timer sur la buche en cours de combustion. */
|
|
void StartFuelTimer();
|
|
|
|
/** Recopie le restant du timer dans la buche courante avant de le modifier. */
|
|
void SyncFuelFromTimer();
|
|
|
|
/**
|
|
* Allume ou coupe tout ce qui se voit quand le feu brule.
|
|
*
|
|
* Un seul endroit pour la flamme et la lumiere : le jour ou s'ajoute une
|
|
* boucle sonore ou un panache de fumee, il n'y aura toujours qu'un point a
|
|
* modifier au lieu de deux appels a retrouver dans Light() et Extinguish().
|
|
*/
|
|
void ApplyFireVisuals(bool bActive);
|
|
|
|
/** Retrouve les buches par leur tag, une fois pour toutes, au demarrage. */
|
|
void CacheFuelIndicators();
|
|
|
|
/**
|
|
* Montre exactement autant de buches qu'il y a de morceaux dans le foyer.
|
|
*
|
|
* Plus aucun calcul de palier ni de timer d'affichage depuis que le
|
|
* carburant est une pile d'objets : une buche visible EST un objet stocke.
|
|
*/
|
|
void RefreshFuelIndicators();
|
|
|
|
/**
|
|
* Ce que cet objet va devenir sur le feu, et en combien de temps.
|
|
* La cuisson passe avant la combustion : voir le commentaire de bCanBurn
|
|
* sur UItemDataAsset.
|
|
*/
|
|
static UItemDataAsset* GetNextStage(const UItemDataAsset* Item, float& OutDuration);
|
|
|
|
/** Inventaire du pawn qui interagit, ou nullptr. */
|
|
static UInventoryComponent* GetInventoryOf(AActor* Interactor);
|
|
|
|
/**
|
|
* Etat courant de chaque emplacement de cuisson. Toujours dimensionne a
|
|
* MaxCookingSlots.
|
|
*
|
|
* Replique : c'est ce qui fait changer le mesh de la nourriture sous les
|
|
* yeux de tous. Le FTimerHandle que porte chaque slot n'est pas une
|
|
* UPROPERTY et ne part donc pas sur le reseau -- c'est voulu, la cuisson se
|
|
* compte uniquement sur le serveur et les clients n'en voient que le
|
|
* resultat.
|
|
*/
|
|
UPROPERTY(Transient, ReplicatedUsing = OnRep_Slots)
|
|
TArray<FCookingSlotState> Slots;
|
|
|
|
/**
|
|
* Le contenu du foyer, dans l'ordre ou il a ete donne. L'index 0 est celui
|
|
* qui brule ; quand il est consomme, tout le monde avance d'un cran et la
|
|
* derniere buche disparait du foyer.
|
|
*/
|
|
/**
|
|
* Replique : le nombre de buches visibles EST la jauge de carburant, c'est
|
|
* la seule facon pour un joueur de savoir combien il reste de feu. Les
|
|
* secondes restantes partent avec, mais seul le serveur les decompte.
|
|
*/
|
|
UPROPERTY(Transient, ReplicatedUsing = OnRep_Fuel)
|
|
TArray<FFuelSlotState> Fuel;
|
|
|
|
FTimerHandle FuelTimer;
|
|
|
|
/**
|
|
* Buches de mise en scene, resolues au BeginPlay et triees par nom.
|
|
* Transient : ces pointeurs designent des composants du Blueprint, il n'y a
|
|
* rien a sauvegarder, seulement a garder du GC le temps de la partie.
|
|
*/
|
|
UPROPERTY(Transient)
|
|
TArray<TObjectPtr<UStaticMeshComponent>> FuelIndicators;
|
|
|
|
UPROPERTY(ReplicatedUsing = OnRep_IsLit)
|
|
bool bIsLit = false;
|
|
|
|
/** Le contenu du grill a change cote serveur : on repose tous les meshes. */
|
|
UFUNCTION()
|
|
void OnRep_Slots();
|
|
|
|
UFUNCTION()
|
|
void OnRep_Fuel();
|
|
|
|
UFUNCTION()
|
|
void OnRep_IsLit();
|
|
};
|