Skip to content

aowlspt_raidstart.h

Source: abi/aowlspt_raidstart.h — 189 lines, 4 file-scope functions.

What this header owns

Reproduced verbatim from the header's own banner comment — these notes are frequently the only written record of why the subsystem is shaped the way it is.

text
 aowlspt_raidstart.h -- the TRUE deploy signal for the shared raid-phase latch.

## The bug this exists for

`raidphase.nim` armed its deploy latch on five READABLE signals (GameWorld
cached, MainPlayer Unity-alive, MainPlayer in AllAlivePlayersList,
SessionEndUIScene absent, Camera.main non-null). All five are satisfied at the
END OF SCENE LOAD -- the world is built, the local player is spawned into the
alive list and a camera exists -- which is roughly TEN SECONDS before the
player actually deploys and the raid is on screen. The user reported the ESP
boxes and the map HUD appearing during that window three separate times. The
latch mechanics were correct; the SIGNAL was early.

## What the true signal is, and what was measured

All of the following are OFFLINE measurements on build 1.1.0.1.46777, from
`tools/il2cpp_resolve.py` (methodPointers + prologue bytes from
GameAssembly.dll) and `tools/fldoff.py` (Il2CppMetadataRegistration.
fieldOffsets). Every RVA below was checked for SHAREDNESS -- 28.3% of by-name
lookups on this build land on an RVA with more than one owner, and detouring
one of those fires for every owner.

  EFT.GameWorld::OnGameStarted        @ 0x2508000  UNIQUE   *** NOT HOOKABLE
  EFT.GameWorld::Dispose              @ 0x2501050  UNIQUE   (verified, not bound)
  EFT.AbstractGame::get_Status        @ 0x8AD140   SHARED x60
  EFT.AbstractGame::set_Status        @ 0x7C9AD0   SHARED x35
  Audio.SpatialSystem.SpatialAudioSystem::AfterGameStarted @ 0x2194770 UNIQUE
  EFT.ExfiltrationTimerSoundPlayer::AfterGameStarted       @ 0xA4CAF0  UNIQUE

### Why OnGameStarted itself is not hooked

Its compiled prologue is
     48 8B 89 30 01 00 00   mov  rcx, [rcx+0x130]   ; GameWorld.AfterGameStarted
     48 85 C9               test rcx, rcx
     74 0F                  je   +0xF
-- ten stealable bytes and then a RELATIVE BRANCH at offset 10. The detour
engine needs `AOWL_JMP_SIZE` = 14 (`jmp qword ptr [rip+0]`) and refuses to
relocate a relative branch (`aowl_stolen_len_why` -> -6). The five-byte
`jmp rel32` + island form that would fit is explicitly documented in
aowlspt_detour.h as the road NOT taken. So this address is a correct fact and
an unusable hook, and `abi/aowlspt_botdiag.h` already recorded it as such.

### What is hooked instead, and why it is the SAME instant

The first two instructions of `OnGameStarted` are the proof: the method's
whole job is to load `GameWorld.AfterGameStarted` (+0x130, an `Action`,
confirmed by `fldoff.py fields EFT.GameWorld`) and invoke it. So every
subscriber to that Action runs INSIDE `OnGameStarted`, i.e. at exactly the
true deploy instant, not near it. An exhaustive method-name search of all
31282 types found precisely three non-generated `AfterGameStarted()` bodies:

  Audio.SpatialSystem.SpatialAudioSystem::AfterGameStarted @0x2194770 UNIQUE
       48 89 5C 24 08   mov [rsp+8], rbx
       48 89 74 24 10   mov [rsp+0x10], rsi
       57               push rdi
       48 83 EC 20      sub rsp, 0x20            -> 15 bytes, whole
                                                    instructions, NO branch,
                                                    NO rip-relative operand.
  EFT.ExfiltrationTimerSoundPlayer::AfterGameStarted @0xA4CAF0 UNIQUE
       40 53            push rbx
       48 83 EC 20      sub rsp, 0x20
       80 3D <disp32> 00  cmp byte [rip+..], 0   (rip-relative -- the engine
                                                  RELOCATES disp32; the disp
                                                  is in the signature only to
                                                  pin the build)
       48 8B D9         mov rbx, rcx             -> 16 bytes, no branch.
  EFT.RaidTimerAnnouncementController::AfterGameStarted @0xA43BC0
       *** SHARED with 2 owners -- REJECTED, not listed below. Hooking it
       would fire for a method we never identified.

BOTH unique ones are listed and BOTH are bound, because either alone is a
subscription we cannot prove offline: a body existing is not a body
subscribed. Either firing is the same instant, and `raidphase` records which.
If NEITHER fires in a live raid the latch reports INCONCLUSIVE and says so --
it does not quietly fall back to the early proxies.

## AbstractGame.Status -- proven offset, no reachable instance

`<Status>k__BackingField` is at **+0x38**, and that is not taken from metadata
alone: both accessors compile to a single instruction each and agree.
     get_Status  8B 41 38 C3        mov eax, [rcx+0x38] ; ret
     set_Status  89 51 38 C3        mov [rcx+0x38], edx ; ret
(Which is also exactly why both RVAs are shared 60 and 35 ways -- identical
one-instruction bodies are folded. Neither may be detoured.)

The offset is recorded here so no future session re-derives it. It is NOT read
by the host, because there is no verified path to an `AbstractGame` instance:
the only two non-compiler-generated fields typed `AbstractGame` in the whole
image (`EFT.NonWavesSpawnScenario._game`, `<LateFixedUpdateWorker>d__5.<>4__this`)
are unreachable from anything this host holds, `EFT.TarkovApplication` has no
game field (its base is an instantiated generic singleton whose layout
CLAUDE.md 5 says is not reachable offline), and `EFT.Player` has none either.
Guessing a hop here would be the "offset that reads a plausible number" this
project keeps paying for. That leg stays INCONCLUSIVE and is reported as such.

## Safety

READ-ONLY. Both targets are located by RVA, VirtualQuery'd for committed
executable memory, and memcmp'd against the recorded prologue; NULL on any
mismatch, so a different build gets a missed bind and never a corrupted game.
The detours read no argument and touch no game memory at all -- they set one
host-side flag and a timestamp. Nothing here writes to the game.

Constants

  • AOWLSPT_RAIDSTART_H
  • AOWL_RS_ABSTRACTGAME_STATUS
  • AOWL_RS_RVA_GW_DISPOSE
  • AOWL_RS_RVA_ONGAMESTARTED
  • AOWL_RS_TARGET_COUNT

Types

  • struct AowlRaidStartTarget

Functions

SignatureLine
int32_t aowl_rs_off_status(void)123
void aowl_rs_target_at(int32_t i)156
char aowl_rs_target_name(int32_t i)181
int32_t aowl_rs_target_count(void)186

aoughwl — self-hosted platform for things n stuff. Contact / Support on Discord for access to the private backends.