Skip to content

feat(ai): per-NPC npc:set_visible_enemy_bias selection lever - #637

Merged
themrdemonized merged 2 commits into
themrdemonized:all-in-one-vs2022-wpofrom
damiansirbu:feat-npc-visible-enemy-bias
Aug 16, 2026
Merged

feat(ai): per-NPC npc:set_visible_enemy_bias selection lever#637
themrdemonized merged 2 commits into
themrdemonized:all-in-one-vs2022-wpofrom
damiansirbu:feat-npc-visible-enemy-bias

Conversation

@damiansirbu

@damiansirbu damiansirbu commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds npc:set_visible_enemy_bias(actor_bias, npc_bias) on the stalker enemy manager. It overrides the two selection terms in CEnemyManager::evaluate() that favour whoever can see the NPC. actor_bias replaces the 900 subtracted when the actor sees the NPC. npc_bias replaces the 300 subtracted when another NPC sees it. Each arg is independent. A negative one keeps that side vanilla. A script can reduce the player magnet, the 3x pull the actor gets, so NPCs stop converging on the player. It can also retune per-NPC threat weighting. Nothing changes without a consumer.

Use cases

The bias gives an enemy that can see the NPC a large selection bonus. The actor bonus is 3x an NPC bonus, so squads converge on the player. A combat-fairness or threat-awareness mod sets it per-NPC to level the field, for example actor_bias equal to npc_bias. It can also weight toward the real threat.

Performance

No Lua runs on the path. The change adds two ternary reads per candidate.

Constraints

Per-object state lives on CEnemyManager and is not serialized. Re-set it on net_spawn, the same as set_vision_speed. Each arg is independent. A negative one keeps that side vanilla. A value of 0 removes the pull.

Files

  • enemy_manager.cpp: fields, ctor init, setter, the two evaluate reads.
  • enemy_manager.h: fields and setter declaration.
  • script_game_object.h: declaration.
  • script_game_object3.cpp: the bind with a CCustomMonster cast and error log, plus the enemy_manager.h include.
  • script_game_object_script3.cpp: the .def next to set_vision_speed.
  • gamedata/scripts/lua_help_ex.script: the manifest entry.

Lua usage

npc:set_visible_enemy_bias(300, -1)  -- player pulls like a regular NPC, npc side stays vanilla
npc:set_visible_enemy_bias(0, -1)    -- no artificial pull toward the player

Testing

Built locally at DX11 with 0 errors. Deployed and probed on the Cordon field. On a blind-spot NPC, set_visible_enemy_bias(0, 0) removes the 900 actor term:

[HITSET] actor_bias=900 | YOU YouseeN=true cost=8210.3 | match=true
[BIAS]   actor_bias=0   | YOU YouseeN=true cost=9112.1 | match=true

The actor cost rises by 900. That 900 is the removed magnet. The reconstruction with bias set to 0 matches the engine, so the row reads match=true. Once the pull is off, a competing enemy becomes selectable where the 900 term dominated before. Later samples can show the engine holding the prior target as a marginally better competitor appears. That is enemy-change inertia, the ENEMY_INERTIA_TIME window. The scoring change itself is exact.

Adds npc:set_visible_enemy_bias(actor_bias, npc_bias) on the stalker's enemy
manager: per-object overrides of the "prefers whoever can see me" bias in
CEnemyManager::evaluate(). Unset (< 0, the ctor default) keeps the current 900
(actor) / 300 (npc) subtracted when the seer sees this NPC; set replaces those
magnitudes. Lets a script dial down the actor-fixation (the player-magnet) or
retune per-NPC threat weighting. Default behavior unchanged with no consumer.
@damiansirbu
damiansirbu force-pushed the feat-npc-visible-enemy-bias branch from 4233e1a to e862703 Compare August 14, 2026 21:52
@themrdemonized
themrdemonized merged commit 748833d into themrdemonized:all-in-one-vs2022-wpo Aug 16, 2026
0 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants