Projet 05 : Gang encounter
Dans les projets précédents, tu as géré des entités uniques : un piéton isolé, un garde du corps ou une voiture. Dans le Projet 05, tu franchis un cap en orchestrant plusieurs acteurs simultanément. Tu vas donner vie à une confrontation de territoire avec trois membres de gang qui montent la garde, se mettent en alerte à ton approche, ouvrent le feu si tu sors une arme et retournent au calme si tu bats en retraite.
La mission
Concevoir une rencontre de gang dynamique répondant à six exigences fondamentales :
- Gérer dynamiquement une escouade de trois membres de gang à l'aide d'une collection générique
List<Ped>. - Faire apparaître les acteurs en ligne défensive face au joueur dans une posture de sentinelle.
- Détecter l'état d'armement du joueur et sa proximité spatiale en temps réel.
- Déclencher une riposte hostile si le joueur dégaine une arme à moins de 8 mètres, ou s'il s'approche à moins de 4 mètres les mains nues.
- Implémenter un véritable retour au calme physique : si le joueur bat en retraite au-delà de 18 mètres, interrompre le combat et reprendre la posture de garde.
- Purger automatiquement les handles d'entités détruites et garantir une suppression propre lors d'un rechargement ou d'une réinitialisation manuelle.
Spécifications, contraintes
- Hygiène des collections dynamiques : purger les entités mortes ou supprimées à chaque frame via
CleanInvalidRefs()avecList.RemoveAllpour prévenir les exceptions d'accès mémoire. - Détection rigoureuse de l'armement : évaluer conjointement
player.IsArmed(WeaponCheckFlags.All)etplayer.Weapons.Current.Hash != WeaponHash.Unarmedpour distinguer une arme à feu d'un téléphone ou de poings nus. - Retour physique au calme : changer une variable interne ne suffit pas ; il est impératif d'appeler
member.Task.ClearAll()puis de relancer le scénario"WORLD_HUMAN_GUARD_STAND". - Contrôle comportemental absolu : activer
member.BlockPermanentEvents = truesur chaque PNJ afin que la panique ambiante native ne vienne pas écraser la logique de ton script. - Zéro fuite d'entité : supprimer tous les membres vivants ou morts dans
ClearGang()lors du déchargement.
Étapes de réalisation
- Déclarer la collection : initialise une liste privée
private readonly List<Ped> _gangMembers = new List<Ped>();dans ta classe. - Brancher les événements : dans le constructeur, enregistre des gestionnaires pour
Tick,AbortedetKeyDown. - Purger les handles obsolètes : en tête de
OnTick, invoqueCleanInvalidRefs()pour retirer de la liste les PNJ devenus nuls ou inexistants. - Instancier l'escouade : si
_gangMembers.Count == 0, appelle la méthodeSpawnGang(). - Évaluer la menace du joueur : détermine si le joueur tient actuellement une arme létale en main.
- Parcourir les membres de l'escouade : pour chaque PNJ vivant de la liste :
- Maintenir
BlockPermanentEvents = true. - Calculer la distance au joueur avec
player.Position.DistanceTo(member.Position). - Si le joueur est armé à moins de 8 mètres ou à moins de 4 mètres désarmé, ordonner
member.Task.Combat(player). - Si la distance dépasse 18 mètres et que le membre combat, effacer les tâches et lancer
member.Task.StartScenarioInPlace("WORLD_HUMAN_GUARD_STAND", 0, false).
- Maintenir
- Bâtir la routine d'apparition : dans
SpawnGang, itère 3 fois, calcule les positions latérales avecplayer.RightVector, donne des pistolets, lance le scénario de sentinelle et ajoute chaque acteur à la liste. - Programmer la purge et le reset : dans
ClearGang, parcours la liste, supprime chaque entité existante et vide la collection. Associe la toucheKeys.NumPad9à la réinitialisation et appelleClearGangdansOnAborted.
APIs, outils à explorer
System.Collections.Generic.List<Ped>: collection dynamique standard pour administrer un groupe d'acteurs de taille variable.List<T>.RemoveAll(Predicate<T> match): supprime sur place tous les éléments satisfaisant une condition donnée.Ped.IsArmed(WeaponCheckFlags flags): méthode native vérifiant si un piéton tient une arme.Ped.Task.StartScenarioInPlace(string scenarioName, int unkDelay, bool playIntroClip): ordonne à une entité d'exécuter un scénario d'animation d'ambiance.Ped.Task.ClearAll(): interrompt immédiatement la file de tâches actives et en attente.Vector3.DistanceTo(Vector3 target): calcule la distance euclidienne 3D entre deux coordonnées dans le monde.
Critères de validation
Ton mod est validé dès que :
- Approche désarmée à 10 mètres : le gang reste en formation de garde et observe sans tirer.
- Arme dégainée à 7 mètres : les trois membres de gang dégainent et ouvrent le feu immédiatement.
- Approche à 3 mètres les mains nues : la proximité critique déclenche les tirs de défense.
- Repli au-delà de 18 mètres : les tirs cessent, le gang annule ses tâches de combat et reprend sa posture de sentinelle.
- Retour désarmé à 10 mètres : le gang reste calme et ne tire pas sans nouvelle provocation.
- Appui sur
Pavé numérique 9ou rechargement avecInser: le gang disparaît complètement sans laisser de cadavres sur le bitume.
Solution, explications
Le sujet, les contraintes et les étapes de réalisation restent 100% libres pour t'exercer par toi-même. Le code source de référence vérifié et les explications détaillées de production sont réservés aux membres du tier Partner.