Valtus Targeting Bug on Vortex Beast
Overview
The purchasable Dreadnought summon ("Valtus") in Siege decides which enemy to attack by scoring every enemy he's aware of as desirability x powerRating-weight and attacks the highest, favoring dangerous enemies out at range.
The reason Valtus typically will not attack the Vortex Beast until all other enemies are eliminated from the map is because the Vortex Beast is stamped powerRating = 1 (fodder level), so Valtus ignores it until almost nothing else is left. Valtus's target picker is set in npc_dreadnought_server.cls:
prop_enemy_processor_mgs -> selectionController (EnemyProcessorControllerSelection)
-> selectionUtility = UtilityFunctionEnemySelectionByPowerLevelThe controller scores every enemy Valtus is aware of and attacks the highest scorer, re-evaluating continuously. The score is a single multiplication:
score(enemy) = Desirability(enemy) x PowerWeight(enemy)Desirability =
UtilityFunctionDefaultEnemySelection(aggressiveness sub-scores + decision stickiness), roughly 0-1.PowerWeight = the enemy's
powerRatingrun through a spline, giving 0.1-1.0.
Because it is a product and PowerWeight differs per enemy, the power term re-ranks targets: a dangerous enemy at range can outscore a weak one nearby. It cannot, however, resurrect a target whose desirability is ~0.
Target Desirability
Captioned "Default Selection With Aggressiveness Override" (UtilityFunctionDefaultEnemySelection).
Its core is UtilityFunctionAggressiveness, a weighted average of three sub-scores:
Desirability_core = (5 x Distance + 2 x Busyness + 3 x Offensiveness) / 10Sub-score (weight) | Input variable | Meaning | Curve |
|---|---|---|---|
Distance (5) |
| how far the target is | "Decay Closer" |
Busyness (2) |
| combined strength of OTHER attackers already on the target | "Decay With Power Level" |
Offensiveness (3) |
| recent damage that enemy dealt to Valtus | "Raise With Damage" |
The Distance curve (Valtus favors range)
Valtus's recipe overrides the Distance sub-score with a "Decay Closer" spline[0, 0.1, 80, 1]. On raw meters-to-target:
Distance | Distance sub-score |
|---|---|
0 m | 0.10 (min) |
20 m | 0.325 |
40 m | 0.55 |
60 m | 0.775 |
80 m+ | 1.00 (max, clamped) |
So the closer an enemy is, the lower this sub-score; the farther (out to 80 m), the higher. This fits Valtus as a long-range gatling unit (perfectAttackDistance = 60). Ordinary enemies use the opposite base default in the same file - a "Decay Further" curve [0,1, 7,1, 16,0.8, 40,0.6, 70,0.2] that prefers close targets.
Decision stickiness
Desirability is wrapped in UtilityFunctionDecisionStickiness with StickinessDuration = 7 and StickinessFadeDuration = 3: once Valtus commits to a target, that target keeps a loyalty bonus for 7 s, fading over the next 3 s. This stops frame-to-frame flip-flopping; a much higher-scoring target can still pull him off early.
Enemy PowerWeight
FloatValueProviderTargetPowerLevel reads the target's powerRating (a fixed value per enemy archetype), then a SplineLinear1d with points [0, 0.1, 100, 1] converts it to a multiplier:
PowerWeight = clamp(0.1 + 0.009 x powerRating, 0.1, 1.0)So powerRating 0 -> 0.10, 1 -> 0.109, 21 -> 0.289, 100+ -> 1.00 (clamped).
Operations reads archetypes_library.sso while Siege merges archetypes_library_hordemode.sso overrides on top. In the tables below, a - in the Siege PR column means the Siege library declares no powerRating for that archetype, so the base value carries through. It does NOT necessarily mean the archetype is absent from the Siege library, several entries there exist only to swap in a _hordemode_ actor class and set no stats at all (the Vortex Beast is one).
powerRating is a separate axis from threatClass (tier): the Vortex Beast is threatClass = BOSS but powerRating = 1. Tier drives HP/damage difficulty scaling; powerRating drives AI target priority (and likely spawn-budget cost).
Tyranids
Enemy | Tier | Base PR | Siege PR | Ops weight | Siege weight |
|---|---|---|---|---|---|
Hormagaunt / Sergeant | FODDER | 1 | - | 0.109 | 0.109 |
Termagant | COMMON | 2 | - | 0.118 | 0.118 |
Spore Mine / Acid Mine | COMMON | 2 | - | 0.118 | 0.118 |
Gargoyle | (unset) | ~0 | - | 0.10 | 0.10 |
Tyranid Warrior (all 5 variants) | ELITE | 18 | - | 0.262 | 0.262 |
Zoanthrope | SPECIAL | 20 | - | 0.280 | 0.280 |
Ravener / Lictor / Biovore | SPECIAL | 30 | - | 0.370 | 0.370 |
Lictor Alpha ( | MINIBOSS | 50 | - | 0.550 | 0.550 |
Neurothrope | MINIBOSS | 150 | 100 | 1.00 | 1.00 |
Carnifex | MINIBOSS | 150 | 100 | 1.00 | 1.00 |
Chaos (Thousand Sons)
Enemy | Tier | Base PR | Siege PR | Ops weight | Siege weight |
|---|---|---|---|---|---|
Cultist / Cultist Sniper | FODDER | 1 | - | 0.109 | 0.109 |
Tzaangor | COMMON | 5 | 2 | 0.145 | 0.118 |
Tzaangor Shieldless | COMMON | 5 | 1 | 0.145 | 0.109 |
Tzaangor Gunner | (unset tier) | 5 | - | 0.145 | 0.145 |
Tzaangor Spearman | ELITE | 18 | - | 0.262 | 0.262 |
Rubric Marine | ELITE | 18 | 21 | 0.262 | 0.289 |
Rubric Marine Flamer | ELITE | 25 | - | 0.325 | 0.325 |
Chaos Spawn | ELITE | 21 | - | 0.289 | 0.289 |
Occult Terminator (Melee/Ranged) | SPECIAL | 30 | - | 0.370 | 0.370 |
Lesser Sorcerer | SPECIAL | 30 | 20 | 0.370 | 0.280 |
Helbrute | MINIBOSS | 150 | 100 | 1.00 | 1.00 |
Terminator Sorcerer (P14) | MINIBOSS | 100 | - | 1.00 | 1.00 |
Terminator Sorcerer - Clone (Simple) | MINIBOSS | 1 | - | 0.109 | 0.109 |
Terminator Sorcerer - Clone (Complex) | MINIBOSS | 30 | - | 0.370 | 0.370 |
Terminator Sorcerer - Clone (Simple Mirror) | (unregistered) | ~0 (unset) | - | 0.10 | 0.10 |
Heldrake | BOSS | ~0 (unset) | - | 0.10 | 0.10 |
Vortex Beast | BOSS | 1 | - | 0.109 | 0.109 |
Game Files
ssl/characters/imperium/dreadnought/npc_dreadnought_server.clsssl/characters/imperium/dreadnought/npc_dreadnought_hordemode_server.clsssl/ai/enemy_selection/advanced_enemy_selection/utility/utility_function_enemy_selection_by_power_level.ssossl/ai/enemy_selection/advanced_enemy_selection/utility/utility_function_aggressiveness.ssossl/spawn_system/archetypes/archetypes_library.ssossl/spawn_system/archetypes/archetypes_library_hordemode.sso