// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" // ESlateVisibility n'est que declare en avant par le moteur : il faut le type // complet pour en stocker une valeur par defaut. Meme raison pour // ECraftingStation, stocke en membre. #include "CharacterAppearanceTypes.h" #include "Components/SlateWrapperTypes.h" #include "CraftingRecipeDataAsset.h" #include "GameFramework/PlayerController.h" #include "FpsPlayerController.generated.h" class AStorageContainer; class UConfirmDialogWidget; class UCraftingComponent; class UHotbarWidget; class UInputAction; class UInventoryComponent; class UInteractionPromptWidget; class UInventoryScreenWidget; class UPauseMenuWidget; class UScreenFadeComponent; class USettingsMenuWidget; class USurvivalStatsWidget; class UUserWidget; struct FInputActionValue; /** * Controller du joueur. C'est ici que vit l'UI, et pas dans le personnage : * le controller survit a la mort du pawn, alors que le personnage non. * Si tu creais le HUD dans AFpsPlayer, il disparaitrait a chaque respawn. */ UCLASS() class SURVIVAL_PROJET_API AFpsPlayerController : public APlayerController { GENERATED_BODY() public: AFpsPlayerController(); /** Ouvre ou ferme l'ecran, toujours sur l'onglet Inventaire. */ UFUNCTION(BlueprintCallable, Category = "UI") void ToggleInventory(); /** * Ouvre l'ecran directement sur l'onglet Fabrication. * Depuis l'onglet Inventaire elle bascule, depuis l'onglet Fabrication elle referme. */ UFUNCTION(BlueprintCallable, Category = "UI") void ToggleCrafting(); /** * Ouvre l'ecran de fabrication depuis un poste de travail. * * L'acces au poste ne dure QUE le temps de l'ecran : il est accorde ici et * repris a la fermeture. C'est le contrat de l'interaction -- on fabrique a * l'etabli parce qu'on est en train de s'en servir, pas parce qu'on en a * croise un un jour. * * Le contrôleur s'en charge et non l'etabli : c'est lui qui sait quand * l'ecran se referme, et lui seul peut donc rendre le poste au bon moment. */ UFUNCTION(BlueprintCallable, Category = "UI") void OpenCraftingAtStation(ECraftingStation Station); UFUNCTION(BlueprintPure, Category = "UI") bool IsInventoryOpen() const { return bInventoryOpen; } /** * Ouvre l'ecran d'inventaire avec le panneau du coffre a cote : le sac a * gauche, son contenu a droite. * * Ce n'est PAS un ecran a part. Le sac du joueur reste exactement au meme * endroit qu'à l'ouverture par Tab -- c'est tout l'interet, un ecran * distinct le ferait sauter a chaque fois qu'on ouvre un coffre. * * Comme pour l'etabli, c'est le controller qui pilote et non le coffre : lui * seul sait quand l'ecran se referme, et donc quand refermer le couvercle. */ UFUNCTION(BlueprintCallable, Category = "UI|Storage") void OpenStorage(AStorageContainer* Container); /** Referme l'ecran de coffre. Sans effet s'il n'y en a pas d'ouvert. */ UFUNCTION(BlueprintCallable, Category = "UI|Storage") void CloseStorage(); UFUNCTION(BlueprintPure, Category = "UI|Storage") bool IsStorageOpen() const { return bStorageOpen; } /** Ferme le menu de pause et relance le monde. */ UFUNCTION(BlueprintCallable, Category = "UI|Pause") void ResumeGame(); /** Ouvre la demande de confirmation. Ne quitte rien par elle-meme. */ UFUNCTION(BlueprintCallable, Category = "UI|Pause") void RequestQuitToMainMenu(); UFUNCTION(BlueprintPure, Category = "UI|Pause") bool IsPauseMenuOpen() const { return bPauseMenuOpen; } /** Ouvre l'ecran de reglages par-dessus le menu de pause. */ UFUNCTION(BlueprintCallable, Category = "UI|Reglages") void OpenSettings(); /** * Ouvre le panneau d'invitation de l'overlay Steam. * * Passe par le controller et non directement du widget au sous-systeme : * inviter est une action du JOUEUR LOCAL, et le controller est justement * l'objet qui le represente. Un widget qui irait chercher un * GameInstanceSubsystem tout seul se brancherait sur le mauvais joueur le * jour ou l'ecran partage existera. */ UFUNCTION(BlueprintCallable, Category = "Coop") void ShowInviteFriends(); /** * Le point d'entree unique d'un changement d'apparence : persiste dans les * reglages du joueur ET l'annonce au serveur. * * Les deux ensemble et jamais l'un sans l'autre -- persister sans annoncer * laisserait le joueur seul a se voir change, annoncer sans persister le * ferait repartir au visage par defaut au prochain lancement. C'est par ici * que passent les commandes console, et par ici que passera l'ecran de * customisation. */ UFUNCTION(BlueprintCallable, Category = "Apparence") void SubmitCharacterAppearance(const FCharacterAppearance& InAppearance); /** Faux quand Steam est absent ou qu'aucune session n'a pu etre creee. */ UFUNCTION(BlueprintPure, Category = "Coop") bool CanInviteFriends() const; protected: virtual void BeginPlay() override; /** Serveur uniquement. Chez un client, c'est AcknowledgePossession qui arrive. */ virtual void OnPossess(APawn* InPawn) override; /** * Le pendant CLIENT de OnPossess. * * OnPossess n'existe QUE sur le serveur : chez un client le pawn arrive par * replication et cette fonction n'est jamais appelee. Comme c'est elle qui * construisait le HUD, un joueur qui se connectait n'avait aucune interface -- * ni viseur, ni barre rapide, ni jauges. Le piege est d'autant plus fourbe * que l'hote, lui, est bien le serveur et voit son HUD parfaitement. */ virtual void AcknowledgePossession(APawn* P) override; virtual void SetupInputComponent() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; // ------------------------------------------------------------------ // Fondus // // La mécanique elle-même vit dans UScreenFadeComponent, partagé avec le // menu principal. Ici on ne garde que les durées propres au jeu. // La couleur et le WBP_Fade se règlent sur le composant. // ------------------------------------------------------------------ /** Le voile. Assigne-lui ton WBP_Fade dans BP_FpsPlayerController. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "UI|Fondu") TObjectPtr ScreenFade; /** Décoche pour démarrer sans fondu, pratique pendant les tests. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Fondu") bool bFadeInOnStart = true; /** * Délai maximal d'attente du pawn avant d'éclaircir quand même. * * Filet de sécurité pur : si la possession n'arrivait jamais, l'écran * resterait noir pour toujours et le joueur croirait le jeu planté. Mieux * vaut une vue bancale qu'un écran mort. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Fondu", meta = (ClampMin = "1", Units = "s")) float StartupFadeTimeout = 10.f; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Fondu", meta = (ClampMin = "0.1")) float StartupFadeDuration = 1.5f; /** Durée du fondu au noir quand le joueur meurt. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Fondu", meta = (ClampMin = "0.1")) float DeathFadeDuration = 1.f; /** * Temps total entre la mort et la réapparition. * Doit rester supérieur à DeathFadeDuration, sinon le joueur réapparaît * avant que l'écran soit entièrement noir. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Fondu", meta = (ClampMin = "0.1")) float RespawnDelay = 3.f; /** * Ouverture de l'inventaire, valeur Digital (bool). * L'input d'interface vit sur le controller et non sur le pawn : ouvrir * son sac doit rester possible meme sans corps a piloter. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") TObjectPtr ToggleInventoryAction; /** * Ouverture directe sur l'onglet Fabrication, valeur Digital (bool). * Sur le controller comme ToggleInventoryAction : elle doit repondre alors * meme que l'input du pawn est coupe, ecran ouvert. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") TObjectPtr ToggleCraftingAction; /** * Jette l'objet survole, valeur Digital (bool). Ctrl enfonce = un seul * exemplaire au lieu de la pile entiere. * Sur le controller aussi : le pawn a ses inputs coupes quand l'inventaire * est ouvert, donc un binding sur le pawn ne repondrait jamais. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") TObjectPtr DropItemAction; /** * Selection directe d'un slot de la barre rapide, valeur Axis1D. * * Une seule action pour toutes les touches : dans IMC_Default, mappe les * touches 1 a 6 sur cette action et donne a chacune un modificateur * Scalar different (1, 2, 3...). Le handler lit la valeur et en deduit * le slot. Six actions separees seraient six assets a maintenir. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") TObjectPtr HotbarSelectAction; /** Molette de souris pour defiler dans la barre, valeur Axis1D. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") TObjectPtr HotbarScrollAction; /** * Echap : ferme l'inventaire s'il est ouvert, sinon bascule la pause. * * ATTENTION : coche "Trigger When Paused" sur l'asset IA_Pause. Un jeu en * pause ne fait plus qu'un tick reduit ou seules les actions portant ce * drapeau sont evaluees -- sans lui, on peut mettre en pause mais plus * jamais en sortir au clavier. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input") TObjectPtr PauseAction; /** * Viseur, affiche en permanence. Widget separe du prompt : ce dernier se * met en Collapsed des qu'on ne vise plus rien, et emporterait le viseur * avec lui s'ils partageaient le meme widget. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI") TSubclassOf CrosshairClass; /** A assigner dans BP_FpsPlayerController : ton WBP_InteractionPrompt. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI") TSubclassOf InteractionPromptClass; /** * Ton WBP_InventoryScreen : l'ecran a onglets qui contient la grille * d'inventaire ET la page de fabrication. Ce n'est plus WBP_Inventory * directement, celui-ci est devenu une page a l'interieur. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI") TSubclassOf InventoryScreenClass; /** * Distance au-dela de laquelle l'ecran de coffre se referme tout seul. * * Sans elle, on viderait un coffre depuis l'autre bout de la carte : rien * n'oblige le joueur a rester devant une fois l'ecran ouvert. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Storage", meta = (ClampMin = "50", Units = "cm")) float MaxStorageDistance = 400.f; /** Ton WBP_Hotbar, affiche en permanence. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI") TSubclassOf HotbarClass; /** Ton WBP_SurvivalStats : les trois jauges. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI") TSubclassOf SurvivalStatsClass; /** Ton WBP_PauseMenu. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Pause") TSubclassOf PauseMenuClass; /** * Ton WBP_ConfirmDialog, le meme que celui du menu principal. Laisse-le * assigne : sans lui on retourne au menu sans rien demander, et la partie * est perdue sur un clic. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Pause") TSubclassOf QuitToMenuDialogClass; /** La question posee avant d'abandonner la partie. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Pause") FText QuitToMenuMessage; /** * Ton WBP_Settings, le meme que celui du menu principal. C'est tout * l'interet de son delegue OnCloseRequested : l'ecran ignore qui l'ouvre. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Reglages") TSubclassOf SettingsMenuClass; /** * Ta map de menu principal. * * TSoftObjectPtr comme dans AMainMenuPlayerController : une reference dure * ferait charger la map du menu en meme temps que celle du jeu. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Pause") TSoftObjectPtr MainMenuLevel; /** Fondu au noir avant de rendre la main au menu principal. */ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UI|Fondu", meta = (ClampMin = "0.1")) float QuitToMenuFadeDuration = 1.f; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI") TObjectPtr Crosshair; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI") TObjectPtr InteractionPrompt; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI") TObjectPtr InventoryScreen; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI") TObjectPtr Hotbar; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI") TObjectPtr SurvivalStatsWidget; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI|Pause") TObjectPtr PauseMenu; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI|Pause") TObjectPtr QuitToMenuDialog; UPROPERTY(Transient, BlueprintReadOnly, Category = "UI|Reglages") TObjectPtr SettingsMenu; private: void CreateHudWidgets(); /** * Tout ce qu'il faut faire quand ce controller prend un pawn, quel que soit * le cote du reseau : creer le HUD s'il manque, rebrancher les widgets sur * le nouveau corps, ecouter sa mort. * * Appelee par OnPossess (serveur) ET AcknowledgePossession (client), donc * potentiellement deux fois chez l'hote qui est les deux a la fois. Elle * doit rester idempotente -- d'ou AddUniqueDynamic sur OnDied, et * CreateHudWidgets qui ne cree que ce qui n'existe pas encore. */ void SetupForPossessedPawn(APawn* InPawn); /** * Éclaircit l'écran d'arrivée, une seule fois, et seulement quand le joueur * a réellement un corps. * * La condition n'est PAS « ai-je un pawn » mais « la caméra est-elle sur mon * pawn ». Chez un client, le contrôleur commence sur un `SpectatorPawn` né * au centre du monde -- sous le terrain -- et y reste encore un instant * APRÈS `AcknowledgePossession`. Mesuré sur une vraie connexion : au moment * où la possession est acquittée, `GetViewTarget()` vaut toujours * `SpectatorPawn_0`. Éclaircir là montre le dessous de la carte. * * Tant que la caméra n'y est pas, on repasse toutes les `StartupFadeRetry` * secondes. L'écran reste noir pendant ce temps -- le rendu du monde est * suspendu par le GameInstance depuis le chargement de la map. */ void TryStartupFadeIn(); /** * Éclaircit pour de bon, sans vérifier la caméra. * Appelée par le filet de sécurité : mieux vaut une vue bancale qu'un écran * noir définitif, qui se lit comme un plantage. */ void CompleteStartupFadeIn(); /** L'éclaircissement lui-même, après le temps de chauffe du monde. */ void StartStartupFade(); /** * Echap. Une seule touche pour trois usages, d'ou une priorite explicite : * boite de confirmation, puis inventaire, puis pause. Sans cet ordre on se * retrouve avec l'inventaire et la pause ouverts en meme temps. */ void HandlePauseInput(); void OpenPauseMenu(); /** Oui : fondu au noir, puis retour au menu principal. */ UFUNCTION() void HandleQuitToMenuConfirmed(); /** * L'hote s'en va : ce client doit partir aussi. * * Une RPC explicite et non un simple abandon de connexion. Quand l'hote * ferme sa partie, le moteur ne previent personne : les clients restent * dans un monde mort, avec le pawn fantome de l'hote encore plante devant * eux, jusqu'a un timeout qui peut ne jamais venir. On leur dit donc de * partir, et ils partent avec leur propre fondu. */ UFUNCTION(Client, Reliable) void Client_ReturnToMainMenu(); /** * Lance le depart : ferme les ecrans, previent le GameInstance, fond au noir. * * Idempotente -- un client peut recevoir l'ordre de l'hote alors qu'il avait * deja clique Quitter de son cote, et deux fondus simultanes se * marcheraient dessus. */ void BeginQuitToMainMenu(); /** * Envoie l'ordre de depart a tous les AUTRES joueurs. Serveur uniquement. * * Appele AVANT le fondu de l'hote et non apres : les clients ont ainsi * toute la duree de ce fondu pour recevoir le message et lancer le leur. * Prevenir a la fin donnerait un client qui decouvre la coupure sans * explication, ecran de jeu fige. */ void KickRemoteClientsToMainMenu(); /** Non : on referme la boite et on rend la main au menu de pause. */ UFUNCTION() void HandleQuitToMenuCancelled(); /** Le fondu est termine : on charge la map du menu, si c'est ce qu'on attendait. */ UFUNCTION() void HandleFadeFinished(); /** * Le joueur a accepte une invitation EN PLEINE PARTIE : on fond au noir * avant que le voyage vers l'autre hote parte. * * bQuittingToMainMenu reste faux : ce n'est pas nous qui chargeons la map * suivante, c'est USessionSubsystem. HandleFadeFinished doit donc laisser * passer ce fondu-la sans rien faire. */ UFUNCTION() void HandleSessionTravelPending(); /** L'ecran de reglages demande a se fermer : on rend la main au menu de pause. */ UFUNCTION() void HandleSettingsCloseRequested(); /** * Point d'entree unique de l'ouverture et de la fermeture de l'ecran. * * Tab et la touche de fabrication passent tous les deux par ici : le mode * d'input, la souris et la barre rapide sont ainsi decides a un seul endroit. * Deux chemins separes finiraient par diverger. */ void SetInventoryScreenOpen(bool bOpen, bool bShowCraftingTab); /** Rend le poste accorde par le dernier OpenCraftingAtStation. Sans effet sinon. */ void ReleaseActiveStation(); /** * Rend le coffre ouvert : couvercle referme, panneau masque, surveillance * arretee. Sans effet s'il n'y en a pas. * * Separee de CloseStorage() pour la meme raison que ReleaseActiveStation : * c'est la fermeture de l'ECRAN qui l'appelle, quelle qu'en soit la cause -- * Tab, Echap, la mort, un autre coffre. Un seul point de sortie, donc aucun * chemin qui laisse un couvercle leve derriere soi. */ void ReleaseActiveStorage(); /** * Mode d'input et curseur pour un ecran plein cadre. * * Partage par l'inventaire et le coffre : deux copies de ces huit lignes * finiraient par diverger, et le symptome -- une camera qui ne repond plus, * un sprint bloque -- se cherche tres longtemps. */ void SetUiInputMode(bool bUiOpen); /** Le joueur s'est-il trop eloigne du coffre ouvert. Appele par un timer. */ void CheckStorageDistance(); /** Raccourci vers le composant de fabrication du pawn possede. */ UCraftingComponent* GetPawnCrafting() const; /** L'ecran a change d'onglet : la barre rapide n'a rien a faire sous la page de craft. */ UFUNCTION() void HandleInventoryTabChanged(bool bInventoryTabActive); /** * Etat unique de la barre rapide : visible partout, sauf par-dessus l'onglet * Fabrication. Passer par une seule fonction evite les cas ou la fermeture * de l'ecran laisserait la barre cachee. */ void UpdateHotbarVisibility(); /** * Relaie le survol d'une case de la barre rapide vers le panneau de detail * de l'ecran d'inventaire. * * Ignore ecran ferme : sans curseur il n'y a pas de survol, mais un widget * masque sous la souris peut encore emettre sa sortie -- et decrire un objet * dans un panneau invisible n'aurait aucun sens. */ UFUNCTION() void HandleHotbarSlotHovered(UInventoryComponent* Inventory, int32 SlotIndex, bool bHovered); /** Jette la pile survolee dans la grille, si l'inventaire est ouvert. */ void DropHoveredItem(); void HandleHotbarSelect(const FInputActionValue& Value); void HandleHotbarScroll(const FInputActionValue& Value); /** Raccourci vers l'inventaire du pawn possede. */ UInventoryComponent* GetPawnInventory() const; /** Branche sur OnDied du pawn possede. */ UFUNCTION() void HandlePawnDied(); /** * Detruit le cadavre et demande un nouveau pawn au GameMode. * * Le GameMode n'existe QUE sur le serveur : chez un client * GetAuthGameMode() rend nullptr, toujours. Un client route donc par * Server_RequestRespawn, et ne garde en local que son fondu de retour -- * c'est de l'affichage, ca lui appartient. */ void RespawnPlayer(); UFUNCTION(Server, Reliable) void Server_RequestRespawn(); // ------------------------------------------------------------------ // Ouverture d'ecran demandee par un acteur du monde // // Interact_Implementation s'execute sur le SERVEUR depuis le passage en // coop. Or ces acteurs ouvrent une interface, qui n'existe que sur la // machine du joueur : l'appel doit donc repartir vers le client par une // RPC Client_. Sans elles, le serveur cree des widgets dans le vide et // l'ecran du joueur ne s'ouvre jamais. // // L'etat "devant quel poste je suis" est tenu des DEUX cotes : le client en // a besoin pour filtrer sa liste de recettes, le serveur pour valider le // craft. Ne le tenir que d'un cote laisserait soit une liste vide, soit un // etabli utilisable depuis la foret. // ------------------------------------------------------------------ UFUNCTION(Client, Reliable) void Client_OpenCraftingAtStation(ECraftingStation Station); UFUNCTION(Client, Reliable) void Client_OpenStorage(AStorageContainer* Container); /** Le joueur a referme son ecran : le serveur reprend le poste accorde. */ UFUNCTION(Server, Reliable) void Server_ReleaseStation(ECraftingStation Station); /** Le joueur a referme le coffre : le serveur rabat le couvercle. */ UFUNCTION(Server, Reliable) void Server_ReleaseStorage(AStorageContainer* Container); /** Accorde le poste sur le composant du pawn et note lequel. */ void GrantStation(ECraftingStation Station); // ------------------------------------------------------------------ // Pseudo // // Le serveur ne peut PAS deviner le pseudo Steam d'un client : l'API // d'identite ne connait que l'utilisateur local de chaque machine. C'est // donc au client de l'annoncer. Sans ca, le moteur laisse le nom par // defaut du fichier de configuration -- on lit "Player" au-dessus des // quatre joueurs, ce qui se remarque tout de suite. // ------------------------------------------------------------------ /** Le pseudo de l'utilisateur Steam local, ou une chaine vide si indisponible. */ FString ResolveLocalPlayerNickname() const; /** Ecrit le pseudo sur le PlayerState, qui le replique a tout le monde. */ UFUNCTION(Server, Reliable) void Server_SetPlayerNickname(const FString& Nickname); /** * Meme chemin que le pseudo, et pour la meme raison : le serveur ne peut * pas deviner l'apparence choisie par un client, elle vit dans le fichier * de reglages de SA machine. C'est donc lui qui l'annonce. * * Treize octets envoyes une fois a la connexion -- l'apparence ne change * pas en cours de partie, l'ecran de customisation vit dans le menu. */ UFUNCTION(Server, Reliable) void Server_SetCharacterAppearance(const FCharacterAppearance& InAppearance); /** Lit l'apparence persistee et l'envoie au serveur. Appelee au BeginPlay. */ void AnnounceCharacterAppearance(); FTimerHandle RespawnTimerHandle; /** Le fondu d'arrivée attend le pawn. */ bool bStartupFadePending = false; FTimerHandle StartupFadeTimeoutHandle; /** Réessai tant que la caméra n'est pas sur le pawn. */ FTimerHandle StartupFadeRetryHandle; /** Période de réessai, en secondes. Assez court pour ne pas se voir. */ static constexpr float StartupFadeRetry = 0.05f; /** Surveillance de l'eloignement, actif seulement pendant qu'un coffre est ouvert. */ FTimerHandle StorageDistanceTimerHandle; /** Le coffre actuellement ouvert, pour lui refermer son couvercle. */ TWeakObjectPtr ActiveStorage; bool bStorageOpen = false; bool bInventoryOpen = false; /** Onglet Fabrication affiche. N'a de sens que si bInventoryOpen est vrai. */ bool bCraftingTabActive = false; /** * Poste accorde par l'ecran actuellement ouvert, a rendre a la fermeture. * Count = aucun, l'ecran a ete ouvert au clavier et pas depuis un etabli. */ ECraftingStation ActiveStation = ECraftingStation::Count; /** * Visibilite d'origine de la barre rapide, relevee a sa creation. * On la restaure telle quelle plutot que de forcer Visible : le Blueprint a * peut-etre choisi SelfHitTestInvisible, et l'ecraser changerait * silencieusement son comportement au clic. */ ESlateVisibility HotbarDefaultVisibility = ESlateVisibility::Visible; bool bPauseMenuOpen = false; /** * La boite de confirmation avale Echap elle-meme quand elle a le focus, * mais un clic ailleurs le lui retire : sans ce booleen, Echap refermerait * alors le menu de pause en laissant la question affichee dans le vide. */ bool bQuitToMenuDialogOpen = false; bool bSettingsOpen = false; /** Distingue le fondu de sortie de tous les autres dans HandleFadeFinished. */ bool bQuittingToMainMenu = false; };