(Feat) Add Animation Fps Charater
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
// 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 "StorageContainer.generated.h"
|
||||
|
||||
class UBoxComponent;
|
||||
class UInventoryComponent;
|
||||
class UItemDataAsset;
|
||||
class USoundBase;
|
||||
class UStaticMeshComponent;
|
||||
|
||||
/**
|
||||
* Contenu initial d'un coffre pose dans le niveau.
|
||||
*
|
||||
* De la donnee de level design, pas du gameplay : un coffre de depart, une
|
||||
* cache a trouver. Verse une seule fois au BeginPlay, jamais relu ensuite.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FStorageStartingItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
TObjectPtr<UItemDataAsset> Item = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage", meta = (ClampMin = "1"))
|
||||
int32 Quantity = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Coffre pose dans le monde.
|
||||
*
|
||||
* Il ne contient AUCUN modele de donnees a lui : son contenu est un
|
||||
* UInventoryComponent, exactement le meme que celui du joueur, simplement
|
||||
* configure sans barre rapide. C'est ce qui rend le glisser-deposer entre le
|
||||
* sac et le coffre gratuit -- ce sont les memes cases, le meme FInventorySlot,
|
||||
* et donc la durabilite d'une hache traverse le coffre sans une ligne de code.
|
||||
*
|
||||
* Toute la collision tient dans UNE boite, et les deux meshes n'en portent
|
||||
* aucune. C'est la difference avec ACraftingStation, qui se contente de son
|
||||
* mesh : un coffre est en deux morceaux dont l'un TOURNE. Se reposer sur leurs
|
||||
* collisions imposerait que le pack en fournisse deux correctes, et laisserait
|
||||
* surtout un trou dans la surface visable des que le couvercle se leve --
|
||||
* viser le haut du coffre ouvert ne toucherait plus rien.
|
||||
*
|
||||
* La boite est fille de la caisse et ne bouge donc jamais : le coffre se vise
|
||||
* exactement pareil ouvert ou ferme. Elle bloque aussi le joueur physiquement,
|
||||
* ce qui evite d'avoir a se demander si le mesh du pack sait le faire.
|
||||
*
|
||||
* Aucun Tick au repos : il ne s'active que le temps d'animer le couvercle, et
|
||||
* se rendort des que l'angle est atteint.
|
||||
*/
|
||||
UCLASS()
|
||||
class EMBERWILD_API AStorageContainer : public AActor, public IInteractable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AStorageContainer();
|
||||
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
/** Le couvercle vient de changer d'etat cote serveur : on joue l'animation. */
|
||||
UFUNCTION()
|
||||
void OnRep_Open();
|
||||
|
||||
/**
|
||||
* Son et relance du tick d'animation. Partage par SetOpen (serveur) et
|
||||
* OnRep_Open (clients) : deux copies finiraient par diverger, et le
|
||||
* symptome serait un couvercle muet chez les invites.
|
||||
*/
|
||||
void ApplyOpenState();
|
||||
|
||||
// --- IInteractable ---
|
||||
virtual FText GetInteractionPrompt_Implementation(AActor* Interactor) const override;
|
||||
virtual void Interact_Implementation(AActor* Interactor) override;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Storage")
|
||||
UInventoryComponent* GetStorage() const { return Storage; }
|
||||
|
||||
/** Nom affiche en titre de l'ecran de coffre. */
|
||||
UFUNCTION(BlueprintPure, Category = "Storage")
|
||||
FText GetDisplayName() const { return DisplayName; }
|
||||
|
||||
/** Cases par ligne souhaitees pour la grille de l'ecran. */
|
||||
UFUNCTION(BlueprintPure, Category = "Storage")
|
||||
int32 GetColumnCount() const { return ColumnCount; }
|
||||
|
||||
/**
|
||||
* Ouvre ou ferme le couvercle.
|
||||
*
|
||||
* Appele par le controller, pas par le coffre lui-meme : c'est lui qui sait
|
||||
* quand l'ecran se referme, que ce soit par Echap, par la mort du joueur ou
|
||||
* parce qu'il s'est trop eloigne. Un coffre qui deciderait seul finirait
|
||||
* ouvert dans la moitie de ces cas.
|
||||
*/
|
||||
/**
|
||||
* Leve ou referme le couvercle. **Serveur uniquement** : le couvercle est
|
||||
* un etat du MONDE, les quatre joueurs doivent le voir bouger. Un client
|
||||
* qui l'appellerait verrait son coffre s'ouvrir tout seul chez lui.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Storage")
|
||||
void SetOpen(bool bInOpen);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Storage")
|
||||
bool IsOpen() const { return bOpen; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Dimensionne le composant AVANT que son InitializeComponent() fige la
|
||||
* taille par defaut. PostInitializeComponents serait deja trop tard, et le
|
||||
* constructeur trop tot -- il ne connait pas les valeurs reglees sur
|
||||
* l'instance posee dans le niveau.
|
||||
*/
|
||||
virtual void PreInitializeComponents() override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
/** Redimensionne la boite quand un mesh change dans le Blueprint. */
|
||||
virtual void OnConstruction(const FTransform& Transform) override;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Composants
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/** La caisse : SM_Chest_Bottom. Racine, purement visuelle. */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
TObjectPtr<UStaticMeshComponent> BaseMesh;
|
||||
|
||||
/**
|
||||
* L'unique collision du coffre : ce que le trace d'interaction vient
|
||||
* toucher, et ce qui empeche le joueur de traverser.
|
||||
*
|
||||
* Fille de la caisse et non du couvercle : elle ne suit surtout pas ce
|
||||
* dernier. Un coffre ouvert doit se viser au meme endroit qu'un coffre
|
||||
* ferme, sinon le prompt disparait au moment precis ou l'on s'en sert.
|
||||
*/
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
TObjectPtr<UBoxComponent> InteractionBox;
|
||||
|
||||
/**
|
||||
* Le couvercle : SM_Chest_Top, enfant direct de la caisse.
|
||||
*
|
||||
* C'est LUI qu'on tourne, donc la charniere est le pivot que l'artiste a
|
||||
* donne au mesh -- un StaticMeshComponent tourne toujours autour de
|
||||
* l'origine de son mesh. Rien a placer a la main, mais rien a rattraper non
|
||||
* plus : si un pack posait ce pivot au centre du couvercle, l'ouverture se
|
||||
* verrait de travers et il faudrait corriger le pivot dans l'editeur de
|
||||
* mesh, pas ici.
|
||||
*/
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
TObjectPtr<UStaticMeshComponent> LidMesh;
|
||||
|
||||
/** Le contenu. Un inventaire ordinaire, sans barre rapide. */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
TObjectPtr<UInventoryComponent> Storage;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Reglages
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Nombre de cases. Reglable PAR INSTANCE : le meme Blueprint donne un petit
|
||||
* coffre de 12 et un grand de 30 selon celui qu'on pose.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage", meta = (ClampMin = "1", ClampMax = "60"))
|
||||
int32 SlotCount = 20;
|
||||
|
||||
/** Cases par ligne dans l'ecran. Purement visuel. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage", meta = (ClampMin = "1"))
|
||||
int32 ColumnCount = 6;
|
||||
|
||||
/** Nom affiche en titre de l'ecran. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
FText DisplayName;
|
||||
|
||||
/** Texte affiche quand le joueur vise le coffre. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
FText InteractionPrompt;
|
||||
|
||||
/** Verse dans le coffre au demarrage. Laisse vide pour un coffre a remplir. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage")
|
||||
TArray<FStorageStartingItem> StartingItems;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Collision
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* La boite epouse toute seule les deux meshes, couvercle ferme.
|
||||
*
|
||||
* Coche par defaut : changer SM_Chest_v1 pour le v3 doit suffire, sans
|
||||
* avoir a retailler une boite a la main derriere. Decoche-le seulement si
|
||||
* tu veux une zone volontairement differente du volume du coffre.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage|Collision")
|
||||
bool bAutoFitInteractionBox = true;
|
||||
|
||||
/**
|
||||
* Marge ajoutee autour des meshes par l'ajustement automatique.
|
||||
*
|
||||
* Garde-la petite. Le trace d'interaction est deja un balayage spherique
|
||||
* tolerant : gonfler la boite ne rendrait pas le coffre plus facile a viser,
|
||||
* ca l'empecherait juste de se coller a un mur.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage|Collision", meta = (ClampMin = "0", Units = "cm"))
|
||||
float InteractionBoxPadding = 0.f;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Couvercle
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Rotation RELATIVE du couvercle ouvert. Le repos vaut toujours zero.
|
||||
*
|
||||
* Un FRotator complet et pas un simple angle : selon l'orientation dans
|
||||
* laquelle le mesh a ete exporte, la charniere peut tomber sur le pitch, le
|
||||
* yaw ou le roll. Regle les trois a l'oeil dans le viewport plutot que
|
||||
* d'aller comprendre quel axe local du mesh pointe ou.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage|Lid")
|
||||
FRotator OpenRotation = FRotator(-100.f, 0.f, 0.f);
|
||||
|
||||
/** Duree de l'ouverture, en secondes. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage|Lid", meta = (ClampMin = "0.05", Units = "s"))
|
||||
float LidDuration = 0.35f;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Sons. Facultatifs : un champ vide ne joue rien.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage|Sound")
|
||||
TObjectPtr<USoundBase> OpenSound;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Storage|Sound")
|
||||
TObjectPtr<USoundBase> CloseSound;
|
||||
|
||||
private:
|
||||
/** Recopie LidAlpha dans la rotation du couvercle. */
|
||||
void ApplyLidRotation();
|
||||
|
||||
/** Cale la boite sur le volume combine des deux meshes, couvercle ferme. */
|
||||
void FitInteractionBox();
|
||||
|
||||
/**
|
||||
* Repliqué à tout le monde : voir le couvercle d'un coffre se lever est le
|
||||
* seul signe qu'un coéquipier est en train de fouiller dedans.
|
||||
*/
|
||||
UPROPERTY(ReplicatedUsing = OnRep_Open)
|
||||
bool bOpen = false;
|
||||
|
||||
/** 0 = ferme, 1 = ouvert. Interpole, jamais pose directement. */
|
||||
float LidAlpha = 0.f;
|
||||
};
|
||||
Reference in New Issue
Block a user