diff --git a/Mods/Editor/Src/Components/Items.cpp b/Mods/Editor/Src/Components/Items.cpp index 2476ddfa..51af1429 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) { @@ -16,7 +17,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,50 +26,125 @@ 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]; + static char s_ItemTitle[2048]{ "" }; - if (s_Action && s_Action->m_eActionType == EActionType::AT_PICKUP) { - s_Actions.push_back(s_Action); - } - } + 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); - 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(), + const ZString& s_ItemTitle2 = s_Item->m_pItemConfigDescriptor->m_sTitle; + + if (!Util::StringUtils::FindSubstringUTF8(s_ItemTitle2.c_str(), s_ItemTitle)) { + continue; + } + + 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; } + + 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(); + + const ZHM5Action* s_Action = s_Hm5ActionManager->m_Actions[s_Selected]; + const ZHM5Item* s_Item = s_Action->m_Object.QueryInterface(); + + if (!s_Item) { + ImGui::PopFont(); + ImGui::End(); + ImGui::PopFont(); + + return; + } + ImGui::SameLine(); ImGui::BeginGroup(); ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); - const ZHM5Action* s_Action = s_Actions[s_Selected]; - const ZHM5Item* s_Item = s_Action->m_Object.QueryInterface(); + if (ImGui::Button("Select In Entity Tree")) { + if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { + UpdateEntities(); + } - if (s_Item) { - if (ImGui::Button("Select In Entity Tree")) { - if (!m_CachedEntityTree || !m_CachedEntityTree->Entity) { - UpdateEntities(); - } + OnSelectEntity(s_Action->m_Object, true, std::nullopt); + } - 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")) { if (auto s_LocalHitman = SDK()->GetLocalPlayer()) { ZSpatialEntity* s_HitmanSpatial = s_LocalHitman.m_entityRef.QueryInterface(); 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 {