2025Private

CS2 Walk Bot

C++23 · Source .nav · micropather · kernel-driver I/O

Overview

A CSGO-era walkbot base ported to CS2 and made to work. The predecessor of camelbot-cs2.

CS2 Walk Bot is a walkbot for Counter-Strike 2: an external console app that reads the game through a kernel driver, parses the map's Source navigation mesh, plans a route across it with A*, and walks that route with synthesized keyboard input. The game process is never modified: the bot is read-only against it, and every move it makes is synthesized input.

The starting point was a CSGO-era walkbot base, and the work was the port: CS2 offsets, CS2's entity-list layout, CS2's nav meshes, and the two fixes that made the walking usable. It worked across the full competitive map pool. It stayed private its whole life and is archived now; camelbot-cs2 is the improved recode that grew out of it.

Where did it come from?

A CSGO-era walkbot base needed a new home. Porting it to CS2 meant regenerated memory offsets (the header in the tree was produced by cs2-dumper in 2025), CS2's entity-list indexing, and CS2's own nav meshes, which kept the Source format the base already parsed: magic 0xFEEDFACE, version 16. Most of the port happened in one long working session in 2025, the last code edits landed in early 2026, and the exe on disk was built that June.

How does it walk a map?

A reader thread polls the game once a millisecond: entity list, view matrix, local position, current map name. When the map changes, the matching .nav file is parsed into areas, each carrying its id, corners, center, four directional connection lists, plus the hiding spots and ladders Valve's analyzer left in the file. A* then runs over that graph through micropather, straight-line distance as the heuristic and area centers as the waypoints. The destination is the nav area around the furthest player, or a random area when none is found.

From there the loop is mechanical: steer at the current waypoint, hold the camera on a point leaning toward the next one, press W/A/S/D per 45° yaw octant, jump for drops and climbs, count a waypoint reached inside 55 units, and reset the whole path after six seconds stuck.

What broke on real maps?

Two things, and both fixes are in the shipped code. Under a bridge, the bot was sure it stood on the deck: the nav format's own containment test compares horizontal coordinates only, so the underside matched the area above it and every approach read as an intersection. The fix was height. Area lookup now takes the nearest area center in full 3-D, and both ends of every path go through that picker.

The other fight was jitter, and it came from an earlier steering design that drove the keyboard and the camera from one controller. The fix was decoupling: keys handle movement per yaw octant, the camera gets its own smoothed path, and the remains of the first design are still in the tree. Dead code as a receipt.

Why kernel reads, and why read-only?

The read-only rule came first. The driver interface in the code exposes a write path and a couple of extras, and the bot wires up none of them; every action happens through synthesized input. Reads go through a kernel driver, the same one camelbot-cs2 later standardizes on: overkill for a walkbot, chosen anyway, because CS2's anti-cheat lives in usermode and a kernel read never enters its view.

What is the honest ledger?

The tree carries its own history. The data path is hardcoded to one user's desktop, so the code as archived only ever ran on one machine. World-to-screen math assumes 1920×1080. The console narrates every path search and per-tick distance from inside the hot loop. Behavior is all compiled-in constants, the map name comes from live memory, and there are no tests. There is no git history either: the filesystem is the only timeline the project has.

What happened to it?

It worked, and then it did its job as a predecessor. The walkbot ran the full competitive map pool; the recode that replaced it, camelbot-cs2, rebuilt the ideas properly on a data-driven memory layer. The port taught its lesson for free: the .nav format carried over from CSGO intact, so the pipeline survived re-targeting almost untouched. What rots is the offsets and the entity walk. The durable part really was the base logic.

Field notes

  • 27 source files, ~3,700 lines with the vendored micropather A* library; console app, C++23 on x64.
  • The .nav parser reads the real Source format: magic 0xFEEDFACE, version 16, four directional connection lists per area, hiding spots and ladders parsed and stored.
  • Reader thread and bot loop both tick at 1 ms; the bot settles 2,050 ms after launch before its first decision.
  • Steering constants: a waypoint counts inside 55 flat units, jumps fire for drops deeper than 14.5 units or climbs higher than 35, a stuck waypoint force-jumps at 3,800 ms, and the path resets after 6,000 ms.
  • Area lookup is 3-D, nearest center including height: the bridge fix.
  • Read-only as built: the driver interface's write path and its guarded-region call sit in the tree, never wired up.
  • Nav and geometry files load from a desktop path hardcoded into the source, which pins the archived tree to one machine.

Private, archived, never distributed. Superseded by camelbot-cs2, the improved recode.