Welcome to hackvshack.net Forum!
Download Free HvH CS2/CS:GO Cheats, CFG, LUA/JS Scripts, and More!
Register

C++ How to Implement Auto-Accept in CS2 (IDA Reversed)

  • Thread starter Thread starter Reev
  • Start date Start date

Reev

Skilled HvHer
User ID:
177876
Messages:
197
Reactions:
90
Badges:
11
REP:
−0/2+
Level:
83
Reversed the match accept flow in CS2 and figured I'd share since I haven't seen anyone break this down. There are some non-obvious gotchas that'll waste your time if you don't know about them.

Finding SetPlayerReady
This is the function that tells the GC "I'm ready." Find it in client.dll by searching for string xrefs to "prematch:" or "deferred" in IDA.

Signature: bool(__fastcall* SetPlayerReady)(void* thisptr, const char* szReadyType);

Pattern: 40 53 48 83 EC 20 48 8B DA 48 8D 15 ? ? ? ? 48 8B CB FF 15 ? ? ? ? 85 C0 75 14 BA 02 00

The "deferred" Trap
SetPlayerReady takes a string that controls which code path runs:

"deferred" → goes through an internal pointer that is often NULL. Accept silently fails. You'll sit there wondering why nothing happens.
"accept" (or any string that isn't "deferred") → takes the working path, sets ready state to 2, sends accept to GC.
The strcmp against "deferred" is the branch point. If it matches, broken path. Anything else, working path. First arg is nullptr — function doesn't use this in the accept path.

SetPlayerReady(nullptr, "deferred"); // WRONG — broken path, silently fails SetPlayerReady(nullptr, "accept"); // CORRECT — sends accept to GC

Hook 1: MatchFoundHandler (primary — instant accept)
Fires when the GC tells the client a match was found. Match data is already stored at this point so you can call SetPlayerReady immediately. No delay needed.

Pattern (client.dll): 48 83 EC 28 48 8B 0D ? ? ? ? 48 85 C9 74 ? 48 8B 01 48 89 7C 24 20 FF 50 78

Implementation: void __fastcall hkMatchFoundHandler() { if (g_bAutoAccept) { SetPlayerReady(nullptr, "accept");

FLASHWINFO fi = {}; fi.cbSize = sizeof(fi); fi.hwnd = g_hWindow; fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG; FlashWindowEx(&fi); } oOriginalMatchFoundHandler();

}

Hook 2: Panorama Event (backup — with delay)
The Panorama event "popup_accept_match_found" fires when the accept popup shows, but BEFORE the GC handler finishes storing match data. If you call SetPlayerReady immediately here, you read a null pointer and nothing happens (or you crash).

Fix: 1.5 second delay.

Pattern (client.dll): 40 56 57 41 57 48 83 EC 40 48 8B 3D ? ? ? ? 4D 85 C0 48 8B 35 ? ? ? ? 4C 8B FA 49 0F 45 F8

Implementation: __int64 __fastcall hkPanoramaEvent(void* pUnk, const char* szEventName, void* pUnk1, float flUnk) { if (szEventName && strcmp(szEventName, "popup_accept_match_found") == 0) { if (g_bAutoAccept) { FLASHWINFO fi = {}; fi.cbSize = sizeof(fi); fi.hwnd = g_hWindow; fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG; FlashWindowEx(&fi);

std::thread( { Sleep(1500); SetPlayerReady(nullptr, "accept"); }).detach(); } } return oOriginalPanoramaEvent(pUnk, szEventName, pUnk1, flUnk);

}



Key Points
Call with "accept", NOT "deferred"
MatchFoundHandler = instant accept, no delay needed
Panorama event = needs ~1.5s delay before calling accept
Use both hooks — MatchFoundHandler as primary, Panorama as fallback
If patterns break after an update, string refs "prematch:" / "deferred" will always lead you to SetPlayerReady in IDA
Patterns current as of latest CS2 update.


Any Q's. my discord is dev.reev
 
Reversed the match accept flow in CS2 and figured I'd share since I haven't seen anyone break this down. There are some non-obvious gotchas that'll waste your time if you don't know about them.

Finding SetPlayerReady
This is the function that tells the GC "I'm ready." Find it in client.dll by searching for string xrefs to "prematch:" or "deferred" in IDA.

Signature: bool(__fastcall* SetPlayerReady)(void* thisptr, const char* szReadyType);

Pattern: 40 53 48 83 EC 20 48 8B DA 48 8D 15 ? ? ? ? 48 8B CB FF 15 ? ? ? ? 85 C0 75 14 BA 02 00

The "deferred" Trap
SetPlayerReady takes a string that controls which code path runs:

"deferred" → goes through an internal pointer that is often NULL. Accept silently fails. You'll sit there wondering why nothing happens.
"accept" (or any string that isn't "deferred") → takes the working path, sets ready state to 2, sends accept to GC.
The strcmp against "deferred" is the branch point. If it matches, broken path. Anything else, working path. First arg is nullptr — function doesn't use this in the accept path.

SetPlayerReady(nullptr, "deferred"); // WRONG — broken path, silently fails SetPlayerReady(nullptr, "accept"); // CORRECT — sends accept to GC

Hook 1: MatchFoundHandler (primary — instant accept)
Fires when the GC tells the client a match was found. Match data is already stored at this point so you can call SetPlayerReady immediately. No delay needed.

Pattern (client.dll): 48 83 EC 28 48 8B 0D ? ? ? ? 48 85 C9 74 ? 48 8B 01 48 89 7C 24 20 FF 50 78

Implementation: void __fastcall hkMatchFoundHandler() { if (g_bAutoAccept) { SetPlayerReady(nullptr, "accept");

FLASHWINFO fi = {}; fi.cbSize = sizeof(fi); fi.hwnd = g_hWindow; fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG; FlashWindowEx(&fi); } oOriginalMatchFoundHandler();

}

Hook 2: Panorama Event (backup — with delay)
The Panorama event "popup_accept_match_found" fires when the accept popup shows, but BEFORE the GC handler finishes storing match data. If you call SetPlayerReady immediately here, you read a null pointer and nothing happens (or you crash).

Fix: 1.5 second delay.

Pattern (client.dll): 40 56 57 41 57 48 83 EC 40 48 8B 3D ? ? ? ? 4D 85 C0 48 8B 35 ? ? ? ? 4C 8B FA 49 0F 45 F8

Implementation: __int64 __fastcall hkPanoramaEvent(void* pUnk, const char* szEventName, void* pUnk1, float flUnk) { if (szEventName && strcmp(szEventName, "popup_accept_match_found") == 0) { if (g_bAutoAccept) { FLASHWINFO fi = {}; fi.cbSize = sizeof(fi); fi.hwnd = g_hWindow; fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG; FlashWindowEx(&fi);

std::thread( { Sleep(1500); SetPlayerReady(nullptr, "accept"); }).detach(); } } return oOriginalPanoramaEvent(pUnk, szEventName, pUnk1, flUnk);

}



Key Points
Call with "accept", NOT "deferred"
MatchFoundHandler = instant accept, no delay needed
Panorama event = needs ~1.5s delay before calling accept
Use both hooks — MatchFoundHandler as primary, Panorama as fallback
If patterns break after an update, string refs "prematch:" / "deferred" will always lead you to SetPlayerReady in IDA
Patterns current as of latest CS2 update.


Any Q's. my discord is dev.reev
it's not technically fully correct but whatever
 
What's not correct exactly?
That's how I have it implemented in Reev & it works as it should.
the post does say Panorama needs 1.5s delay (Sleep(1500)). MatchFoundHandler is claimed instant/no delay. If your "Reev" works fine, cool
 

Who has read this thread (Total: 0) in last 1 hours View details