Skip to content

Game.Simulation.CommercialAISystem

Assembly: Assembly-CSharp (game code)
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
CommercialAISystem updates commercial (service/retail) company AI logic on a periodic schedule. It schedules a parallel IJobChunk (CommercialCompanyAITickJob) that iterates over company entities and: - adjusts the WorkProvider.max workers based on property/service availability and building capacity, - enables PropertySeeker on companies that can afford to look for property (based on company worth), - deletes very poor companies that have no renters and are below worth thresholds, - uses many Prefab/Component lookups (building, prefab, service company data, resource data, trucks, layouts) and the ResourceSystem prefabs. The system requires EconomyParameterData and company-related components and synchronizes with the simulation frame using UpdateFrame and an EndFrameBarrier command buffer.


Fields

  • public static readonly int kUpdatesPerDay = 32
    Constant: number of updates per in-game day used to compute update frames.

  • public static readonly int kLowestCompanyWorth = -10000
    Constant: threshold for deleting very poor companies (companies below this total worth may be removed).

  • public static readonly int kMinimumEmployee = 5
    Constant: minimum employee count used when adjusting WorkProvider.m_MaxWorkers.

  • private EntityQuery m_EconomyParameterQuery
    Query used to fetch the EconomyParameterData singleton required for job parameters.

  • private SimulationSystem m_SimulationSystem
    Reference to the SimulationSystem (used to compute update frames).

  • private EndFrameBarrier m_EndFrameBarrier
    Reference to EndFrameBarrier used to create an EntityCommandBuffer.ParallelWriter for safe structural changes from the job.

  • private ResourceSystem m_ResourceSystem
    Reference to the ResourceSystem (provides resource prefab access and reader registrations).

  • private EntityQuery m_CompanyQuery
    Query selecting commercial/service companies to be processed by the job. It requires ServiceAvailable, WorkProvider, UpdateFrame, PrefabRef, Resources and excludes Created/Deleted.

  • private TypeHandle __TypeHandle
    Internal cached handles for entity/component/buffer/shared component lookups used when scheduling the job.

Properties

  • None (the system exposes no public properties).

Constructors

  • public CommercialAISystem()
    Default constructor. Systems in this codebase typically rely on OnCreate for initialization rather than constructor logic.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the update interval in ticks for scheduling this system. Uses kUpdatesPerDay and a hardcoded factor so the system runs periodically across the game's update frames.

  • protected override void OnCreate()
    Initializes the system: obtains references to SimulationSystem, EndFrameBarrier, ResourceSystem; creates EntityQueries (m_EconomyParameterQuery, m_CompanyQuery); marks required queries for update (RequireForUpdate) so the system only runs when relevant data exists.

  • protected override void OnStopRunning()
    Teardown hook. Currently calls base.OnStopRunning() and has no additional logic, but kept for lifecycle completeness.

  • protected override void OnUpdate()
    Main update entry. Computes the current update frame index via SimulationUtils.GetUpdateFrame, creates and populates a CommercialCompanyAITickJob with component/type handles, prefab lookups, resource prefabs, random seed and EconomyParameterData, then schedules the job in parallel using JobChunkExtensions.ScheduleParallel. Adds the produced job dependency to the EndFrameBarrier and registers a prefabs reader with the ResourceSystem.

Key behaviors performed by the scheduled job: - Filters chunks by matching UpdateFrame.shared component index to the computed update frame. - For each company entity: - Reads prefab and service/company data. - If the company is a renter (PropertyRenter present), compute suitable maximum workers using CompanyUtils.GetCommercialMaxFittingWorkers and adjust WorkProvider.m_MaxWorkers up or down depending on service availability and current worker counts. - For entities without an enabled PropertySeeker, occasionally (randomized) checks company worth via EconomyUtils.GetCompanyTotalWorth. If worth > kLowestCompanyWorth, enables PropertySeeker; otherwise, if the company is not a renter, marks the entity Deleted via command buffer. - Uses many read-only lookups (building/prefab/commodity data, layouts, trucks) and buffer accessors for company resources, employees and owned vehicles.

  • private void __AssignQueries(ref SystemState state)
    Internal method used by compiler-generated OnCreateForCompiler to initialize/validate query state. This implementation currently creates and disposes an empty query builder (compiler artifact).

  • protected override void OnCreateForCompiler()
    Compiler-time initialization: assigns query handles and calls __TypeHandle.__AssignHandles to populate internal type handles for later scheduling.

  • Nested type: CommercialCompanyAITickJob : IJobChunk
    Job struct used to process company archetype chunks in parallel. Contains handles for EntityType, ComponentType and BufferType, many ComponentLookup/BufferLookup instances, RandomSeed, EconomyParameterData, update frame index and an EntityCommandBuffer.ParallelWriter. Its Execute method contains the per-entity logic described above.

  • Nested type: TypeHandle
    Compiler helper struct that stores component/entity/buffer/shared component handles and provides __AssignHandles(ref SystemState) to fetch those handles from the system state.

Usage Example

// This system is a world/system class: it initializes itself in OnCreate and schedules a job in OnUpdate.
// Example showing how OnCreate sets up required queries (simplified - the real system does more):
[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_SimulationSystem = World.GetOrCreateSystemManaged<SimulationSystem>();
    m_EndFrameBarrier = World.GetOrCreateSystemManaged<EndFrameBarrier>();
    m_ResourceSystem = World.GetOrCreateSystemManaged<ResourceSystem>();
    m_EconomyParameterQuery = GetEntityQuery(ComponentType.ReadOnly<EconomyParameterData>());
    m_CompanyQuery = GetEntityQuery(
        ComponentType.ReadOnly<ServiceAvailable>(),
        ComponentType.ReadWrite<WorkProvider>(),
        ComponentType.ReadOnly<UpdateFrame>(),
        ComponentType.ReadOnly<PrefabRef>(),
        ComponentType.ReadOnly<Resources>(),
        ComponentType.ReadOnly<Game.Companies.ProcessingCompany>(),
        ComponentType.ReadOnly<TradeCost>(),
        ComponentType.Exclude<Created>(),
        ComponentType.Exclude<Deleted>()
    );
    RequireForUpdate(m_CompanyQuery);
    RequireForUpdate(m_EconomyParameterQuery);
}

Notes and modding considerations: - The system relies heavily on computed update frames (UpdateFrame shared component). If you add or change update frame logic you must ensure companies receive the correct UpdateFrame values. - The job performs structural changes (AddComponent/Delete/SetComponentEnabled) via an EntityCommandBuffer.ParallelWriter created from EndFrameBarrier — modifications are deferred to end of frame. - Many lookups are read-only; adding new writable component usage would require altering the TypeHandle and job data accordingly. - If you want to modify company AI behavior, consider creating a patch or custom system that runs at a different update interval or intercepts the relevant components (WorkProvider, PropertySeeker, PropertyRenter, ServiceAvailable).