Aller au contenu

Architecture du HUD

medusa-hud est l'unique propriétaire de la NUI du HUD joueur. Sa page transparente contient trois zones indépendantes : la pile de statuts en haut à droite, l'inlay date/heure en bas à droite et un cadre de navigation transparent autour de la minimap native en bas à gauche. Le client surveille le menu pause toutes les 250 ms et ne transmet un message de visibilité que lors d'un changement d'état.

Les systèmes métier restent découplés du rendu :

  • medusa-buffs applique les effets et publie medusa:hud:buffs après chaque synchronisation ;
  • medusa-time-weather calcule l'horloge autoritaire et publie medusa:hud:datetime uniquement lorsque la minute en jeu change.

Ces événements sont locaux au client et consommés par medusa-hud, qui seul appelle SendNUIMessage. Les dépendances de ressources et l'ordre de server.cfg.template garantissent que le consommateur est démarré avant ses producteurs. Ajouter un futur élément HUD consiste à ajouter un événement local, son état de présentation et une zone visuelle dédiée, sans ajouter une nouvelle NUI superposée.

La NUI repose volontairement sur la même structure minimale que l'ancien affichage des buffs, déjà validé en jeu. FiveM fournit lui-même l'iframe fullscreen ; le document ne crée donc aucun wrapper plein écran. body est transparent, sans color-scheme, opacité, transformation, filtre, backdrop ou pseudo-élément global. Seuls les panneaux bornés #buffs et #clock portent un fond. Masquer le HUD utilise display: none uniquement sur ses trois zones, sans modifier le canevas racine.

Le client positionne minimap, minimap_mask et minimap_blur avec SetMinimapComponentPosition et les valeurs documentées dans common:/data/ui/frontend.xml : la carte utilise (-0.0045, 0.002, 0.150, 0.188888), avec les géométries natives correspondantes du masque et du flou. Le client reprend la méthode du cookbook FiveM : SetScriptGfxAlign('L', 'B') et GetScriptGfxPosition convertissent le coin supérieur gauche frontend en coordonnées normalisées d'écran, après application native du ratio et de la zone sûre. Aucun delta inverse n'est appliqué : sur certains artifacts, la transformation calculée ne déplace pas le Scaleform du radar de façon identique au cadre NUI et crée un décalage persistant.

La géométrie du cadre complète le coin renvoyé par le cookbook avec la largeur 1 / (4 * ratio) et la hauteur 1 / 5.674 de GetMinimapAnchor. Une extension de 16 px est ajoutée uniquement au bord droit : elle couvre la marge visuelle du Scaleform constatée au-delà de sa largeur théorique sans déplacer les trois autres bords déjà alignés. Le message NUI radarLayout transmet ce rectangle normalisé ; le script web définit directement left, top, width et height du cadre. Le cadre ne devient visible qu'après réception d'un rectangle valide. Après le placement, un cycle du grand radar limité à un seul tick reconstruit le Scaleform pour que la cartographie réapparaisse. SetMinimapClipType(0) rétablit immédiatement le masque rectangulaire. La méthode Scaleform SETUP_HEALTH_ARMOUR(3) supprime les jauges natives de santé et d'armure. GTA peut réinitialiser ce type durant le rendu ; ce seul override Scaleform est donc maintenu à chaque frame lorsque le radar est visible, puis passe sur une attente de 250 ms avant le spawn ou pendant la pause. Les natives multijoueur de visibilité et d'autorisation de la barre de capacité sont également désactivées lorsqu'elles sont exposées par l'artifact client. Le repositionnement reste appliqué uniquement au chargement, au spawn, à la fermeture du menu pause et lors d'un changement de résolution, jamais à chaque frame. medusa-world-control reste propriétaire de l'affichage du radar avant/après le spawn ; le HUD ne possède que sa géométrie et son habillage.

Le cadre #radar-shell ne possède aucun fond de panneau. Sa grille très légère, ses quatre angles, ses télémétries et son réticule sont strictement bornés aux dimensions du radar. Il reste masqué avant medusa:character:spawned et suit la visibilité globale pendant le menu pause.

Le script NUI appelle le callback ready après son chargement. Le client publie alors medusa:hud:ready : medusa-time-weather invalide son cache de minute et redemande l'état serveur s'il ne l'a pas encore, tandis que medusa-buffs republie son cache local. Ce handshake empêche la perte des événements émis avant l'installation du listener JavaScript. Le HUD expose aussi isReady. Au démarrage, chaque producteur attend cet export avant sa première publication ; cette vérification couvre le cas où le callback NUI précède l'enregistrement de leurs handlers locaux. L'événement reste nécessaire pour les redémarrages ultérieurs du HUD.

Suppression temporaire

L'événement local medusa:hud:setSuppressed masque/restaure la NUI et le radar sans changer l'état durable. L'ARPhone l'utilise pendant la capture photo afin que le HUD ne soit pas inclus dans l'image.

Adaptateur compteur véhicule

medusa-hud ne décide jamais si un véhicule ou un joueur sont autorisés. Il reçoit localement le snapshot versionné medusa:hud:vehicleSpeedometer et le transmet directement au renderer natif. Le contrat v3 contient visibilité, aperçu, préférence et télémétrie normalisée, sans état de régulateur. Les contrats v1/v2 restent lisibles uniquement pour convertir une ancienne taille vers 80/100/120 et le bas-centre ; seules les préférences v3 sont émises et écrites.

client/vehicle_speedometer_native.lua est l'adaptateur de rendu unique. Les fichiers stream/default.ytd, stream/id6.ytd et stream/id7.ytd sont byte-identiques au commit amont 1e150965034d575ea3eb3ffebe7bd0fa848daf79. Les trois sources vendor/fivem-speedometer/skins/*.lua et la licence BSD 2-Clause sont elles aussi conservées octet pour octet comme vérité vérifiable, mais ne sont jamais démarrées. L'adaptateur recopie leurs constantes et leur ordre de dessin, puis appelle RequestStreamedTextureDict et DrawSprite avec l'ancrage normalisé demandé, la compensation globale du ratio, la zone sûre et une échelle de 0,60 à 1,40 par pas de 0,05. Il ne charge ni thread, commande, KVP, default_middle, son, MPH ni dépendance web du projet amont.

Une demande de dictionnaire est bornée à cinq secondes. Un échec produit un diagnostic unique, remonte le thème à F5 et utilise CLASSIC comme repli lorsque seul D6 ou D7 est indisponible. F5 interdit alors Appliquer sur le thème fautif. Le HUD NUI ne dessine plus de compteur ni de badge véhicule : il reste transparent et conserve seulement horloge, buffs et radar.

Les six aperçus F5 Jour/Nuit sont des PNG transparents lossless générés par fivem/tools/export-speedometer-previews.py. L'outil vérifie d'abord les sept SHA-256 canoniques, extrait les textures avec les dépendances épinglées de requirements-speedometer.txt, applique les compositions exactes sans retouche et écrit un manifeste des hashes. La NUI Véhicules les affiche avec un simple élément img; aucun SVG ou second cadran interprété n'existe.

Le renderer dérive une enveloppe conservatrice de toutes les coordonnées de chaque composition, inclut le rayon diagonal des aiguilles et ignore uniquement les sentinelles amont hors écran. La fonction exportée resolveSpeedometerGeometry sépare toujours la position désirée persistée de la position rendue bornée. GetSafeZoneSize() et GetAspectRatio(false) sont intégrés au clamp : un changement de résolution déplace temporairement le rendu sans PATCH et la position désirée réapparaît lorsqu'elle redevient compatible. La géométrie est mise en cache tant que thème, échelle, position, ratio et zone sûre ne changent pas.

La télémétrie reste locale, bornée à 50 ms et dédupliquée. Le mode d'éclairage auto résout Nuit à partir de 20 h, avant 6 h ou avec les phares/pleins phares ; day/night sont forcés. Le harness non-runtime fivem/tests/fixtures/vehicle-speedometer-visual.html vérifie les cartes F5 et la transparence NUI avec des snapshots synthétiques. Il ne peut pas capturer les DrawSprite natifs : les comparaisons du compteur réellement streamé restent une recette FiveM à effectuer aux résolutions et ratios prévus.

Le compteur natif, la barre de placement et leurs pseudo-éléments restent bornés. html et body déclarent explicitement background: transparent !important, [hidden] reste prioritaire et aucun color-scheme n'est autorisé. Le test global nui-transparency.test.mjs parcourt toutes les ui_page Medusa afin d'empêcher le retour du backdrop noir.

Enrichissement énergie

La télémétrie locale fournit type/niveau/autonomie/moyenne aux trois compositions existantes. Les bornes de fiabilité, flags et performances sont détaillés dans Énergie des véhicules.