Orchestration d'événements
Les vraies missions de GTA V ne se résument jamais à faire apparaître des ennemis qui tirent aussitôt. Pense aux meilleurs moments du jeu : deux dealers discutent dans une allée sombre, un troisième personnage émerge de l'ombre, un téléphone sonne, et c'est seulement là que la transaction dérape.
Orchestrer plusieurs acteurs demande de synchroniser leurs lignes de temps : quand l'acteur A atteint la porte, l'acteur B réagit et l'acteur C prend la fuite.
Le piège des minuteries fixes
Les débutants tentent souvent de coordonner leurs scènes avec de simples chronomètres :
// Fragile : que se passe-t-il si l'acteur A est bloqué par une voiture ?
acteurA.Task.GoTo(pointRencontre);
// 5 secondes plus tard, on suppose que l'acteur A est arrivé...
acteurB.Task.PlayAnimation(...);
Si l'acteur A trébuche sur un trottoir ou est contourné par un camion, l'acteur B commence à parler dans le vide cinq secondes plus tard. Toute la mise en scène s'écroule.
La chorégraphie par signaux (cue-based)
Une scène de modding professionnelle repose sur des signaux observables et non sur des délais d'attente aveugles. L'étape N ne démarre que lorsque l'étape N-1 a validé ses conditions physiques :
[ Étape 1 : Rapprochement ]
Les deux acteurs marchent vers le point de rendez-vous.
Attendre : Distance entre acteurs < 2,5 m.
| (signal : EnPosition)
v
[ Étape 2 : Discussion ]
Les acteurs s'animent et discutent.
Attendre : Le joueur s'approche à moins de 6 m OU sort une arme.
| (signal : Provocation)
v
[ Étape 3 : Dégénération ]
L'acheteur s'enfuit à pied. Le vendeur dégaine et ouvre le feu.
Implémenter un coordinateur de scène en C#
On structure ce déroulement à l'aide d'états de scène explicites :
public sealed class CoordinateurTransaction
{
private enum EtapeScene { Marche, Discussion, FusilladeEtFuite, Termine }
private EtapeScene _etape = EtapeScene.Marche;
public void Actualiser(Ped vendeur, Ped acheteur, Ped joueur)
{
switch (_etape)
{
case EtapeScene.Marche:
if (vendeur.Position.DistanceTo(acheteur.Position) < 2.5f)
{
// Les deux sont arrivés : démarrer la discussion
vendeur.Task.ChatTo(acheteur);
acheteur.Task.ChatTo(vendeur);
_etape = EtapeScene.Discussion;
}
break;
case EtapeScene.Discussion:
// Interruption si le joueur intervient
if (joueur.Position.DistanceTo(vendeur.Position) < 6f || joueur.IsArmed(WeaponCheckFlags.All))
{
DeclencherDegeneration(vendeur, acheteur, joueur);
_etape = EtapeScene.FusilladeEtFuite;
}
break;
case EtapeScene.FusilladeEtFuite:
// Vérifier si la scène est terminée
if (vendeur.IsDead && acheteur.Position.DistanceTo(joueur.Position) > 50f)
{
_etape = EtapeScene.Termine;
}
break;
}
}
private void DeclencherDegeneration(Ped vendeur, Ped acheteur, Ped joueur)
{
vendeur.Task.ClearAll();
acheteur.Task.ClearAll();
// L'un riposte, l'autre prend la fuite
vendeur.Weapons.Give(WeaponHash.MicroSMG, 100, true, true);
vendeur.Task.Combat(joueur, TaskCombatFlags.None, TaskThreatResponseFlags.None);
acheteur.Task.FleeFrom(joueur);
GTA.UI.Notification.PostTicker("Le deal tourne mal !", false);
}
}
En reliant chaque transition à une condition physique vérifiable, ta scène s'adapte naturellement, que le joueur observe discrètement aux jumelles depuis un toit ou fonce dans le tas au volant d'un camion.
Dans le Projet 06, nous construisons cet événement dynamique de transaction qui dérape.