Skip to content

NPC Combat Balancing

Overview

Combat Action Evaluator (CAE) files configure the utility-AI system that drives NPC combat. Each file defines how frequently the evaluator runs, a set of named available actions with scoring conditions, and one or more action sets that group which actions and basic attacks are active in a given combat state. The evaluator scores all available actions each tick and executes the highest-scoring one above a minimum threshold.

Combat AI Flow

flowchart TD;
A[NPC Enters Combat] --> B[Load Action Sets];
B --> C["Active Action Set<br>e.g. Default Combat"];
C --> D["Evaluator Tick<br>every N frames"];
D --> E[Score All Available Actions];
E --> F["Action: Melee Attack<br>Conditions → Score: 0.7"];
E --> G["Action: Ranged Attack<br>Conditions → Score: 0.3"];
E --> H["Action: Shield Block<br>Conditions → Score: 0.85"];
E --> I["Action: Flee<br>Conditions → Score: 0.2"];
F --> J["Highest Score<br>Above Threshold?"];
G --> J;
H --> J;
I --> J;
J -->|"Shield Block: 0.85"| K[Execute Shield Block];
J -->|"All below threshold"| L["Use Basic Attack<br>from ActionSet"];
K --> M{Action Complete};
L --> M;
M --> D;
style A fill:darkred,color:white;
style K fill:rebeccapurple,color:white;
style L fill:steelblue,color:white;

Action Set Transitions

flowchart LR;
A["Default Set<br>Melee + Block"] -->|"HP < 30%"| B["Enraged Set<br>Aggressive + No Block"];
A -->|"Target far away"| C["Ranged Set<br>Projectile + Retreat"];
C -->|"Target close"| A;
B -->|"Healing received"| A;
style A fill:darkgreen,color:white;
style B fill:darkred,color:white;
style C fill:steelblue,color:white;

File Location

  • Assets/Server/NPC/Balancing/Beast/*.json — Animal and creature CAEs
  • Assets/Server/NPC/Balancing/Intelligent/*.json — Faction NPC CAEs
  • Assets/Server/NPC/Balancing/CAE_Test_*.json — Test and reference CAEs

Schema

Top-level fields

FieldTypeRequiredDefaultDescription
Type"CombatActionEvaluator"YesIdentifies this as a CAE file.
TargetMemoryDurationnumberNoHow many seconds the NPC remembers a target after losing sight of it.
CombatActionEvaluatorobjectYesThe evaluator configuration block (see below).

CombatActionEvaluator block

FieldTypeRequiredDefaultDescription
RunConditionsarrayNoConditions evaluated before running the full evaluator. All must pass for the evaluator to proceed this tick.
MinRunUtilitynumberNoMinimum combined utility score from RunConditions required to run the evaluator.
MinActionUtilitynumberNoMinimum utility score an action must reach to be considered for execution.
AvailableActionsobjectYesNamed action definitions. Keys are action IDs referenced by ActionSets.
ActionSetsobjectYesNamed sets of active actions and basic attacks. The active set is controlled by the NPC’s combat sub-state.

RunConditions array entry

Each entry is a condition object (see NPC Decision Making). Commonly used:

TypePurpose
TimeSinceLastUsedThrottles how often the evaluator fires.
RandomiserAdds randomness to prevent perfectly predictable behavior.

AvailableActions entry

Each key in AvailableActions is a named action. The action object fields:

FieldTypeRequiredDefaultDescription
TypestringYesAction type. See action types table below.
DescriptionstringNoHuman-readable description of the action.
TargetstringNoTarget category: "Hostile", "Friendly", "Self".
WeaponSlotnumberNoWeapon slot index used for this action.
SubStatestringNoCombat sub-state to activate when this action runs (maps to an ActionSets key).
AbilitystringNoAbility ID to execute.
AttackDistanceRange[number, number]No[min, max] distance in blocks within which this action can be used.
PostExecuteDistanceRange[number, number]NoDistance range the NPC tries to maintain after executing.
ChargeFornumberNoSeconds to charge before executing.
WeightCoefficientnumberNo1.0Multiplier applied to this action’s final utility score.
InteractionVarsobjectNoInteraction variable overrides applied when this action fires.
ConditionsarrayNoScoring conditions for this specific action (see NPC Decision Making).

Action Types

TypeDescription
SelectBasicAttackTargetSelects a target for basic attacks using the conditions to score candidates.
AbilityExecutes a named ability (melee swing, ranged throw, heal, etc.).

ActionSets entry

Each key in ActionSets is a sub-state name (e.g. "Default", "Ranged", "Attack"). The value:

FieldTypeRequiredDefaultDescription
BasicAttacksobjectNoBasic attack configuration for this sub-state (see below).
Actionsstring[]NoList of action IDs from AvailableActions that are evaluated in this sub-state.

BasicAttacks object

FieldTypeRequiredDefaultDescription
Attacksstring[]YesAbility IDs used as basic attacks.
RandomisebooleanNofalseIf true, selects randomly from the Attacks list each cycle.
MaxRangenumberNoMaximum range in blocks for basic attacks.
TimeoutnumberNoSeconds to wait for the attack to land before cancelling.
CooldownRange[number, number]No[min, max] cooldown in seconds between basic attacks.
UseProjectedDistancebooleanNofalseIf true, uses projected (predicted) distance instead of current distance.
InteractionVarsobjectNoInteraction variable overrides for all basic attacks in this set.

Examples

Simple beast CAE (Rat)

A rat with a single bite attack, no special abilities:

{
"Type": "CombatActionEvaluator",
"TargetMemoryDuration": 10,
"CombatActionEvaluator": {
"RunConditions": [
{
"Type": "TimeSinceLastUsed",
"Curve": { "ResponseCurve": "Linear", "XRange": [0, 10] }
},
{
"Type": "Randomiser",
"MinValue": 0.9,
"MaxValue": 1
}
],
"MinRunUtility": 0.5,
"MinActionUtility": 0.01,
"AvailableActions": {
"SelectTarget": {
"Type": "SelectBasicAttackTarget",
"Description": "Select a target",
"Conditions": [
{
"Type": "TargetDistance",
"Curve": { "ResponseCurve": "SimpleDescendingLogistic", "XRange": [0, 15] }
}
]
}
},
"ActionSets": {
"Default": {
"BasicAttacks": {
"Attacks": ["Rat_Bite"],
"Randomise": false,
"MaxRange": 2,
"Timeout": 0.5,
"CooldownRange": [0.001, 0.001]
},
"Actions": ["SelectTarget"]
}
}
}
}

Intelligent NPC CAE (Goblin Scrapper) — multiple action sets

A goblin that switches between melee and ranged sub-states:

{
"Type": "CombatActionEvaluator",
"TargetMemoryDuration": 5,
"CombatActionEvaluator": {
"RunConditions": [
{
"Type": "TimeSinceLastUsed",
"Curve": { "ResponseCurve": "Linear", "XRange": [0, 5] }
},
{ "Type": "Randomiser", "MinValue": 0.9, "MaxValue": 1 }
],
"MinRunUtility": 0.5,
"MinActionUtility": 0.01,
"AvailableActions": {
"Melee": {
"Type": "Ability",
"Description": "Quick melee swing",
"WeaponSlot": 0,
"SubState": "Default",
"Ability": "Goblin_Scrapper_Attack",
"Target": "Hostile",
"AttackDistanceRange": [2.5, 2.5],
"PostExecuteDistanceRange": [2.5, 2.5],
"Conditions": [
{
"Type": "TimeSinceLastUsed",
"Curve": { "ResponseCurve": "Linear", "XRange": [0, 1] }
}
]
},
"Ranged": {
"Type": "Ability",
"Description": "Throw rubble from range",
"WeaponSlot": 0,
"SubState": "Ranged",
"Ability": "Goblin_Scrapper_Rubble_Throw",
"Target": "Hostile",
"AttackDistanceRange": [15, 15],
"PostExecuteDistanceRange": [2.5, 2.5],
"Conditions": [
{
"Type": "TimeSinceLastUsed",
"Curve": { "ResponseCurve": "Linear", "XRange": [0, 2] }
},
{
"Type": "TargetDistance",
"Curve": { "ResponseCurve": "SimpleLogistic", "XRange": [0, 15] }
}
]
}
},
"ActionSets": {
"Default": {
"BasicAttacks": {
"Attacks": ["Goblin_Scrapper_Attack"],
"Randomise": false,
"MaxRange": 2.5,
"Timeout": 0.5,
"CooldownRange": [0.001, 0.001]
},
"Actions": ["SwingDown", "Ranged"]
},
"Ranged": {
"BasicAttacks": {
"Attacks": ["Goblin_Scrapper_Rubble_Throw"],
"Randomise": false,
"MaxRange": 15,
"Timeout": 0.5,
"CooldownRange": [0.8, 2]
},
"Actions": ["Melee"]
}
}
}
}
  • NPC Decision Making — Condition types used in RunConditions and AvailableActions[*].Conditions
  • NPC Roles — Role files that reference CAE files via the _CombatConfig field in Modify
  • NPC Templates — Templates that wire up the combat evaluator via the Instructions tree