dwgx@blog:~$dwgx
> cd ../posts

cs2-walkbot-ext: 照準が人の手のように動く CS2 外部ウォークボット

// created

CS2 の外部パトロールボットで、DLL の注入もゲーム関数の hook も一切しない。ReadProcessMemorycs2.exe の状態を読み出し、SendInput でプロセス外からキーボードとマウス入力を合成するだけ。メモリは読み取り専用、入力は外から打ち込む。

解きたかった問題は一つだけ。機械が動かすマウスをどうやって機械らしく見せないか、だ。市販チートの照準はどれも一発でターゲットに貼り付く、線形のテレポートで一目で偽物とわかる。欲しかったのは人の手のあの曲線、振りかぶり、滑走、ポイントでの収束、そこに少しの揺れを乗せたもの。楽しさの大半はそこにあった。

照準は 3 種類書いてあって、実行時に切り替えられる。Legacy Smooth が最初で、スカラーの EMA、用は足りるがかなり数値的。Adaptive Servo はサーボ制御として組み、PID に jerk 制限を加えて、ようやく物理的な感触が出てきた。Humanized が一番気に入っている。WindMouse の風ノイズに Fitts の法則を組み合わせて目標速度を計算するので、start-glide-settle が自然に生えてくる。そこに tremor、drift、ランダムな kick を重ねると、動かしたときに本当に人の手のように見える。さらに運動予測と緊急ブレーキも加えた。停止時に逆方向へ打って滑走を打ち消す、そうしないとポイントを行き過ぎる。敵の対応は最寄りを追跡し、味方を敵として扱うこともできる。

移動は録画したウェイポイントマップを辿る。通常のポイントは直結、分岐ポイントは Sequential / Random / Cycle の 3 モードで走り、すべて paths.json に落ちる。別途 Python スクリプトをいくつか用意してパスを生成する。demo の軌跡から抽出したり、Mirage のセンターラインを抜き出したりで、C++ 本体とは完全に分離していてビルドには関与しない。

本体は C++20、Windows コンソール、UI は Dear ImGui + DX11。overlay は専用スレッドを 1 本立て、WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST でクリックスルーにし、WorldToScreen でウェイポイントを画面に投影して描画する。実行には管理者権限が要る、ReadProcessMemory に昇格が必要だからだ。ゲーム内では F6 で起動、F7 で停止。

データフローはだいたいこんな感じ:

cs2.exe memory ─┐
                ├─> interfaces ─> walkbot_core (state) ─> path_runner (decision) ─> SendInput
process/memory ─┘                        │
                                         └─> Overlay Thread ─> WorldToScreen

最大の落とし穴は一言、オフセットだ。CS2 が更新されると、SDK から dump したオフセットとシグネチャが失効しうる。メンテ箇所は 2 つに絞ってある、interfaces.h::Initialize() のパターンスキャンのシグネチャと、sdk/*.hppMEM_PAD(offset) で、更新後は基本この 2 つを補うだけ。純粋に実験的なもので、テストも CI も linter もなく、オフセットが壊れたら手動で補う。練習用プロジェクトとしては十分やる価値がある。