Итак. Возвращаемся к картинкам. Я обосрался

  1. Неправильная структура листа. Да, вот так банально. Я почему-то забыл полностью как должен выглядеть нормальный список.
    struct List {
      uint8_t* next;
      uint8_t* prev;
      void* v;
    };

Тогда алгоритм действий такой

gui = *(UnityPlayer.dll + 0x1f03188); // Getting s_GUIManager

List *newNode = new List;
newNode->next = nullptr;
newNode->v = gui; // Just a way to bypass check of "empty" list

// Very crude way of adding new element to some sort of chain
List* pLVar1 = (List*) ((List*) gui)->next;
param_1->prev = (uint8_t*) gui;
pLVar1->prev = (uint8_t*) param_1;
((List*) (param_1->prev))->next = (uint8_t*) param_1;
  1. Хукнуть придётся целых 2 метода

Мы добились того что IMGUI::BeginWindows(GUIState *param_1,bool param_2,bool param_3) Успешно вызывается. Но если посмотреть на декомпиляцию, то видно что там есть проверка

*(param_1 + 0x18) != 0

Это некоторое поле GUIWindowState, которое будет пустое. Как его норм заполнить я хз и мне похуй Из-за него не вызывается GUIClipState::BeginOnGUI(GUIClipState *this,InputEvent *param_1) Где мы и будем делать отрисовку текстур

Я просто делаю так

void HookedBeginWindows(void* self, bool a, bool b)
{
  originalBeginWindows(self, a, b);

  if((void*) (reinterpret_cast<uint8_t*>(self) + 0x250) == nullptr) {
    LK_ERROR("No inputEvent");
    return;
  }

  void* inputEvent = *(void**) (reinterpret_cast<uint8_t*>(self) + 0x250);
  void* guiClipState = (void*) (reinterpret_cast<uint8_t*>(self) + 0xd8);

  HookedBeginOnGui(guiClipState, inputEvent); // Calling BeginOnGui ourself
}
  1. Сам BeginOnGui
void HookedBeginOnGui(void* self, void* inputEvent)
{
  originalBeginOnGui(self, inputEvent);

  if(!inputEvent || ((uint8_t) ((uint8_t*) inputEvent)[0]) != 7) return;

  // Extract texture
  // texture.DrawClipped
}

Ну вот, в принципе и всё, вроде. Работает стабильно. Но я мог обосраться ещё раз. Кто знает, кто знает