// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Components/WidgetComponent.h" #include "PlayerNameplateComponent.generated.h" class APlayerState; /** * L'etiquette de pseudo posee au-dessus d'un joueur. * * Herite de UWidgetComponent et le configure en espace ECRAN : c'est ce qui la * fait toujours faire face a la camera, gratuitement et exactement, sans le * moindre calcul d'orientation par frame. En espace Monde il faudrait la * reorienter soi-meme a chaque image, et elle serait occultee par le decor -- * un pseudo qui disparait derriere un caillou n'aide personne. * * Contrepartie assumee de l'espace ecran : la taille ne diminue pas avec la * distance. C'est le comportement des jeux coop du genre, et c'est justement * pourquoi une distance de disparition est indispensable -- sans elle, quatre * pseudos resteraient lisibles a l'autre bout de la carte. * * Le composant ne replique RIEN : le pseudo vit deja sur le PlayerState, qui * est replique par le moteur. Ajouter une propriete ici enverrait deux fois la * meme chaine sur le reseau. */ UCLASS(ClassGroup = (Survival), meta = (BlueprintSpawnableComponent)) class SURVIVAL_PROJET_API UPlayerNameplateComponent : public UWidgetComponent { GENERATED_BODY() public: UPlayerNameplateComponent(); virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; protected: /** * Au-dela de cette distance, l'etiquette disparait. 2500 cm = 25 m, soit un * peu plus que la portee a laquelle on distingue un coequipier dans un * decor dense. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Nameplate", meta = (ClampMin = "100", Units = "cm")) float MaxDrawDistance = 2500.f; /** * Periode de reevaluation, en secondes. * * Un timer et pas un Tick : la distance a la camera n'a aucune raison * d'etre recalculee 120 fois par seconde pour une etiquette qui apparait ou * disparait une fois toutes les dix secondes. Quatre joueurs a 120 ips * feraient 480 calculs de distance par seconde pour rien. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Nameplate", meta = (ClampMin = "0.05", Units = "s")) float RefreshInterval = 0.25f; /** * Cacher l'etiquette de son PROPRE personnage. * * Vrai par defaut : en vue premiere personne on ne voit jamais son propre * corps, mais une etiquette en espace ecran, elle, se projetterait en plein * milieu du viseur. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Nameplate") bool bHideOnOwningPlayer = true; private: /** Distance a la camera locale, puis mise a jour du texte si besoin. */ void Refresh(); /** Le PlayerState du pawn porteur, ou nullptr tant qu'il n'est pas arrive. */ APlayerState* GetOwnerPlayerState() const; FTimerHandle RefreshTimer; /** * Dernier pseudo reellement ecrit dans le widget. * * Le PlayerState arrive APRES le pawn chez un client : la premiere passe * trouve donc un nom vide, et il faut continuer a regarder. Comparer plutot * que reecrire evite de reconstruire la mise en page du Text Block quatre * fois par seconde pour une chaine identique. */ FString LastShownName; };