From 6b6283db6bd0e04a676eee8c980283fa0183689e Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Sat, 31 Oct 2026 20:06:03 +0000 Subject: [PATCH] Decompile 2 functions in Source/UI/Quest/UIRenewQuestWnd.cpp, Source/UI/Quest/UIRenewQuestWnd.h, ... Batch #8655 by eAthena: 0 byte-identical, 2 confirmed by peer review. - fn_09935 UINpcSprWnd::Slot31: logic confirmed by peer review - fn_19611 CNavigationManager::sub_B99030: logic confirmed by peer review Peer-reviewed-by: gordaoprogramas, youko Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Contents/NavigationManager.h | 4 +- Source/Contents/NavigationRoute.cpp | 153 ++++++++++++++++++++++++++++ Source/UI/Quest/UIRenewQuestWnd.cpp | 9 ++ Source/UI/Quest/UIRenewQuestWnd.h | 1 + 4 files changed, 165 insertions(+), 2 deletions(-) diff --git a/Source/Contents/NavigationManager.h b/Source/Contents/NavigationManager.h index c69a3eca..61c64253 100644 --- a/Source/Contents/NavigationManager.h +++ b/Source/Contents/NavigationManager.h @@ -311,7 +311,7 @@ public: void SetViewIcon(int icon); bool SetViewMode(int mode); bool sub_B995D0(std::string name, int type, bool flag); - void sub_B99030(std::string name, int type, unsigned char mode, bool flag, int x, int y, int id); + bool sub_B99030(std::string name, int type, unsigned char mode, bool flag, int x, int y, int id); void BuildGridLabels(); bool LoadScript(LuaScript* script); bool BuildRoute(int startX, int startY, int destX, int destY, bool collectCells); @@ -320,7 +320,7 @@ public: int RequestRoute(int cellX, int cellY); NaviCell* MapCellToView(NaviCell* out, const char* mapName, int cellX, int cellY, float size); std::string RouteText(); - void ShowRouteResult(int result, int mode, WindowDialogs& dialogs); + __declspec(noinline) void ShowRouteResult(int result, int mode, WindowDialogs& dialogs); void Reset(bool clearAll); void ClearRouteNodes(); void ClearNodePaths(); diff --git a/Source/Contents/NavigationRoute.cpp b/Source/Contents/NavigationRoute.cpp index 51ae97f7..13f57802 100644 --- a/Source/Contents/NavigationRoute.cpp +++ b/Source/Contents/NavigationRoute.cpp @@ -580,6 +580,159 @@ std::string CNavigationManager::DestinationTitle() { return this->destinationTitle; } +#pragma pack(push, 1) +struct NavigationRouteRecord { + /* 0000 */ std::uint32_t header; + /* 0004 */ std::int16_t length; + /* 0006 */ char mapName[30]; + /* 0024 */ int type; + /* 0028 */ unsigned char mode; + /* 0029 */ bool flag; + /* 002A */ int x; + /* 002E */ int y; + /* 0032 */ int id; +}; +#pragma pack(pop) + +static_assert(sizeof(NavigationRouteRecord) == 0x36); + +// OFFSET: 0x00B99030 +// FUNCTION: fn_19611 +bool CNavigationManager::sub_B99030(std::string name, int type, unsigned char mode, bool flag, int x, int y, int id) { + if (static_cast(type) > 4 || name.size() == 0) { + return false; + } + + if (std::strchr(g_session.m_navigationPlayerMap, '@')) { + bool same; + { + std::string target = name; + std::string player = g_session.m_navigationPlayerMap; + std::size_t position = player.rfind("@"); + if (position != std::string::npos && position >= 4) { + player.erase(position - 4, 3); + } + position = target.rfind("@"); + if (position != std::string::npos && position >= 4) { + target.erase(position - 4, 3); + } + same = player == target; + } + if (!same) { + this->ShowRouteResult(-90, 1, *reinterpret_cast(&g_windowMgr)); + return false; + } + } + + CNaviInfo* info = this->FindObject(name.c_str()); + if (!info) { + const std::string resolved = ResourceMgr::Instance().aliases.ResolveMapName(name.c_str()); + info = this->FindObject(resolved.c_str()); + if (!info) { + return false; + } + } + + NavigationTarget target(type, nullptr); + std::string text = info->GetName(); + void* object = info; + if (type != 1) { + if (type == 2) { + CNavi_Object* npc = info->FindNpcAt(x, y); + if (!npc) { + this->ShowRouteResult(-94, 1, *reinterpret_cast(&g_windowMgr)); + return false; + } + text += ' '; + text += npc->GetName(); + object = npc; + } else if (type == 3) { + CNavi_Object* mob = info->FindMobByIndex(id); + if (!mob) { + this->ShowRouteResult(-94, 1, *reinterpret_cast(&g_windowMgr)); + return false; + } + text += ' '; + text += mob->GetName(); + object = mob; + } else if (type != 0) { + return false; + } + } + + target.object = object; + this->currentTarget = this->savedTarget = target; + this->unknown_1264 = text; + this->unknown_1248 = flag; + this->unknown_127E = (mode >> 2) & 1; + this->unknown_127C = mode & 1; + this->unknown_127D = (mode >> 1) & 1; + if (this->UpdateSearchResults()) { + this->unknown_12C4 = 0; + this->unknown_12C8 = 0; + } + + const int result = this->Navigate(x, y); + this->ShowRouteResult(result, 1, *reinterpret_cast(&g_windowMgr)); + if (result < 0) { + return false; + } + + if (g_windowMgr.modal) { + reinterpret_cast(g_windowMgr.modal)->RefreshWorldMapSelection(); + reinterpret_cast(g_windowMgr.modal)->RefreshWorldMapLevels(); + reinterpret_cast(g_windowMgr.modal)->RefreshWorldMapMarks(); + } + + this->unknown_125C = 1; + if (g_windowMgr.window_4F174) { + this->unknown_1248 = false; + } + if (g_windowMgr.window_4F174) { + static_cast(g_windowMgr.window_4F174)->RefreshLayout(); + } else if (!this->unknown_1248) { + g_windowMgr.EnsureWindow(203); + } + + { + std::string recordName = name; + if (Replay::Instance().state == 2) { + char packet[400] = {}; + NavigationRouteRecord record; + record.header = 0x038E08AE; + record.length = sizeof(record); + std::memset(record.mapName, 0, sizeof(record.mapName)); + std::memcpy(record.mapName, recordName.c_str(), recordName.size()); + record.type = type; + record.mode = mode; + record.flag = flag; + record.x = x; + record.y = y; + record.id = id; + std::memcpy(packet, &record, sizeof(record)); + + Replay& replay = Replay::Instance(); + ReplayPacketRecorder recorder = { + g_packetLengths, + replay.baseFrame, + replay.started, + replay.frame, + replay.header.key0, + replay.header.key1, + replay.header.options.recordRestricted, + replay.file, + replay.fileOffset, + replay.records, + replay.cipherIndex, + replay.cipherBase, + replay.cipherKey, + }; + recorder.Record(static_cast(record.length), packet, 0x29, 0); + } + } + return true; +} + // OFFSET: 0x00B996D0 // FUNCTION: fn_19613 void CNavigationManager::LoadSettings() { diff --git a/Source/UI/Quest/UIRenewQuestWnd.cpp b/Source/UI/Quest/UIRenewQuestWnd.cpp index 8bd4b56a..e6c269f2 100644 --- a/Source/UI/Quest/UIRenewQuestWnd.cpp +++ b/Source/UI/Quest/UIRenewQuestWnd.cpp @@ -6,6 +6,7 @@ #include "Contents/Configuration/ServiceConfiguration.h" #include "Contents/Items/ItemDescription.h" #include "Contents/MessageTable.h" +#include "Contents/NavigationManager.h" #include "Contents/RenewQuestMgr.h" #include "Network/Connection/Connection.h" #include "Network/Packets/PacketLengths.h" @@ -124,6 +125,14 @@ void UINpcSprWnd::Paint() { } } +// OFFSET: 0x007F9770 +// FUNCTION: fn_09935 +void UINpcSprWnd::Slot31(int, int) { + if (this->m_mapName.size() != 0) { + g_navigationManager.sub_B99030(this->m_mapName, 0, 5, false, this->m_destinationX, this->m_destinationY, 1002); + } +} + // OFFSET: 0x007F97F0 // FUNCTION: fn_09936 void UINpcSprWnd::ResetCursor(int, int) { diff --git a/Source/UI/Quest/UIRenewQuestWnd.h b/Source/UI/Quest/UIRenewQuestWnd.h index 4a222535..febd8c9b 100644 --- a/Source/UI/Quest/UIRenewQuestWnd.h +++ b/Source/UI/Quest/UIRenewQuestWnd.h @@ -28,6 +28,7 @@ public: } void Paint() override; void ResetCursor(int x, int y) override; + void Slot31(int x, int y) override; int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; void SetSprite(int width, int height, std::string name);