summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-28 13:02:26 +0100
committersalmonik <salmonik@tuta.io>2026-10-28 13:02:26 +0100
commitb212e8e13835cfdc4849a61c1b57146bd0312a29 (patch)
tree128a64c8c20411749ee8ea4a78ef4a51a9604515
parentCombat: fix silent-aim spread seed and lead projectiles (diff)
downloadhl2h-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.
Diffstat (limited to '')
-rw-r--r--CONTEXT.md6
-rw-r--r--src/bones.cpp13
-rw-r--r--src/esp.cpp19
-rw-r--r--src/hl2h.cpp9
-rw-r--r--src/hl2h.h1
5 files changed, 47 insertions, 1 deletions
diff --git a/CONTEXT.md b/CONTEXT.md
index a9e34d8..a9b85b9 100644
--- a/CONTEXT.md
+++ b/CONTEXT.md
@@ -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.
512void 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
512int aim_points(int idx, unsigned group_mask, Vector *out, int max) { 525int 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;
diff --git a/src/hl2h.h b/src/hl2h.h
index 9b4fa8a..9c0440f 100644
--- a/src/hl2h.h
+++ b/src/hl2h.h
@@ -286,6 +286,7 @@ bool bone_is_skeleton_core(int idx, int bone);
286int bone_nearest_core_parent(int idx, int bone); 286int bone_nearest_core_parent(int idx, int bone);
287bool bones_is_humanoid(int idx); 287bool bones_is_humanoid(int idx);
288bool hitbox_center(int idx, const char *hitbox_name, Vector &out); 288bool hitbox_center(int idx, const char *hitbox_name, Vector &out);
289void bones_clear();
289bool head_position(int idx, Vector &out); 290bool head_position(int idx, Vector &out);
290int aim_points(int idx, unsigned group_mask, Vector *out, int max); 291int aim_points(int idx, unsigned group_mask, Vector *out, int max);
291 292