TAB map content centred again; key bindings no longer pass on Ctrl/Alt
- megamap: the zoomed view (0x6cc950) is shared by the large map and the TAB overview map; its centre is now set per call from the drawing window's offset (hud::DrawOffsetX) instead of fixed to the render width - input: drop the Ctrl/Alt pass-through; GetKeyState reports Alt as held after Alt+Tab, which switched all bindings back to the game's handling Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
037fc73158
commit
e914bd1590
4 files changed
+50
-14
No files matched your search
@@ -431,6 +431,10 @@ int CursorOffsetX() {
|
|||||||
return g_cursorDx;
|
return g_cursorDx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DrawOffsetX() {
|
||||||
|
return g_offsetX;
|
||||||
|
}
|
||||||
|
|
||||||
void* CursorFor(void* cursor) {
|
void* CursorFor(void* cursor) {
|
||||||
return g_cursorDx != 0 && cursor == g_cursorShadow.real ? g_cursorShadow.bytes : cursor;
|
return g_cursorDx != 0 && cursor == g_cursorShadow.real ? g_cursorShadow.bytes : cursor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ void OnDevice(void* device);
|
|||||||
// the current thread (0 outside): polled mouse positions are reduced by it.
|
// the current thread (0 outside): polled mouse positions are reduced by it.
|
||||||
int CursorOffsetX();
|
int CursorOffsetX();
|
||||||
|
|
||||||
|
// Horizontal offset the current thread's UI drawing is shifted by (the
|
||||||
|
// outermost hooked window's; 0 outside).
|
||||||
|
int DrawOffsetX();
|
||||||
|
|
||||||
// The mouse cursor object as the current thread should see it: inside a moved
|
// The mouse cursor object as the current thread should see it: inside a moved
|
||||||
// window, a private copy with x shifted by CursorOffsetX().
|
// window, a private copy with x shifted by CursorOffsetX().
|
||||||
void* CursorFor(void* cursor);
|
void* CursorFor(void* cursor);
|
||||||
|
|||||||
+5
-7
@@ -10,8 +10,10 @@
|
|||||||
// hotkey post that hotkey's key event to the game's event kernel, the way the window
|
// hotkey post that hotkey's key event to the game's event kernel, the way the window
|
||||||
// procedure does (the kernel dispatches it right away, on the window thread).
|
// procedure does (the kernel dispatches it right away, on the window thread).
|
||||||
//
|
//
|
||||||
// While a text field has the keyboard, or Ctrl / Alt is held, keys pass
|
// While a text field has the keyboard, keys pass through unchanged. (Keys
|
||||||
// through unchanged.
|
// with Ctrl / Alt held used to pass too; GetKeyState reports Alt as held after
|
||||||
|
// Alt+Tab until it is pressed again in the game, which switched the bindings
|
||||||
|
// off. Alt+key arrives as WM_SYSKEYDOWN and is not handled here anyway.)
|
||||||
//
|
//
|
||||||
// sacred_re.ini (key names: A-Z, 0-9, F1-F24, Space, None):
|
// sacred_re.ini (key names: A-Z, 0-9, F1-F24, Space, None):
|
||||||
// [keys]
|
// [keys]
|
||||||
@@ -173,10 +175,6 @@ void Release(const Binding& binding, int vk) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModifierHeld() {
|
|
||||||
return (GetKeyState(VK_CONTROL) & 0x8000) != 0 || (GetKeyState(VK_MENU) & 0x8000) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Virtual keys whose WM_KEYDOWN was taken: their WM_CHAR / WM_KEYUP are
|
// Virtual keys whose WM_KEYDOWN was taken: their WM_CHAR / WM_KEYUP are
|
||||||
// swallowed too, even if the state changed in between.
|
// swallowed too, even if the state changed in between.
|
||||||
bool g_taken[256] = {};
|
bool g_taken[256] = {};
|
||||||
@@ -212,7 +210,7 @@ bool HandleWindowMessage(HWND, UINT message, WPARAM wParam, LPARAM lParam) {
|
|||||||
const bool repeat = (lParam & (1 << 30)) != 0;
|
const bool repeat = (lParam & (1 << 30)) != 0;
|
||||||
if (!repeat) {
|
if (!repeat) {
|
||||||
g_taken[vk] = false;
|
g_taken[vk] = false;
|
||||||
if (ModifierHeld() || TypingIntoTextField()) {
|
if (TypingIntoTextField()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const Binding* binding = BindingFor(vk);
|
const Binding* binding = BindingFor(vk);
|
||||||
|
|||||||
+37
-7
@@ -10,11 +10,13 @@
|
|||||||
// the zoom buttons at the bottom stay centred. The window is drawn and clicked
|
// the zoom buttons at the bottom stay centred. The window is drawn and clicked
|
||||||
// unshifted (mods/hud.cpp, Anchor::Screen). See docs/hud.md.
|
// unshifted (mods/hud.cpp, Anchor::Screen). See docs/hud.md.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "game/addresses.h"
|
#include "game/addresses.h"
|
||||||
|
#include "mods/hud.h"
|
||||||
#include "mods/megamap.h"
|
#include "mods/megamap.h"
|
||||||
#include "mods/widescreen.h"
|
#include "mods/widescreen.h"
|
||||||
#include "re/hook.h"
|
#include "re/hook.h"
|
||||||
@@ -37,12 +39,16 @@ constexpr uint32_t kScrollLimit = 0x006c9edd;
|
|||||||
// The view centre 200h: the zoom-in frame (0x6ca53f) and the image centred
|
// The view centre 200h: the zoom-in frame (0x6ca53f) and the image centred
|
||||||
// on it (0x6ca637, 0x6ca645).
|
// on it (0x6ca637, 0x6ca645).
|
||||||
constexpr uint32_t kCentreImmediates[] = {0x006ca53f, 0x006ca637, 0x006ca645};
|
constexpr uint32_t kCentreImmediates[] = {0x006ca53f, 0x006ca637, 0x006ca645};
|
||||||
// fsub/fld/fadd [512.0]: centring the scroll on the hero (opening the map
|
// fsub [512.0]: centring the scroll on the hero (opening the map 0x6c7bfe,
|
||||||
// 0x6c7bfe, 0x6cb27a), the zoomed view (0x6ccb7f) and its quest markers
|
// 0x6cb27a).
|
||||||
// (0x6cf782).
|
constexpr uint32_t kCentreFloatUses[] = {0x006c7bfe, 0x006cb27a};
|
||||||
constexpr uint32_t kCentreFloatUses[] = {0x006c7bfe, 0x006cb27a, 0x006ccb7f, 0x006cf782};
|
// The zoomed view (0x6cc950, cdecl) is drawn by the large map and by the TAB
|
||||||
// fld [768.0] as an x: markers in the zoomed view at 768 - d (0x6ce156), the
|
// overview map (cUI_OverviewMap 0x6c69d0, a centred window: shifted by the
|
||||||
// centre plus 256.
|
// HUD layer). Its centre: fld [512.0] (0x6ccb7f), quest markers fadd [512.0]
|
||||||
|
// (0x6cf782), other markers fld [768.0] as an x, 768 - d = centre + 256
|
||||||
|
// (0x6ce156). It is set on every call from the window's draw offset.
|
||||||
|
constexpr uint32_t kZoomView = 0x006cc950;
|
||||||
|
constexpr uint32_t kZoomCentreUses[] = {0x006ccb7f, 0x006cf782};
|
||||||
constexpr uint32_t kZoomMarkerX = 0x006ce156;
|
constexpr uint32_t kZoomMarkerX = 0x006ce156;
|
||||||
constexpr float kZoomMarkerFromCentre = 256.0f;
|
constexpr float kZoomMarkerFromCentre = 256.0f;
|
||||||
// The dark band around the view (10 vertices, mov [esp+..], imm32): its right
|
// The dark band around the view (10 vertices, mov [esp+..], imm32): its right
|
||||||
@@ -52,6 +58,7 @@ constexpr uint32_t kBandRightInner[] = {0x006ca7bc, 0x006ca84c};
|
|||||||
constexpr int kBandWidth = 70;
|
constexpr int kBandWidth = 70;
|
||||||
|
|
||||||
float g_halfWidth = 512.0f;
|
float g_halfWidth = 512.0f;
|
||||||
|
float g_zoomCentre = 512.0f;
|
||||||
float g_zoomMarkerX = 768.0f;
|
float g_zoomMarkerX = 768.0f;
|
||||||
|
|
||||||
uint32_t FloatBits(float value) {
|
uint32_t FloatBits(float value) {
|
||||||
@@ -172,7 +179,9 @@ void PatchLayout(int width) {
|
|||||||
for (uint32_t instruction : kCentreFloatUses) {
|
for (uint32_t instruction : kCentreFloatUses) {
|
||||||
failed += !re::RedirectOperand(instruction, game::addr::kScreenHalfWidthF, &g_halfWidth);
|
failed += !re::RedirectOperand(instruction, game::addr::kScreenHalfWidthF, &g_halfWidth);
|
||||||
}
|
}
|
||||||
g_zoomMarkerX = g_halfWidth + kZoomMarkerFromCentre;
|
for (uint32_t instruction : kZoomCentreUses) {
|
||||||
|
failed += !re::RedirectOperand(instruction, game::addr::kScreenHalfWidthF, &g_zoomCentre);
|
||||||
|
}
|
||||||
failed += !re::RedirectOperand(kZoomMarkerX, game::addr::kScreenHeightF, &g_zoomMarkerX);
|
failed += !re::RedirectOperand(kZoomMarkerX, game::addr::kScreenHeightF, &g_zoomMarkerX);
|
||||||
failed += re::PatchAll(kBandRightOuter, FloatBits(1024.0f), FloatBits(static_cast<float>(width)));
|
failed += re::PatchAll(kBandRightOuter, FloatBits(1024.0f), FloatBits(static_cast<float>(width)));
|
||||||
failed += re::PatchAll(kBandRightInner, FloatBits(1024.0f - kBandWidth),
|
failed += re::PatchAll(kBandRightInner, FloatBits(1024.0f - kBandWidth),
|
||||||
@@ -180,10 +189,31 @@ void PatchLayout(int width) {
|
|||||||
re::Log("megamap: view width %d%s", width, failed ? " (some patches FAILED)" : "");
|
re::Log("megamap: view width %d%s", width, failed ? " (some patches FAILED)" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before each zoomed view: its centre in the coordinates of the window that
|
||||||
|
// draws it (the large map is unshifted: width / 2; a centred window, which
|
||||||
|
// the HUD layer shifts: 512).
|
||||||
|
void __cdecl SetZoomCentre() {
|
||||||
|
const int width = std::max(mods::widescreen::RenderWidth(), kLayoutWidth);
|
||||||
|
g_zoomCentre = width / 2.0f - static_cast<float>(mods::hud::DrawOffsetX());
|
||||||
|
g_zoomMarkerX = g_zoomCentre + kZoomMarkerFromCentre;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mods::megamap
|
} // namespace mods::megamap
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
|
// The zoomed view (0x6cc950, cdecl): sets its centre, then runs it unchanged.
|
||||||
|
void ZoomView();
|
||||||
|
RE_HOOK(mods::megamap::kZoomView, ZoomView);
|
||||||
|
__declspec(naked) void ZoomView() {
|
||||||
|
__asm {
|
||||||
|
pushad
|
||||||
|
call mods::megamap::SetZoomCentre
|
||||||
|
popad
|
||||||
|
jmp dword ptr [ZoomView_original]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// cUI_Megamap::Show (vf24 0x6c7930, the argument: show / hide).
|
// cUI_Megamap::Show (vf24 0x6c7930, the argument: show / hide).
|
||||||
void __fastcall UiMegamap_Show(void* self, void* edx, int show);
|
void __fastcall UiMegamap_Show(void* self, void* edx, int show);
|
||||||
RE_HOOK(0x006c7930, UiMegamap_Show);
|
RE_HOOK(0x006c7930, UiMegamap_Show);
|
||||||
|
|||||||
Reference in new issue
Block a user