1

I'm trying to simulate mouse movement in FPS games, more specifically Valorant. I am aware of the SetCursorPos() function and the mouse_event() function, which both work fine for changing the cursor's position. This works in FPS games that use the technique of constantly centering the cursor, but Valorant doesn't seem to do that. I wrote a program to constantly check my cursor's position (using GetCursorPos()) and my cursor never got centered, if I moved the mouse to a corner and then kept moving it, my character kept rotating. So, how does Valorant sense that I'm moving my mouse when my cursor's position isn't changing, and how can I counter that and simulate mouse movement in Valorant?

By the way, don't worry - I'm not trying to cheat, just trying to make smooth motions in freecam for cinematic shots.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
BubLblckZ
  • 434
  • 4
  • 14
  • FYI, `mouse_event()` is deprecated, use `SendInput()` instead. But you will likely still run into the same problem. I don't know how Valorant tracks mouse movements. Maybe it is just seeing the mouse move to the corner where it can't move any more, and assumes you want to keep "moving" in that direction until the mouse is moved out of the corner? – Remy Lebeau Jul 15 '20 at 18:42
  • *how does Valorant sense that I'm moving my mouse when my cursor's position isn't changing* I'm not sure how *Valorant* is implemented, but you can use [`RegisterRawInputDevices`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerrawinputdevices) with `usUsage = 0x02`(Mouse), here is a [sample](https://stackoverflow.com/a/62130039/10611792) (you need to change the usUsage to 0x02)to use it. – Drake Wu Jul 16 '20 at 06:03
  • @DrakeWu-MSFT Interesting! Looked a little into it but couldn't find much about `RegisterRawInputDevices`, how would I go about registering a new input device and then "control" that input device? – BubLblckZ Jul 17 '20 at 17:56
  • `RegisterRawInputDevices` can be used to detect the mouse movement described by you. For "control", you could use `SendInput` with relative coordinates to simulate. – Drake Wu Jul 20 '20 at 06:51

1 Answers1

1

I'm not sure how Valorant is implemented, but I can use the RegisterRawInputDevices to get the mouse event when the cursor's position isn't changing:

#include <windows.h>
#include <iostream>

using namespace std;
BOOL registerTouchpadForInput(HWND hWnd)
{
    RAWINPUTDEVICE rid;
    rid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
    rid.usUsagePage = 1;                            
    rid.usUsage = 2;
    rid.hwndTarget = hWnd;
    return RegisterRawInputDevices(&rid, 1, sizeof(rid));
}

static LRESULT CALLBACK NVTouch_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    BOOL  registrationStatus = false;
    switch (message)
    {
    case WM_CREATE:
        registrationStatus = registerTouchpadForInput(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_INPUT:
        printf("WM_INPUT ");
        return DefWindowProc(hwnd, message, wParam, lParam);
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

int main()
{
    WNDCLASSEX wndclass = {
        sizeof(WNDCLASSEX),
        CS_DBLCLKS,
        NVTouch_WindowProc,
        0,
        0,
        GetModuleHandle(0),
        LoadIcon(0,IDI_APPLICATION),
        LoadCursor(0,IDC_ARROW),
        HBRUSH(COLOR_WINDOW + 1),
        0,
        L"myclass",
        LoadIcon(0,IDI_APPLICATION)
    };
    bool isClassRegistered = false;
    isClassRegistered = RegisterClassEx(&wndclass);
    if (isClassRegistered)
    {
        HWND window = CreateWindow(wndclass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), NULL);
        if (window)
        {
            ShowWindow(window, SW_SHOWDEFAULT);
            MSG msg;
            while (GetMessage(&msg, 0, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
}

And then, use SendInput to simulate the relative mouse move at the border of the screen:

INPUT buffer;
ZeroMemory(&buffer, sizeof(buffer));
buffer.type = INPUT_MOUSE;
buffer.mi.dx = 10;
buffer.mi.dy = 10;
buffer.mi.mouseData = 0;
buffer.mi.dwFlags = MOUSEEVENTF_MOVE;
buffer.mi.time = 0;
buffer.mi.dwExtraInfo = 0;
while (1)
{
    Sleep(1000);
    SendInput(1, &buffer, sizeof(INPUT));
}
Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • Thanks for the code! However, `SendInput()` doesn't seem to send _raw_ mouse input, so it doesn't move me around in-game, how would I go about simulating _raw_ mouse input? – BubLblckZ Jul 21 '20 at 16:27
  • 1
    Raw input cannot be simulated by user. `WM_INPUT` messages can only be distributed by the system. The sample I use raw input is just an example to illustrate "how does an application sense that I'm moving my mouse when my cursor's position isn't changing". Make sure that the mouse focus is on your window when you call `SendInput`. Valorant seems to have its own anti-cheat system, if it prevents the injection of `SendInput`(see [`LLMHF_INJECTED`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msllhookstruct)), then you may have to create a system driver api to simulate. – Drake Wu Jul 22 '20 at 10:04