summaryrefslogtreecommitdiffstats
path: root/src/esp.cpp
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-28 12:12:33 +0100
committersalmonik <salmonik@tuta.io>2026-10-28 12:12:33 +0100
commita6f1e039ce988cf139c52d7853e96dc8496fb806 (patch)
tree731021e0a401e08ddb8b1b5f4bc9adb589efc859 /src/esp.cpp
parentItem ESP: fix AR2/RPG/stunstick world-model names (diff)
downloadhl2h-a6f1e039ce988cf139c52d7853e96dc8496fb806.tar.gz
hl2h-a6f1e039ce988cf139c52d7853e96dc8496fb806.zip
Item ESP: recover CPhysicsProp model names from the server
Client CPhysicsProp entities frequently report m_nModelIndex == 0, so item crates appeared as model=? and were never classified. Fall back to the server entity's m_nModelIndex (set in CItem_ItemCrate::Spawn) when the client model index is missing, then resolve the name through the shared modelinfo.
Diffstat (limited to '')
-rw-r--r--src/esp.cpp22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/esp.cpp b/src/esp.cpp
index 2fb5d1b..ec3e94b 100644
--- a/src/esp.cpp
+++ b/src/esp.cpp
@@ -100,10 +100,9 @@ static const char *entity_class_name(void *net, void **out_cc) {
100 100
101// m_nModelIndex -> IVModelInfoClient(006)::GetModel/GetModelName. 101// m_nModelIndex -> IVModelInfoClient(006)::GetModel/GetModelName.
102// Itanium ABI: two dtor slots, so GetModel=2, GetModelName=4. 102// Itanium ABI: two dtor slots, so GetModel=2, GetModelName=4.
103static const char *entity_model_name(void *ent) { 103static const char *model_name_from_index(int modelindex) {
104 if (!g_iface.modelinfo || g_net.modelindex < 0) return nullptr; 104 if (!g_iface.modelinfo || modelindex <= 0)
105 int modelindex = *(int *)((uintptr_t)ent + g_net.modelindex); 105 return nullptr;
106 if (modelindex <= 0) return nullptr;
107 const void *model = 106 const void *model =
108 vfunc<GetModelFn>(g_iface.modelinfo, 2)(g_iface.modelinfo, modelindex); 107 vfunc<GetModelFn>(g_iface.modelinfo, 2)(g_iface.modelinfo, modelindex);
109 if (!model) 108 if (!model)
@@ -111,6 +110,12 @@ static const char *entity_model_name(void *ent) {
111 return vfunc<GetModelNameFn>(g_iface.modelinfo, 4)(g_iface.modelinfo, model); 110 return vfunc<GetModelNameFn>(g_iface.modelinfo, 4)(g_iface.modelinfo, model);
112} 111}
113 112
113static const char *entity_model_name(void *ent) {
114 if (!g_iface.modelinfo || g_net.modelindex < 0) return nullptr;
115 int modelindex = *(int *)((uintptr_t)ent + g_net.modelindex);
116 return model_name_from_index(modelindex);
117}
118
114// HL2 SP: generic NPCs (combine, metrocop, zombie, citizen, antlion, ...) all 119// HL2 SP: generic NPCs (combine, metrocop, zombie, citizen, antlion, ...) all
115// use the single client class "CAI_BaseNPC" — only special NPCs register their 120// use the single client class "CAI_BaseNPC" — only special NPCs register their
116// own class names (CNPC_Manhack, CNPC_Strider, CNPC_CombineGunship, ...). 121// own class names (CNPC_Manhack, CNPC_Strider, CNPC_CombineGunship, ...).
@@ -1629,6 +1634,7 @@ static void items_collect(int local_idx) {
1629 g_nitems = 0; 1634 g_nitems = 0;
1630 if (!g_iface.entitylist || g_net.origin < 0 || g_net.modelindex < 0) 1635 if (!g_iface.entitylist || g_net.origin < 0 || g_net.modelindex < 0)
1631 return; 1636 return;
1637 resolve_server_netvars();
1632 1638
1633 using Fn = int (*)(void *); 1639 using Fn = int (*)(void *);
1634 int hi = vfunc<Fn>(g_iface.entitylist, 6)(g_iface.entitylist); 1640 int hi = vfunc<Fn>(g_iface.entitylist, 6)(g_iface.entitylist);
@@ -1664,6 +1670,14 @@ static void items_collect(int local_idx) {
1664 continue; 1670 continue;
1665 const char *cls = entity_class_name(net, nullptr); 1671 const char *cls = entity_class_name(net, nullptr);
1666 const char *model = entity_model_name(ent); 1672 const char *model = entity_model_name(ent);
1673 // CPhysicsProp's client m_nModelIndex is often 0 (e.g. item_item_crate);
1674 // fall back to the server entity's model index, which is set in Spawn().
1675 if ((!model || !*model) && g_iface.engineserver) {
1676 void *sbase = nullptr;
1677 server_entity_health(idx, nullptr, nullptr, &sbase);
1678 if (sbase)
1679 model = model_name_from_index(server_model_index(sbase));
1680 }
1667 char label[128]; 1681 char label[128];
1668 int kind = classify_item(model, cls, label, sizeof(label)); 1682 int kind = classify_item(model, cls, label, sizeof(label));
1669 1683