diff --git a/Source/CS2/Classes/Panorama.h b/Source/CS2/Classes/Panorama.h index 80e3720133b..7c0d5456743 100644 --- a/Source/CS2/Classes/Panorama.h +++ b/Source/CS2/Classes/Panorama.h @@ -265,12 +265,17 @@ struct CUIPanel { using setParent = void (*)(CUIPanel* thisptr, CUIPanel* parent); using setVisible = void (*)(CUIPanel* thisptr, bool visible); - using findChildInLayoutFile = CUIPanel* (*)(CUIPanel* thisptr, const char* childId); using getAttributeString = const char* (*)(CUIPanel* thisptr, CPanoramaSymbol attributeName, const char* defaultValue); using setAttributeString = void (*)(CUIPanel* thisptr, CPanoramaSymbol attributeName, const char* value); using childrenVector = CUtlVector; using classesVector = CUtlVector; + using m_pchID = CUtlString; + using PanelFlags = std::uint8_t; +}; + +enum EPanelFlag { + k_EPanelFlag_HasOwnLayoutFile = 0x40 }; struct ImageProperties { diff --git a/Source/GameClasses/Implementation/PanoramaUiPanelImpl.h b/Source/GameClasses/Implementation/PanoramaUiPanelImpl.h index 73f34516fe2..039e610b4b4 100644 --- a/Source/GameClasses/Implementation/PanoramaUiPanelImpl.h +++ b/Source/GameClasses/Implementation/PanoramaUiPanelImpl.h @@ -9,13 +9,14 @@ struct PanoramaUiPanelImpl { explicit PanoramaUiPanelImpl(const PanoramaUiPanelPatterns& panoramaUiPanelPatterns) noexcept : setParent{panoramaUiPanelPatterns.setParent()} , setVisible{panoramaUiPanelPatterns.setVisible()} - , findChildInLayoutFile{panoramaUiPanelPatterns.findChildInLayoutFile()} , getAttributeString{panoramaUiPanelPatterns.getAttributeString()} , setAttributeString{panoramaUiPanelPatterns.setAttributeString()} , childPanels{panoramaUiPanelPatterns.childPanelsVectorOffset()} , classes{panoramaUiPanelPatterns.classesVectorOffset()} , panelStyle{panoramaUiPanelPatterns.panelStyleOffset()} , parentWindowOffset{panoramaUiPanelPatterns.parentWindowOffset()} + , offsetToPanelId{panoramaUiPanelPatterns.offsetToPanelId()} + , offsetToPanelFlags{panoramaUiPanelPatterns.offsetToPanelFlags()} { } @@ -26,7 +27,6 @@ struct PanoramaUiPanelImpl { Offset setParent; Offset setVisible; - Offset findChildInLayoutFile; Offset getAttributeString; Offset setAttributeString; @@ -34,4 +34,6 @@ struct PanoramaUiPanelImpl { PanelClassesVectorOffset classes; PanelStyleOffset panelStyle; ParentWindowOffset parentWindowOffset; + OffsetToPanelId offsetToPanelId; + OffsetToPanelFlags offsetToPanelFlags; }; diff --git a/Source/GameClasses/OffsetTypes/PanoramaUiPanelOffset.h b/Source/GameClasses/OffsetTypes/PanoramaUiPanelOffset.h index ac523ff03e8..46fed6a467c 100644 --- a/Source/GameClasses/OffsetTypes/PanoramaUiPanelOffset.h +++ b/Source/GameClasses/OffsetTypes/PanoramaUiPanelOffset.h @@ -12,3 +12,5 @@ using ChildPanelsVectorOffset = PanoramaUiPanelOffset; using PanelStyleOffset = PanoramaUiPanelOffset; using ParentWindowOffset = PanoramaUiPanelOffset; +using OffsetToPanelId = PanoramaUiPanelOffset; +using OffsetToPanelFlags = PanoramaUiPanelOffset; diff --git a/Source/GameClasses/PanoramaUiPanel.h b/Source/GameClasses/PanoramaUiPanel.h index d0bfa84e992..01d24d50978 100644 --- a/Source/GameClasses/PanoramaUiPanel.h +++ b/Source/GameClasses/PanoramaUiPanel.h @@ -29,9 +29,9 @@ struct PanoramaUiPanel { [[nodiscard]] PanoramaUiPanel findChildInLayoutFile(const char* childId) const noexcept { - if (const auto fn = impl().findChildInLayoutFile.of(thisptr->vmt).get()) - return PanoramaUiPanel{ (*fn)(thisptr, childId) }; - return PanoramaUiPanel{ nullptr }; + if (!impl().offsetToPanelFlags || !impl().offsetToPanelId) + return PanoramaUiPanel{nullptr}; + return PanoramaUiPanel{findChildInLayoutFileInternal(thisptr, childId)}; } [[nodiscard]] const char* getAttributeString(cs2::CPanoramaSymbol attributeName, const char* defaultValue) const noexcept @@ -86,6 +86,31 @@ struct PanoramaUiPanel { } private: + [[nodiscard]] cs2::CUIPanel* findChildInLayoutFileInternal(cs2::CUIPanel* parentPanel, const char* idToFind) const noexcept + { + const auto children = impl().childPanels.of(parentPanel).get(); + if (!children) + return nullptr; + + for (int i = 0; i < children->size; ++i) { + const auto panel = children->memory[i]; + const auto panelId = impl().offsetToPanelId.of(panel).get()->m_pString; + if (panelId && std::strcmp(panelId, idToFind) == 0) + return panel; + } + + for (int i = 0; i < children->size; ++i) { + const auto panel = children->memory[i]; + const auto panelFlags = *impl().offsetToPanelFlags.of(panel).get(); + if ((panelFlags & cs2::k_EPanelFlag_HasOwnLayoutFile) == 0) { + if (const auto found = findChildInLayoutFileInternal(panel, idToFind)) + return found; + } + } + + return nullptr; + } + [[nodiscard]] static const PanoramaUiPanelImpl& impl() noexcept { return PanoramaUiPanelImpl::instance(); diff --git a/Source/MemoryPatterns/Linux/PanoramaUiPanelPatternsLinux.h b/Source/MemoryPatterns/Linux/PanoramaUiPanelPatternsLinux.h index 3329c3aebdc..9a08fedd71b 100644 --- a/Source/MemoryPatterns/Linux/PanoramaUiPanelPatternsLinux.h +++ b/Source/MemoryPatterns/Linux/PanoramaUiPanelPatternsLinux.h @@ -19,11 +19,6 @@ struct PanoramaUiPanelPatterns { return patternFinders.clientPatternFinder("F6 48 8B 78 ? 48 8B 07 FF 90 ? ? ? ? E9 ? ? ? ? ? 8D"_pat).add(10).template as(); } - [[nodiscard]] std::int32_t* findChildInLayoutFile() const noexcept - { - return patternFinders.clientPatternFinder("49 89 84 24 ? ? ? ? 48 8B 07 FF 90 ? ? ? ? 49 8B 7C 24 ? 48 8D 35 ? ? ? ? 48 8B 07 FF 90 ? ? ? ? 48 85 C0 0F 84 ? ? ? ? 48 89 C7 48 8B 00 FF 50 50 49 89 C6 48 8D 05 ? ? ? ? 0F B7 18"_pat).add(34).template as(); - } - [[nodiscard]] std::int32_t* getAttributeString() const noexcept { return patternFinders.clientPatternFinder("FF 90 ? ? ? ? 41 80 BC 24 ? ? ? ? ? 48 89 C2"_pat).add(2).template as(); @@ -53,5 +48,14 @@ struct PanoramaUiPanelPatterns { { return patternFinders.panoramaPatternFinder("4D 89 ? 24 ? 4D 85 ? 0F 84 ? ? ? ? 4C"_pat).add(4).template readOffset(); } -}; + + [[nodiscard]] OffsetToPanelId offsetToPanelId() const noexcept + { + return patternFinders.panoramaPatternFinder("00 48 83 7B ? 00 74 ? 48 8D 7B ? 5B 41 5C 41"_pat).add(4).template readOffset(); + } + [[nodiscard]] OffsetToPanelFlags offsetToPanelFlags() const noexcept + { + return patternFinders.panoramaPatternFinder("D8 41 F6 85 ? ? ? ?"_pat).add(4).template readOffset(); + } +}; diff --git a/Source/MemoryPatterns/Windows/PanoramaUiPanelPatternsWindows.h b/Source/MemoryPatterns/Windows/PanoramaUiPanelPatternsWindows.h index d17e6e22e79..e6053b8d88f 100644 --- a/Source/MemoryPatterns/Windows/PanoramaUiPanelPatternsWindows.h +++ b/Source/MemoryPatterns/Windows/PanoramaUiPanelPatternsWindows.h @@ -19,11 +19,6 @@ struct PanoramaUiPanelPatterns { return patternFinders.clientPatternFinder("01 FF 90 ? ? ? ? 45 33 C0 33 D2 ? 8B ? E8"_pat).add(3).template as(); } - [[nodiscard]] std::int32_t* findChildInLayoutFile() const noexcept - { - return patternFinders.clientPatternFinder("48 8B 48 ? 48 8D 15 ? ? ? ? 4C 89 74 24 ? 48 8B 01 FF 90 ? ? ? ? 48 85"_pat).add(21).template as(); - } - [[nodiscard]] std::int32_t* getAttributeString() const noexcept { return patternFinders.clientPatternFinder("12 48 8B 01 FF 90 ? ? ? ? 48 8B D0 48 85 C0"_pat).add(6).template as(); @@ -53,4 +48,14 @@ struct PanoramaUiPanelPatterns { { return patternFinders.panoramaPatternFinder("48 89 ? ? 48 85 ? 75 ? 48 85"_pat).add(3).template readOffset(); } + + [[nodiscard]] OffsetToPanelId offsetToPanelId() const noexcept + { + return patternFinders.panoramaPatternFinder("? 48 8B 6C 24 ? 74 ? FF 15 ? ? ? ? 48 8D"_pat).template readOffset(); + } + + [[nodiscard]] OffsetToPanelFlags offsetToPanelFlags() const noexcept + { + return patternFinders.panoramaPatternFinder("06 48 8B 0C 07 F6 81 ? ? ? ?"_pat).add(7).template readOffset(); + } };