(Feat) Add Craft Systeme

This commit is contained in:
2026-07-30 23:08:33 +02:00
parent 9b5ad7c8a4
commit 3f3ae1f5fa
57 changed files with 2276 additions and 127 deletions
+127 -13
View File
@@ -8,13 +8,57 @@
class APickupItem;
class UCameraComponent;
class UCraftingComponent;
class UInputAction;
class UInputMappingContext;
class UInteractionComponent;
class UInventoryComponent;
class UItemDataAsset;
class USurvivalStatsComponent;
struct FInputActionValue;
/**
* Ressort amorti à une dimension, partagé par les effets de caméra.
*
* Pourquoi un ressort plutôt qu'une courbe paramétrée par le temps : un ressort
* n'a pas d'animation « en cours » qu'il faudrait annuler pour en jouer une
* autre. Une nouvelle impulsion s'ajoute simplement à l'état courant, position
* et vitesse restent continues, donc le mouvement est interruptible à n'importe
* quel instant sans jamais produire de saut. C'est exactement ce que le crouch
* demande quand le joueur martèle la touche.
*/
struct FCameraSpring
{
/** Déplacement courant, dans l'unité de ce que le ressort pilote. */
float Offset = 0.f;
/** Vitesse courante, par seconde. */
float Velocity = 0.f;
/** Impulsion pas encore versée, étalée sur RampTime pour éviter l'à-coup. */
float PendingImpulse = 0.f;
void AddImpulse(float Strength) { PendingImpulse += Strength; }
/** Remet le ressort au repos, sans transition (respawn, téléportation). */
void Reset()
{
Offset = 0.f;
Velocity = 0.f;
PendingImpulse = 0.f;
}
/**
* Intègre le ressort d'un pas de temps et renvoie le nouvel Offset.
*
* @param Frequency fréquence propre en Hz : vitesse de retour au repos.
* @param Damping 1 = retour net sans rebond, en dessous ça oscille.
* @param RampTime durée sur laquelle une impulsion est versée (0 = d'un coup).
* @param MaxOffset garde-fou d'amplitude.
*/
float Update(float Step, float Frequency, float Damping, float RampTime, float MaxOffset);
};
/**
* Personnage joueur en vue première personne.
* Les assets d'input (Input Mapping Context + Input Actions) se branchent
@@ -48,6 +92,9 @@ public:
UFUNCTION(BlueprintPure, Category = "Inventaire")
UInventoryComponent* GetInventoryComponent() const { return InventoryComponent; }
UFUNCTION(BlueprintPure, Category = "Crafting")
UCraftingComponent* GetCraftingComponent() const { return CraftingComponent; }
UFUNCTION(BlueprintPure, Category = "Survie")
USurvivalStatsComponent* GetSurvivalStats() const { return SurvivalStats; }
@@ -100,6 +147,20 @@ public:
UFUNCTION()
void ApplyUserSettings();
/**
* Pose la transform de la camera juste avant que la vue soit lue.
*
* Le gestionnaire de camera passe par ici pour construire le point de vue :
* c'est le seul endroit ou l'on est certain de lire la position de l'acteur
* et la demi-hauteur de la capsule au MEME instant. Le Tick du pawn, lui,
* n'a aucune dependance de tick vis-a-vis du CharacterMovement (verifie dans
* Character.cpp : seul le Mesh en recoit une), donc la frame ou la capsule
* change de taille pouvait etre calculee avec l'ancienne demi-hauteur --
* soit un decalage de 28 cm sur une frame, a chaque accroupissement.
* Bonus : le regard n'a plus une frame de retard sur la souris.
*/
virtual void CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult) override;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
@@ -133,6 +194,13 @@ protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inventaire")
TObjectPtr<UInventoryComponent> InventoryComponent;
/**
* Fabrication. Sur le pawn comme l'inventaire : c'est ce corps qui fabrique,
* et il lit l'inventaire du meme acteur.
*/
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Crafting")
TObjectPtr<UCraftingComponent> CraftingComponent;
/** Vie, faim, soif. Sur le pawn : c'est ce corps qui a faim. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Survie")
TObjectPtr<USurvivalStatsComponent> SurvivalStats;
@@ -259,17 +327,44 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Accroupi", meta = (ClampMin = "0.01"))
float CrouchTransitionDuration = 0.4f;
/** Tangage (degrés) au pic de la transition. Positif = le regard plonge. */
/**
* Tangage (degrés) au pic de la bascule. Positif = le regard plonge.
*
* Le tilt n'est plus une courbe indexée sur l'avancement de la transition
* mais un ressort relancé à chaque changement d'état : c'est ce qui permet
* de s'accroupir et de se relever coup sur coup sans que la caméra saute.
* L'impulsion est normalisée pour que le pic tombe bien sur cette valeur.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Accroupi")
float CrouchTiltPitch = 3.f;
/**
* Roulis (degrés) au pic de la transition : bascule sur le côté.
* Roulis (degrés) au pic de la bascule : bascule sur le côté.
* A 0 par defaut, le mouvement reste purement vertical.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Accroupi")
float CrouchTiltRoll = 0.f;
/**
* Fréquence du ressort de bascule (Hz). Le pic est atteint après environ
* 1/(2*PI*f) secondes : 0.9 Hz place le sommet vers 0.18 s, soit à peu près
* au milieu d'une transition de 0.4 s. Plus haut = plus sec et plus court.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Accroupi", meta = (ClampMin = "0.1"))
float CrouchTiltFrequency = 0.9f;
/** Amortissement de la bascule. 1 = aucun rebond ; en dessous, la tête oscille. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Accroupi", meta = (ClampMin = "0.05", ClampMax = "2.0"))
float CrouchTiltDamping = 1.f;
/**
* Durée (s) sur laquelle l'impulsion de bascule est versée dans le ressort.
* A 0 la rotation démarre à pleine vitesse angulaire en une frame, ce qui
* se lit comme un claquement ; quelques centièmes suffisent à l'adoucir.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Accroupi", meta = (ClampMin = "0"))
float CrouchTiltRampTime = 0.05f;
// ------------------------------------------------------------------
// Réglages : impacts caméra (saut / atterrissage)
// ------------------------------------------------------------------
@@ -379,13 +474,34 @@ protected:
void UseSelectedItem();
private:
/** Fait avancer toutes les animations de caméra et les applique. */
/** Fait avancer toutes les animations de caméra (intégration uniquement). */
void UpdateCameraEffects(float DeltaTime);
/**
* Recopie l'état des animations dans la transform de la caméra.
* Séparée de l'intégration : appelée à la fois en fin de Tick et depuis
* CalcCamera, elle doit rester idempotente et sans notion de temps.
*/
void ApplyCameraTransform();
/** Relance la bascule de tête. Direction : +1 on s'accroupit, -1 on se relève. */
void AddCrouchTilt(float Direction);
/** Branche sur OnDied du composant de survie. */
UFUNCTION()
void HandleDeath();
/**
* Le resultat d'une fabrication n'est pas entre dans l'inventaire : on le
* pose aux pieds du joueur plutot que de le laisser disparaitre.
*
* C'est le pawn qui fait ca et non UCraftingComponent : le composant n'a pas
* a savoir comment on engendre un objet dans le monde, et un etabli qui
* porterait le meme composant deposerait son surplus sur sa propre table.
*/
UFUNCTION()
void HandleCraftOverflow(UItemDataAsset* Item, int32 Quantity, int32 RemainingUses);
/** Fait apparaitre un pickup deja configure a un endroit donne. */
APickupItem* SpawnPickup(const struct FInventorySlot& Slot, const FVector& Location);
@@ -400,17 +516,15 @@ private:
/** Valeur visée par CrouchAlpha. */
float CrouchTargetAlpha = 0.f;
/** +1 quand on s'accroupit, -1 quand on se relève : inverse le sens du tilt. */
float CrouchTiltDirection = 1.f;
/** Déplacement vertical de la caméra (cm) : sauts, atterrissages, explosions. */
FCameraSpring PunchSpring;
/** Décalage vertical courant de la caméra (cm), état du ressort d'impact. */
float PunchOffset = 0.f;
/** Vitesse du ressort d'impact (cm/s). */
float PunchVelocity = 0.f;
/** Impulsion restant à injecter dans le ressort, étalée sur PunchImpulseRampTime. */
float PendingPunch = 0.f;
/**
* Bascule de tête pendant l'accroupissement, en unités normalisées :
* son pic vaut 1, ce sont CrouchTiltPitch et CrouchTiltRoll qui le
* convertissent en degrés.
*/
FCameraSpring CrouchTiltSpring;
/** Vitesse verticale mémorisée pendant la chute, pour calibrer l'atterrissage. */
float LastFallSpeed = 0.f;