diff --git a/Source/Client/Mode/CLoginMode.h b/Source/Client/Mode/CLoginMode.h index d2aa1a67..4805dea3 100644 --- a/Source/Client/Mode/CLoginMode.h +++ b/Source/Client/Mode/CLoginMode.h @@ -23,6 +23,7 @@ struct CharacterPagePacket; struct RefuseLoginPacket; struct NotifyZoneServerPacket; struct NotifyZoneServer2Packet; +struct PasswordModePacket; #pragma pack(push, 1) struct CharacterInfo { @@ -78,7 +79,8 @@ public: /* 6EFC */ CharacterSlotExtension slotExtension; /* 6F10 */ unsigned char unknown_6F10[0x4]; /* 6F14 */ UIWindow* window_6F14; - /* 6F18 */ unsigned char unknown_6F18[0x38]; + /* 6F18 */ int passwordRetryCount; + /* 6F1C */ unsigned char unknown_6F1C[0x34]; /* 6F50 */ std::string unknown_6F50; /* 6F68 */ std::vector mapStates; /* 6F74 */ bool unknown_6F74; @@ -91,6 +93,8 @@ public: void SubD8D4F0(int); void SubD8D500(const char* packet); + void SubD90C90(const PasswordModePacket* packet); + void SubD911C0(const PasswordModePacket* packet); int GetMaxCharacterSlot(); void ReceiveCharacterSlots(const CharacterSlotsPacket* packet); void ReceiveAcceptEnter(const AcceptEnterPacket* packet, WindowDialogs& dialogs); diff --git a/Source/Client/Mode/LoginMode.cpp b/Source/Client/Mode/LoginMode.cpp index e0db8477..5d57170d 100644 --- a/Source/Client/Mode/LoginMode.cpp +++ b/Source/Client/Mode/LoginMode.cpp @@ -16,6 +16,7 @@ #include "Security/NProtectGameGuardMgr.h" #include "UI/Window/UIWindow.h" #include "UI/Window/UIWindowMgr.h" +#include "UI/Dialogs/UIPasswordWnd.h" #include "UI/Window/UINewSelectCharWnd.h" #include "UI/Window/WindowDialogs.h" #include "Utility/Cipher/XorBytes.h" @@ -1311,3 +1312,188 @@ void CLoginMode::ReceiveNotifyZoneServer2(const NotifyZoneServer2Packet* packet) std::string host(std::begin(packet->host), std::end(packet->host)); this->ConnectZoneServer(packet->gid, std::string(std::begin(packet->mapName), std::end(packet->mapName)).c_str(), packet->ip, packet->port, host.c_str()); } + +#pragma pack(push, 1) +struct PasswordModePacket { + /* 0000 */ std::int16_t id; + /* 0002 */ std::uint32_t accountId; + /* 0006 */ std::int32_t value; + /* 000A */ std::uint16_t mode; + /* 000C */ unsigned char count; +}; +#pragma pack(pop) + +// GLOBAL: gl_25133 +std::uint32_t g_loginAccountId; + +// GLOBAL: gl_25134 +std::int32_t g_passwordWndAccountId; + +// OFFSET: 0x00D90C90 +// FUNCTION: fn_22286 +void CLoginMode::SubD90C90(const PasswordModePacket* packet) { + g_loginAccountId = packet->accountId; + switch (packet->mode) { + case 0: + g_windowMgr.CloseWindow(199); + g_passwordWndMode = 0; + this->pendingCursorType = 7; + break; + case 1: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 2; + this->passwordRetryCount = 0; + this->pendingCursorType = 7; + break; + case 2: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 4; + this->pendingCursorType = 7; + break; + case 3: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 3; + this->pendingCursorType = 7; + break; + case 4: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 5; + this->pendingCursorType = 7; + break; + case 5: + g_windowMgr.CloseWindow(199); + this->pendingCursorType = 7; + reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(0x768), 0, true, false, 0, "Message", 280, 120, 0); + break; + case 6: + g_windowMgr.CloseWindow(199); + this->pendingCursorType = 7; + reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(0x769), 0, true, false, 0, "Message", 280, 120, 0); + break; + case 7: + g_passwordWndMode = 1; + this->pendingCursorType = 7; + break; + case 8: + g_windowMgr.CloseWindow(199); + if (packet->count != 0) { + this->pendingCursorType = 7; + std::string message = FormatOwnedString(LookupMessage(0x764), packet->count); + reinterpret_cast(&g_windowMgr)->Confirm(message.c_str(), 0, true, false, 0, "Message", 280, 120, 0); + } else { + reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(0xD7E), 0, true, false, 0, "Message", 280, 120, 0); + this->SendMsg(2, 0, 0, 0, 0); + } + break; + case 9: { + const char* text = LookupMessage(0xC81); + const std::uint8_t source[] = {0xF2, 0xE6, 0x37, 0xBE, 0x35, 0x6C, 0x87}; + thread_local EncryptedName format(source); + reinterpret_cast(&g_windowMgr)->Confirm(FormatString(format.Text(), text, 9), 0, true, false, 0, "Message", + 280, 120, 0); + break; + } + case 10: { + const char* text = LookupMessage(0xC81); + const std::uint8_t source[] = {0xF0, 0x4A, 0x03, 0x6C, 0x83, 0x8E, 0x97}; + thread_local EncryptedName format(source); + reinterpret_cast(&g_windowMgr)->Confirm(FormatString(format.Text(), text, 10), 0, true, false, 0, "Message", + 280, 120, 0); + break; + } + case 11: { + const char* text = LookupMessage(0xC81); + const std::uint8_t source[] = {0x56, 0x9C, 0x93, 0xF4, 0xB1, 0xCA, 0xAB}; + thread_local EncryptedName format(source); + reinterpret_cast(&g_windowMgr)->Confirm(FormatString(format.Text(), text, 11), 0, true, false, 0, "Message", + 280, 120, 0); + break; + } + } +} + +// OFFSET: 0x00D911C0 +// FUNCTION: fn_22287 +void CLoginMode::SubD911C0(const PasswordModePacket* packet) { + g_loginAccountId = packet->accountId; + switch (packet->mode) { + case 0: + g_windowMgr.CloseWindow(199); + g_passwordWndMode = 0; + this->pendingCursorType = 7; + break; + case 1: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 2; + this->passwordRetryCount = 0; + this->pendingCursorType = 7; + break; + case 2: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 4; + this->pendingCursorType = 7; + break; + case 3: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 3; + this->pendingCursorType = 7; + break; + case 4: + g_passwordWndAccountId = packet->value; + g_passwordWndMode = 5; + this->pendingCursorType = 7; + break; + case 5: + g_windowMgr.CloseWindow(199); + this->pendingCursorType = 7; + reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(0x768), 0, true, false, 0, "Message", 280, 120, 0); + break; + case 6: + g_windowMgr.CloseWindow(199); + this->pendingCursorType = 7; + reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(0x769), 0, true, false, 0, "Message", 280, 120, 0); + break; + case 7: + g_passwordWndMode = 1; + this->pendingCursorType = 7; + break; + case 8: { + g_windowMgr.CloseWindow(199); + ++this->passwordRetryCount; + const int remaining = 3 - this->passwordRetryCount; + this->pendingCursorType = 7; + if (remaining > 0) { + std::string message = FormatOwnedString(LookupMessage(0x764), remaining); + reinterpret_cast(&g_windowMgr)->Confirm(message.c_str(), 0, true, false, 0, "Message", 280, 120, 0); + } else { + reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(0x773), 0, true, false, 0, "Message", 280, 120, 0); + this->SendMsg(2, 0, 0, 0, 0); + } + break; + } + case 9: { + const char* text = LookupMessage(0xC81); + const std::uint8_t source[] = {0x16, 0x10, 0x7D, 0xD4, 0x4D, 0x1C, 0xD3}; + thread_local EncryptedName format(source); + reinterpret_cast(&g_windowMgr)->Confirm(FormatString(format.Text(), text, 9), 0, true, false, 0, "Message", + 280, 120, 0); + break; + } + case 10: { + const char* text = LookupMessage(0xC81); + const std::uint8_t source[] = {0x14, 0x8A, 0xFB, 0xDC, 0x79, 0x66, 0xCB}; + thread_local EncryptedName format(source); + reinterpret_cast(&g_windowMgr)->Confirm(FormatString(format.Text(), text, 10), 0, true, false, 0, "Message", + 280, 120, 0); + break; + } + case 11: { + const char* text = LookupMessage(0xC81); + const std::uint8_t source[] = {0xB2, 0xBA, 0xE1, 0xBE, 0xA9, 0x92, 0xB1}; + thread_local EncryptedName format(source); + reinterpret_cast(&g_windowMgr)->Confirm(FormatString(format.Text(), text, 11), 0, true, false, 0, "Message", + 280, 120, 0); + break; + } + } +}