diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-28 13:02:26 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-28 13:02:26 +0100 |
| commit | b212e8e13835cfdc4849a61c1b57146bd0312a29 (patch) | |
| tree | 128a64c8c20411749ee8ea4a78ef4a51a9604515 | |
| parent | Combat: fix silent-aim spread seed and lead projectiles (diff) | |
| download | hl2h-b212e8e13835cfdc4849a61c1b57146bd0312a29.tar.gz hl2h-b212e8e13835cfdc4849a61c1b57146bd0312a29.zip | |
Melee: surface weapon state across maps; reset stale caches
- Map transitions often leave a non-crowbar weapon active, so the killbot
silently does nothing. Log every active-weapon change as a normal
`melee: active ... crowbar=0/1` line and toast once suggesting the crowbar.
- Recover the crowbar model from the server entity when the client weapon
model index is missing/0 after a map change.
- Clear the bone cache and aim/silent locks when the local player entity
changes (map load/respawn) so stale entity/model data cannot poison melee
target selection.
| -rw-r--r-- | CONTEXT.md | 6 | ||||
| -rw-r--r-- | src/bones.cpp | 13 | ||||
| -rw-r--r-- | src/esp.cpp | 19 | ||||
| -rw-r--r-- | src/hl2h.cpp | 9 | ||||
| -rw-r--r-- | src/hl2h.h | 1 |
5 files changed, 47 insertions, 1 deletions
| @@ -190,6 +190,12 @@ vocabulary / decisions. | |||
| 190 | client `m_hActiveWeapon` handle is used first; if it is missing, the | 190 | client `m_hActiveWeapon` handle is used first; if it is missing, the |
| 191 | authoritative server `m_hActiveWeapon` handle (0x824) is used to get the | 191 | authoritative server `m_hActiveWeapon` handle (0x824) is used to get the |
| 192 | weapon entity index. | 192 | weapon entity index. |
| 193 | - Map transitions often switch the active weapon away from the crowbar. The | ||
| 194 | state change is logged as `melee: active ... crowbar=0/1` (normal log), and | ||
| 195 | a one-time toast says to equip the crowbar. If the client weapon model is | ||
| 196 | missing/0, the server model index is used to recognize it. | ||
| 197 | - Bone caches and aim locks are cleared when the local player entity changes | ||
| 198 | (map load/respawn). | ||
| 193 | - Crowbar range is `CROWBAR_RANGE` 75 units from `Weapon_ShootPosition`. The | 199 | - Crowbar range is `CROWBAR_RANGE` 75 units from `Weapon_ShootPosition`. The |
| 194 | selector computes the closest point on each hostile NPC's AABB to the eye, | 200 | selector computes the closest point on each hostile NPC's AABB to the eye, |
| 195 | rejects anything farther than 75, sorts by that distance, and picks the | 201 | rejects anything farther than 75, sorts by that distance, and picks the |
diff --git a/src/bones.cpp b/src/bones.cpp index 0df13f2..c777067 100644 --- a/src/bones.cpp +++ b/src/bones.cpp | |||
| @@ -509,6 +509,19 @@ bool head_position(int idx, Vector &out) { | |||
| 509 | // Collect world-space aim points for the selected hit groups (HITGROUP_*). | 509 | // Collect world-space aim points for the selected hit groups (HITGROUP_*). |
| 510 | // Group 1 (head) uses head_position for its bone fallback; other groups are | 510 | // Group 1 (head) uses head_position for its bone fallback; other groups are |
| 511 | // the hitbox centers. The caller picks the point nearest to the crosshair. | 511 | // the hitbox centers. The caller picks the point nearest to the crosshair. |
| 512 | void bones_clear() { | ||
| 513 | for (auto &e : g_entries) { | ||
| 514 | e.ent = nullptr; | ||
| 515 | e.valid = false; | ||
| 516 | e.hdr = nullptr; | ||
| 517 | e.count = 0; | ||
| 518 | e.stamp = 0.0; | ||
| 519 | } | ||
| 520 | g_next = 0; | ||
| 521 | g_logged = 0; | ||
| 522 | g_renderable_warned = false; | ||
| 523 | } | ||
| 524 | |||
| 512 | int aim_points(int idx, unsigned group_mask, Vector *out, int max) { | 525 | int aim_points(int idx, unsigned group_mask, Vector *out, int max) { |
| 513 | if (!out || max <= 0) | 526 | if (!out || max <= 0) |
| 514 | return 0; | 527 | return 0; |
diff --git a/src/esp.cpp b/src/esp.cpp index 06bafaf..a0d84dd 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -873,6 +873,8 @@ bool melee_weapon_active(void *local_ent) { | |||
| 873 | if (!local_ent) | 873 | if (!local_ent) |
| 874 | return false; | 874 | return false; |
| 875 | int local = engine_get_local_player(); | 875 | int local = engine_get_local_player(); |
| 876 | if (g_iface.engineserver) | ||
| 877 | resolve_server_netvars(); | ||
| 876 | 878 | ||
| 877 | auto check = [&](int idx, const char **cls_out, | 879 | auto check = [&](int idx, const char **cls_out, |
| 878 | const char **model_out) -> bool { | 880 | const char **model_out) -> bool { |
| @@ -882,6 +884,14 @@ bool melee_weapon_active(void *local_ent) { | |||
| 882 | void *net = entity_networkable(idx); | 884 | void *net = entity_networkable(idx); |
| 883 | const char *cls = net ? entity_class_name(net, nullptr) : nullptr; | 885 | const char *cls = net ? entity_class_name(net, nullptr) : nullptr; |
| 884 | const char *model = wep ? entity_model_name(wep) : nullptr; | 886 | const char *model = wep ? entity_model_name(wep) : nullptr; |
| 887 | // Client weapon models can be missing/0 after a map change; recover the | ||
| 888 | // server model index so the crowbar is still recognized. | ||
| 889 | if ((!model || !*model) && g_iface.engineserver) { | ||
| 890 | void *sbase = nullptr; | ||
| 891 | server_entity_health(idx, nullptr, nullptr, &sbase); | ||
| 892 | if (sbase) | ||
| 893 | model = model_name_from_index(server_model_index(sbase)); | ||
| 894 | } | ||
| 885 | *cls_out = cls; | 895 | *cls_out = cls; |
| 886 | *model_out = model; | 896 | *model_out = model; |
| 887 | return (cls && strstr(cls, "Crowbar")) || | 897 | return (cls && strstr(cls, "Crowbar")) || |
| @@ -916,8 +926,15 @@ bool melee_weapon_active(void *local_ent) { | |||
| 916 | if (idx != last_idx || crowbar != last_crowbar) { | 926 | if (idx != last_idx || crowbar != last_crowbar) { |
| 917 | last_idx = idx; | 927 | last_idx = idx; |
| 918 | last_crowbar = crowbar; | 928 | last_crowbar = crowbar; |
| 919 | logd("melee: active idx=%d cls=%s model=%s crowbar=%d", idx, | 929 | logf("melee: active idx=%d cls=%s model=%s crowbar=%d", idx, |
| 920 | cls ? cls : "?", model ? model : "?", (int)crowbar); | 930 | cls ? cls : "?", model ? model : "?", (int)crowbar); |
| 931 | if (!crowbar) { | ||
| 932 | static bool warned = false; | ||
| 933 | if (!warned) { | ||
| 934 | warned = true; | ||
| 935 | toastf(TOAST_WARN, "Melee killbot: equip the crowbar"); | ||
| 936 | } | ||
| 937 | } | ||
| 921 | } | 938 | } |
| 922 | return crowbar; | 939 | return crowbar; |
| 923 | } | 940 | } |
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 4f5673f..f95f6ed 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -556,6 +556,15 @@ static void do_move(int seq, float frametime) { | |||
| 556 | if (!ent) | 556 | if (!ent) |
| 557 | return; | 557 | return; |
| 558 | 558 | ||
| 559 | // New map / respawn: drop stale bone caches and target locks. | ||
| 560 | static void *last_local_ent = nullptr; | ||
| 561 | if (ent != last_local_ent) { | ||
| 562 | last_local_ent = ent; | ||
| 563 | bones_clear(); | ||
| 564 | aimbot_reset_lock(); | ||
| 565 | silentaim_reset_lock(); | ||
| 566 | } | ||
| 567 | |||
| 559 | if (feature_active(FEAT_SPREAD)) { | 568 | if (feature_active(FEAT_SPREAD)) { |
| 560 | resolve_server_netvars(); | 569 | resolve_server_netvars(); |
| 561 | void *srv = nullptr; | 570 | void *srv = nullptr; |
| @@ -286,6 +286,7 @@ bool bone_is_skeleton_core(int idx, int bone); | |||
| 286 | int bone_nearest_core_parent(int idx, int bone); | 286 | int bone_nearest_core_parent(int idx, int bone); |
| 287 | bool bones_is_humanoid(int idx); | 287 | bool bones_is_humanoid(int idx); |
| 288 | bool hitbox_center(int idx, const char *hitbox_name, Vector &out); | 288 | bool hitbox_center(int idx, const char *hitbox_name, Vector &out); |
| 289 | void bones_clear(); | ||
| 289 | bool head_position(int idx, Vector &out); | 290 | bool head_position(int idx, Vector &out); |
| 290 | int aim_points(int idx, unsigned group_mask, Vector *out, int max); | 291 | int aim_points(int idx, unsigned group_mask, Vector *out, int max); |
| 291 | 292 | ||
