Skip to content

[P1][Singleplayer AI] Réactions complètes des conducteurs et passagers #92

Description

@Dryxio

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-driverwaiting, 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-submergedleave, in-water, drowning ou drown-in-car ;
  • ped-on-fire → état feu authentifié, leave, flee ou terminal ;
  • dying-in-carstop/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-vehicleCarDriveMissionFleeScene ;
  • leave-vehicleLeaveCar avec porte/siège et délai borné ;
  • flee-on-footSmartFleeEntity ou SmartFleePoint ;
  • road-rageleave, threat, seek/fight/destroy, return-to-car ;
  • carjackedentry-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 :

  1. détecter véhicule, siège et epoch ;
  2. suspendre l’entrée et ouvrir un incident carjack ;
  3. transférer atomiquement la cohorte vers le client du joueur entrant ;
  4. vérifier streaming, portes, sièges et relations ;
  5. relancer la vraie tâche GTA EnterCarAsDriver ;
  6. faire recevoir à la victime EVENT_PED_ENTERED_MY_VEHICLE, puis EVENT_DRAGGED_OUT_CAR ;
  7. suivre les milestones porte/victime/joueur ;
  8. laisser chaque passager choisir rester, sortir, fuir, combattre ou reprendre le véhicule ;
  9. faire sortir le véhicule du trafic après réussite, mais transférer les anciens occupants au lifecycle pédestre ;
  10. 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 :

  1. collision légère/navigation → laisser l’autopilot freiner/reculer/contourner ;
  2. obstruction persistante sans dégâts → phase native recovery/horn, sans stuck restart tant qu’elle progresse ;
  3. collision hostile avec dégâts → authentifier l’attaquant et laisser GTA choisir fuite/sortie/road rage/riposte ;
  4. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions