From 4cc6acc2e128d45708e00f8a0d88143c82feb777 Mon Sep 17 00:00:00 2001 From: Pavle Date: Mon, 16 Feb 2026 16:35:07 +0100 Subject: [PATCH 1/6] Iterate ZHM5ActionManager actions directly instead of using temporary vector --- Mods/Editor/Src/Components/Items.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index 2476ddfa..a0554466 100644 --- a/Mods/Editor/Src/Components/Items.cpp +++ b/Mods/Editor/Src/Components/Items.cpp @@ -16,7 +16,6 @@ void Editor::DrawItems(bool p_HasFocus) { if (s_Showing) { const ZHM5ActionManager* s_Hm5ActionManager = Globals::HM5ActionManager; - std::vector s_Actions; if (s_Hm5ActionManager->m_Actions.size() == 0) { ImGui::PopFont(); @@ -26,20 +25,17 @@ void Editor::DrawItems(bool p_HasFocus) { return; } - for (unsigned int i = 0; i < s_Hm5ActionManager->m_Actions.size(); ++i) { - ZHM5Action* s_Action = s_Hm5ActionManager->m_Actions[i]; - - if (s_Action && s_Action->m_eActionType == EActionType::AT_PICKUP) { - s_Actions.push_back(s_Action); - } - } - static size_t s_Selected = 0; ImGui::BeginChild("left pane", ImVec2(300, 0), true, ImGuiWindowFlags_HorizontalScrollbar); - for (size_t i = 0; i < s_Actions.size(); i++) { - const ZHM5Action* s_Action = s_Actions[i]; + for (size_t i = 0; i < s_Hm5ActionManager->m_Actions.size(); i++) { + const ZHM5Action* s_Action = s_Hm5ActionManager->m_Actions[i]; + + if (!s_Action || s_Action->m_eActionType != EActionType::AT_PICKUP) { + continue; + } + const ZHM5Item* s_Item = s_Action->m_Object.QueryInterface(); std::string s_Title = fmt::format( "{} ({:016x})###{}", s_Item->m_pItemConfigDescriptor->m_sTitle.c_str(), From 2dbbbabebb6268c353003980205e5784d2b9c8a6 Mon Sep 17 00:00:00 2001 From: Pavle Date: Mon, 16 Feb 2026 16:42:40 +0100 Subject: [PATCH 2/6] Add search bar to Items menu --- Mods/Editor/Src/Components/Items.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index a0554466..43caf903 100644 --- a/Mods/Editor/Src/Components/Items.cpp +++ b/Mods/Editor/Src/Components/Items.cpp @@ -4,6 +4,7 @@ #include #include +#include "Util/StringUtils.h" void Editor::DrawItems(bool p_HasFocus) { if (!p_HasFocus || !m_ItemsMenuActive) { @@ -25,6 +26,14 @@ void Editor::DrawItems(bool p_HasFocus) { return; } + static char s_ItemTitle[2048]{ "" }; + + ImGui::AlignTextToFramePadding(); + ImGui::Text("Item Title"); + ImGui::SameLine(); + + ImGui::InputText("##ItemName", s_ItemTitle, sizeof(s_ItemTitle)); + static size_t s_Selected = 0; ImGui::BeginChild("left pane", ImVec2(300, 0), true, ImGuiWindowFlags_HorizontalScrollbar); @@ -37,8 +46,14 @@ void Editor::DrawItems(bool p_HasFocus) { } const ZHM5Item* s_Item = s_Action->m_Object.QueryInterface(); + const ZString& s_ItemTitle2 = s_Item->m_pItemConfigDescriptor->m_sTitle; + + if (!Util::StringUtils::FindSubstringUTF8(s_ItemTitle2.c_str(), s_ItemTitle)) { + continue; + } + std::string s_Title = fmt::format( - "{} ({:016x})###{}", s_Item->m_pItemConfigDescriptor->m_sTitle.c_str(), + "{} ({:016x})###{}", s_ItemTitle2.c_str(), s_Action->m_Object->GetType()->m_nEntityID, i + 1 ); @@ -53,7 +68,7 @@ void Editor::DrawItems(bool p_HasFocus) { ImGui::BeginGroup(); ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); - const ZHM5Action* s_Action = s_Actions[s_Selected]; + const ZHM5Action* s_Action = s_Hm5ActionManager->m_Actions[s_Selected]; const ZHM5Item* s_Item = s_Action->m_Object.QueryInterface(); if (s_Item) { From 304aa200b873b75599fed4564824b165e38b47d3 Mon Sep 17 00:00:00 2001 From: Pavle Date: Mon, 16 Feb 2026 16:44:11 +0100 Subject: [PATCH 3/6] Rename s_Title to s_ItemLabel in Editor::DrawItems --- Mods/Editor/Src/Components/Items.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index 43caf903..8154b6b8 100644 --- a/Mods/Editor/Src/Components/Items.cpp +++ b/Mods/Editor/Src/Components/Items.cpp @@ -51,13 +51,13 @@ void Editor::DrawItems(bool p_HasFocus) { if (!Util::StringUtils::FindSubstringUTF8(s_ItemTitle2.c_str(), s_ItemTitle)) { continue; } - - std::string s_Title = fmt::format( + + std::string s_ItemLabel = fmt::format( "{} ({:016x})###{}", s_ItemTitle2.c_str(), s_Action->m_Object->GetType()->m_nEntityID, i + 1 ); - if (ImGui::Selectable(s_Title.c_str(), s_Selected == i)) { + if (ImGui::Selectable(s_ItemLabel.c_str(), s_Selected == i)) { s_Selected = i; } } From c596dc1430ba5e039675bae9e130dc5d69ad795b Mon Sep 17 00:00:00 2001 From: Pavle Date: Tue, 17 Feb 2026 00:05:19 +0100 Subject: [PATCH 4/6] Add tooltip with entity name, entity ID, and owner entity name and ID --- Mods/Editor/Src/Components/Items.cpp | 45 ++++++++++++++++++++++++++++ ZHMModSDK/Include/Glacier/ZItem.h | 28 +++++++++-------- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index 8154b6b8..e7f04a56 100644 --- a/Mods/Editor/Src/Components/Items.cpp +++ b/Mods/Editor/Src/Components/Items.cpp @@ -60,6 +60,51 @@ void Editor::DrawItems(bool p_HasFocus) { if (ImGui::Selectable(s_ItemLabel.c_str(), s_Selected == i)) { s_Selected = i; } + + if (ImGui::IsItemHovered()) { + std::shared_lock s_TreeLock(m_CachedEntityTreeMutex); + + if (!m_CachedEntityTreeMap.empty()) { + std::string s_EntityName; + + if (s_Action->m_Object.GetLogicalParent() && + s_Action->m_Object.GetLogicalParent().GetLogicalParent()) { + auto s_Iterator = m_CachedEntityTreeMap.find( + s_Action->m_Object.GetLogicalParent().GetLogicalParent() + ); + + if (s_Iterator != m_CachedEntityTreeMap.end()) { + s_EntityName = s_Iterator->second->Name; + } + } + + std::string s_OwningEntityName; + + if (s_Item->m_pOwner) { + auto s_Iterator = m_CachedEntityTreeMap.find(s_Item->m_pOwner); + + if (s_Iterator != m_CachedEntityTreeMap.end()) { + s_OwningEntityName = s_Iterator->second->Name; + } + + ImGui::SetTooltip( + "%s\nOwning Entity: %s", + s_EntityName.c_str(), + s_OwningEntityName.c_str() + ); + } + else { + ImGui::SetTooltip("%s", s_EntityName.c_str()); + } + } + else { + if (s_Item->m_pOwner) { + ImGui::SetTooltip( + fmt::format("Owning Entity: {:016x}", s_Item->m_pOwner->GetType()->m_nEntityID).c_str() + ); + } + } + } } ImGui::EndChild(); diff --git a/ZHMModSDK/Include/Glacier/ZItem.h b/ZHMModSDK/Include/Glacier/ZItem.h index 211050f1..5cb4f9a8 100644 --- a/ZHMModSDK/Include/Glacier/ZItem.h +++ b/ZHMModSDK/Include/Glacier/ZItem.h @@ -61,14 +61,14 @@ class ZItemConfigDescriptor { class ZVrHandAlignPose; class ZHM5Item : - public ZEntityImpl, // Offset 0x0 - public IItemBase, // Offset 0x18 - public IItem, // Offset 0x20 - public IKeywordHolder, // Offset 0x28 - public ZUIDataProvider, // Offset 0x30 - public IAIGameplayConcept, // Offset 0x70 - public IBoolConditionListener, // Offset 0x78 - public IColliderController // Offset 0x80 + public ZEntityImpl, // Offset 0x0 + public IItemBase, // Offset 0x18 + public IItem, // Offset 0x20 + public IKeywordHolder, // Offset 0x28 + public ZUIDataProvider, // Offset 0x30 + public IAIGameplayConcept, // Offset 0x70 + public IBoolConditionListener, // Offset 0x78 + public IColliderController // Offset 0x80 { public: enum class EUseTypes { @@ -121,11 +121,13 @@ class ZHM5Item : TEntityRef m_rItemCanTurnOn; // 0x2E8 TEntityRef m_rItemCanTurnOff; // 0x2F8 TEntityRef m_pVariationResource; // 0x308 - ZEntityRef m_rSpawner; - ZEntityRef m_rFactoryEntity; - PAD(0x10); - TEntityRef m_pGeomEntity; //0x2C0 - PAD(0x1A8); + ZEntityRef m_rSpawner; // 0x318 + ZEntityRef m_rFactoryEntity; // 0x320 + PAD(0x10); // 0x328 + TEntityRef m_pGeomEntity; //0x338 + PAD(0x10); // 0x2D0 + ZEntityRef m_pOwner; // 0x358 + PAD(0x190); }; class IItemWeapon : public IComponentInterface { From 7b2d3dfce224f4e4b1ca8df83bb4ed3312661275 Mon Sep 17 00:00:00 2001 From: Pavle Date: Tue, 17 Feb 2026 00:11:56 +0100 Subject: [PATCH 5/6] Add button in Items menu to select owner in entity tree --- Mods/Editor/Src/Components/Items.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index e7f04a56..bd3798cb 100644 --- a/Mods/Editor/Src/Components/Items.cpp +++ b/Mods/Editor/Src/Components/Items.cpp @@ -124,6 +124,18 @@ void Editor::DrawItems(bool p_HasFocus) { OnSelectEntity(s_Action->m_Object, true, std::nullopt); } + + ImGui::BeginDisabled(!s_Item->m_pOwner); + + if (ImGui::Button("Select Owner In Entity Tree")) { + if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { + UpdateEntities(); + } + + OnSelectEntity(s_Item->m_pOwner, true, std::nullopt); + } + + ImGui::EndDisabled(); } if (ImGui::Button("Teleport Item To Player")) { From 50cfc4912c07112ab0f9597a7316f7d28933ecf3 Mon Sep 17 00:00:00 2001 From: Pavle Date: Tue, 17 Feb 2026 00:21:12 +0100 Subject: [PATCH 6/6] Only show buttons when item is selected in Items menu --- Mods/Editor/Src/Components/Items.cpp | 41 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index bd3798cb..51af1429 100644 --- a/Mods/Editor/Src/Components/Items.cpp +++ b/Mods/Editor/Src/Components/Items.cpp @@ -108,36 +108,43 @@ void Editor::DrawItems(bool p_HasFocus) { } ImGui::EndChild(); - ImGui::SameLine(); - - ImGui::BeginGroup(); - ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); const ZHM5Action* s_Action = s_Hm5ActionManager->m_Actions[s_Selected]; const ZHM5Item* s_Item = s_Action->m_Object.QueryInterface(); - if (s_Item) { - if (ImGui::Button("Select In Entity Tree")) { - if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { - UpdateEntities(); - } + if (!s_Item) { + ImGui::PopFont(); + ImGui::End(); + ImGui::PopFont(); - OnSelectEntity(s_Action->m_Object, true, std::nullopt); + return; + } + + ImGui::SameLine(); + + ImGui::BeginGroup(); + ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); + + if (ImGui::Button("Select In Entity Tree")) { + if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { + UpdateEntities(); } - ImGui::BeginDisabled(!s_Item->m_pOwner); + OnSelectEntity(s_Action->m_Object, true, std::nullopt); + } - if (ImGui::Button("Select Owner In Entity Tree")) { - if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { - UpdateEntities(); - } + ImGui::BeginDisabled(!s_Item->m_pOwner); - OnSelectEntity(s_Item->m_pOwner, true, std::nullopt); + if (ImGui::Button("Select Owner In Entity Tree")) { + if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { + UpdateEntities(); } - ImGui::EndDisabled(); + OnSelectEntity(s_Item->m_pOwner, true, std::nullopt); } + ImGui::EndDisabled(); + if (ImGui::Button("Teleport Item To Player")) { if (auto s_LocalHitman = SDK()->GetLocalPlayer()) { ZSpatialEntity* s_HitmanSpatial = s_LocalHitman.m_entityRef.QueryInterface();