Configuration

Every ATG AI setting, its default, and how to override them for your server: garrison profiles, the response to an attack, civilians and AI pacing.

Where settings come from

Settings arrive in three layers, each overriding the one before.

Layer 1: defaults. Compiled into the mod. Every Default column on this page is the value the mod ships with, which is what the Workbench panel shows you. The mod’s own settings file carries only the three lists, the garrison profiles, the responders and the civilian prefabs, which cannot be expressed as script defaults.

Layer 2: an override in your own mod. In Workbench, with ATG AI among your loaded addons:

  1. Find Configs/ATG/AI/InitialSettings.conf in the Resource Browser.
  2. Right-click it → Override. Choose your own addon when asked where the override should live.
  3. Open your new override and change only the settings you care about.

Everything you leave alone keeps the mod’s default. Lists in an override stack with the mod’s own entries rather than replacing them, which is how a map mod adds a garrison profile or swaps the shipped one out.

Layer 3: a per-server JSON file. $profile:ATG/atg-ai.json on the server, applied key by key. Only active when ATG Core is loaded ahead of this mod. It needs no mod changes at all, and /atg reload re-reads it on a running server — see ATG Core configuration for what a reload reaches.

Writing the JSON file by hand

  • Booleans are true and false. A 1 is ignored, and the setting keeps the value it already had. Defaults on this page are listed as true/false, matching the tickboxes in Workbench.
  • Enums are written by name, e.g. VETERAN, not by number.
  • Resource paths carry a resource identity prefix in braces before the path. Take them from the Workbench picker rather than typing them.
  • Lists are replaced whole. Naming one replaces every entry, layer-2 additions from other mods included, so a list you touch has to be written out in full and every entry needs a $type naming its class. A mistyped $type gives you an entry that loads and then does nothing.

The complete file is at the bottom of this page.

Editing settings from the Game Master

Open Game Master, then Scenario properties, and pick the ATG AI tab. It carries the switches this mod expects to be flipped while a session is running, at the values the server is actually using.

RowSetting
Responsem_bResponseEnabled
Responds to shotsm_bResponseHearsShots
Ambushesm_bResponseAmbushEnabled
Civiliansm_bCiviliansEnabled
Civilians go in at nightm_bCivilianDayNight

Confirming the dialog puts the values live at once, writes them to $profile:ATG/atg-ai.json, and sends them to every connected player. Only settings that differ from the shipped ones are written, and the previous file is kept beside it as atg-ai.bak.json. Without ATG Core loaded there is no file to write: the change lasts until the restart, and the server log says so.

Writing needs the administrator role. Reading does not, so any Game Master may open the tab and look. A confirm from somebody without the role changes nothing, and the server log names who tried and what:

[ATG_AI] <player> changed <settings> from Scenario properties and was refused - changing this mod's settings needs the administrator role, and they hold roles <roles>. Nothing changed.

Everything else on this page is set in the file. The distances, timings and thresholds are deliberately left off the tab.

Turning a subsystem off

A switch turned off stops ATG AI starting anything new, and lets what is already out run its course. Nothing is despawned to make the change take hold.

  • m_bResponseEnabled: no position calls for help. Help already on its way still arrives.
  • m_bCiviliansEnabled: no town is populated. People already out stay until they leave on their own.

Turning one back on takes effect without a restart.

Spawning

SettingDefaultMeaning
m_iAiSpawnStaggerSec5Gap between AI groups arriving where many are placed at once. 0 is no pacing.

A garrison’s groups and a town’s residents arrive one at a time rather than together. Every man carries a uniform, a vest, a helmet, a weapon and its magazines, and a server comfortably inside its own frame budget can still hand a joining or nearby client more replicated state in one frame than that client can clear. The client reports that as its connection being dropped as flooded or stalled, which looks nothing like a spawning problem and sends you looking at the server.

The first group of a garrison and the first resident of a town are placed at once; only the ones behind them wait. So a garrison takes this long per group to be fully on its ground and a large town fills over a minute or two, both well before anybody arrives.

A group placed in answer to something a player has just done is never paced, whatever this is set to, because it is wanted standing there at the moment it is asked for: reinforcements, a hunting party, a relief section, or a named individual a scenario has put in a particular town. Zero switches the pacing off for everything else too.

Response

How a garrison under attack calls for help, hunts a distant shooter and gets ahead of a force that is leaving. What that looks like on an ATG Scenario server is on Reinforcements.

SettingDefaultMeaning
m_bResponseEnabledtrueMaster switch. Off, a position fields whatever it was placed with and nothing more.
m_bResponseHearsShotstrueWhether being shot at counts as coming under attack. Off, nothing responds until a defender dies.
m_fResponseStrengthCeiling1.5Most men alive at once, as a multiple of the garrison as placed. The server-performance brake.
m_iResponseCasualtyThreshold4Defenders killed since the last wave before more are called.
m_fResponseForceRatio1.5Attackers on the position per surviving defender before more are called.
m_iResponseWaveBaseSec60Shortest gap between waves.
m_fResponseWaveBackoff1.5How much longer each wave takes than the one before it.
m_iResponseWaveMaxSec900Longest a wave gap can grow to.
m_iResponseQuietDecaySec300How long without casualties before the backoff starts winding back.
m_iResponseWarningSec45Warning players get between the intercepted-comms message and help arriving.
m_fResponseSpawnMinM600Closest to the position help may appear. Never in view, whatever this says.
m_fResponseSpawnMaxM2500Furthest out to look for somewhere concealed.
m_fResponseSpawnStepM250How much the search widens each time a ring turns out to be in view.
m_fResponseMountThresholdM400Beyond this, help arrives in a vehicle rather than on foot. Keep it below the minimum above.
m_fResponseDebusM60How far short of its destination a mounted force stops and gets out.
m_fResponseDefendRadiusM60How much ground a force holds once it arrives. This is its leash, not a tolerance.
m_iResponseHuntCooldownSec180Shortest gap between hunting parties.
m_iResponseHuntDurationSec300How long a hunting party searches before giving up.
m_iResponseLingerSec120How long an off-map party waits after its hunt before deciding what to do.
m_fResponseWithdrawRadiusM60How close a withdrawing party must get to where it came in before it leaves.
m_fResponseHuntErrorMinM60Tightest a hunting party’s search area can ever be.
m_fResponseHuntErrorMaxM250Widest it can be, on a long first shot before any honing.
m_fResponseFlankOffsetM200How far to one side a hunting party swings before closing in.
m_fResponseHuntMinRangeM150How far outside the position the shooting must be before anyone is sent after it.
m_fResponseAvengeFraction0.5Share of the garrison as placed that must survive a finished position for it to come after you.
m_bResponseAmbushEnabledtrueWhether a force will try to get ahead of attackers who have broken contact and left.
m_iResponseAmbushLeadSec120How far ahead of a withdrawing force an ambush is set, as their own travel time.
m_fResponseAmbushSpawnMinM250Closest to the ambush point the party laying it may appear. Never in view, whatever this says.
m_iResponseAmbushHoldSec600How long an ambush party waits before giving up.
m_aResponders3The responses a position in contact can make, in the order it tries them. See below.

The ceiling is concurrent, not cumulative: help keeps coming, but never more than this multiple of the garrison is standing at once. Multiply m_iGarrisonStrengthMax by it, then by the number of positions held at once, to get the most AI that can be standing.

If nothing ever arrives in a vehicle, read the mounting distance against the minimum spawn distance. The concealment search usually succeeds on its first ring, so help is placed at almost exactly the minimum, and if the mounting distance is higher every wave walks the whole way with nothing in the log to say why.

The order responses are tried in

m_aResponders is the list a position in contact works down. It stops at the first entry that sends something, so an earlier entry is preferred over a later one, and removing an entry means that response is never made.

$typeSends
ATG_AIAmbushResponderA party ahead of attackers who have broken contact and are leaving.
ATG_AIHuntResponderThe garrison’s own detachment, or a party from off the map, after a distant shooter.
ATG_AIReinforceResponderMore men onto the position. Never once the position is finished with.

The mod ships them in that order. An ambush only goes out when attackers have broken contact and their heading can be read, so trying it first costs nothing while a fight is still on.

Other mods add entries here. ATG Scenario adds ATG_ScenarioAssaultWaveResponder, which attacks a Defend posting players have taken over. An entry like that can claim a position outright, so on a posting it is the only one tried, wherever it sits in the list. A JSON file that sets this list must keep it: the file replaces the whole list, entries added by other mods included, and a posting with no assault responder is never attacked.

{
  "m_aResponders": [
    { "$type": "ATG_AIAmbushResponder" },
    { "$type": "ATG_AIHuntResponder" },
    { "$type": "ATG_AIReinforceResponder" },
    { "$type": "ATG_ScenarioAssaultWaveResponder" }
  ]
}

Garrison

Who defends a position, and how dangerous they are. Where the men end up standing and what they do there is on Garrisons.

SettingDefaultMeaning
m_aGarrisonProfiles(USSR regulars)Forces that can defend. One is drawn per garrison, weighted. With none, no garrison.
m_iGarrisonStrengthMax40Hard ceiling on men in one garrison, whatever the ladder and player scaling ask for.

Difficulty is meant to come from who turns up and how good they are, not from how many bodies there are. Headcount costs server performance and makes a fight tedious rather than dangerous; skill and composition cost nothing. So player count scales the size of a fight, while the profile decides how hard it is.

A garrison is budgeted in men, not groups. Groups are drawn from the profile until the budget is filled, and the group that would overshoot it is trimmed to fit, which lets one profile list sentry teams and rifle squads together.

The shipped profile

The mod ships one profile, USSR regulars, built on the base game’s USSR groups, so a garrison is defended out of the box. It cannot be printed in the complete file below, because it arrives as a reference to a config file rather than as inline values.

To replace it in your own mod, override Configs/ATG/AI/InitialSettings.conf and re-parent its profile entry onto a profile of your own; to add one alongside it, add an entry. Both are done in the Workbench panel. In the JSON, write every profile you want out in full, the shape below.

Garrison profiles

Each entry has $type ATG_AIGarrisonProfile.

FieldDefaultMeaning
m_sName(empty)Name for logs. Not shown to players.
m_iMinTier / m_iMaxTier0 / -1Tier range this profile is valid for. -1 for no upper limit.
m_fWeight1Relative likelihood among profiles valid at the current tier.
m_aGroupPrefabs(empty)AI group prefabs; one is drawn at random per group spawned. Sizes may differ freely.
m_aTiers(empty)How strong and how well trained this force is at each tier. See below.
m_fPerceptionFactor1How quickly they notice you. Above 1 is sharper. Set per profile, not per tier.
m_bCanCallResponsetrueWhether this force can call for help. Off for opposition meant to be on its own.
m_aResponseGroups(empty)Who comes when it calls. Empty draws from the group list above.
m_aVehicles(empty)What it drives. With none, it stays on foot and help comes only from walking range.
m_iHuntReserve4Fewest men that may ever be left holding the position.
m_fHuntReserveFraction0.4Share of the garrison as placed that must stay behind. The larger of the two wins.
m_bHunkerWhileHuntingtrueWhether the men left behind hold their fire until something threatens them.
m_sArmourResponseGroup(empty)Group sent after somebody in a vehicle: an anti-tank team. Empty draws at random.
m_sMortarEmplacement(empty)Emplacement set up against somebody gone to ground indoors. Empty uses the default.

The reserve is measured against the garrison as placed rather than against who is still alive, so casualties make hunting harder rather than easier.

m_sMortarEmplacement must be a composition holding both a mortar and an ammo box. The base game’s USSR, US and FIA mortar placements qualify; a bare mortar stands silent, because the crew draw every round from a nearby arsenal.

The skill ladder runs NONE, NOOB, ROOKIE, REGULAR, VETERAN, EXPERT, CYLON, the last deliberately superhuman. Stepping a profile up the ladder as tiers rise is the cheapest way to make later fights harder.

Tier bounds are what let opposition change character rather than merely grow. Retiring a light profile at a given tier while a heavier one becomes available produces a genuine shift in who you are fighting, and overlapping the ranges gives a transition period where either might turn up.

The tier ladder

Each entry in m_aTiers has $type ATG_AIGarrisonTier. List a band wherever something changes; the highest band the faction has reached wins. Below every band listed, the lowest band applies. A profile with no bands fields nobody, and says so in the log.

FieldDefaultMeaning
m_iTier0Tier this band takes effect at.
m_iStrength8Men fielded at this tier, before player scaling.
m_fMenPerPlayer2Extra men per connected player at this tier.
m_eAISkillREGULARHow competent they are in a fight at this tier.

Strength and skill share a band because they trade against each other: a rung that steps the skill up while dropping the headcount is a harder fight that costs the server less.

Response groups

Each entry in m_aResponseGroups has $type ATG_AIGarrisonResponseGroup.

FieldDefaultMeaning
m_sGroupPrefab(empty)Group to send. Its strength is read from the prefab.
m_fWeight1Relative likelihood against the other entries. 0 retires it.
m_iPurposes0Which calls for help it may answer. 0 answers every call.

In Workbench the purposes are tick boxes. In the JSON they are one number, the sum of the ones wanted: Reinforce 1, Hunt 2, Exfil 4, Ambush 8, Assault 16, Avenge 32, HVT 64, Patrol 128. Hunt and Exfil together is 6. A call no entry is ticked for is answered from the profile’s own group list, so ticking only Hunt and Exfil on a few better-equipped squads gives those two calls squads of their own and leaves the rest as they were.

Vehicles

Each entry in m_aVehicles has $type ATG_AIGarrisonVehicle.

FieldDefaultMeaning
m_sVehiclePrefab(empty)The vehicle.
m_iSeats8How many men it may carry. Declared, so a truck can move fewer than it seats.
m_fWeight1Relative likelihood against the other vehicles.
m_iMinTier / m_iMaxTier0 / -1Tier range it can be fielded in. -1 for no upper limit.
m_bParkWithGarrisontruePark one with the garrison, to mount up and go hunting. Players can steal it.
m_bCarriesReinforcementstrueUse it to bring help in.
m_bManTurrettruePut a gunner behind its gun, from the prefab’s own crew.

A tier range lets a force’s motor pool grow with the campaign without a profile per tier. The shipped USSR profile runs jeeps and an open lorry from the start, a second jeep from tier 2, a covered lorry from tier 3, a BRDM from tier 4 and a BTR-70 from tier 5.

A parked gunner is one man on top of the garrison’s strength, and he holds the position like anyone else: it cannot be cleared while he is alive at his gun. A gunner on a wave’s transport belongs to the wave. An unarmed vehicle ignores the flag, so it can stay on for every entry.

AI cannot fly. Listing a helicopter will not give you an air response.

Fortifications the garrison mans

A garrison puts pairs of men on the guns, structures and posts standing on its ground. Guns and posts say what they are; a bunker does not, so the structures are a list, Configs/ATG/AI/GarrisonPosts.conf. It names the base game’s bunkers, sandbag bunkers, MG nests and small towers, and anything built from one of them counts as well.

A mod that ships fortifications of its own adds them by overriding that config in Workbench, the same way as InitialSettings.conf above, and listing its own prefabs. Overrides stack, so the base game’s entries stay.

A complete profile

{
  "m_aGarrisonProfiles": [
    {
      "$type": "ATG_AIGarrisonProfile",
      "m_sName": "Regulars",
      "m_iMinTier": 0,
      "m_iMaxTier": -1,
      "m_fWeight": 1,
      "m_fPerceptionFactor": 1,
      "m_bCanCallResponse": true,
      "m_iHuntReserve": 4,
      "m_fHuntReserveFraction": 0.4,
      "m_bHunkerWhileHunting": true,
      "m_aGroupPrefabs": [
        "{E552DABF3636C2AD}Prefabs/Groups/OPFOR/Group_USSR_RifleSquad.et"
      ],
      "m_aResponseGroups": [
        {
          "$type": "ATG_AIGarrisonResponseGroup",
          "m_sGroupPrefab": "{96BAB56E6558788E}Prefabs/Groups/OPFOR/Group_USSR_Team_AT.et",
          "m_fWeight": 1,
          "m_iPurposes": 6
        }
      ],
      "m_aVehicles": [
        {
          "$type": "ATG_AIGarrisonVehicle",
          "m_sVehiclePrefab": "{D9B91FAB817A6033}Prefabs/Vehicles/Wheeled/Ural4320/Ural4320_transport_covered.et",
          "m_iSeats": 12,
          "m_iMinTier": 3,
          "m_iMaxTier": -1,
          "m_fWeight": 3,
          "m_bParkWithGarrison": false,
          "m_bCarriesReinforcements": true,
          "m_bManTurret": true
        },
        {
          "$type": "ATG_AIGarrisonVehicle",
          "m_sVehiclePrefab": "{0B4DEA8078B78A9B}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469_PKM.et",
          "m_iSeats": 4,
          "m_iMinTier": 0,
          "m_iMaxTier": -1,
          "m_fWeight": 2,
          "m_bParkWithGarrison": true,
          "m_bCarriesReinforcements": true,
          "m_bManTurret": true
        }
      ],
      "m_aTiers": [
        {
          "$type": "ATG_AIGarrisonTier",
          "m_iTier": 1,
          "m_iStrength": 8,
          "m_fMenPerPlayer": 2,
          "m_eAISkill": "REGULAR"
        },
        {
          "$type": "ATG_AIGarrisonTier",
          "m_iTier": 4,
          "m_iStrength": 6,
          "m_fMenPerPlayer": 2,
          "m_eAISkill": "VETERAN"
        }
      ]
    }
  ]
}

Naming m_aGarrisonProfiles with an empty array leaves every position undefended, and on ATG Scenario, Clear area objectives stop being placed at all.

Civilians

Who lives in the towns, how many, and when they are out. The towns themselves come from the scenario mod: on ATG Scenario they are its zones. What the people in them do is on Civilians.

SettingDefaultMeaning
m_bCiviliansEnabledtrueMaster switch. Off leaves every town empty and costs nothing.
m_aCivilianPrefabs4 CIVCharacter prefabs to draw from. Emptying it places nobody.
m_sCivilianFactionKeyCIVFaction whose name tags are suppressed. Must match what the prefabs carry. Empty keeps tags.
m_fCiviliansPer100M4People per 100 m of a town’s radius. The main cost dial: it multiplies across every town.
m_iCiviliansMin2Fewest a town will hold. Below about two, nowhere reads as inhabited.
m_iCiviliansMax16Most one town may hold, whatever the scaling works out to. 0 means no ceiling.
m_fCivilianSpawnDistanceM600How close a player must come to a town’s edge before its people are placed.
m_fCivilianDespawnDistanceM900How far every player must be from the edge before they are taken away.
m_fCivilianWanderRadiusM60How far somebody wanders from their own house.
m_bCivilianDayNighttrueWhether a share of them go in for the night. Off, everybody wanders around the clock.
m_fCivilianNightIndoorsFraction0.6Share who stay in after dark. The rest keep wandering.

Population is the rate multiplied by the town’s radius, then held between the floor and the ceiling, so the ceiling bounds one very large town and the rate bounds your server.

The prefabs are character prefabs, not groups: each civilian gets a group of their own and takes their faction from the prefab. The mod ships the base game’s generic civilian, businessman, dockworker and construction worker.

ATG Scenario reads the two distances for one more thing: a base capture’s standing garrison is on the ground while a player is inside the spawn distance, and gone once everyone is past the despawn distance.

If nobody appears

The server log says which reason applies at startup:

[ATG_AI] No civilian prefabs configured - none will be placed until the list has one
[ATG_AI] Civilians switched off in the settings - 6 town(s), and none fills until they are switched on

A healthy start names how many towns took part:

[ATG_AI] Civilians active - 6 town(s), 4 per 100m of radius (min 2, max 16), spawning within 600m, day/night 1

At verbose each town reports itself as it fills and stands down, with the number of houses it found. If people appear but every one of them is on the outskirts, the town’s buildings are not being recognised as somewhere anyone could live, and that house count is what to look at.

Logging

SettingDefaultMeaning
m_iLogVerbosity-1How much this mod writes to the server log.
ValueLevelWhat it prints
-1inheritUse the level set in ATG Core, or normal where Core is not loaded.
0quietWarnings and errors only.
1normalWhat each mechanic decided, once per event.
2verboseThe detail behind those decisions while a mechanic runs.
3surveyA line per group as lists are built, plus repeating reports.

The levels are cumulative, and warnings and errors are never suppressed at any level. Lines from this mod start [ATG_AI], including the ones about garrisons, reinforcements and civilians on an ATG Scenario server, so this is the dial for those rather than ATG Scenario’s.

The complete settings file

Every setting, at the value the mod ships with, as <profile>/ATG/atg-ai.json. Delete the lines you do not want to change: a key you leave out keeps its shipped value. Keep a list intact if you keep it at all, since it replaces rather than merges.

{
  "m_iAiSpawnStaggerSec": 5,

  "m_iGarrisonStrengthMax": 40,

  "m_bResponseEnabled": true,
  "m_bResponseHearsShots": true,
  "m_fResponseStrengthCeiling": 1.5,
  "m_iResponseCasualtyThreshold": 4,
  "m_fResponseForceRatio": 1.5,
  "m_iResponseWaveBaseSec": 60,
  "m_fResponseWaveBackoff": 1.5,
  "m_iResponseWaveMaxSec": 900,
  "m_iResponseQuietDecaySec": 300,
  "m_iResponseWarningSec": 45,
  "m_fResponseSpawnMinM": 600,
  "m_fResponseSpawnMaxM": 2500,
  "m_fResponseSpawnStepM": 250,
  "m_fResponseMountThresholdM": 400,
  "m_fResponseDebusM": 60,
  "m_fResponseDefendRadiusM": 60,
  "m_iResponseHuntCooldownSec": 180,
  "m_iResponseHuntDurationSec": 300,
  "m_iResponseLingerSec": 120,
  "m_fResponseWithdrawRadiusM": 60,
  "m_fResponseHuntErrorMinM": 60,
  "m_fResponseHuntErrorMaxM": 250,
  "m_fResponseFlankOffsetM": 200,
  "m_fResponseHuntMinRangeM": 150,
  "m_fResponseAvengeFraction": 0.5,
  "m_bResponseAmbushEnabled": true,
  "m_iResponseAmbushLeadSec": 120,
  "m_fResponseAmbushSpawnMinM": 250,
  "m_iResponseAmbushHoldSec": 600,
  "m_aResponders": [
    { "$type": "ATG_AIAmbushResponder" },
    { "$type": "ATG_AIHuntResponder" },
    { "$type": "ATG_AIReinforceResponder" },
    { "$type": "ATG_ScenarioAssaultWaveResponder" }
  ],

  "m_bCiviliansEnabled": true,
  "m_aCivilianPrefabs": [
    "{22E43956740A6794}Prefabs/Characters/Factions/CIV/GenericCivilians/Character_CIV_Randomized.et",
    "{B3AB6D12D247DDB5}Prefabs/Characters/Factions/CIV/Businessman/Character_CIV_Businessman_Randomized.et",
    "{5882AE7A4543AFB4}Prefabs/Characters/Factions/CIV/Dockworker/Character_CIV_Dockworker_Randomized.et",
    "{D97EAE64721478F3}Prefabs/Characters/Factions/CIV/ConstructionWorker/Character_CIV_ConstructionWorker_Randomized.et"
  ],
  "m_sCivilianFactionKey": "CIV",
  "m_fCiviliansPer100M": 4,
  "m_iCiviliansMin": 2,
  "m_iCiviliansMax": 16,
  "m_fCivilianSpawnDistanceM": 600,
  "m_fCivilianDespawnDistanceM": 900,
  "m_fCivilianWanderRadiusM": 60,
  "m_bCivilianDayNight": true,
  "m_fCivilianNightIndoorsFraction": 0.6,

  "m_iLogVerbosity": -1
}

Three things above are not copy-and-go:

  • m_aGarrisonProfiles is missing on purpose. The shipped profile is a reference to a config file and cannot be written inline. Leave the key out to keep it, or write your own profiles in full from A complete profile.
  • m_aResponders lists ATG Scenario’s assault responder. Drop that entry on a server without ATG Scenario, where the class does not exist; keep it on one with.
  • m_aCivilianPrefabs ships the four base game civilians. Replace them if your setting wants different people, with resource strings taken from the Workbench picker.