32: ラジオボタンを使って攻撃方法を変える

概要

16回19回 では、炎魔法を柱状にして打ったり、水平状に並べて打ったりと、複数の攻撃方法を作成した。 このように、単純なオン/オフではなく、複数の攻撃方法を選びたい時はラジオボタンを使うのが便利です。
今回は、チートクライアント上でラジオボタンを使い、攻撃方法を変える事を目標にやっていきます。
チート対象のゲームは、x86でチートの練習用に作られた、Pwn Adventure 3を使います。
Windows対象で、Visual Studio 2019を使用しC++/CLIで記述する。ソースコードはまとめてページの一番下にある。 この記事は 25回 からの続きです。

アイテム全取得チートのボタン設置

炎魔法の攻撃方法を変える前に炎魔法が無いといけないので、このタイミングで 22回 の記事で作成したアイテム全取得のチート用のボタンをいれちゃいます。
この記事で作る全ボタンはItemWindowに追加しますが、正直今後どのようにItemWindowに機能を追加していくか未定なので、パネル分けとかはせず、 一旦適当にボタンを配置しちゃいます。

まず、ItemWindow.hのデザインビューを開き、「Label」と「CheckBox」をドラッグ&ドロップしましょう。
プロパティは以前と同じく以下のように設定します。

Label

CheckBox


できたら、ボタンをダブルクリックしてイベントハンドラーのコードへ行き、 ItemWindow.hの上部に #include "SocketClient.h" を追加した後、 以下のように以前実装した load コマンドを送るようにします。 このチートは一回オンにしたらオフにできないので、Enabled にしたらもうこのボタンを押せないようにします。
これで、このボタンを押してアイテム全取得が動いてる事を確認し、次に進みましょう。

魔法切り替え用のラジオボタンの設置

次に、炎魔法の柱打ちや水平打ちを切り替えるためのラジオボタンを設置していきます。
ここで気を付けるべきなのは、例えば同じパネルに複数のラジオボタンがある場合、下図のように5つでワンセットなのか、 2つの選択肢と3つの選択肢でツーセットなのかを区別するものが必要と言う点です。 これは、「GroupBox」を使って分けられるので、まずはそれを配置します。
プロパティは以下のように設定します。
ここに、まずは一つ「RadioButton」を以下のプロパティで配置しましょう。 そして、このDefaultボタンをコピーし、以下のプロパティだけ変えます。
(Locationは適当に下図を見て調整していただければ) 上記を終えるとこのようになってるはずです。

魔法切り替えの機能実装

柱打ち も 水平打ち/ビーム も、どれもフック系のチートで、ゲーム内のコード上の同じ場所をフックします。
ボタンで魔法を切り替える前に、それぞれのチートのDLLにエクスポート関数でHook関数とUnHook関数を作らないといけないので、28回 を参考に付け足してください。出来たら次に進みます。

サーバー側では、もう既に hook/unhook のコマンドを実装しているので、コマンドの実装は必要ありませんが、 以下の事前に読み込んでおくDLLリストに追加するチートのDLLを追加しましょう。 終ったらビルドしておきましょう。

クライアントの方に戻り、上記で作成したラジオボタンをダブルクリックしてイベントハンドラーを開き、以下のように記述しましょう。 horizontalbeam-shot は自分の水平打ちやビームのチートのDLL名です。 Defaultでは horizontal のDLLのunhookを呼び出してますが、unhookの挙動はどれも同じで元のコードを戻すだけで、 horizontal でも vertical-shot でもくり抜いてるコードの位置は一緒なので、どのunhookを呼び出しても構いません。

動かしてみる

これで動くはずなので、実際に試してみましょう。 以下のように切り替わったら成功です。

ソースコード

ItemWindow.hに追加したイベントハンドラー

private: System::Void ItemGetAllButton_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
    SocketClient* sc = new SocketClient();

    if (ItemGetAllButton->Checked) {
        sc->Send("load", "get-item");
        ItemGetAllButton->Text = "Enabled";
        ItemGetAllButton->Enabled = false;
    }
}

private: System::Void ItemDefaultMagicRadioButton_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
    SocketClient* sc = new SocketClient();
    if (ItemDefaultMagicRadioButton->Checked)
        sc->Send("unhook", "horizontal");
}
private: System::Void ItemHorizontalMagicRadioButton_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
    SocketClient* sc = new SocketClient();
    sc->Send("unhook", "horizontal");
    if (ItemHorizontalMagicRadioButton->Checked) {
        sc->Send("hook", "horizontal");
    }
}
private: System::Void ItemBeamMagicRadioButton_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
    SocketClient* sc = new SocketClient();
    sc->Send("unhook", "beam-shot");
    if (ItemBeamMagicRadioButton->Checked) {
        sc->Send("hook", "beam-shot");
    }
}
private: System::Void ItemVerticalMagicRadioButton_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
    SocketClient* sc = new SocketClient();
    sc->Send("unhook", "vertical-shot");
    if (ItemVerticalMagicRadioButton->Checked) {
        sc->Send("hook", "vertical-shot");
    }
}
#include "SocketClient.h" を追加するのも忘れずに