rodecomp/Source/UI/Window/UIWindowMgr.cpp
ragnarok-clanker baa5c7db01 Decompile fn_17234 (UIWindowMgr::sub_AA6B80)
Batch #7063 by Landruca: 0 byte-identical, 1 confirmed by peer review.

- fn_17234 UIWindowMgr::sub_AA6B80: logic confirmed by peer review

Peer-reviewed-by: eAthena, Snow
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
2026-10-31 03:44:37 +00:00

1489 lines
44 KiB
C++

#include "Render/Renderer.h"
#include "UI/Chat/UISubChatHisWnd.h"
#include "Client/Browser/WebBrowser.h"
#include "Client/Input/Mouse.h"
#include "Client/Mode/ModeMgr.h"
#include "Client/Replay.h"
#include "Client/ReplayPacketRecorder.h"
#include "Client/Session.h"
#include "Contents/Configuration/ServiceConfiguration.h"
#include "Contents/Configuration/ServiceOptions.h"
#include "Network/Connection/Connection.h"
#include "Network/Packets/PacketId.h"
#include "Network/Packets/PacketLengths.h"
#include "Render/TextureQuad.h"
#include "Render/Textures/Texture.h"
#include "Render/Textures/TextureCache.h"
#include "UI/Dialogs/UIMemorialDunWnd.h"
#include "UI/Layout/SnapMgr.h"
#include "UI/Lists/UIDropDownBox.h"
#include "UI/Chat/ChatSuggestions.h"
#include "UI/Window/MiniPartyWndAreaMgr.h"
#include "UI/Window/WindowDialogs.h"
#include "UI/Window/UIWindow.h"
#include "UI/Window/UIWindowMgr.h"
#include "Render/DeviceContext/DCSurface.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <new>
#include <timeapi.h>
#include "Render/Textures/Surface.h"
namespace {
#pragma pack(push, 1)
struct AddFriendPacket {
/* 0000 */ std::int16_t id;
/* 0002 */ char name[24];
};
#pragma pack(pop)
static_assert(sizeof(AddFriendPacket) == 26);
static_assert(offsetof(AddFriendPacket, name) == 2);
}
// GLOBAL: gl_24525
CMiniPartyWndAreaMgr* g_miniPartyWndAreaMgr = nullptr;
// GLOBAL: gl_24366
UIWindowMgr g_windowMgr;
// GLOBAL: gl_25090
unsigned char g_windowCloseByte;
// GLOBAL: gl_24686
int g_closeWindow137State;
// OFFSET: 0x00A94FD0
// FUNCTION: fn_17179
void UIWindowMgr::InitializeWindowPolicy() {
for (WindowPolicyEntry& entry : this->policy) {
entry = {};
entry.actions[3] = 1;
}
this->policy[15].actions[3] = 0;
this->policy[16].actions[3] = 0;
this->policy[17].actions[3] = 0;
this->policy[22].actions[3] = 0;
this->policy[23].actions[3] = 0;
this->policy[24].actions[3] = 0;
this->policy[25].actions[3] = 0;
this->policy[27].actions[3] = 0;
this->policy[28].actions[3] = 0;
this->policy[31].actions[3] = 0;
this->policy[32].actions[3] = 0;
this->policy[35].actions[3] = 0;
this->policy[39].actions[3] = 0;
this->policy[41].actions[3] = 0;
this->policy[43].actions[3] = 1;
this->policy[44].actions[3] = 0;
this->policy[45].actions[3] = 0;
this->policy[56].actions[3] = 0;
this->policy[70].actions[3] = 0;
this->policy[73].actions[3] = 0;
this->policy[74].actions[3] = 0;
this->policy[79].actions[3] = 0;
this->policy[80].actions[3] = 0;
this->policy[88].actions[3] = 0;
this->policy[90].actions[3] = 0;
this->policy[94].actions[3] = 0;
this->policy[99].actions[3] = 0;
this->policy[100].actions[3] = 0;
this->policy[105].actions[3] = 0;
this->policy[107].actions[3] = 0;
this->policy[109].actions[3] = 0;
this->policy[110].actions[3] = 0;
this->policy[111].actions[3] = 0;
this->policy[113].actions[3] = 0;
this->policy[119].actions[3] = 0;
this->policy[125].actions[3] = 0;
this->policy[160].actions[3] = 1;
this->policy[161].actions[3] = 1;
this->policy[174].actions[3] = 0;
this->policy[176].actions[3] = 0;
this->policy[178].actions[3] = 0;
this->policy[177].actions[3] = 0;
this->policy[179].actions[3] = 0;
this->policy[203].actions[3] = 0;
this->policy[157].actions[3] = 0;
this->policy[209].actions[3] = 0;
this->policy[210].actions[3] = 0;
this->policy[275].actions[3] = 0;
this->policy[315].actions[3] = 0;
this->policy[8].actions[5] = 1;
this->policy[22].actions[5] = 1;
this->policy[23].actions[5] = 1;
this->policy[24].actions[5] = 1;
this->policy[31].actions[5] = 1;
this->policy[10011].actions[5] = 1;
this->policy[33].actions[5] = 1;
this->policy[40].actions[5] = 1;
this->policy[41].actions[5] = 1;
this->policy[42].actions[5] = 1;
this->policy[43].actions[5] = 1;
this->policy[44].actions[5] = 1;
this->policy[160].actions[5] = 1;
this->policy[161].actions[5] = 1;
this->policy[174].actions[5] = 1;
this->policy[175].actions[5] = 1;
this->policy[178].actions[5] = 1;
this->policy[36].actions[5] = 1;
this->policy[159].actions[5] = 1;
this->policy[80].actions[5] = 1;
this->policy[1].actions[6] = 1;
this->policy[4].actions[6] = 1;
this->policy[15].actions[6] = 1;
this->policy[27].actions[6] = 1;
this->policy[28].actions[6] = 1;
this->policy[31].actions[6] = 1;
this->policy[10011].actions[6] = 1;
this->policy[41].actions[6] = 1;
this->policy[55].actions[6] = 1;
this->policy[56].actions[6] = 1;
this->policy[84].actions[6] = 1;
this->policy[88].actions[6] = 1;
this->policy[100].actions[6] = 1;
this->policy[101].actions[6] = 1;
this->policy[113].actions[6] = 1;
this->policy[116].actions[6] = 1;
this->policy[120].actions[6] = 1;
this->policy[121].actions[6] = 1;
this->policy[128].actions[6] = 1;
this->policy[125].actions[6] = 1;
this->policy[130].actions[6] = 1;
this->policy[145].actions[6] = 1;
this->policy[168].actions[6] = 1;
this->policy[169].actions[6] = 1;
this->policy[174].actions[6] = 1;
this->policy[181].actions[6] = 1;
this->policy[191].actions[6] = 1;
this->policy[203].actions[6] = 1;
this->policy[16].actions[7] = 1;
this->policy[17].actions[7] = 1;
this->policy[23].actions[7] = 1;
this->policy[24].actions[7] = 1;
this->policy[25].actions[7] = 1;
this->policy[28].actions[7] = 1;
this->policy[31].actions[7] = 1;
this->policy[10011].actions[7] = 1;
this->policy[32].actions[7] = 1;
this->policy[33].actions[7] = 1;
this->policy[35].actions[7] = 1;
this->policy[39].actions[7] = 1;
this->policy[41].actions[7] = 1;
this->policy[43].actions[7] = 1;
this->policy[44].actions[7] = 1;
this->policy[45].actions[7] = 1;
this->policy[70].actions[7] = 1;
this->policy[73].actions[7] = 1;
this->policy[74].actions[7] = 1;
this->policy[79].actions[7] = 1;
this->policy[80].actions[7] = 1;
this->policy[94].actions[7] = 1;
this->policy[105].actions[7] = 1;
this->policy[107].actions[7] = 1;
this->policy[109].actions[7] = 1;
this->policy[110].actions[7] = 1;
this->policy[111].actions[7] = 1;
this->policy[119].actions[7] = 1;
this->policy[161].actions[7] = 1;
this->policy[174].actions[7] = 1;
this->policy[176].actions[7] = 1;
this->policy[178].actions[7] = 1;
this->policy[177].actions[7] = 1;
this->policy[179].actions[7] = 1;
this->policy[203].actions[7] = 1;
this->policy[157].actions[7] = 1;
this->policy[209].actions[7] = 1;
this->policy[210].actions[7] = 1;
this->policy[321].actions[7] = 1;
this->policy[322].actions[7] = 1;
this->policy[307].actions[7] = 1;
this->policy[247].actions[7] = 1;
this->policy[316].actions[7] = 1;
}
// OFFSET: 0x00AA5F70
// FUNCTION: fn_17227
UIWindow* UIWindowMgr::LookupWindow(int id) {
if (g_replayAnimationScaling != 0 && id == 600) {
return this->window_4F16C;
}
switch (id) {
case 1:
return this->window_01C8;
case 3:
return this->window_01CC;
case 27:
return this->window_0274;
case 28:
return this->window_027C;
case 30:
return this->window_0278;
case 33:
return this->window_0288;
case 34:
return this->window_02C8;
case 37:
return this->window_02C4;
case 60:
return this->window_0320;
case 61:
return this->window_0324;
case 63:
return this->window_032C;
case 88:
return this->window_038C;
case 103:
return this->window_0388;
case 113:
return this->window_03C0;
case 114:
return this->window_03C4;
case 125:
return this->window_03C8;
case 126:
return this->window_03CC;
case 180:
return this->window_01D0;
case 196:
return this->window_4F18C;
case 203:
return this->window_4F174;
case 204:
return this->window_0428;
case 237:
return this->window_0444;
case 253:
return this->window_044C;
case 273:
return this->window_4F1CC;
case 274:
return this->window_4F1D0;
case 275:
return this->window_0448;
case 277:
return this->window_03D4;
case 284:
return this->window_4F1E8;
case 285:
return this->window_4F1EC;
case 286:
return this->window_4F1F0;
case 287:
return this->window_4F1F4;
case 288:
return this->window_4F1F8;
case 315:
return this->window_0468;
case 325:
return this->window_4F25C;
case 359:
return this->window_4F288;
case 10024:
return this->window_4F2AC;
case 301:
if (!this->snapExcluded.empty()) {
return this->snapExcluded.front();
}
[[fallthrough]];
case 318:
return this->window_4F254;
default: {
const auto found = this->windows.find(id);
return found != this->windows.end() ? found->second : nullptr;
}
}
}
// OFFSET: 0x00AA1800
// FUNCTION: fn_17209
void UIWindowMgr::ResetWindows() {
this->windows.clear();
this->window_01B8 = nullptr;
this->inputWindow = nullptr;
this->hoverWindow = nullptr;
this->window_01C8 = nullptr;
this->unknown_01BC = 0;
this->unknown_01DC = 0;
this->unknown_01D4 = 0;
this->unknown_01E0 = 0;
this->unknown_01E4 = 0;
this->unknown_01C4 = 0;
this->unknown_01C0 = 0;
this->window_01EC = nullptr;
this->unknown_01F0 = 0;
this->unknown_01F4 = 0;
this->unknown_01F8 = 0;
this->unknown_01FC = 0;
this->unknown_0208 = 0;
this->unknown_020C = 0;
this->unknown_0210 = 0;
this->unknown_0214 = 0;
this->unknown_0218 = 0;
this->unknown_021C = 0;
this->unknown_0220 = 0;
this->unknown_0228 = 0;
this->unknown_022C = 0;
this->window_0230 = nullptr;
this->unknown_0234 = 0;
this->unknown_0238 = 0;
this->unknown_023C = 0;
this->unknown_0240 = 0;
this->unknown_0244 = 0;
this->unknown_0248 = 0;
this->unknown_024C = 0;
this->unknown_0250 = 0;
this->unknown_0254 = 0;
this->unknown_0258 = 0;
this->unknown_025C = 0;
this->unknown_0260 = 0;
this->unknown_0264 = 0;
this->unknown_0268 = 0;
this->unknown_026C = 0;
this->window_0274 = nullptr;
this->window_0278 = nullptr;
this->window_027C = nullptr;
this->unknown_0280 = 0;
this->unknown_0284 = 0;
this->window_0288 = nullptr;
this->unknown_028C = 0;
this->unknown_0290 = 0;
this->unknown_0294 = 0;
this->unknown_0298 = 0;
this->unknown_029C = 0;
this->unknown_02A0 = 0;
this->unknown_02A4 = 0;
this->unknown_02A8 = 0;
this->unknown_02AC = 0;
this->window_02C4 = nullptr;
this->window_02C8 = nullptr;
this->unknown_02CC = 0;
this->unknown_02D0 = 0;
this->unknown_02D4 = 0;
this->unknown_02D8 = 0;
this->unknown_02DC = 0;
this->unknown_02E0 = 0;
this->unknown_02E4 = 0;
this->unknown_02E8 = 0;
this->unknown_02EC = 0;
this->window_01E8 = nullptr;
this->unknown_02F0 = 0;
this->unknown_02F4 = 0;
this->unknown_02F8 = 0;
this->unknown_02FC = 0;
this->unknown_0300 = 0;
this->unknown_0308 = 0;
this->unknown_0304 = 0;
this->window_03A4 = 0;
this->unknown_03A8 = 0;
this->window_03AC = 0;
this->unknown_030C = 0;
this->unknown_0310 = 0;
this->unknown_0314 = 0;
this->unknown_0318 = 0;
this->unknown_031C = 0;
this->window_0320 = nullptr;
this->window_0324 = nullptr;
this->unknown_0328 = 0;
this->window_032C = nullptr;
this->unknown_0330 = 0;
this->unknown_0334 = 0;
this->unknown_0338 = 0;
this->unknown_033C = 0;
this->unknown_0340 = 0;
this->unknown_0344 = 0;
this->unknown_0348 = 0;
this->unknown_034C = 0;
this->unknown_0350 = 0;
this->unknown_0354 = 0;
this->unknown_0358 = 0;
this->unknown_035C = 0;
this->unknown_0360 = 0;
this->unknown_0364 = 0;
this->unknown_0368 = 0;
this->unknown_036C = 0;
this->unknown_0370 = 0;
this->window_038C = nullptr;
this->unknown_0390 = 0;
this->unknown_0394 = 0;
this->unknown_0200 = 0;
this->unknown_0398 = 0;
this->unknown_039C = 0;
this->unknown_0380 = 0;
this->unknown_0384 = 0;
this->unknown_03B0 = 0;
this->unknown_03B4 = 0;
this->window_03C0 = nullptr;
this->window_03C4 = nullptr;
this->window_03C8 = nullptr;
this->window_03CC = nullptr;
this->unknown_03D0 = 0;
this->unknown_03B8 = 0;
this->unknown_03BC = 0;
this->window_03D4 = nullptr;
this->window_03D8 = nullptr;
this->unknown_03E0 = 0;
this->unknown_03E4 = 0;
this->unknown_03E8 = 0;
this->unknown_03F0 = 0;
this->unknown_03EC = 0;
this->unknown_03F8 = 0;
this->unknown_03FC = 0;
this->modal = 0;
this->unknown_0404 = 0;
this->unknown_0408 = 0;
this->unknown_040C = 0;
this->unknown_0410 = 0;
this->unknown_0414 = 0;
this->unknown_0418 = 0;
this->unknown_041C = 0;
this->unknown_0424 = 0;
this->retainedWindows.clear();
this->unknown_02B0 = 0;
this->unknown_02B4 = 0;
this->unknown_02B8 = 0;
this->unknown_02BC = 0;
this->unknown_02C0 = 0;
this->window_4F18C = nullptr;
this->window_4F164 = nullptr;
this->unknown_01D8 = 0;
this->window_0428 = nullptr;
this->window_4F174 = nullptr;
this->unknown_0440 = 0;
this->window_0444 = nullptr;
this->window_0448 = nullptr;
this->messageBoxes.clear();
this->window_044C = nullptr;
this->unknown_0204 = 0;
this->unknown_0378 = 0;
this->unknown_0374 = 0;
this->window_4F170 = nullptr;
this->unknown_0450 = 0;
this->unknown_0454 = 0;
this->unknown_0458 = 0;
this->unknown_045C = 0;
this->unknown_0430 = 0;
this->unknown_0434 = 0;
this->unknown_0438 = 0;
this->unknown_0460 = 0;
this->unknown_0464 = 0;
this->hiddenWindows.clear();
const bool hadWindow0270 = this->window_0270 != nullptr;
this->unknown_0508 = 0;
this->window_4F1CC = nullptr;
this->window_4F1D0 = nullptr;
this->window_4F1D4 = nullptr;
this->window_4F1E8 = nullptr;
this->window_4F1F0 = nullptr;
this->window_4F1F4 = nullptr;
this->window_4F1FC = nullptr;
this->window_4F250 = nullptr;
this->window_4F254 = nullptr;
this->window_4F258 = nullptr;
this->window_01CC = nullptr;
this->window_0468 = nullptr;
this->window_4F25C = nullptr;
this->unknown_042C = 0;
this->window_4F260 = nullptr;
this->window_4F264 = nullptr;
this->window_4F268 = nullptr;
this->window_4F26C = nullptr;
this->window_4F270 = nullptr;
this->window_4F274 = nullptr;
this->window_4F278 = nullptr;
this->window_4F27C = nullptr;
this->unknown_0420 = 0;
this->unknown_043C = 0;
this->window_01D0 = nullptr;
this->unknown_0224 = 0;
if (hadWindow0270) {
if (CMode* mode = g_modeMgr.GetGameMode()) {
mode->SendMsg(292, 0, 0, 0, 0);
}
}
const bool hadWindow276 = this->window_4F1E4 != nullptr;
this->window_0270 = nullptr;
this->unknown_037C = 0;
this->window_0388 = nullptr;
this->unknown_03A0 = 0;
if (hadWindow276) {
this->visible_276 = 0;
this->window_4F1E4 = nullptr;
}
this->window_4F1F8 = nullptr;
this->window_0A30 = nullptr;
this->window_4F2AC = nullptr;
}
// OFFSET: 0x00A88490
// FUNCTION: fn_17086
UIWindowMgr::UIWindowMgr()
: activeWindowId(0), retainedPersistentWindow(false), window_03DC(nullptr), unknown_046C(-1), unknown_0470(-1), unknown_0526(true),
window_0A30(nullptr), unknown_4F210(false), unknown_4F211(false), window_4F2AC(nullptr) {
this->ResetWindows();
this->unknown_0478 = nullptr;
this->unknown_047C = 0;
this->unknown_0480 = 0;
this->unknown_04DC.assign("", 0);
this->unknown_004C = 1;
this->unknown_0038 = 98;
this->unknown_0030 = 0;
this->unknown_0034 = 0;
this->unknown_003C = 1;
this->unknown_0050 = 1.0f;
this->unknown_0054 = 1;
this->unknown_005C = 0xAAFFFFFFu;
this->unknown_0060 = 1;
this->unknown_04F8 = 0;
this->unknown_04F4 = 0;
this->unknown_04FC = 0;
this->unknown_03F4 = 1;
this->unknown_03F6 = 0;
this->unknown_0068 = g_language == 2;
this->unknown_0048 = 0;
this->unknown_049C = 0;
this->unknown_049E = g_serviceType != 0 ? 0 : -25;
this->unknown_04A0 = {};
this->unknown_04A4 = {};
this->unknown_04A8 = {};
this->unknown_04AC = {};
this->unknown_04B0 = 0;
this->unknown_04B4 = 203;
this->unknown_04B8 = 115;
this->unknown_04BC = 0;
this->unknown_04C0 = 0;
this->windowHistory.clear();
this->lastWindowId = -1;
this->unknown_0024 = 0;
this->unknown_0026 = 1;
this->unknown_0508 = 0;
this->window_4F168 = nullptr;
this->window_4F164 = nullptr;
this->window_4F16C = nullptr;
this->InitializeWindowPolicy();
this->window_4F174 = nullptr;
this->unknown_09CC = 0;
this->browser_09D0 = nullptr;
this->currentHitUid = 0;
this->previousHitUid = 0;
this->visible_276 = 0;
this->window_4F1EC = nullptr;
this->window_4F250 = nullptr;
this->unknown_0058 = 0;
this->unknown_4F238 = 151;
this->unknown_4F23C = 37;
}
// OFFSET: 0x007375E0
// FUNCTION: fn_07649
CMiniPartyWndAreaMgr::CMiniPartyWndAreaMgr() {
SetRect(&this->area, 0, 0, g_windowMgr.unknown_047C, g_windowMgr.unknown_0480);
}
// OFFSET: 0x00AA66D0
// FUNCTION: fn_17233
void UIWindowMgr::Shutdown() {
if (!this->modalWindows.empty() && this->modalWindows.back()) {
this->activeWindowId = 185;
}
if (this->window_0A30 && this->window_0A30->geometry.visible) {
static_cast<CUIDropDownBox*>(this->window_0A30)->Detach();
this->window_0A30->Show(0);
}
for (UIWindow*& window : this->rendered) {
if (!this->modalWindows.empty() && this->modalWindows.back() && this->persistentWindows.find(window) != this->persistentWindows.end()) {
this->retainedPersistentWindow = true;
} else if (this->modalWindows.empty() || !this->modalWindows.back() ||
std::find(this->modalWindows.begin(), this->modalWindows.end(), window) == this->modalWindows.end()) {
this->persistentWindows.erase(window);
window->Slot11();
delete window;
window = nullptr;
}
}
for (auto& entry : this->browsers) {
delete entry.second;
entry.second = nullptr;
}
this->browsers.clear();
if (this->browser_09D0) {
delete this->browser_09D0;
this->browser_09D0 = nullptr;
}
for (auto entry = this->overlays.begin(); entry != this->overlays.end();) {
delete entry->second;
entry = this->overlays.erase(entry);
}
this->rendered.clear();
this->retired.clear();
this->snapRectangles.clear();
this->messageBoxes.clear();
this->ResetWindows();
for (UIWindow*& window : this->snapExcluded) {
this->Destroy(window);
window = nullptr;
}
this->snapExcluded.clear();
}
// OFFSET: 0x00AA6B80
// FUNCTION: fn_17234
void UIWindowMgr::sub_AA6B80() {
if (!this->modalWindows.empty() && this->modalWindows.back()) {
this->activeWindowId = 185;
}
this->SaveVisibleWindowIds();
if (!this->window_01C8) {
this->Shutdown();
return;
}
if (this->window_0A30 && this->window_0A30->geometry.visible) {
static_cast<CUIDropDownBox*>(this->window_0A30)->Detach();
this->window_0A30->Show(0);
}
for (auto entry = this->rendered.begin(); entry != this->rendered.end();) {
bool unregistered = true;
for (unsigned index = 0; index < this->retainedWindows.size(); ++index) {
if (*entry == this->retainedWindows[static_cast<int>(index)]) {
unregistered = false;
}
}
if (!unregistered) {
++entry;
continue;
}
UIWindow* window = *entry;
if (this->window_01C8 == window || window == this->window_4F1EC || window->geometry.id == 67) {
++entry;
continue;
}
if (window == reinterpret_cast<UIWindow*>(this->unknown_03F8) && g_closeWindow137State != 0) {
g_memorialDunWndX = window->geometry.x;
g_memorialDunWndY = window->geometry.y;
}
if (!this->modalWindows.empty() && this->modalWindows.back()) {
if (this->persistentWindows.find(window) != this->persistentWindows.end()) {
this->retainedPersistentWindow = true;
++entry;
continue;
}
if (std::find(this->modalWindows.begin(), this->modalWindows.end(), window) != this->modalWindows.end()) {
++entry;
continue;
}
}
this->persistentWindows.erase(window);
window->Slot11();
delete window;
entry = this->rendered.erase(entry);
}
for (auto entry = this->retired.begin(); entry != this->retired.end();) {
bool unregistered = true;
for (unsigned index = 0; index < this->retainedWindows.size(); ++index) {
if (*entry == this->retainedWindows[static_cast<int>(index)]) {
unregistered = false;
}
}
if (!unregistered || this->window_01C8 == *entry) {
++entry;
continue;
}
entry = this->retired.erase(entry);
}
for (auto entry = this->snapRectangles.begin(); entry != this->snapRectangles.end();) {
if (this->window_01C8 == entry->first) {
++entry;
} else {
entry = this->snapRectangles.erase(entry);
}
}
std::uint32_t saved03E4 = 0;
if (this->unknown_03E4) {
saved03E4 = this->unknown_03E4;
}
std::uint32_t saved03E8 = 0;
if (this->unknown_03E8) {
saved03E8 = this->unknown_03E8;
}
std::uint32_t saved03F0 = 0;
if (this->unknown_03F0) {
saved03F0 = this->unknown_03F0;
}
UIWindow* saved01C8 = nullptr;
if (this->window_01C8) {
saved01C8 = this->window_01C8;
}
std::map<int, UIWindow*> savedWindows(this->retainedWindows);
this->ResetWindows();
this->window_01C8 = saved01C8;
this->unknown_03E4 = saved03E4;
this->unknown_03F0 = saved03F0;
this->unknown_03E8 = saved03E8;
this->retainedWindows = savedWindows;
for (UIWindow*& window : this->snapExcluded) {
this->Destroy(window);
window = nullptr;
}
this->snapExcluded.clear();
}
// OFFSET: 0x00A8A1C0
// FUNCTION: fn_17099
UIWindowMgr::~UIWindowMgr() {
if (!g_miniPartyWndAreaMgr) {
g_miniPartyWndAreaMgr = new (std::nothrow) CMiniPartyWndAreaMgr;
}
if (g_miniPartyWndAreaMgr) {
delete g_miniPartyWndAreaMgr;
g_miniPartyWndAreaMgr = nullptr;
}
this->Shutdown();
if (this->unknown_0478) {
delete this->unknown_0478;
this->unknown_0478 = nullptr;
}
for (auto& entry : this->savedRectangles) {
delete entry.second;
}
this->savedRectangles.clear();
}
// OFFSET: 0x00A8B0A0
// FUNCTION: fn_17121
void UIWindowMgr::SelectWhisperName(const char* name) {
if (!name || !this->window_01C8) {
return;
}
char* list = *reinterpret_cast<char**>(reinterpret_cast<char*>(this->window_01C8) + 0xC0);
std::vector<std::string>& names = *reinterpret_cast<std::vector<std::string>*>(list + 0x11C);
int index = 0;
bool found = false;
for (const std::string& entry : names) {
if (entry == name) {
found = true;
break;
}
++index;
}
if (!found) {
names.push_back(std::string(name));
}
UIWindow* field = *reinterpret_cast<UIWindow**>(reinterpret_cast<char*>(this->window_01C8) + 0xC0);
*reinterpret_cast<int*>(reinterpret_cast<char*>(field) + 0x128) = index;
this->window_01C8->SendMsg(field, 0x27, index, 0, 0, 0);
}
// OFFSET: 0x00A8B240
// FUNCTION: fn_17122
void UIWindowMgr::AddWhisperName(const char* name) {
if (!this->window_01C8) {
return;
}
char* list = *reinterpret_cast<char**>(reinterpret_cast<char*>(this->window_01C8) + 0xC0);
std::vector<std::string>& names = *reinterpret_cast<std::vector<std::string>*>(list + 0x11C);
for (const std::string& entry : names) {
if (entry == name) {
return;
}
}
names.push_back(std::string(name));
const unsigned count = static_cast<unsigned>(names.size());
unsigned& current = *reinterpret_cast<unsigned*>(*reinterpret_cast<char**>(reinterpret_cast<char*>(this->window_01C8) + 0xC0) + 0x128);
if (count - 1 <= current) {
current = count;
}
}
// OFFSET: 0x00A8B840
// FUNCTION: fn_17124
void UIWindowMgr::RegisterNamedWindow(std::string name, UIWindow* window) {
if (this->namedWindows.find(name) == this->namedWindows.end()) {
this->namedWindows[name] = window;
}
}
// OFFSET: 0x00AA9B00
// FUNCTION: fn_17254
void UIWindowMgr::NotifyMode() {
if (CMode* mode = g_modeMgr.GetGameMode()) {
mode->SendMsg(292, 0, 0, 0, 0);
}
}
// OFFSET: 0x00A8AD60
// FUNCTION: fn_17116
void UIWindowMgr::ShowTransient(UIWindow* window) {
if (this->window_4F250) {
this->Schedule(this->window_4F250);
}
this->window_4F250 = window;
window->geometry.targetAlpha = 128;
window->geometry.alphaStart = timeGetTime();
this->rendered.push_back(this->window_4F250);
}
// OFFSET: 0x00A8ADB0
// FUNCTION: fn_17117
void UIWindowMgr::RequestAddFriend(const char* name) {
AddFriendPacket packet;
packet.id = ID_CZ_ADD_FRIENDS;
std::memcpy(packet.name, name, sizeof(packet.name));
GetRagConnection().Send(g_packetLengths.FixedLength(packet.id), &packet);
}
// OFFSET: 0x00A8AE20
// FUNCTION: fn_17118
void UIWindowMgr::AddOverlay(int id, UIWindow* window) {
this->overlays.emplace(id, window);
}
// OFFSET: 0x00A8B9F0
// FUNCTION: fn_17126
void UIWindowMgr::AddRenderedFront(UIWindow* window) {
this->rendered.push_front(window);
}
// OFFSET: 0x00A8C150
// FUNCTION: fn_17129
void UIWindowMgr::ShowWindows189(unsigned char show) {
for (auto it = this->rendered.begin(); it != this->rendered.end(); ++it) {
if ((*it)->geometry.id != 189) {
continue;
}
if (show == 1) {
(*it)->Show(g_serviceOptions.Get(250) ? 1 : 0);
} else {
(*it)->Show(0);
}
}
}
// OFFSET: 0x00A8C310
// FUNCTION: fn_17131
void UIWindowMgr::DestroyPersistentWindows() {
while (!this->modalWindows.empty()) {
UIWindow* window = this->modalWindows.back();
this->persistentWindows.erase(window);
delete window;
this->modalWindows.pop_back();
}
for (UIWindow* window : this->persistentWindows) {
delete window;
}
this->persistentWindows.clear();
}
// OFFSET: 0x00A8CD70
// FUNCTION: fn_17140
void UIWindowMgr::RemoveSnapRectangle(UIWindow* window) {
if (g_serviceOptions.Get(141)) {
const auto entry = this->snapRectangles.find(window);
if (entry != this->snapRectangles.end()) {
this->snapRectangles.erase(entry);
}
}
}
// OFFSET: 0x00A8CDE0
// FUNCTION: fn_17141
void UIWindowMgr::ReleaseRetainedWindow(int id) {
const auto entry = this->retainedWindows.find(id);
if (entry != this->retainedWindows.end()) {
this->Schedule(entry->second);
this->retainedWindows.erase(entry);
}
}
// OFFSET: 0x00A8CE50
// FUNCTION: fn_17142
void UIWindowMgr::UnregisterNamedWindow(std::string name) {
const auto entry = this->namedWindows.find(name);
if (entry != this->namedWindows.end()) {
this->namedWindows.erase(entry);
}
}
// OFFSET: 0x00AAD8E0
// FUNCTION: fn_17285
void UIWindowMgr::SendMsgToNamedWindow(const char* name) {
if (this->namedWindows.find(name) != this->namedWindows.end()) {
this->namedWindows[name]->SendMsg(nullptr, 48, 0, 0, 0, 0);
}
}
// OFFSET: 0x00AAA280
// FUNCTION: fn_17267
void UIWindowMgr::SetWindows189Visible(unsigned char show) {
for (auto it = this->rendered.begin(); it != this->rendered.end(); ++it) {
if ((*it)->geometry.id == 189) {
(*it)->Show(show);
}
}
}
// OFFSET: 0x00AAA2D0
// FUNCTION: fn_17268
void UIWindowMgr::ShowWindowsWithId(int id, unsigned char show) {
for (UIWindow* window : this->rendered) {
if (id == window->geometry.id) {
window->Show(show);
}
}
}
namespace {
#pragma pack(push, 1)
struct ReplaySettingHeader {
/* 0000 */ std::int16_t tag;
/* 0002 */ int size;
ReplaySettingHeader() : tag(0), size(0) {
}
~ReplaySettingHeader() {
this->tag = 0;
this->size = 0;
}
void Read(const unsigned char* source) {
this->size = 0;
this->tag = 0;
std::memcpy(this, source, sizeof(*this));
}
};
#pragma pack(pop)
static_assert(sizeof(ReplaySettingHeader) == 6);
}
// OFFSET: 0x00AA80A0
// FUNCTION: fn_17240
void UIWindowMgr::CenterSurface0478() {
this->unknown_04FC = 0;
if (this->unknown_0478) {
int x = static_cast<int>(GetRenderSystemHolder()->Width() - this->unknown_047C) / 2;
int height = this->unknown_0480;
int y = static_cast<int>(GetRenderSystemHolder()->Height() - height) / 2;
reinterpret_cast<CSurface*>(this->unknown_0478)->Stretch(x, y, this->unknown_047C, height);
}
}
// OFFSET: 0x00AA8130
// FUNCTION: fn_17242
std::vector<unsigned char> UIWindowMgr::SaveReplaySettings() {
std::vector<unsigned char> data;
{
std::vector<unsigned char> chunk(6);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 25000;
*reinterpret_cast<int*>(&chunk[2]) = 0;
data.insert(data.end(), chunk.begin(), chunk.end());
}
{
std::vector<unsigned char> chunk(10);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 25010;
*reinterpret_cast<int*>(&chunk[2]) = 4;
*reinterpret_cast<int*>(&chunk[6]) = this->unknown_0064;
data.insert(data.end(), chunk.begin(), chunk.end());
}
{
std::vector<unsigned char> chunk(6);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 25001;
*reinterpret_cast<int*>(&chunk[2]) = 0;
data.insert(data.end(), chunk.begin(), chunk.end());
}
return data;
}
// OFFSET: 0x00AA8440
// FUNCTION: fn_17243
std::vector<unsigned char> UIWindowMgr::SaveReplayReserved() {
std::vector<unsigned char> data;
{
std::vector<unsigned char> chunk(6);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 26000;
*reinterpret_cast<int*>(&chunk[2]) = 0;
data.insert(data.end(), chunk.begin(), chunk.end());
}
{
std::vector<unsigned char> chunk(6);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 26001;
*reinterpret_cast<int*>(&chunk[2]) = 0;
data.insert(data.end(), chunk.begin(), chunk.end());
}
return data;
}
// OFFSET: 0x00AA8980
// FUNCTION: fn_17245
void UIWindowMgr::ApplyReplayOptions(const ReplayOptions& options) {
this->unknown_05A4 = 0;
this->unknown_0588 = 0;
this->unknown_0568 = 0;
this->unknown_054C = 0;
this->unknown_073C = 0;
this->unknown_077C = 0;
this->unknown_05BC = 0;
this->unknown_05D0 = 0;
this->unknown_0758 = options.unknown_0007;
this->unknown_003C = options.recordRestricted;
}
// OFFSET: 0x00AA8B20
// FUNCTION: fn_17247
int UIWindowMgr::LoadReplaySettings(const std::vector<unsigned char>& data) {
if (data.empty()) {
return -1;
}
ReplaySettingHeader header;
unsigned offset = 6;
header.Read(data.data());
if (header.tag != 25000) {
offset = static_cast<unsigned>(-1);
} else {
while (offset < data.size()) {
header.Read(data.data() + offset);
offset += 6;
if (header.tag == 25001) {
break;
}
if (header.tag == 25010) {
std::memcpy(&this->unknown_0064, data.data() + offset, header.size);
}
offset += header.size;
}
}
return static_cast<int>(offset);
}
// OFFSET: 0x00AA8C30
// FUNCTION: fn_17248
int UIWindowMgr::LoadReplayReserved(const std::vector<unsigned char>& data) {
if (data.empty()) {
return -1;
}
ReplaySettingHeader header;
unsigned offset = 6;
header.Read(data.data());
if (header.tag != 26000) {
offset = static_cast<unsigned>(-1);
} else {
while (offset < data.size()) {
header.Read(data.data() + offset);
offset += 6;
if (header.tag == 26001) {
break;
}
offset += header.size;
}
}
return static_cast<int>(offset);
}
// OFFSET: 0x00AA8F50
// FUNCTION: fn_17252
void UIWindowMgr::BroadcastMessage21() {
UIWindow* window = this->window_03DC;
if (window || (window = this->unknown_03B0) != nullptr) {
window->SendMsg(nullptr, 21, 0, 0, 0, 0);
return;
}
for (UIWindow* rendered : this->rendered) {
if (rendered->Slot02()) {
rendered->SendMsg(nullptr, 21, 0, 0, 0, 0);
}
}
}
// OFFSET: 0x00AB1120
// FUNCTION: fn_17332
bool UIWindowMgr::IsHoverOnWindow01C8Button() {
const UIWindow* window = this->window_01C8;
if (window) {
UIWindow* const* buttons = reinterpret_cast<UIWindow* const*>(reinterpret_cast<const char*>(window) + 0xBC);
if (this->hoverWindow == buttons[0] || this->hoverWindow == buttons[1]) {
return true;
}
}
return false;
}
// OFFSET: 0x007D5250
// FUNCTION: fn_09589
bool UIWindowMgr::HasModalWindow() {
UIWindow* top = this->modalWindows.empty() ? nullptr : this->modalWindows.back();
return top != nullptr;
}
// OFFSET: 0x00A8BC00
// OFFSET: 0x00AA8660
// FUNCTION: fn_17244
std::vector<unsigned char> UIWindowMgr::SaveReplayWindows() {
std::vector<unsigned char> data;
{
std::vector<unsigned char> chunk(6);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 20000;
*reinterpret_cast<int*>(&chunk[2]) = 0;
data.insert(data.end(), chunk.begin(), chunk.end());
}
for (UIWindow* window : this->rendered) {
const unsigned id = static_cast<unsigned>(window->geometry.id);
if (id <= 10040 && this->policy[id].actions[7]) {
std::vector<std::uint32_t> state = window->Slot44();
const int tag = window->geometry.id + 20100;
std::vector<unsigned char> chunk(state.size() * sizeof(std::uint32_t) + 6, 0);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = static_cast<std::int16_t>(tag);
*reinterpret_cast<int*>(&chunk[2]) = static_cast<int>(state.size() * sizeof(std::uint32_t));
if (state.size() * sizeof(std::uint32_t)) {
std::memcpy(&chunk[6], state.data(), state.size() * sizeof(std::uint32_t));
}
data.insert(data.end(), chunk.begin(), chunk.end());
}
}
{
std::vector<unsigned char> chunk(6);
*reinterpret_cast<std::int16_t*>(&chunk[0]) = 20001;
*reinterpret_cast<int*>(&chunk[2]) = 0;
data.insert(data.end(), chunk.begin(), chunk.end());
}
return data;
}
void __fastcall sub_DFF150(CSession* session);
// OFFSET: 0x00A8C4B0
// FUNCTION: fn_17132
void UIWindowMgr::sub_A8C4B0(int id) {
g_session.EraseRecord0734(id);
this->unknown_4F248.push_back(id);
sub_DFF150(&g_session);
}
__forceinline void RecordEditTextsNoArg(UIWindow* window) {
union {
int (UIWindow::*method)(WindowReplayRecorder&);
void (__thiscall* call)(UIWindow*);
} convert;
convert.method = &UIWindow::RecordEditTexts;
convert.call(window);
}
// OFFSET: 0x00A8CA20
// FUNCTION: fn_17139
bool UIWindowMgr::sub_A8CA20() {
if (g_replayAnimationScaling != 0) {
return false;
}
bool handled = true;
if (!this->modalWindows.empty() && this->modalWindows.back() != nullptr) {
reinterpret_cast<const WindowDialogs*>(this)->Top()->SendMsg(nullptr, 0, 0, 0, 0, 0);
return true;
}
UIWindow* window = reinterpret_cast<UIWindow*>(static_cast<std::uintptr_t>(this->unknown_0234));
if (window == nullptr) {
window = reinterpret_cast<UIWindow*>(static_cast<std::uintptr_t>(this->unknown_0314));
if (window != nullptr) {
if (Replay::Instance().state == 2) {
RecordEditTextsNoArg(window);
}
window->SendMsg(nullptr, 0, 0, 0, 0, 0);
return true;
}
window = reinterpret_cast<UIWindow*>(static_cast<std::uintptr_t>(this->unknown_0318));
if (window != nullptr) {
if (Replay::Instance().state == 2) {
RecordEditTextsNoArg(window);
}
window->SendMsg(nullptr, 0, 0, 0, 0, 0);
return true;
}
window = this->unknown_01F8;
if (window == nullptr) {
window = this->unknown_01F0;
}
if (window == nullptr) {
window = this->unknown_01F4;
}
if (window == nullptr) {
window = this->unknown_0214;
}
if (window == nullptr) {
window = this->unknown_021C;
if (window != nullptr) {
window->SendMsg(nullptr, 0x13, 0, 0, 0, 0);
return true;
}
window = this->unknown_020C;
if (window == nullptr) {
window = this->unknown_0374;
}
if (window == nullptr) {
window = reinterpret_cast<UIWindow*>(static_cast<std::uintptr_t>(this->unknown_0378));
}
if (window == nullptr) {
window = reinterpret_cast<UIWindow*>(static_cast<std::uintptr_t>(this->unknown_030C));
}
if (window == nullptr) {
if (this->hoverWindow != nullptr) {
if (this->window_01C8 != nullptr && this->hoverWindow->parent == this->window_01C8) {
if (reinterpret_cast<const ChatSuggestions*>(this->window_01C8)->Visible()) {
UIWindow* child = *reinterpret_cast<UIWindow**>(reinterpret_cast<unsigned char*>(this->window_01C8) + 0x13C);
if (child != nullptr) {
child->SendMsg(nullptr, 0xB0, 0xD, 0, 0, 0);
return true;
}
}
handled = false;
}
if (Replay::Instance().state == 2 && handled) {
RecordEditTextsNoArg(this->hoverWindow->Root());
}
if (g_windowCloseByte == 0) {
handled = true;
} else if (!handled) {
return false;
}
this->hoverWindow->SendMsg(nullptr, 0, 0, 0, 0, 0);
return handled;
}
window = this->window_03D4;
if (window == nullptr) {
if (this->window_01C8 != nullptr && reinterpret_cast<const unsigned char*>(&g_windowCloseByte)[-2] == 1) {
handled = false;
RecordEditTextsNoArg(this->window_01C8);
window = this->window_01C8;
} else {
for (UIWindow* item : this->rendered) {
if (!item->Slot02()) {
continue;
}
if (g_replayAnimationScaling == 0) {
RecordEditTextsNoArg(item->Root());
}
item->SendMsg(nullptr, 0, 0, 0, 0, 0);
}
return false;
}
}
}
}
}
window->SendMsg(nullptr, 0, 0, 0, 0, 0);
return handled;
}
// OFFSET: 0x00A97580
// FUNCTION: fn_17205
UIWindow* UIWindowMgr::sub_A97580(int id, int x, int y, int width, int height) {
if (x == -1 && y == -1) {
x = (id + 10) * 10;
y = (id + 5) * 20;
}
if (width == 0 || width > g_renderer->viewport.width) {
width = 300;
}
if (height == 0 || height > g_renderer->viewport.height) {
height = 0x5F;
}
int posX = g_renderer->viewport.width - width;
if (x <= g_renderer->viewport.width) {
posX = x;
}
int posY = y;
if (y > g_renderer->viewport.height) {
posY = 100;
}
UIWindow* window = this->retainedWindows[id];
if (window == nullptr) {
UISubChatHisWnd* created = new UISubChatHisWnd();
created->m_index = id;
created->SetSize(width, height);
created->Move(posX, posY);
this->rendered.push_back(created);
this->retainedWindows[id] = created;
window = created;
}
window->Show(1);
return window;
}
// OFFSET: 0x00AA76F0
// FUNCTION: fn_17239
void UIWindowMgr::DrawLoginOverlay() {
const short quarter = static_cast<short>(g_renderer->viewport.width / 4);
const short third = static_cast<short>(g_renderer->viewport.height / 3);
char name[256];
if (CTexture* grade = g_texMgr.Load("유저인터페이스\\\0_GameGrade.tga", 0, false, true, false)) {
this->unknown_04B4 = grade->Width();
this->unknown_04B8 = grade->Height();
}
int gradeLeft = this->unknown_04BC;
if (gradeLeft == 0) {
gradeLeft = g_renderer->viewport.width - this->unknown_04B4 - 10;
this->unknown_04BC = gradeLeft;
}
int gradeTop = this->unknown_04C0;
if (gradeTop == 0) {
this->unknown_04C0 = 10;
gradeTop = 10;
}
if (g_mouse.buttons[0] == 1) {
if (!this->inputWindow) {
this->unknown_04B0 = 0;
if (g_mouse.x > gradeLeft && g_mouse.x < this->unknown_04B4 + gradeLeft && g_mouse.y > gradeTop && g_mouse.y < this->unknown_04B8 + gradeTop) {
this->unknown_04B0 = 3;
}
const float columns = static_cast<float>(quarter);
const float mouseX = static_cast<float>(g_mouse.x);
if (mouseX > columns * 3.3f + this->unknown_04A8.x && mouseX < columns * 3.9f + this->unknown_04A8.x &&
static_cast<float>(g_mouse.y) > static_cast<float>(third) * 2.4f + this->unknown_04A8.y &&
static_cast<float>(g_mouse.y) < static_cast<float>(third) * 2.8f + this->unknown_04A8.y) {
this->unknown_04B0 = 2;
}
if (static_cast<float>(g_mouse.x) > columns * 0.1f + this->unknown_049C && static_cast<float>(g_mouse.x) < columns * 1.8f + this->unknown_049C &&
static_cast<float>(g_mouse.y) > static_cast<float>(third) * 0.3f + this->unknown_049E &&
static_cast<float>(g_mouse.y) < static_cast<float>(third) * 1.2f + this->unknown_049E) {
this->unknown_04B0 = 1;
}
if (g_serviceType != 0 && static_cast<signed char>(g_startupSecondPhase) > 0 && static_cast<float>(g_mouse.x) > columns * 2.2f + this->unknown_04A0.x &&
static_cast<float>(g_mouse.x) < columns * 3.5f + this->unknown_04A0.x && g_mouse.y > this->unknown_04A0.y &&
g_mouse.y < this->unknown_04A0.y + third * 3) {
this->unknown_04B0 = 5;
}
if (static_cast<float>(g_mouse.y) > static_cast<float>(third) * 2.7f + this->unknown_04A4.x &&
static_cast<float>(g_mouse.y) < static_cast<float>(third) * 3.0f + this->unknown_04A4.x) {
this->unknown_04B0 = 4;
}
}
} else if (g_mouse.buttons[0] == 2 && !this->inputWindow) {
if (this->unknown_04B0 == 1) {
this->unknown_049C += static_cast<short>(g_mouse.deltaX);
this->unknown_049E += static_cast<short>(g_mouse.deltaY);
} else if (this->unknown_04B0 == 2) {
this->unknown_04A8.x += static_cast<short>(g_mouse.deltaX);
this->unknown_04A8.y += static_cast<short>(g_mouse.deltaY);
} else if (this->unknown_04B0 == 3) {
this->unknown_04BC += g_mouse.deltaX;
this->unknown_04C0 += g_mouse.deltaY;
} else if (this->unknown_04B0 == 6) {
this->unknown_04AC.x += static_cast<short>(g_mouse.deltaX);
this->unknown_04AC.y += static_cast<short>(g_mouse.deltaY);
} else if (this->unknown_04B0 == 4) {
if (this->unknown_04A4.x + g_mouse.deltaY >= 0) {
this->unknown_04A4.x += static_cast<short>(g_mouse.deltaY);
}
} else if (this->unknown_04B0 == 5) {
if (g_serviceType != 0 || this->unknown_04A0.x + g_mouse.deltaX >= 0) {
this->unknown_04A0.x += static_cast<short>(g_mouse.deltaX);
}
}
}
RECT rect = {0, 0, g_renderer->viewport.width, g_renderer->viewport.height};
const TextureRegion region = {0.0f, 0.0f, 1.0f, 1.0f};
if (CTexture* login = g_texMgr.Load("유저인터페이스\\t_login.jpg", 0, false, true, false)) {
g_modeMgr.GetGameMode()->DrawTexture(rect, 0, 0.0999f, 0xFFFFFFFF, login, region);
}
const int step = quarter;
const float rows = static_cast<float>(third);
char tape = 0;
for (int x = 0; x < step * 4;) {
++tape;
rect.left = x;
x += step;
rect.right = x;
rect.bottom = static_cast<int>(this->unknown_04A4.x + rows * 3.0f);
rect.top = static_cast<int>(this->unknown_04A4.x + rows * 2.5f);
this->unknown_04A4.y = static_cast<short>(rect.top);
std::sprintf(name, "유저인터페이스\\\0_테입%d.tga", tape);
g_modeMgr.GetGameMode()->DrawTexture(rect, 0, 0.0999f, 0xFFFFFFFF, g_texMgr.Load(name, 0, false, true, false), region);
}
rect.left = this->unknown_04BC;
rect.top = this->unknown_04C0;
rect.right = this->unknown_04B4 + this->unknown_04BC;
rect.bottom = this->unknown_04B8 + this->unknown_04C0;
g_modeMgr.GetGameMode()->DrawTexture(rect, 0, 0.0999f, 0xFFFFFFFF, g_texMgr.Load("유저인터페이스\\\0_GameGrade.tga", 0, false, true, false), region);
rect.left = static_cast<int>(this->unknown_04A8.x + static_cast<float>(step) * 3.1f);
rect.right = step + rect.left;
rect.top = static_cast<int>(this->unknown_04A8.y + rows * 2.4f);
const float half = rows * 0.5f;
rect.bottom = static_cast<int>(static_cast<float>(rect.top) + half);
g_modeMgr.GetGameMode()->DrawTexture(rect, 0, 0.0999f, 0xFFFFFFFF, g_texMgr.Load("유저인터페이스\\\0_중력성인.tga", 0, false, true, false), region);
char row = -2;
for (int column = this->unknown_049C; column < this->unknown_049C + step * 2; column += step) {
++row;
int y = static_cast<int>(this->unknown_049E + rows * 0.1f);
if (this->unknown_049E + (rows + rows) > static_cast<float>(y)) {
const int left = static_cast<int>(static_cast<float>(step) * 0.05f + column);
char index = row;
do {
index += 2;
rect.left = left;
rect.top = y;
rect.right = step + left;
if (index <= 2) {
y += third;
rect.bottom = y;
} else {
rect.bottom = static_cast<int>(static_cast<float>(y) + half);
y += third;
}
std::sprintf(name, "유저인터페이스\\\0_R%d.tga", index);
g_modeMgr.GetGameMode()->DrawTexture(rect, 0, 0.0999f, 0xFFFFFFFF, g_texMgr.Load(name, 0, false, true, false), region);
} while (this->unknown_049E + (rows + rows) > static_cast<float>(y));
}
}
}