#pragma once class MainMenuPatch : public RE::MainMenu { public: static void Install() { REL::Relocation vtbl(RE::VTABLE_MainMenu[0]); _ProcessMessage = vtbl.write_vfunc(0x4, &ProcessMessageEx); } private: void ProcessEx(RE::GPtr a_movie) { RE::GFxValue entryList; if (!uiMovie->Invoke("_root.MenuHolder.Menu_mc.MainList.__get__entryList", &entryList, nullptr, 0)) { return; } std::array values{ "$CREATIONS", "$CREATION CLUB", "$DOWNLOADABLE CONTENT", "$MOD MANAGER", "$HELP", }; bool bUpdated = false; const auto size = entryList.GetArraySize(); for (uint32_t i = size; i > 0; i--) { RE::GFxValue entry; if (!entryList.GetElement(i - 1, &entry)) continue; RE::GFxValue entryText; if (!entry.GetMember("text", &entryText)) continue; const std::string text = entryText.GetString(); if (text.empty()) continue; for (const auto name : values) { if (text == name) { bUpdated = true; entryList.RemoveElement(i - 1); } } } if (bUpdated) { uiMovie->Invoke("_root.MenuHolder.Menu_mc.MainList.InvalidateData", nullptr, nullptr, 0); } } RE::UI_MESSAGE_RESULTS ProcessMessageEx(RE::UIMessage* a_message) { if (a_message->type == RE::UI_MESSAGE_TYPE::kShow) { _show = true; } else if (_show && (iIterations < 15) && a_message->type == RE::UI_MESSAGE_TYPE::kUpdate) { iIterations++; ProcessEx(uiMovie); } return _ProcessMessage(this, a_message); } inline static REL::Relocation _ProcessMessage; inline static bool _show{ false }; inline static uint32_t iIterations{ 0 }; };