Jump to content

Kaptan Yosun

Active+ Member
  • Posts

    153
  • Joined

  • Last visited

  • Days Won

    2
  • Feedback

    0%

Kaptan Yosun last won the day on October 11 2025

Kaptan Yosun had the most liked content!

1 Follower

About Kaptan Yosun

  • Birthday January 24

Informations

  • Gender
    Male
  • Country
    Thailand

Recent Profile Visitors

2311 profile views

Kaptan Yosun's Achievements

Proficient

Proficient (10/16)

  • Very Popular Rare
  • Very Important Person Rare
  • One Year In
  • One Month Later
  • Conversation Starter

Recent Badges

863

Reputation

  1. Cmake is one of the most disgusting things that I can think of. Really. If you don't maintain it for a week it breaks and backwards compatibility is a mess, not even mentioning the horrible syntax. So confusing. However, besides that, thank you for your efforts, my feelings are besides the point.
  2. Only in which specific function causes issue. Do not pass that argument everwhere
  3. You did not pass D3DUSAGE_DYNAMIC arguments to necessary places.
  4. I have updated the topic to make this fix Per-Monitor DPI Aware. You only need to do the UserInterface.cpp part if you have applied this fix earlier.
  5. Fix: // Edited again, we just need to change the order the logic We’re capturing the mouse before checking ImGui, so when ImGui consumes the click, capture is never released, breaking the title bar close button. Find case WM_LBUTTONDOWN: #ifdef __BL_IMGUI__ if (GetCapture() != hWnd) SafeSetCapture(); if (ImGui::GetIO().WantCaptureMouse) return 0; #else SafeSetCapture(); #endif Change case WM_LBUTTONDOWN: #ifdef __BL_IMGUI__ if (ImGui::GetIO().WantCaptureMouse) return 0; if (GetCapture() != hWnd) SafeSetCapture(); #else SafeSetCapture(); #endif Find case WM_LBUTTONUP: #ifdef __BL_IMGUI__ if (GetCapture() != hWnd) SafeSetCapture(); if (ImGui::GetIO().WantCaptureMouse) return 0; #endif Change case WM_LBUTTONUP: #ifdef __BL_IMGUI__ if (ImGui::GetIO().WantCaptureMouse) return 0; if (GetCapture() != hWnd) SafeSetCapture(); #endif
  6. While working with the GF-based atlas mark system, I noticed a 1-pixel north-west offset on the 2×2 WhiteMark dots of NPCs that have an active quest on the minimap. This offset was visible only on quest-marked NPCs; normal NPC dots looked correct at first glance. Why Was This Not Noticed Before? With the old atlas data and previous loading functions, atlas mark positions were processed using low-resolution / coarse coordinates, which effectively masked the issue in practice. In the newer GF __LoadAtlasMarkInfo implementation, atlas coordinates are used more accurately and directly, which made this previously unnoticed alignment issue visible. For example, this is an entry from the old Server\Binary\share\locale\xx\map\metin2_map_c1\npc.txt, where the coordinates are written roughly: m 732 390 0 0 0 0 1m 100 1 9009 And this is the corresponding entry from the new Client\Binary\pack\locale\locale\xx\map\metin2_map_c1_point.txt, where the coordinates are written precisely (×100): #index x y npc_vnum enable_helper icon 0 73200 39000 9009 0 0 This higher-precision data likely exposed floating-point alignment differences. In other words, this is not a bug introduced by the new function, but rather a previously existing logical issue that was hidden and has now surfaced. Cause During the atlas mark loading stage: Half of the sprite width/height was subtracted, applying early centering During rendering, the sprite was already assumed to be centered This resulted in: Atlas mark positions being centered twice A visible 1-pixel north-west shift, especially in the quest highlight pixel inside the WhiteMark Solution The responsibility between logic layers was clearly separated: Atlas mark positions are now stored as center coordinates Sprite size–dependent half-width / half-height offsets are applied only during rendering As a result: NPC dots Quest highlight pixels Waypoint and target markers are all aligned using the same reference point. Result The quest pixel offset on WhiteMark is completely fixed Atlas and minimap rendering logic is now more consistent Future refactors or visual changes are less likely to reintroduce similar issues Client\Source\UserInterface\PythonMiniMap.cpp: // Search @@ void CPythonMiniMap::__LoadAtlasMarkInfo() aAtlasMarkInfo.m_fScreenX = aAtlasMarkInfo.m_fX / m_fAtlasMaxX * m_fAtlasImageSizeX - (float)m_WhiteMark.GetWidth() / 2.0f; aAtlasMarkInfo.m_fScreenY = aAtlasMarkInfo.m_fY / m_fAtlasMaxY * m_fAtlasImageSizeY - (float)m_WhiteMark.GetHeight() / 2.0f; // Change /* - ATLAS_MARK_INFO [REFACTOR] ------------------------ * [KaptanYosun Dev Note] * Atlas mark positions must be stored as CENTER coordinates. * * The previous implementation subtracted half of the mark size * here, effectively converting the position to top-left space * too early. This caused double-centering during rendering and * resulted in a 1px north-west offset in quest-highlight pixels. * * Centering (subtracting half width/height) is now applied ONLY * at render time, ensuring consistent alignment between: * - NPC dots * - Quest highlight pixels * - Waypoints and target marks * * Rule: store logical positions as center, apply sprite offsets * only in the rendering layer. */ aAtlasMarkInfo.m_fScreenX = aAtlasMarkInfo.m_fX / m_fAtlasMaxX * m_fAtlasImageSizeX; aAtlasMarkInfo.m_fScreenY = aAtlasMarkInfo.m_fY / m_fAtlasMaxY * m_fAtlasImageSizeY; /* ----------------------------------------------------- */ // Search @@ void CPythonMiniMap::RenderAtlas(float fScreenX, float fScreenY) STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, CInstanceBase::GetIndexedNameColor(CInstanceBase::NAMECOLOR_NPC)); m_AtlasMarkInfoVectorIterator = m_AtlasNPCInfoVector.begin(); // Add below /* - ATLAS_MARK_INFO [REFACTOR] ------------------------ */ const float halfWidth = static_cast<float>(m_WhiteMark.GetWidth()) * 0.5f; const float halfHeight = static_cast<float>(m_WhiteMark.GetHeight()) * 0.5f; /* ----------------------------------------------------- */ // Search (2x) @@ void CPythonMiniMap::RenderAtlas(float fScreenX, float fScreenY) m_WhiteMark.SetPosition(rAtlasMarkInfo.m_fScreenX, rAtlasMarkInfo.m_fScreenY); // Change (2x) /* - ATLAS_MARK_INFO [REFACTOR] ------------------------ */ m_WhiteMark.SetPosition( rAtlasMarkInfo.m_fScreenX - halfWidth, rAtlasMarkInfo.m_fScreenY - halfHeight ); /* ----------------------------------------------------- */ This fix applies to all clients using the GF Atlas Mark system.
  7. I haven't as I only have one monitor, thank you for your contribution
  8. Problem Description There has been a small but long-standing issue in the Metin2 client: the game window was opening a few pixels shifted to the right, instead of being perfectly centered. On my system, this offset was around 7 pixels. Not a huge problem, but the “not exactly centered” feeling was clearly noticeable. All fixes shared so far were hard-coded workarounds rather than a proper fix. Today, we'll fix it for good. Before: the window is slightly shifted to the right After: the window is perfectly centered, regardless of taskbar position What Is the Problem? This is not a simple math mistake. On Windows 10/11: GetWindowRect() does not always reflect the exact visual bounds of the window Due to DWM (Desktop Window Manager), the left and right window frames are not symmetrical Because of this, the classic calculation: (screenWidth - windowWidth) / 2 does not always produce a true visual center. What Changed? Along with fixing the centering issue, a few small but important cleanups were made: Fixed the centering logic that caused the client window to open ~7 pixels off to the right The window is now centered based on the actual visual frame seen by the user (Win10/11 DWM-aware) Removed an unnecessary GetWindowRect wrapper that conflicted with the WinAPI function name Completely removed the legacy “another window” reposition logic based on FindWindow This logic was not deterministic on modern Windows It also interfered with correct centering No fixed offsets, magic numbers, or “just move it a bit” hacks were used The window now always opens inside the work area, without overlapping the taskbar or appearing offset How to Client\Source\EterLib\MSWindow.cpp: // Find and erase void CMSWindow::GetWindowRect(RECT* prc) { ::GetWindowRect(m_hWnd, prc); } // Add new helper functions static bool GetVisualWindowRect(HWND hwnd, RECT& outRect) { if (!::GetWindowRect(hwnd, &outRect)) return false; using DwmGetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, PVOID, DWORD); constexpr DWORD ExtendedFrameBounds = 9; static HMODULE s_dwm = ::LoadLibraryA("dwmapi.dll"); if (!s_dwm) return true; static auto s_getAttr = reinterpret_cast<DwmGetWindowAttributeFn>( ::GetProcAddress(s_dwm, "DwmGetWindowAttribute")); if (!s_getAttr) return true; RECT visual{}; if (SUCCEEDED(s_getAttr(hwnd, ExtendedFrameBounds, &visual, sizeof(visual)))) { outRect = visual; } return true; } static POINT GetCenteredPosition(const RECT& visualRect, const RECT& workArea, const RECT& windowRect) { const int width = visualRect.right - visualRect.left; const int height = visualRect.bottom - visualRect.top; const int dx = visualRect.left - windowRect.left; const int dy = visualRect.top - windowRect.top; POINT pt{}; pt.x = workArea.left + ((workArea.right - workArea.left) - width) / 2 - dx; pt.y = workArea.top + ((workArea.bottom - workArea.top) - height) / 2 - dy; return pt; } // change function void CMSWindow::SetCenterPosition() void CMSWindow::SetCenterPosition() { RECT window{}; RECT visual{}; RECT workArea{}; if (!::GetWindowRect(m_hWnd, &window)) return; visual = window; GetVisualWindowRect(m_hWnd, visual); ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0); const POINT pos = GetCenteredPosition(visual, workArea, window); SetPosition(pos.x, pos.y); } Client\Source\EterLib\MSWindow.h: // Find and erase void GetWindowRect(RECT* prc); Client\Source\UserInterface\PythonApplication.cpp: // Find and erase bool bAnotherWindow = false; if (FindWindow(NULL, c_szName)) { bAnotherWindow = true; } // Find @@ bool CPythonApplication::Create(PyObject * poSelf, const char* c_szName, int wid AdjustSize(m_pySystem.GetWidth(), m_pySystem.GetHeight()); // Add this underneath CMSWindow::SetCenterPosition(); // Find and erase @@ bool CPythonApplication::Create(PyObject * poSelf, const char* c_szName, int wid if (bAnotherWindow) { RECT rc; GetClientRect(&rc); int windowWidth = rc.right - rc.left; int windowHeight = (rc.bottom - rc.top); CMSApplication::SetPosition(GetScreenWidth() - windowWidth, GetScreenHeight() - 60 - windowHeight); } Client\Source\UserInterface\UserInterface.cpp: // Add to the top of the file #include <shellscalingapi.h> #pragma comment(lib, "Shcore.lib") // Find int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // Add this SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
  9. Download Alternative download links → Metin2.Download Pre-Requisites: DirectX 9 DirectX 9Ex has some serious benefits like around 30% less ram usage and the 3D device never getting lost. So no more CTRL+Alt+Del crashes. You can simply paste the diff file here and see the changes needed to be done. You don't need any new libs or anything, it simply works. Here is before and after RAM usage, difference is substantial.
  10. You're legendary! Everything works super smooth. I implemented it to my ImGUI admin panel just like you did.
  11. For a more in-depth cleanup, you can remove BPP from config and source as it's useless now.
  12. I'd recommend you to upgrade to Dx9Ex so device never gets lost
  13. I love such releases
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.