From 3249caf17de0dcab005398995ef3e611b3f81131 Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 3 Nov 2026 23:07:40 +0100 Subject: AI: fix relationship lookup; classify citizen/hacked turrets m_Relationship is DEFINE_UTLVECTOR (FIELD_CUSTOM), not FIELD_EMBEDDED, so the datamap scan always returned -1 and every NPC fell back to the model heuristic. Resolve it as FIELD_CUSTOM with an embedded fallback. Floor turrets never add relationship rows when friendly: CNPC_FloorTurret overrides Classify() to CLASS_PLAYER_ALLY for citizen-built (SF_FLOOR_TURRET_CITIZEN) and Alyx-hacked turrets. Read m_spawnflags and m_bHackedByAlyx from the server instead. Widen the datamap offset window (0x4..0x4000) for derived-class fields and log the new offsets plus turret state in the NPC debug line. --- src/esp.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/esp.cpp') diff --git a/src/esp.cpp b/src/esp.cpp index b09588f..40e00f6 100644 --- a/src/esp.cpp +++ b/src/esp.cpp @@ -148,9 +148,18 @@ static bool model_is_neutral(const char *m) { return false; } +static bool model_is_floor_turret(const char *m) { + return m && strstr(m, "floor_turret"); +} + static bool npc_is_friendly(int idx, const char *model, int local_idx, bool &neutral) { int rel = server_npc_relation(idx, local_idx); + int turret = -1; + // Citizen-built and Alyx-hacked turrets never add an m_Relationship row; + // their Classify() (CLASS_PLAYER_ALLY) comes from server runtime state. + if (model_is_floor_turret(model)) + turret = server_npc_turret_flags(idx); // Debug-only: relation values are the authoritative answer and are the // first thing to check when a friendly NPC still looks hostile. Logged only // when an entity's relation changes, so this does not flood the log. @@ -163,9 +172,9 @@ static bool npc_is_friendly(int idx, const char *model, int local_idx, } if (idx > 0 && idx < 2048 && rel_cache[idx] != rel) { rel_cache[idx] = rel; - logd("npc %d (%s): relation=%d followtarget=%d local=%d", idx, + logd("npc %d (%s): relation=%d followtarget=%d turret=%d local=%d", idx, model ? model : "?", rel, - (int)server_npc_has_follow_target(idx), local_idx); + (int)server_npc_has_follow_target(idx), turret, local_idx); } if (rel == 3) { // D_LI neutral = false; @@ -179,6 +188,10 @@ static bool npc_is_friendly(int idx, const char *model, int local_idx, neutral = false; return false; } + if (turret >= 0) { + neutral = false; + return turret != 0; + } // Bugbait-controlled antlions follow a target even when their default // relationship was never rewritten. if (model && strstr(model, "antlion") && -- cgit v1.2.3