Skip to content

Game.MedicalAircraftAISystem

Assembly:
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
{{ Handles the AI and lifecycle of medical aircraft (helicopters/air ambulances) in the simulation. This system schedules a Burst-compiled chunk job (MedicalAircraftTickJob) that runs in parallel over all aircraft/ambulance entities and performs job-indexed ticking: path reset and pathfinding setup, dispatch handling (loading/unloading patients, selecting next dispatch), parking/return-to-depot logic, emergency state handling, blocker/parked-vehicle cleanup, and interaction with other game data (healthcare requests, hospitals, spawn locations, district lookup). The system integrates with PathfindSetupSystem (to enqueue pathfinding requests) and EndFrameBarrier (to obtain a parallel command buffer) and runs on a coarse update cadence (interval/offset). Intended for modders to understand how air ambulance behavior is implemented and where to hook or modify dispatch, pathfinding and parking logic. }}


Fields

  • private EndFrameBarrier m_EndFrameBarrier
    {{ Reference to the EndFrameBarrier system used to create a parallel EntityCommandBuffer for deferred entity/component changes produced by the job. The buffer is obtained during OnUpdate and passed into the job so modifications are recorded safely from worker threads. }}

  • private PathfindSetupSystem m_PathfindSetupSystem
    {{ Reference to the PathfindSetupSystem used to obtain a pathfinding queue writer (NativeQueue) that the job uses to schedule pathfind setup items for asynchronous pathfinding. }}

  • private EntityQuery m_VehicleQuery
    {{ EntityQuery matching air ambulances to be processed by this system. Query filters include Ambulance (read/write), AircraftCurrentLane (read/write), Owner, PrefabRef (read-only), PathOwner, Target and excludes components like Deleted, Temp, TripSource and OutOfControl. The query is required for the system to run. }}

  • private EntityArchetype m_HandleRequestArchetype
    {{ Archetype used to create temporary HandleRequest entities (with HandleRequest and Event components) that represent requests created by the system when it picks up or processes healthcare requests. Created in OnCreate. }}

  • private ComponentTypeSet m_MovingToParkedAircraftRemoveTypes
    {{ A ComponentTypeSet listing components to remove when an aircraft transitions from moving to parked (e.g. Moving, TransformFrame, InterpolatedTransform, AircraftNavigation, AircraftNavigationLane, AircraftCurrentLane, PathOwner, Target, Blocker, PathElement, PathInformation, ServiceDispatch). Used by command buffer calls in ParkAircraft. }}

  • private ComponentTypeSet m_MovingToParkedAddTypes
    {{ A ComponentTypeSet for components to add when parking (ParkedCar, Stopped, Updated). Used by command buffer calls in ParkAircraft. }}

  • private TypeHandle __TypeHandle
    {{ Internal helper struct containing all ComponentTypeHandle/BufferTypeHandle/ComponentLookup/BufferLookup instances used by the job. Set up in OnCreateForCompiler / __AssignHandles. This is compiler-generated scaffolding for fast access to component data in the scheduled job. }}


Properties

  • None
    {{ This system exposes no public properties. All state is internal and driven by job data, command buffers and referenced systems. }}

Constructors

  • public MedicalAircraftAISystem()
    {{ Default constructor. The system is initialized by the framework; most initialization occurs in OnCreate. The constructor is preserved for runtime usage. }}

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    {{ Returns the update interval in ticks; this system is scheduled at a coarse frequency to avoid running every simulation tick. The implementation returns 16. This means the system will run once every 16 simulation steps (subject to offset). Useful for modders to know for performance/behavior timing. }}

  • public override int GetUpdateOffset(SystemUpdatePhase phase)
    {{ Returns the offset to combine with the interval for scheduling; the implementation returns 10. Combined with the interval, this determines the exact update cadence. }}

  • [Preserve] protected override void OnCreate()
    {{ Sets up required systems and queries:

  • Retrieves EndFrameBarrier and PathfindSetupSystem references.
  • Creates m_VehicleQuery that targets ambulances/aircraft.
  • Creates m_HandleRequestArchetype for temporary HandleRequest entities.
  • Builds component type sets used when switching a vehicle to parked state.
  • Calls RequireForUpdate with the query so the system only runs when matching entities exist. This is where you would change the query to include/exclude extra components for custom aircraft behavior. }}

  • [Preserve] protected override void OnUpdate()
    {{ Schedules the Burst-compiled MedicalAircraftTickJob as a parallel, chunk-based job. It:

  • Populates the job's type handles, lookups and runtime data (RandomSeed, archetype, type sets).
  • Provides the job with a parallel EntityCommandBuffer from EndFrameBarrier.
  • Gets a parallel writer for the PathfindSetupSystem queue.
  • Schedules the job using m_VehicleQuery and wires dependencies so EndFrameBarrier and PathfindSetupSystem know about the job. This is the execution entry point that modders can use to inject changes to job parameters, or to schedule additional work before/after. }}

  • protected override void OnCreateForCompiler()
    {{ Compiler-time helper that assigns query/handle scaffolding used by the generated job code. Modders typically don't need to change this. }}

  • private struct MedicalAircraftTickJob : IJobChunk
    {{ The core per-chunk worker that processes aircraft entities. It's Burst compiled and contains:

  • Component type handles and lookups (EntityTypeHandle, ComponentTypeHandle, BufferTypeHandle, ComponentLookup, BufferLookup, EntityStorageInfoLookup).
  • RandomSeed and other read-only data.
  • m_CommandBuffer (EntityCommandBuffer.ParallelWriter) for deferred structural/ component changes.
  • m_PathfindQueue (NativeQueue.ParallelWriter) to enqueue pathfind requests.

Key methods inside the job: - Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask): iterates entities in a chunk, performs VehicleUtils.CheckUnspawned and calls Tick for each entity. - Tick(...): high-level tick per-vehicle that invokes: - CheckServiceDispatches: prune or pick dispatch requests. - ResetPath: update internal path information and set emergency flags. - Path stuck handling: resolve blockers, delete parked vehicles blocking the aircraft, clear stuck flags. - Path existence checks and handling when target no longer exists or pathfinding failed => either delete vehicle or ReturnToDepot. - End-of-path handling: unloading/loading patients, parking, selecting next dispatch or returning to depot. - Movement-state transitions: StopVehicle / StartVehicle (add/remove Moving/Stopped, TransformFrame, InterpolatedTransform). - Path requirement checks: VehicleUtils.RequireNewPath -> FindNewPath, or CheckParkingSpace when path is valid. - Dispatch selection and path-append logic (SelectNextDispatch), handling of HandleRequest creation and appending an existing path from a request. - TransportToHospital / ReturnToDepot and other helpers that set flags and targets.

The job encapsulates almost all AI logic for medical aircraft. Modders can examine or replace pieces by: - Replacing or altering the job code (advanced, requires recompilation/Burst). - Intercepting the pathfind queue from PathfindSetupSystem or modifying Create/HandleRequest archetype behavior to change how requests are processed. }}

  • void IJobChunk.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    {{ Explicit interface implementation that forwards to the job's Execute method. Included for completeness. }}

  • (Job internal helper methods — signatures only)

  • private void Tick(int jobIndex, Entity entity, Owner owner, PrefabRef prefabRef, PathInformation pathInformation, DynamicBuffer<AircraftNavigationLane> navigationLanes, DynamicBuffer<Passenger> passengers, DynamicBuffer<ServiceDispatch> serviceDispatches, bool isStopped, ref Random random, ref Game.Vehicles.Ambulance ambulance, ref Aircraft aircraft, ref AircraftCurrentLane currentLane, ref PathOwner pathOwner, ref Target target)
  • private void CheckParkingSpace(ref Aircraft aircraft, ref AircraftCurrentLane currentLane, ref PathOwner pathOwner)
  • private void ParkAircraft(int jobIndex, Entity entity, Owner owner, ref Aircraft aircraft, ref Game.Vehicles.Ambulance ambulance, ref AircraftCurrentLane currentLane)
  • private void StopVehicle(int jobIndex, Entity entity)
  • private void StartVehicle(int jobIndex, Entity entity)
  • private bool LoadPatients(int jobIndex, Entity entity, DynamicBuffer<Passenger> passengers, DynamicBuffer<ServiceDispatch> serviceDispatches, bool isStopped, ref Random random, ref Game.Vehicles.Ambulance ambulance, ref Target target)
  • private bool UnloadPatients(DynamicBuffer<Passenger> passengers, ref Game.Vehicles.Ambulance ambulance)
  • private void FindNewPath(Entity vehicleEntity, PrefabRef prefabRef, ref Game.Vehicles.Ambulance ambulance, ref Aircraft aircraft, ref AircraftCurrentLane currentLane, ref PathOwner pathOwner, ref Target target)
  • private Entity FindDistrict(Entity building)
  • private void CheckServiceDispatches(Entity vehicleEntity, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.Ambulance ambulance)
  • private bool SelectNextDispatch(int jobIndex, Entity vehicleEntity, DynamicBuffer<AircraftNavigationLane> navigationLanes, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.Ambulance ambulance, ref Aircraft aircraft, ref AircraftCurrentLane currentLane, ref PathOwner pathOwner, ref Target targetData)
  • private void TransportToHospital(Owner owner, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.Ambulance ambulance, ref Aircraft aircraft, ref PathOwner pathOwner, ref Target target)
  • private void ReturnToDepot(Owner owner, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.Ambulance ambulance, ref Aircraft aircraft, ref PathOwner pathOwner, ref Target target)
  • private void ResetPath(int jobIndex, Entity vehicleEntity, PathInformation pathInformation, DynamicBuffer<Passenger> passengers, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.Ambulance ambulance, ref Aircraft aircraft, ref AircraftCurrentLane currentLane, ref Target target) {{ These methods implement the granular behavior of the aircraft AI — dispatch matching, appending paths from service requests, emergency flagging, parked-space checks, and more. Modders can inspect or alter them to change loading/unloading rules, dispatch priorities, or parking transitions. }}

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();

    // Typical setup inside the system (taken from the system source).
    m_EndFrameBarrier = World.GetOrCreateSystemManaged<EndFrameBarrier>();
    m_PathfindSetupSystem = World.GetOrCreateSystemManaged<PathfindSetupSystem>();

    // Example: change the vehicle query to include/exclude custom components:
    // m_VehicleQuery = GetEntityQuery(ComponentType.ReadWrite<Game.Vehicles.Ambulance>(),
    //                                  ComponentType.ReadWrite<AircraftCurrentLane>(),
    //                                  ComponentType.ReadOnly<Owner>(),
    //                                  ComponentType.ReadOnly<PrefabRef>(),
    //                                  ComponentType.ReadWrite<PathOwner>(),
    //                                  ComponentType.ReadWrite<Target>(),
    //                                  ComponentType.Exclude<Deleted>(),
    //                                  ComponentType.Exclude<Temp>(),
    //                                  ComponentType.Exclude<TripSource>(),
    //                                  ComponentType.Exclude<OutOfControl>());

    RequireForUpdate(m_VehicleQuery);
}

{{ Example shows how the system acquires required systems and registers its query. To modify behavior, change the query, alter m_MovingToParked* type sets, or add additional logic in OnUpdate before scheduling the job. For advanced changes you can replace or modify MedicalAircraftTickJob to change per-entity logic, but remember to keep Burst and parallel safety in mind (use command buffers / lookups appropriately). }}