Skip to content

aowlspt_botcap.h

Source: abi/aowlspt_botcap.h — 185 lines, 6 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_botcap.h -- OFFLINE SCAV-CAP LIFT for the post-1.0 EFT host.

One Unity-thread int32 field poke that neutralises the offline bot cap so the
generated scav wave pool actually places. It applies the SAME proven,
reflection-free raw-field-write capability as the version brand and the
settings/botdiag probes (static-RVA detour, `aowl_is_readable`-guarded raw
hops, VirtualQuery-guarded write, flag-gated, fail-safe) -- no runtime_invoke,
no reflection (both are DEAD on this build).

## The gate (RE, byte-verified against build 1.1.0.1.46777)

  `EFT.BotSpawner.MaxBots` = int32 at offset **+0xC0** on the live BotSpawner.
  Verified by the property accessors:
    get_MaxBots @0x698410 = `8B 81 C0 00 00 00`  (mov eax,[rcx+0xC0])
    set_MaxBots @0x698420 = `89 91 C0 00 00 00`  (mov [rcx+0xC0],edx)
  `BotSpawner::CheckOnMax` computes room = MaxBots - (alive@+0x7C + loading@+0x70);
  room<=0 defers the bot forever. **MaxBots==0 means UNLIMITED** (CheckOnMax's
  first test short-circuits to allow-all). Bosses carry IgnoreMaxBots and bypass
  the cap; scav waves do NOT, so Tagilla+escort consume the small offline
  MaxBots and the 24 assault never place. Writing MaxBots=0 lifts the cap.

## What it hooks -- primary: `EFT.BotSpawner::AddPlayer` @ RVA 0x2563AE0

  Called EXACTLY ONCE from `<LocalBotsSpawnInitialization>d__12::MoveNext`
  (+0xad3fad) at raid init, with RCX = the live BotSpawner (`this`). One-shot,
  minimal hot-path work: set `[BotSpawner+0xC0] = 0` once, before the waves
  fire. That BotSpawner is the same object CheckOnMax reads, so RCX=BotSpawner
  here is confirmed by the accessor form ([rcx+0xC0]).

  Prologue @ 0x2563AE0 (byte-verified) -- clean whole-instruction steal, no
  RIP-relative operand and no branch in the stolen region:
    48 89 5C 24 18       mov  [rsp+0x18], rbx      (5)
    57                   push rdi                  (1)
    48 83 EC 20          sub  rsp, 0x20            (4)
    80 3D 99 F6 B5 04 .. cmp  byte [rip+0x4B5F699], 0   (disp32 pins the build)
  The first three instructions (10 bytes) relocate cleanly; the `cmp`'s disp32
  is included in the signature only to pin the build, not stolen. On any other
  build the bytes differ, the guard fails, and NULL is returned -- a missed
  bind, never a corrupted game. (CheckOnMax @0x2560940 is the belt-and-suspenders
  alternative -- runs before every check -- but fires very frequently; AddPlayer
  is preferred for the one-shot minimal write.)

Fail-safe throughout: prologue verified before the pointer is handed out, the
BotSpawner pointer and the +0xC0 slot are guarded before the write, only an
int32 is written, and the whole detour body runs under the VEH/SEH guard so a
fault can never reach the game. A low-risk write (it only relaxes an int
compare the game already performs) but guarded anyway -- it runs during raid
entry, a fragile path.

Constants

  • AOWLSPT_BOTCAP_H
  • AOWL_BC_MAXBOTS_OFF
  • AOWL_BOTCAP_TARGET_COUNT

Types

  • struct AowlBotCapTarget

Functions

SignatureLine
int32_t aowl_bc_off_maxbots(void)61
void aowl_botcap_target_at(int32_t i)96
char aowl_botcap_target_name(int32_t i)122
int32_t aowl_botcap_target_count(void)127
int32_t aowl_botcap_read_i32(void* p, int32_t off, int32_t* ok)132
int32_t aowl_botcap_write_i32(void* p, int32_t off, int32_t value)162

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