(Feat) Add Cooking and Workbench

This commit is contained in:
2026-08-01 00:03:53 +02:00
parent 3f3ae1f5fa
commit d50ef564ba
360 changed files with 5316 additions and 67 deletions
+112 -5
View File
@@ -6,6 +6,7 @@
#include "Engine/DataAsset.h"
#include "ItemDataAsset.generated.h"
class UMaterialInterface;
class UStaticMesh;
class UTexture2D;
@@ -47,6 +48,18 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
TObjectPtr<UStaticMesh> WorldMesh;
/**
* Materiau force sur le WorldMesh. Vide = celui du mesh.
*
* Indispensable des qu'un pack partage une geometrie entre plusieurs
* aliments : une chaine de cuisson demande un visuel par etape, et sans ca
* il faudrait trois meshes distincts la ou un seul suffit avec trois
* teintes. N'ecrase que le PREMIER slot de materiau -- un mesh qui en
* expose plusieurs garde les autres tels quels.
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
TObjectPtr<UMaterialInterface> WorldMeshMaterial;
/**
* Nombre maximum d'exemplaires par slot.
* 1 = ne s'empile pas (outils, armes), 20 = ressource classique.
@@ -75,11 +88,22 @@ public:
UFUNCTION(BlueprintPure, Category = "Item")
int32 GetEffectiveMaxStack() const { return MaxUses > 1 ? 1 : FMath::Max(1, MaxStackSize); }
/**
* Pose le mesh et le materiau de l'objet sur un composant.
*
* Un DataAsset ne devrait pas piloter un composant, mais la regle "mesh plus
* materiau optionnel" a deja deux appelants -- l'objet au sol et l'objet sur
* le feu -- et en aura d'autres, l'objet en main le premier. La dupliquer
* garantit qu'un jour l'un des deux oubliera le materiau.
*/
UFUNCTION(BlueprintCallable, Category = "Item")
void ApplyWorldVisualsTo(class UStaticMeshComponent* Component) const;
/**
* Slots ajoutes a l'inventaire quand cet objet est equipe comme sac.
* Laisse a 0 pour tout ce qui n'est pas un contenant.
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Sac", meta = (ClampMin = "0"))
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Backpack", meta = (ClampMin = "0"))
int32 BonusInventorySlots = 0;
// ------------------------------------------------------------------
@@ -87,18 +111,101 @@ public:
// ------------------------------------------------------------------
/** Coche pour qu'un clic gauche consomme l'objet et applique ses effets. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consommable")
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consumable")
bool bIsConsumable = false;
/** Faim rendue a la consommation. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consommable", meta = (EditCondition = "bIsConsumable"))
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consumable", meta = (EditCondition = "bIsConsumable"))
float HungerRestore = 0.f;
/** Soif rendue. Une valeur negative deshydrate -- utile pour l'eau salee. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consommable", meta = (EditCondition = "bIsConsumable"))
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consumable", meta = (EditCondition = "bIsConsumable"))
float ThirstRestore = 0.f;
/** Vie rendue. Negative pour un aliment avarie ou toxique. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consommable", meta = (EditCondition = "bIsConsumable"))
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Consumable", meta = (EditCondition = "bIsConsumable"))
float HealthRestore = 0.f;
// ------------------------------------------------------------------
// Cuisson
//
// Modele en CHAINE D'OBJETS, sans recette : cuire n'est pas un choix que le
// joueur fait dans un menu, c'est une propriete de l'objet. "Steak cru"
// pointe vers "Steak cuit", qui pointe vers "Steak brule". Chaque maillon
// est un asset complet, donc le changement de mesh sur le feu ne coute pas
// une ligne : c'est le WorldMesh du maillon suivant.
//
// Ce qui n'est PAS ici, et ne doit jamais y venir : le temps deja passe sur
// le feu. C'est de l'etat, il vit sur ACookingStation. Le mettre dans le
// DataAsset ferait cuire tous les steaks du monde en meme temps.
// ------------------------------------------------------------------
/** Cet objet se transforme quand on le pose sur un feu allume. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Cooking")
bool bCanBeCooked = false;
/** Secondes de feu ACTIF necessaires. Un feu eteint met le compteur en pause. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Cooking", meta = (EditCondition = "bCanBeCooked", ClampMin = "0.1", Units = "s"))
float CookDuration = 20.f;
/** Ce que l'objet devient une fois cuit. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Cooking", meta = (EditCondition = "bCanBeCooked"))
TObjectPtr<UItemDataAsset> CookedResult;
/**
* L'objet se degrade s'il reste sur le feu.
*
* Volontairement independant de bCanBeCooked : un objet peut bruler sans
* jamais avoir ete cuisinable (une planche jetee dans les flammes), et un
* plat peut rester indefiniment au chaud sans jamais se gacher. Une seule
* chaine commune imposerait l'un ou l'autre a tout le monde.
*
* Si les deux sont coches, la CUISSON passe en premier : c'est le maillon
* cuit qui portera bCanBurn pour continuer vers le brule.
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Cooking")
bool bCanBurn = false;
/** Secondes de feu actif avant que l'objet se gache. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Cooking", meta = (EditCondition = "bCanBurn", ClampMin = "0.1", Units = "s"))
float BurnDuration = 40.f;
/** Ce que l'objet devient une fois brule. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Cooking", meta = (EditCondition = "bCanBurn"))
TObjectPtr<UItemDataAsset> BurntResult;
/**
* Le feu accepte-t-il cet objet sur un emplacement de cuisson.
*
* Un maillon final -- le steak brule -- repond non : on ne peut plus le
* poser, et il ne fait plus rien s'il est deja la. La regle est centralisee
* ici pour que la station n'ait pas a la reconstruire a chaque appel.
*/
UFUNCTION(BlueprintPure, Category = "Item|Cooking")
bool CanBePlacedOnFire() const
{
return (bCanBeCooked && CookedResult != nullptr) || (bCanBurn && BurntResult != nullptr);
}
// ------------------------------------------------------------------
// Carburant
// ------------------------------------------------------------------
/** Cet objet peut alimenter un feu. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Fuel")
bool bIsFuel = false;
/** Secondes de combustion apportees par exemplaire. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item|Fuel", meta = (EditCondition = "bIsFuel", ClampMin = "1", Units = "s"))
float FuelDuration = 60.f;
#if WITH_EDITOR
/**
* Une chaine de cuisson mal branchee ne planterait pas : la viande resterait
* simplement crue sur le feu, sans rien dire. C'est exactement le genre de
* bug qu'on cherche une heure -- autant que l'editeur le refuse a la
* sauvegarde.
*/
virtual EDataValidationResult IsDataValid(class FDataValidationContext& Context) const override;
#endif
};