feat(ai): per-NPC npc:set_visible_enemy_bias selection lever - #637
Merged
themrdemonized merged 2 commits intoAug 16, 2026
Conversation
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
force-pushed
the
feat-npc-visible-enemy-bias
branch
from
August 14, 2026 21:52
4233e1a to
e862703
Compare
themrdemonized
merged commit Aug 16, 2026
748833d
into
themrdemonized:all-in-one-vs2022-wpo
0 of 17 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
npc:set_visible_enemy_bias(actor_bias, npc_bias)on the stalker enemy manager. It overrides the two selection terms inCEnemyManager::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
CEnemyManagerand is not serialized. Re-set it onnet_spawn, the same asset_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 theenemy_manager.hinclude.script_game_object_script3.cpp: the.defnext toset_vision_speed.gamedata/scripts/lua_help_ex.script: the manifest entry.Lua usage
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: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.