diff options
Diffstat (limited to 'src/esp.cpp')
| -rw-r--r-- | src/esp.cpp | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/src/esp.cpp b/src/esp.cpp index 405dea7..50d7b5d 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -139,8 +139,10 @@ static bool model_is_friendly(const char *m) { | |||
| 139 | 139 | ||
| 140 | // harmless wildlife that also happens to be CAI_BaseNPC | 140 | // harmless wildlife that also happens to be CAI_BaseNPC |
| 141 | static bool model_is_neutral(const char *m) { | 141 | static bool model_is_neutral(const char *m) { |
| 142 | // Lamarr is Kleiner's pet headcrab: scripted and harmless, and the user | ||
| 143 | // wants her shown neutral rather than hostile. | ||
| 142 | static const char *patterns[] = {"crow", "gull", "pigeon", "seagull", | 144 | static const char *patterns[] = {"crow", "gull", "pigeon", "seagull", |
| 143 | "bird", nullptr}; | 145 | "bird", "Lamarr", nullptr}; |
| 144 | if (!m) return false; | 146 | if (!m) return false; |
| 145 | for (int i = 0; patterns[i]; i++) | 147 | for (int i = 0; patterns[i]; i++) |
| 146 | if (strstr(m, patterns[i])) | 148 | if (strstr(m, patterns[i])) |
| @@ -155,42 +157,55 @@ static bool model_is_floor_turret(const char *m) { | |||
| 155 | static bool npc_is_friendly(int idx, const char *model, int local_idx, | 157 | static bool npc_is_friendly(int idx, const char *model, int local_idx, |
| 156 | bool &neutral) { | 158 | bool &neutral) { |
| 157 | int rel = server_npc_relation(idx, local_idx); | 159 | int rel = server_npc_relation(idx, local_idx); |
| 160 | int state = server_npc_state(idx); | ||
| 158 | int turret = -1; | 161 | int turret = -1; |
| 159 | // Citizen-built and Alyx-hacked turrets never add an m_Relationship row; | 162 | // Citizen-built and Alyx-hacked turrets never add an m_Relationship row; |
| 160 | // their Classify() (CLASS_PLAYER_ALLY) comes from server runtime state. | 163 | // their Classify() (CLASS_PLAYER_ALLY) comes from server runtime state. |
| 161 | if (model_is_floor_turret(model)) | 164 | if (model_is_floor_turret(model)) |
| 162 | turret = server_npc_turret_flags(idx); | 165 | turret = server_npc_turret_flags(idx); |
| 163 | // Debug-only: relation values are the authoritative answer and are the | 166 | // Debug-only: relation/state changes are the authoritative signals and the |
| 164 | // first thing to check when a friendly NPC still looks hostile. Logged only | 167 | // first thing to check when a friendly NPC still looks hostile. |
| 165 | // when an entity's relation changes, so this does not flood the log. | ||
| 166 | static int rel_cache[2048]; | 168 | static int rel_cache[2048]; |
| 167 | static bool rel_cache_init = false; | 169 | static int state_cache[2048]; |
| 168 | if (!rel_cache_init) { | 170 | static bool cache_init = false; |
| 171 | if (!cache_init) { | ||
| 169 | for (int i = 0; i < 2048; i++) | 172 | for (int i = 0; i < 2048; i++) |
| 170 | rel_cache[i] = -999; | 173 | rel_cache[i] = state_cache[i] = -999; |
| 171 | rel_cache_init = true; | 174 | cache_init = true; |
| 172 | } | 175 | } |
| 173 | if (idx > 0 && idx < 2048 && rel_cache[idx] != rel) { | 176 | if (idx > 0 && idx < 2048 && |
| 177 | (rel_cache[idx] != rel || state_cache[idx] != state)) { | ||
| 174 | rel_cache[idx] = rel; | 178 | rel_cache[idx] = rel; |
| 175 | logd("npc %d (%s): relation=%d followtarget=%d turret=%d local=%d", idx, | 179 | state_cache[idx] = state; |
| 176 | model ? model : "?", rel, | 180 | logd("npc %d (%s): relation=%d state=%d followtarget=%d turret=%d " |
| 181 | "local=%d", idx, model ? model : "?", rel, state, | ||
| 177 | (int)server_npc_has_follow_target(idx), turret, local_idx); | 182 | (int)server_npc_has_follow_target(idx), turret, local_idx); |
| 178 | } | 183 | } |
| 179 | if (rel == 3) { // D_LI | 184 | if (rel == 3) { // D_LI |
| 180 | neutral = false; | 185 | neutral = false; |
| 181 | return true; | 186 | return true; |
| 182 | } | 187 | } |
| 188 | if (turret > 0) { // citizen-built / Alyx-hacked | ||
| 189 | neutral = false; | ||
| 190 | return true; | ||
| 191 | } | ||
| 183 | if (rel == 4) { // D_NU | 192 | if (rel == 4) { // D_NU |
| 184 | neutral = true; | 193 | neutral = true; |
| 185 | return false; | 194 | return false; |
| 186 | } | 195 | } |
| 196 | // NPC_STATE_SCRIPT = 4: cutscene actors and scripted pets are passive even | ||
| 197 | // when their class relationship says hate (Lamarr, scripted Combine, ...). | ||
| 198 | if (state == 4) { | ||
| 199 | neutral = true; | ||
| 200 | return false; | ||
| 201 | } | ||
| 187 | if (rel == 1 || rel == 2) { // D_HT / D_FR | 202 | if (rel == 1 || rel == 2) { // D_HT / D_FR |
| 188 | neutral = false; | 203 | neutral = false; |
| 189 | return false; | 204 | return false; |
| 190 | } | 205 | } |
| 191 | if (turret >= 0) { | 206 | if (turret >= 0) { // ordinary floor turret |
| 192 | neutral = false; | 207 | neutral = false; |
| 193 | return turret != 0; | 208 | return false; |
| 194 | } | 209 | } |
| 195 | // Bugbait-controlled antlions follow a target even when their default | 210 | // Bugbait-controlled antlions follow a target even when their default |
| 196 | // relationship was never rewritten. | 211 | // relationship was never rewritten. |
