onward mod build

what you get: libonward_esp.so for arm64, hooks for ESP / no-recoil / inf-ammo.
what you need: NDK r26b, CMake 3.20+. nothing else. no java, no apktool, no
keystore. this is just the .so build.


files
-----
onward_cheats.cpp     source
CMakeLists.txt        build config

layout has to be:

  your_folder/
  ├── CMakeLists.txt
  └── jni/
      └── onward_cheats.cpp

the cpp MUST be in jni/. otherwise cmake won't find it.


ndk
---
r26b. not r25, not r27. clang 17 ships with it, and the source needs it for
__builtin___clear_cache. other versions give you linker errors or mangled
mprotect symbols.

  export ANDROID_NDK=/path/to/android-ndk-r26b

check:
  ls $ANDROID_NDK/build/cmake/android.toolchain.cmake

if that file isn't there, the path is wrong.


build
-----
  cd your_folder

  cmake -B build \
    -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
    -DANDROID_ABI=arm64-v8a \
    -DANDROID_PLATFORM=android-26 \
    -DCMAKE_BUILD_TYPE=Release

  cmake --build build -j4

first run takes 30-60 seconds. after that, instant.

output: build/libonward_esp.so


quick check
-----------
  file build/libonward_esp.so
    has to say "ELF 64-bit LSB shared object, ARM aarch64".
    if it says x86_64, you screwed up ANDROID_ABI. wipe build/, re-run.

  nm -D build/libonward_esp.so | grep JNI_OnLoad
    has to show "T JNI_OnLoad".
    if nothing, you removed the extern "C" from the source.

  readelf -d build/libonward_esp.so | grep NEEDED
    should only list liblog, libdl, libandroid, libm, libc.
    if libc++_shared shows up, add -static-libstdc++ to CMakeLists and rebuild.


getting it into the game
------------------------
the source does nothing with the APK. it's just a JNI lib that starts a
thread on load, waits 25 seconds for IL2CPP to come up, then hooks two
methods. how you get the lib into the process is your problem. three ways:

1) patch the APK

   apktool d Onward.apk -o onward_src

   the game loads the lib itself. check what the line is called:

     grep -n loadLibrary onward_src/smali/com/unity3d/player/UnityPlayerActivity.smali

   you'll see something like:
     const-string v2, "onward_esp"
     invoke-static {v2}, Ljava/lang/System;->loadLibrary(...)V

   the name is fixed. your .so has to be named libonward_esp.so. not
   anything else. otherwise the game won't load it and will crash on start.

   drop it in:
     cp build/libonward_esp.so onward_src/lib/arm64-v8a/libonward_esp.so

   rebuild the apk:
     apktool b onward_src -o onward_mod.apk
     zipalign -p -f 4 onward_mod.apk onward_aligned.apk
     apksigner sign --ks your.keystore --ks-pass pass:yourpass \
       --key-pass pass:yourpass --out onward_signed.apk onward_aligned.apk

   install:
     adb uninstall com.downpourinteractive.onward
     adb install onward_signed.apk

   uninstall is required if the old build was signed with a different key.
   otherwise INSTALL_FAILED_UPDATE_INCOMPATIBLE.

   push obb after (uninstall wipes it):
     adb shell mkdir -p /sdcard/Android/obb/com.downpourinteractive.onward/
     adb push /path/to/obb_backup/. /sdcard/Android/obb/com.downpourinteractive.onward/

   3-4 minutes for 9GB. don't interrupt.

2) frida gadget

   if you don't want to touch the apk. needs root or a pre-patched apk with
   the gadget baked in. not covered here.

3) existing loader

   if your apk already has a loader that dlopens a fixed filename, name your
   .so after that. default is libonward_esp.so.


logcat
------
  adb logcat -c
  adb logcat -s 'OnwardESP:*'

after launch you should see:

  OnwardESP: ==== JNI_OnLoad cheats v3 (clean) ====
  OnwardESP: init_thread: entered
  OnwardESP: api resolved
  OnwardESP: worker: waiting 25s
  OnwardESP: worker: domain=0x...
  OnwardESP: do_worker_init: entered
  OnwardESP: OVRInput.Update hook OK
  OnwardESP: RenderLoop hook OK
  OnwardESP: do_worker_init: done

if "OVRInput.Update hook OK" shows up, the mod is running.


when shit breaks
----------------
undefined symbol: mprotect
  wrong NDK. install r26b.

__builtin___clear_cache missing
  clang too old. r26b.

cmake: command not found
  install cmake 3.20+.

toolchain file not found
  ANDROID_NDK is wrong. check with ls $ANDROID_NDK/build/cmake/

build runs, game crashes right on launch
  the .so in the apk is named wrong. check:
    unzip -l onward_signed.apk | grep '\.so'
  it has to say ...lib/arm64-v8a/libonward_esp.so. anything else is wrong.

build runs, game launches, no hooks in the log
  IL2CPP didn't come up in 25 seconds, or the methods don't exist in your
  game version. the source is pinned for 2.0.4.

hooks install but nothing happens in game
  offsets are hardcoded for 2.0.4. different version = different offsets. you
  need a fresh IL2CPP dump of your version and update the #define block at
  the top of the cpp.

crash ~30 seconds after launch
  one of the hooks landed on a PC-relative prologue or a stub method. the
  source checks for that, but with other game versions something can still
  slip through. check the log for "install_hook: no window".


what's in it
------------
ESP           boxes around players, green ally / red enemy, 12 edges.
              LineRenderer, ZTest=8, so visible through walls.
no-recoil     18 floats on the active WeaponSO zeroed, every frame.
inf-ammo      get_IsEmpty and RefillMagazine hooked, mag refilled when empty.

what's NOT in it: rapid-fire, godmode, auth bypass, signature spoof,
multiplayer tampering, spawner, lobby crasher. the source has no assets, no
apk, no keystore, no obb.
