Objectif
Faire évoluer native-vehicle-traffic d’un trafic dont l’unique état valide est « conducteur assis exécutant TASK_COMPLEX_CAR_DRIVE_WANDER, passagers immobiles dans leurs sièges » vers une cohorte véhicule/occupants capable d’exécuter et synchroniser les réactions GTA:SA suivantes :
- panique/fuite après tirs et dégâts ;
- sortie du conducteur et des passagers ;
- réaction à un accident, véhicule immobilisé, retourné ou en feu ;
- road rage après agression/collision et réaction à une obstruction ;
- carjack automobile normal ;
- réactions des passagers selon les gates retail par événement, siège et présence d’un conducteur ;
- reprise correcte de chaque branche après handoff ou perte d’owner.
Le serveur reste autoritaire sur l’incident, la cohorte, l’owner, l’epoch et la branche engagée. Le client owner exécute les tâches GTA natives. Aucun pointeur de tâche, événement ou path node local n’est sérialisé.
État actuel
Le client définit un seul oracle durable, TASK_COMPLEX_CAR_DRIVE_WANDER, dans test-resources/native-vehicle-traffic/client.lua.
L’acceptation et chaque échantillon exigent actuellement :
- conducteur dans le siège 0 ;
- tous les passagers dans leurs sièges initiaux ;
- tous les acteurs sous le même syncer ;
DriveWander toujours présent.
Références :
test-resources/native-vehicle-traffic/client.lua:3 ;
test-resources/native-vehicle-traffic/client.lua:55-64 ;
test-resources/native-vehicle-traffic/client.lua:181-240 ;
test-resources/native-vehicle-traffic/client.lua:269-319 ;
test-resources/native-vehicle-traffic/server.lua:1286-1361.
Une réaction native légitime qui remplace DriveWander, fait sortir un occupant ou change son siège devient donc une perte d’état.
Le handoff ne conserve que la cinématique du véhicule avant de réinstaller DriveWander. Le carjack joueur actuel révoque l’unité et retire ses occupants avant de céder le véhicule ; il ne joue pas le carjack GTA complet. Enfin, addPedNativeBikeJackTask est volontairement limité aux bikes/BMX/quads et à une victime joueur locale.
Référence GTA:SA
Branches retail à conserver comme oracles dans gta-reversed-dryxio :
- tirs :
Events/EventHandler.cpp:2934-2980 ;
- dégâts véhicule, fuite/road rage/riposte :
Events/EventHandler.cpp:3192-3289 ;
- véhicule retourné :
Events/EventHandler.cpp:751-763 ;
- véhicule en feu/détruit :
Events/EventHandler.cpp:3294-3340 ;
- intrusion/carjack :
Events/EventHandler.cpp:2257-2304 ;
- victime tirée du véhicule :
Events/EventHandler.cpp:1216-1285 ;
- road rage :
Tasks/TaskTypes/TaskComplexRoadRage.cpp ;
- cri puis sortie/fuite :
Tasks/TaskTypes/TaskComplexScreamInCarThenLeave.cpp ;
- sortie et fuite :
Tasks/TaskTypes/TaskComplexLeaveCarAndFlee.cpp ;
- vol de véhicule NPC :
Tasks/TaskTypes/TaskComplexStealCar.cpp.
Architecture cible
Cohorte autoritaire versionnée
Étendre chaque unité avec :
unit = {
id,
epoch,
revision,
owner,
vehicle,
occupants = {
{
ped,
originalRole, -- driver | passenger
currentRole,
originalSeat,
currentSeat,
branch,
phase,
target,
incidentId,
terminal,
}
},
incident = {
id,
kind,
source,
target,
position,
serverTick,
seed,
},
vehicleState = {
mode,
drivable,
burning,
overturned,
immobilized,
}
}
Branches minimales :
cruise ;
flee-in-vehicle ;
leave-vehicle ;
flee-on-foot ;
scream-then-leave ;
road-rage ;
carjacked ;
fight-or-retaliate ;
await-reentry ;
incapacitated ;
dead ;
settled-on-foot.
Le serveur valide et déduplique par (unit id, epoch, incident id). Le client owner peut proposer la décision GTA sélectionnée, mais ne peut ni inventer une cible ni modifier seul la cohorte.
Owner commun pendant les transitions
Véhicule, conducteur et passagers gardent un owner et un epoch communs pendant toute branche transitoire, y compris après sortie physique.
Après stabilisation :
- conducteur revenu au volant →
cruise ;
- occupant durablement à pied → admission explicite dans
native-ped-traffic ;
- véhicule sans conducteur avec passager avant
PED_GAME non groupé éligible → branche takeover-driver après le délai retail de 4 000 ms ;
- véhicule sans conducteur sans reprise éligible, ou après échec/timeout explicite → unité abandonnée avec TTL ;
- ped mort/incapable → aucun redémarrage de
DriveWander.
Profil natif occupant owner-only
Ajouter un profil resource-scoped ambient-vehicle-occupant, distinct de ambient-wander et mission.
Il doit :
- fonctionner pour un occupant assis sans probe de ground support pédestre ;
- être actif uniquement sur le syncer de l’epoch courant ;
- rétablir l’identité NPC uniquement aux call sites GTA audités ;
- laisser le decision maker du modèle choisir la réponse ;
- bloquer scanners et event-response tasks sur observers ;
- purger les slots de réponses lors d’un revoke ;
- conserver les pipelines MTA autoritaires de santé/dégâts/mort ;
- publier uniquement état sémantique, branche, phase et cible résolvable.
Événements minimum :
EVENT_SHOT_FIRED ;
EVENT_DAMAGE, dont WEAPON_DROWNING pour un occupant encore dans un véhicule submergé ;
EVENT_VEHICLE_DAMAGE_WEAPON ;
EVENT_VEHICLE_DAMAGE_COLLISION ;
EVENT_VEHICLE_ON_FIRE ;
EVENT_VEHICLE_DIED ;
EVENT_CAR_UPSIDE_DOWN ;
EVENT_PED_ENTERED_MY_VEHICLE ;
EVENT_DRAGGED_OUT_CAR ;
EVENT_KNOCK_OFF_BIKE pour bike/BMX/quad ;
EVENT_ON_FIRE pour le ped lui-même, distinct du véhicule en feu.
EVENT_SHOT_FIRED_WHIZZED_BY reste optionnel pour un decision maker custom : les decision makers civils ambient audités ne sélectionnent pas cette réponse. EVENT_DANGER reste P2/futur trafic aérien : les constructions retail retrouvées concernent principalement un appareil volant dangereusement bas, pas une explosion routière générique. EVENT_COP_CAR_BEING_STOLEN reste conditionnel à une cohorte contenant réellement un occupant PED_TYPE_COP.
Les événements géométriques locaux sont consommés seulement par l’owner. Les tirs/dégâts cross-owner utilisent un replay comportemental authentifié par le serveur. Chaque replay précise s’il est decision-only ou exige un état GTA réel ; aucun replay ne doit appliquer santé, dégâts, mort, crime ou wanted une seconde fois.
Contrat d’audit retail avant implémentation
Les branches minimales incluent désormais aussi takeover-driver, knocked-off-bike, escape-submerged, ped-on-fire et dying-in-car. Le véhicule expose submerged, drowning, recoveryAction et recoveryDeadline. L’occupant distingue originalRole de currentRole afin qu’un passager puisse devenir conducteur.
Éligibilité et propagation par occupant
La réaction n’est jamais diffusée indistinctement à toute la cohorte :
| Événement |
Éligibilité/propagation retail |
EVENT_SHOT_FIRED |
conducteur, ou passager seulement si le véhicule n’a pas de conducteur valide |
EVENT_VEHICLE_DAMAGE_WEAPON/COLLISION |
même gate que les tirs |
EVENT_DAMAGE direct |
victime autoritative ; clones informatifs non dommageables aux co-occupants, sauf noyade |
EVENT_VEHICLE_ON_FIRE |
occupants éligibles ; préserver la nuance des membres de groupe non-leaders |
EVENT_PED_ENTERED_MY_VEHICLE |
occupants concernés du véhicule exact |
EVENT_DANGER |
conducteur seulement pour la réponse véhicule auditée |
EVENT_GUN_AIMED_AT |
hors minimum occupé civil : les DM ambient sélectionnent TASK_NONE en véhicule |
EVENT_VEHICLE_COLLISION concerne le ped à pied heurté/évité par une voiture et ne remplace pas EVENT_VEHICLE_DAMAGE_COLLISION.
Effets secondaires natifs et autorité
Avant CP2, renseigner pour chaque événement :
détection | décision | tâche | santé | mort | wanted/crime | propagation | autorité/fence.
Cas obligatoires :
EVENT_VEHICLE_DIED peut mettre localement la santé du ped à zéro ;
EVENT_KNOCK_OFF_BIKE calcule chute et fall damage ;
EVENT_ON_FIRE exige un m_pFire réel et inflige des dégâts continus ;
- la buoyancy produit d’abord
EVENT_DAMAGE/WEAPON_DROWNING dans le véhicule ; EVENT_IN_WATER vient après la sortie physique ;
- le carjack d’un cop peut publier un crime et modifier le wanted level.
MTA reste autoritaire sur santé, armour, dégâts, mort, crime et wanted. Les écritures natives sont neutralisées, capturées puis validées, ou réconciliées explicitement — jamais simplement rejouées.
Priorité, préemption et décision DM
La déduplication d’un même incident ne résout pas deux incidents distincts concurrents. Une matrice serveur doit couvrir dégâts fatals/mort face à noyade, feu et knock-off ; feu/retournement face à carjack ; carjack face à road rage/takeover ; destruction pendant une sortie ; owner loss pendant une préemption.
Un état terminal est monotone : aucune réaction tardive ne ressuscite un occupant ou ne réinstalle DriveWander.
Le client owner peut proposer la réponse choisie par GTA, mais le serveur la valide contre une allowlist event × decision maker × siège/contexte, la conserve dans lockedBranch et la réutilise au handoff. incident.seed ne contrôle pas à lui seul le RNG global GTA ; aucun handoff ne refait la décision.
Checkpoints supplémentaires
takeover-driver → waiting, leave-passenger-seat, enter-driver-seat, resume-cruise ;
knocked-off-bike → snapshot physique, puis landed/recovering ou dead ; handoff différé/normalisé pendant une chute non reconstructible ;
escape-submerged → leave, in-water, drowning ou drown-in-car ;
ped-on-fire → état feu authentifié, leave, flee ou terminal ;
dying-in-car → stop/handbrake, délai retail borné, leave-and-die ou dead-in-seat.
Snapshot et handoff sémantiques
Remplacer le snapshot limité à la cinématique par :
{
incidentId,
revision,
vehicle = {
pose, velocity, angularVelocity,
health, burning, overturned, engineState,
},
occupants = {
{
ped, role, seat, pose, velocity,
health, armour, branch, phase,
target, taskRoot, taskLeaf,
}
}
}
Ne jamais cloner l’état interne arbitraire d’une tâche GTA. Chaque branche expose des checkpoints reconstructibles :
flee-in-vehicle → CarDriveMissionFleeScene ;
leave-vehicle → LeaveCar avec porte/siège et délai borné ;
flee-on-foot → SmartFleeEntity ou SmartFleePoint ;
road-rage → leave, threat, seek/fight/destroy, return-to-car ;
carjacked → entry-requested, dragging, victim-out, jacker-seated, flee-scene ;
scream-then-leave → temps restant borné ou phase leave ;
dead/incapacitated → état terminal.
Une animation physique non reconstructible peut différer brièvement le handoff, puis normaliser vers un checkpoint sûr. Sur owner quit, utiliser le dernier snapshot serveur validé.
APIs C++/Lua nécessaires
Profil et diagnostic
acquirePedNativeEventProfile(ped, "ambient-vehicle-occupant") ;
getPedNativeEventResponseState(ped) retournant uniquement current event, root/leaf, cible résolue, véhicule/porte/siège et phase reconnue ;
- télémétrie owner-only des décisions et transitions.
Replays comportementaux authentifiés
- tirs/whizzed-by pour occupants ;
- vehicle damage weapon/collision ;
- fire/died/upside-down ;
- entered-my-vehicle/dragged-out.
Chaque binding exige lease valide, éléments streamés, syncer de l’epoch, relations siège/véhicule/cible exactes, enums allowlistés et incident non consommé.
Constructeurs de reprise
Exposer seulement les tâches nécessaires aux checkpoints :
CarDriveMissionFleeScene ;
LeaveCarAndFlee ;
LeaveCarAndWander ;
ScreamInCarThenLeave ;
RoadRage ;
- éventuellement
StealCar ;
- entrée conducteur/passager et
LeaveCar, déjà partiellement disponibles.
setPedDriveMission actuel ne suffit pas : il est limité à MISSION_ESCORT_LEFT après validation spécifique.
Carjack automobile joueur
Remplacer la suppression des occupants par :
- détecter véhicule, siège et epoch ;
- suspendre l’entrée et ouvrir un incident
carjack ;
- transférer atomiquement la cohorte vers le client du joueur entrant ;
- vérifier streaming, portes, sièges et relations ;
- relancer la vraie tâche GTA
EnterCarAsDriver ;
- faire recevoir à la victime
EVENT_PED_ENTERED_MY_VEHICLE, puis EVENT_DRAGGED_OUT_CAR ;
- suivre les milestones porte/victime/joueur ;
- laisser chaque passager choisir rester, sortir, fuir, combattre ou reprendre le véhicule ;
- faire sortir le véhicule du trafic après réussite, mais transférer les anciens occupants au lifecycle pédestre ;
- revenir au dernier checkpoint en cas d’annulation, mort ou timeout.
Cas requis : conducteur seul, passager avant/arrière, véhicule deux portes, porte bloquée, joueur interrompu/tué, deux joueurs concurrents et carjack pendant feu/retournement/handoff.
Accident, immobilisation et obstruction
Distinguer :
- collision légère/navigation → laisser l’autopilot freiner/reculer/contourner ;
- obstruction persistante sans dégâts → phase native recovery/horn, sans stuck restart tant qu’elle progresse ;
- collision hostile avec dégâts → authentifier l’attaquant et laisser GTA choisir fuite/sortie/road rage/riposte ;
- véhicule non viable → sortie si retourné/immobilisé/en feu, mort ou knock-off à l’explosion.
Les watchdogs actuels sont suspendus lorsqu’une branche valide progresse et restent le fallback en absence de progression.
Checkpoints ordonnés
CP1 — Contrat de cohorte et observabilité
Branches, phases, incidents, revisions, snapshots par occupant ; matrices d’éligibilité, effets secondaires, priorité/préemption et validation DM ; plusieurs oracles de tâches ; monitor/cleanup/leases adaptés sans nouveau comportement.
Sortie : tous les tests trafic actuels passent sans régression.
CP2 — Profil natif occupant et fencing
ambient-vehicle-occupant, audit IsPlayer, observers neutralisés, cleanup des event-response tasks, allowlist event × DM × siège/contexte, verrouillage de branche et fences santé/mort/crime/wanted.
Sortie : une seule décision native validée et verrouillée par incident, aucune tâche observer et aucun effet autoritatif appliqué deux fois.
CP3 — Feu, destruction, retournement, submersion et deux-roues
Sorties selon la matrice retail, ped-on-fire, noyade, mort dans le véhicule, knock-off bike/BMX/quad, véhicule abandonné, occupants à pied et handoff à chaque checkpoint reconstructible.
Sortie : aucun occupant attaché à un siège détruit ou submergé, aucun double dégât, aucune fausse perte de state et normalisation documentée des animations non reconstructibles.
CP4 — Tirs, dégâts et fuite
Replays cross-owner, CarDriveMissionFleeScene, gates et clones informatifs propres aux passagers, validation DM, verrouillage de branche et déduplication.
Sortie : exactement une branche serveur validée par tir/dégât et zéro réaction d’un passager inéligible derrière un conducteur valide.
CP5 — Collision, obstruction et road rage
Classification des incidents, reconstruction RoadRage, confrontation/retour au véhicule et suspension du stuck recovery.
Sortie : obstruction normale non destructive ; collision hostile capable d’atteindre les branches retail.
CP6 — Carjack automobile complet
Protocole GTA natif, anciens occupants conservés, concurrence gérée et transfert au trafic pédestre.
Sortie : le joueur obtient le siège par animation native et les occupants survivent/réagissent.
CP7 — Handoff exhaustif et owner loss
Snapshots/reprise de toutes les phases, takeover du volant par le passager avant éligible, deferred handoff borné, crash/quit et cleanup exact.
Sortie : A→B, B→A et owner quit passent sans reroll DM, double autorité ni tâche orpheline ; un véhicule sans conducteur tente la reprise retail avant abandon.
CP8 — Soak et activation production
Harness déterministe, incidents concurrents à densité production, métriques et feature flags par famille.
Tests d’acceptation
Ajouter :
cartraffic test gunpanic
cartraffic test collision
cartraffic test obstruction
cartraffic test fire
cartraffic test overturned
cartraffic test immobilized
cartraffic test roadrage
cartraffic test carjack
cartraffic test passengerreactions
cartraffic test passengergating
cartraffic test passengertakeover
cartraffic test bikefall
cartraffic test bikefire
cartraffic test submergedcar
cartraffic test submergedbike
cartraffic test occupantonfire
cartraffic test deathincar
cartraffic test reactionpriority
cartraffic test healthauthority
cartraffic test wantedauthority
cartraffic test dmbranchvalidation
cartraffic test reactionhandoff
cartraffic test reactionownerquit
cartraffic test reactionsoak [cycles]
Chaque scénario couvre un puis deux clients, owner quit, conducteur seul et plusieurs passagers, véhicules variés, epoch monotone, owner commun, incident unique, aucune réponse observer, sièges/portes cohérents, checkpoint valide au handoff et cleanup complet.
Invariants :
- aucune réinstallation de
DriveWander sur ped sorti, mort ou carjacked ;
- état terminal monotone, sans résurrection ni réaction tardive ;
- retour
cruise uniquement avec conducteur valide au siège 0 ;
- aucune nouvelle décision/reroll DM au handoff : reprendre
lockedBranch ;
- aucun dégât, mort, crime ou wanted appliqué deux fois ;
- aucun split ownership ni double syncer ;
- aucune croissance mémoire ou task root orpheline ;
- jump au handoff et heading delta bornés ;
- abandon/despawn uniquement après branche terminale ou timeout explicite.
Risques
- script peds basés sur
CPlayerPed : audit ciblé de chaque call site IsPlayer ;
- collision/obstruction calculées localement : fencing observer obligatoire ;
- même événement vu par MTA et GTA : déduplication stricte ;
- handlers/tâches GTA pouvant modifier santé, mort, fall damage, crime ou wanted : fences et réconciliation testées ;
- le RNG global GTA n’est pas contrôlé par
incident.seed : validation puis verrouillage de la branche owner ;
- portes/sièges/animations variables par classe de véhicule ;
- road rage croise le pipeline combat/dégâts ;
- occupant sorti pouvant s’éloigner : split uniquement après checkpoint serveur ;
- root task insuffisant pour reprendre une tâche complexe ;
- packaging production encore séparé de
test-resources.
Dépendances
- heartbeat/reassignment recommandé avant activation production ;
- coordination avec l’issue crime/wanted/police pour publier carjack, collision volontaire et agressions sans lui céder les réactions civiles ;
- admission explicite vers
native-ped-traffic pour les occupants devenus walkers ;
- changements C++ à construire au minimum dans
Game SA et Client Deathmatch, Release|Win32 ;
- exécuter
./utils/clang-format.ps1 après changements C++ et suivre utils/vm-build.ps1.
Definition of Done
Les conducteurs et passagers éligibles selon la matrice retail peuvent quitter DriveWander pour toutes les branches couvertes ; le serveur valide puis verrouille la décision DM et arbitre les préemptions ; l’exécution reste strictement owner-only ; chaque branche survit au handoff ou à la perte d’owner sans reroll ; chaque acteur termine dans un lifecycle cohérent — reprise du volant, retour au trafic, trafic pédestre, abandon, incapacité ou mort — sans suppression artificielle, double simulation, double effet autoritatif ni tâche orpheline.
Discipline de livraison
Chaque commit doit préciser le prompt/but, la motivation, le modèle d’autorité, les invariants de handoff, les décisions GTA auditées et les builds/scénarios runtime réellement testés.
Réaction aux sirènes et véhicules prioritaires
Ajouter une branche sémantique yield-to-siren déclenchée par le contexte autoritaire emergency-passage publié par le système police (#91). Le client propriétaire du véhicule civil reste seul exécuteur et choisit une réaction native temporaire inspirée de CCarAI::MakeWayForCarWithSiren : TEMPACT_WAIT, TEMPACT_BRAKE, TEMPACT_SWIRVELEFT_STOP ou TEMPACT_SWIRVERIGHT_STOP selon géométrie, direction et distance.
À couvrir : conducteur valide, exclusions véhicules d’urgence/law-enforcement et branches incompatibles, passagers conservés, déduplication par unité+epoch+nonce, TTL/cooldown, retour sûr à la branche précédente, et checkpoint/reconstruction lors du handoff. Le watchdog anti-stuck doit reconnaître yield-to-siren comme une immobilisation intentionnelle et ne pas réinstaller DriveWander ni téléporter le véhicule.
Ajouter cartraffic test sirenyield avec deux clients et propriétaires distincts pour le véhicule de police et le véhicule civil ; vérifier passage, freinage/écart, absence de double application, handoff pendant la manœuvre, reprise du trafic et cleanup.
Objectif
Faire évoluer
native-vehicle-trafficd’un trafic dont l’unique état valide est « conducteur assis exécutantTASK_COMPLEX_CAR_DRIVE_WANDER, passagers immobiles dans leurs sièges » vers une cohorte véhicule/occupants capable d’exécuter et synchroniser les réactions GTA:SA suivantes :Le serveur reste autoritaire sur l’incident, la cohorte, l’owner, l’epoch et la branche engagée. Le client owner exécute les tâches GTA natives. Aucun pointeur de tâche, événement ou path node local n’est sérialisé.
État actuel
Le client définit un seul oracle durable,
TASK_COMPLEX_CAR_DRIVE_WANDER, danstest-resources/native-vehicle-traffic/client.lua.L’acceptation et chaque échantillon exigent actuellement :
DriveWandertoujours présent.Références :
test-resources/native-vehicle-traffic/client.lua:3;test-resources/native-vehicle-traffic/client.lua:55-64;test-resources/native-vehicle-traffic/client.lua:181-240;test-resources/native-vehicle-traffic/client.lua:269-319;test-resources/native-vehicle-traffic/server.lua:1286-1361.Une réaction native légitime qui remplace
DriveWander, fait sortir un occupant ou change son siège devient donc une perte d’état.Le handoff ne conserve que la cinématique du véhicule avant de réinstaller
DriveWander. Le carjack joueur actuel révoque l’unité et retire ses occupants avant de céder le véhicule ; il ne joue pas le carjack GTA complet. Enfin,addPedNativeBikeJackTaskest volontairement limité aux bikes/BMX/quads et à une victime joueur locale.Référence GTA:SA
Branches retail à conserver comme oracles dans
gta-reversed-dryxio:Events/EventHandler.cpp:2934-2980;Events/EventHandler.cpp:3192-3289;Events/EventHandler.cpp:751-763;Events/EventHandler.cpp:3294-3340;Events/EventHandler.cpp:2257-2304;Events/EventHandler.cpp:1216-1285;Tasks/TaskTypes/TaskComplexRoadRage.cpp;Tasks/TaskTypes/TaskComplexScreamInCarThenLeave.cpp;Tasks/TaskTypes/TaskComplexLeaveCarAndFlee.cpp;Tasks/TaskTypes/TaskComplexStealCar.cpp.Architecture cible
Cohorte autoritaire versionnée
Étendre chaque unité avec :
Branches minimales :
cruise;flee-in-vehicle;leave-vehicle;flee-on-foot;scream-then-leave;road-rage;carjacked;fight-or-retaliate;await-reentry;incapacitated;dead;settled-on-foot.Le serveur valide et déduplique par
(unit id, epoch, incident id). Le client owner peut proposer la décision GTA sélectionnée, mais ne peut ni inventer une cible ni modifier seul la cohorte.Owner commun pendant les transitions
Véhicule, conducteur et passagers gardent un owner et un epoch communs pendant toute branche transitoire, y compris après sortie physique.
Après stabilisation :
cruise;native-ped-traffic;PED_GAMEnon groupé éligible → branchetakeover-driveraprès le délai retail de 4 000 ms ;DriveWander.Profil natif occupant owner-only
Ajouter un profil resource-scoped
ambient-vehicle-occupant, distinct deambient-wanderetmission.Il doit :
Événements minimum :
EVENT_SHOT_FIRED;EVENT_DAMAGE, dontWEAPON_DROWNINGpour un occupant encore dans un véhicule submergé ;EVENT_VEHICLE_DAMAGE_WEAPON;EVENT_VEHICLE_DAMAGE_COLLISION;EVENT_VEHICLE_ON_FIRE;EVENT_VEHICLE_DIED;EVENT_CAR_UPSIDE_DOWN;EVENT_PED_ENTERED_MY_VEHICLE;EVENT_DRAGGED_OUT_CAR;EVENT_KNOCK_OFF_BIKEpour bike/BMX/quad ;EVENT_ON_FIREpour le ped lui-même, distinct du véhicule en feu.EVENT_SHOT_FIRED_WHIZZED_BYreste optionnel pour un decision maker custom : les decision makers civils ambient audités ne sélectionnent pas cette réponse.EVENT_DANGERreste P2/futur trafic aérien : les constructions retail retrouvées concernent principalement un appareil volant dangereusement bas, pas une explosion routière générique.EVENT_COP_CAR_BEING_STOLENreste conditionnel à une cohorte contenant réellement un occupantPED_TYPE_COP.Les événements géométriques locaux sont consommés seulement par l’owner. Les tirs/dégâts cross-owner utilisent un replay comportemental authentifié par le serveur. Chaque replay précise s’il est
decision-onlyou exige un état GTA réel ; aucun replay ne doit appliquer santé, dégâts, mort, crime ou wanted une seconde fois.Contrat d’audit retail avant implémentation
Les branches minimales incluent désormais aussi
takeover-driver,knocked-off-bike,escape-submerged,ped-on-fireetdying-in-car. Le véhicule exposesubmerged,drowning,recoveryActionetrecoveryDeadline. L’occupant distingueoriginalRoledecurrentRoleafin qu’un passager puisse devenir conducteur.Éligibilité et propagation par occupant
La réaction n’est jamais diffusée indistinctement à toute la cohorte :
EVENT_SHOT_FIREDEVENT_VEHICLE_DAMAGE_WEAPON/COLLISIONEVENT_DAMAGEdirectEVENT_VEHICLE_ON_FIREEVENT_PED_ENTERED_MY_VEHICLEEVENT_DANGEREVENT_GUN_AIMED_ATTASK_NONEen véhiculeEVENT_VEHICLE_COLLISIONconcerne le ped à pied heurté/évité par une voiture et ne remplace pasEVENT_VEHICLE_DAMAGE_COLLISION.Effets secondaires natifs et autorité
Avant CP2, renseigner pour chaque événement :
détection | décision | tâche | santé | mort | wanted/crime | propagation | autorité/fence.Cas obligatoires :
EVENT_VEHICLE_DIEDpeut mettre localement la santé du ped à zéro ;EVENT_KNOCK_OFF_BIKEcalcule chute et fall damage ;EVENT_ON_FIREexige unm_pFireréel et inflige des dégâts continus ;EVENT_DAMAGE/WEAPON_DROWNINGdans le véhicule ;EVENT_IN_WATERvient après la sortie physique ;MTA reste autoritaire sur santé, armour, dégâts, mort, crime et wanted. Les écritures natives sont neutralisées, capturées puis validées, ou réconciliées explicitement — jamais simplement rejouées.
Priorité, préemption et décision DM
La déduplication d’un même incident ne résout pas deux incidents distincts concurrents. Une matrice serveur doit couvrir dégâts fatals/mort face à noyade, feu et knock-off ; feu/retournement face à carjack ; carjack face à road rage/takeover ; destruction pendant une sortie ; owner loss pendant une préemption.
Un état terminal est monotone : aucune réaction tardive ne ressuscite un occupant ou ne réinstalle
DriveWander.Le client owner peut proposer la réponse choisie par GTA, mais le serveur la valide contre une allowlist
event × decision maker × siège/contexte, la conserve danslockedBranchet la réutilise au handoff.incident.seedne contrôle pas à lui seul le RNG global GTA ; aucun handoff ne refait la décision.Checkpoints supplémentaires
takeover-driver→waiting,leave-passenger-seat,enter-driver-seat,resume-cruise;knocked-off-bike→ snapshot physique, puislanded/recoveringoudead; handoff différé/normalisé pendant une chute non reconstructible ;escape-submerged→leave,in-water,drowningoudrown-in-car;ped-on-fire→ état feu authentifié,leave,fleeou terminal ;dying-in-car→stop/handbrake, délai retail borné,leave-and-dieoudead-in-seat.Snapshot et handoff sémantiques
Remplacer le snapshot limité à la cinématique par :
{ incidentId, revision, vehicle = { pose, velocity, angularVelocity, health, burning, overturned, engineState, }, occupants = { { ped, role, seat, pose, velocity, health, armour, branch, phase, target, taskRoot, taskLeaf, } } }Ne jamais cloner l’état interne arbitraire d’une tâche GTA. Chaque branche expose des checkpoints reconstructibles :
flee-in-vehicle→CarDriveMissionFleeScene;leave-vehicle→LeaveCaravec porte/siège et délai borné ;flee-on-foot→SmartFleeEntityouSmartFleePoint;road-rage→leave,threat,seek/fight/destroy,return-to-car;carjacked→entry-requested,dragging,victim-out,jacker-seated,flee-scene;scream-then-leave→ temps restant borné ou phaseleave;dead/incapacitated→ état terminal.Une animation physique non reconstructible peut différer brièvement le handoff, puis normaliser vers un checkpoint sûr. Sur owner quit, utiliser le dernier snapshot serveur validé.
APIs C++/Lua nécessaires
Profil et diagnostic
acquirePedNativeEventProfile(ped, "ambient-vehicle-occupant");getPedNativeEventResponseState(ped)retournant uniquement current event, root/leaf, cible résolue, véhicule/porte/siège et phase reconnue ;Replays comportementaux authentifiés
Chaque binding exige lease valide, éléments streamés, syncer de l’epoch, relations siège/véhicule/cible exactes, enums allowlistés et incident non consommé.
Constructeurs de reprise
Exposer seulement les tâches nécessaires aux checkpoints :
CarDriveMissionFleeScene;LeaveCarAndFlee;LeaveCarAndWander;ScreamInCarThenLeave;RoadRage;StealCar;LeaveCar, déjà partiellement disponibles.setPedDriveMissionactuel ne suffit pas : il est limité àMISSION_ESCORT_LEFTaprès validation spécifique.Carjack automobile joueur
Remplacer la suppression des occupants par :
carjack;EnterCarAsDriver;EVENT_PED_ENTERED_MY_VEHICLE, puisEVENT_DRAGGED_OUT_CAR;Cas requis : conducteur seul, passager avant/arrière, véhicule deux portes, porte bloquée, joueur interrompu/tué, deux joueurs concurrents et carjack pendant feu/retournement/handoff.
Accident, immobilisation et obstruction
Distinguer :
Les watchdogs actuels sont suspendus lorsqu’une branche valide progresse et restent le fallback en absence de progression.
Checkpoints ordonnés
CP1 — Contrat de cohorte et observabilité
Branches, phases, incidents, revisions, snapshots par occupant ; matrices d’éligibilité, effets secondaires, priorité/préemption et validation DM ; plusieurs oracles de tâches ; monitor/cleanup/leases adaptés sans nouveau comportement.
Sortie : tous les tests trafic actuels passent sans régression.
CP2 — Profil natif occupant et fencing
ambient-vehicle-occupant, auditIsPlayer, observers neutralisés, cleanup des event-response tasks, allowlistevent × DM × siège/contexte, verrouillage de branche et fences santé/mort/crime/wanted.Sortie : une seule décision native validée et verrouillée par incident, aucune tâche observer et aucun effet autoritatif appliqué deux fois.
CP3 — Feu, destruction, retournement, submersion et deux-roues
Sorties selon la matrice retail, ped-on-fire, noyade, mort dans le véhicule, knock-off bike/BMX/quad, véhicule abandonné, occupants à pied et handoff à chaque checkpoint reconstructible.
Sortie : aucun occupant attaché à un siège détruit ou submergé, aucun double dégât, aucune fausse perte de state et normalisation documentée des animations non reconstructibles.
CP4 — Tirs, dégâts et fuite
Replays cross-owner,
CarDriveMissionFleeScene, gates et clones informatifs propres aux passagers, validation DM, verrouillage de branche et déduplication.Sortie : exactement une branche serveur validée par tir/dégât et zéro réaction d’un passager inéligible derrière un conducteur valide.
CP5 — Collision, obstruction et road rage
Classification des incidents, reconstruction
RoadRage, confrontation/retour au véhicule et suspension du stuck recovery.Sortie : obstruction normale non destructive ; collision hostile capable d’atteindre les branches retail.
CP6 — Carjack automobile complet
Protocole GTA natif, anciens occupants conservés, concurrence gérée et transfert au trafic pédestre.
Sortie : le joueur obtient le siège par animation native et les occupants survivent/réagissent.
CP7 — Handoff exhaustif et owner loss
Snapshots/reprise de toutes les phases, takeover du volant par le passager avant éligible, deferred handoff borné, crash/quit et cleanup exact.
Sortie : A→B, B→A et owner quit passent sans reroll DM, double autorité ni tâche orpheline ; un véhicule sans conducteur tente la reprise retail avant abandon.
CP8 — Soak et activation production
Harness déterministe, incidents concurrents à densité production, métriques et feature flags par famille.
Tests d’acceptation
Ajouter :
Chaque scénario couvre un puis deux clients, owner quit, conducteur seul et plusieurs passagers, véhicules variés, epoch monotone, owner commun, incident unique, aucune réponse observer, sièges/portes cohérents, checkpoint valide au handoff et cleanup complet.
Invariants :
DriveWandersur ped sorti, mort ou carjacked ;cruiseuniquement avec conducteur valide au siège 0 ;lockedBranch;Risques
CPlayerPed: audit ciblé de chaque call siteIsPlayer;incident.seed: validation puis verrouillage de la branche owner ;test-resources.Dépendances
native-ped-trafficpour les occupants devenus walkers ;Game SAetClient Deathmatch,Release|Win32;./utils/clang-format.ps1après changements C++ et suivreutils/vm-build.ps1.Definition of Done
Les conducteurs et passagers éligibles selon la matrice retail peuvent quitter
DriveWanderpour toutes les branches couvertes ; le serveur valide puis verrouille la décision DM et arbitre les préemptions ; l’exécution reste strictement owner-only ; chaque branche survit au handoff ou à la perte d’owner sans reroll ; chaque acteur termine dans un lifecycle cohérent — reprise du volant, retour au trafic, trafic pédestre, abandon, incapacité ou mort — sans suppression artificielle, double simulation, double effet autoritatif ni tâche orpheline.Discipline de livraison
Chaque commit doit préciser le prompt/but, la motivation, le modèle d’autorité, les invariants de handoff, les décisions GTA auditées et les builds/scénarios runtime réellement testés.
Réaction aux sirènes et véhicules prioritaires
Ajouter une branche sémantique
yield-to-sirendéclenchée par le contexte autoritaireemergency-passagepublié par le système police (#91). Le client propriétaire du véhicule civil reste seul exécuteur et choisit une réaction native temporaire inspirée deCCarAI::MakeWayForCarWithSiren:TEMPACT_WAIT,TEMPACT_BRAKE,TEMPACT_SWIRVELEFT_STOPouTEMPACT_SWIRVERIGHT_STOPselon géométrie, direction et distance.À couvrir : conducteur valide, exclusions véhicules d’urgence/law-enforcement et branches incompatibles, passagers conservés, déduplication par unité+epoch+nonce, TTL/cooldown, retour sûr à la branche précédente, et checkpoint/reconstruction lors du handoff. Le watchdog anti-stuck doit reconnaître
yield-to-sirencomme une immobilisation intentionnelle et ne pas réinstallerDriveWanderni téléporter le véhicule.Ajouter
cartraffic test sirenyieldavec deux clients et propriétaires distincts pour le véhicule de police et le véhicule civil ; vérifier passage, freinage/écart, absence de double application, handoff pendant la manœuvre, reprise du trafic et cleanup.