MENU
目次

【HearthstoneReconnector】タスキルツールでバトグラの戦闘をスキップする方法【Battlegrounds】

ハースストーンのタスキルツール

この記事を読むと

目次

HearthstoneReconnectorで出来ること

このツールを利用することで、ハースストーン(バトルグラウンド)の戦闘フェーズをスキップし、酒場フェーズの時間を長くすることができます。
これを通称タスクキルと呼んでいます。

タスキルのメリット

  • 思考時間が増える
  • 勝率が上がる
  • 戦闘が長すぎて雇用フェーズが無くなるケースを防げる
こちらは簡易版ツールの動画です
うる

酒場フェーズが長くなれば忙しい構成では有利ね

U

タスキルすると勝率は間違いなく上がりますね

本アプリケーションのご利用は自己責任でお願いします。一切の責任は負いません。

VS Windowsファイアーウォール

Windowsファイアーウォールによる切断は手軽ですが、挙動が不安定なのでお勧めしません
これはファイアーウォールでHearthstoneの通信を切断する際、再接続するために必要な通信まで切断してしまうためです。

Windowsファイアーウォールの場合

Windowsファイアーウォールの場合、サーバーとHearthstoneの全ての通信を遮断してしまう
Windowsファイアーウォールの場合、すべての通信を遮断してしまう

Reconnectorの場合

Reconnectorはアニメーションスキップに必要な通信のみ切断できる
Reconnectorはアニメーションスキップに必要な通信のみ切断
スクロールできます
Itemメリットデメリット
ファイアーウォール手軽に実装可能挙動が不安定で再接続できない場合が多い
Reconnector
ほぼ100%切断して再接続できる実装が少し手間

私の環境ではファイアーウォール切断時の再接続率が50%くらいだったので、使い物になりませんでした。
雇用フェーズの時間を増やしたいのに、再接続できずに逆に雇用時間が短くなるのは厳しいです。。

ファイアーウォールによるタスキル参考記事

note(ノート)
ダラランのために~数秒でできるタスキル~|chox ■この記事について  この記事では、ハースストーン バトルグラウンドにおいて、雇用フェイズでの操作時間を確保するための手段「タスキル(=タスクキル)」と呼ばれる方...

HearthstoneReconnectorを作成する手順

こちらは簡易版のタスキルツールの作成方法です。
より高機能な構築済みタスキルツールをすぐに利用したい場合は、以下のボタンから構築済みツールをダウンロードしてください。

それではタスキルツールを構築していきましょう。

1. VisualStudioをインストール

Windowsアプリケーションを作成するため、Visual Studioの公式サイトから最新版をインストールしてください。コミュニティエディションでOKです。

Visual Studio
Visual Studio Tools のダウンロード - Windows、Mac、Linux 用の無料インストール Visual Studio IDE または VS Code を無料でダウンロードします。 Windows、Mac で Visual Studio Professional または Enterprise エディションをお試しください。

※Visual Studio Codeではありません

以下のような選択画面が表示されたら、画像のように3つ選択してください。

必要な機能をインストール

2. 新規プロジェクトを作成

① 新しいプロジェクトの作成をクリックしてください。
②「Windows Forms アプリケーション (.NET Framework)」を検索し、C# のテンプレートを選択します。
③ プロジェクト名(例:HearthstoneReconnector)を入力し、適当な保存場所を指定して「作成」をクリックします。

3. コードをコピペ

コードをコピペしてアプリケーションを構築していきます。

Program.cs の編集

プロジェクト作成時に自動生成された Program.cs を開き、以下のコードに書き換えます。

Program.csは画面左上のソリューションエクスプローラーで開いてください。

ソリューションエクスプローラーでProgram.csを開く
ソリューションエクスプローラー
Program.cs
using System;
using System.Windows.Forms;

namespace HearthstoneReconnector
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Form1.cs の編集

ソリューションエクスプローラーから Form1.cs をダブルクリックしてエディタで開きます。

ソリューションエクスプローラーでForm.csを開く

コードエディターが開かない場合は、フォームの空白部分をダブルクリックすると、Form.csのコードエディターが開きます。

Form.csが開けない場合の開き方
Form.csのエディターが開かない場合は、フォームをダブルクリックして開く


以下のコードをコピペしてください。

Form1.cs
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace HearthstoneReconnector
{
    public partial class Form1 : Form
    {
        private const uint MIB_TCP_STATE_DELETE_TCB = 12;
        private const uint MIB_TCP_STATE_ESTAB = 5;
        private Button btnDisconnect;
        private Timer autoRestoreTimer;
        private Timer restoreTimer;
        private bool enableLogging = true;
        private readonly int targetRemotePort = 3724;
        private Color originalButtonBackColor;

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Formロード時の処理
        /// ・ウィンドウサイズとタイトルの調整
        /// ・常に最前面に表示する設定 (TopMost)
        /// </summary>
        private void Form1_Load(object sender, EventArgs e)
        {
            // ウィンドウタイトルの設定
            this.Text = "HearthstoneReconnector";
            // 常に最前面に表示
            this.TopMost = true;
            // クライアントサイズを調整(ボタンサイズに合わせ余白を残す)
            this.ClientSize = new Size(350, 140);

            // Disconnect ボタンの生成とデザイン設定
            btnDisconnect = new Button
            {
                Text = "Disconnect",
                Size = new Size(150, 50),
                Location = new Point((this.ClientSize.Width - 150) / 2, 20),
                Font = new Font("Segoe UI", 14, FontStyle.Bold),
                FlatStyle = FlatStyle.Flat,
                BackColor = Color.SteelBlue,
                ForeColor = Color.White,
                Cursor = Cursors.Hand
            };
            // ボタンの枠線設定
            btnDisconnect.FlatAppearance.BorderSize = 2;
            btnDisconnect.FlatAppearance.BorderColor = Color.DarkBlue;
            btnDisconnect.FlatAppearance.MouseOverBackColor = Color.CornflowerBlue;

            // 元の背景色を保持
            originalButtonBackColor = btnDisconnect.BackColor;

            btnDisconnect.Click += BtnDisconnect_Click;
            this.Controls.Add(btnDisconnect);
        }

        /// <summary>
        /// Disconnect ボタン押下時の処理
        /// ・対象通信を切断
        /// ・0.5秒後に切断解除処理(restoreTimer)
        /// ・5秒後にボタンを再有効化(autoRestoreTimer)
        /// </summary>
        private void BtnDisconnect_Click(object sender, EventArgs e)
        {
            // ボタンの連続クリック防止&グレーアウト
            btnDisconnect.Enabled = false;
            btnDisconnect.BackColor = Color.Gray;

            try
            {
                // 対象通信を切断
                ForceDisconnectTargetConnections();

                // 0.5秒後に切断解除処理
                restoreTimer = new Timer();
                restoreTimer.Interval = 500;
                restoreTimer.Tick += RestoreTimer_Tick;
                restoreTimer.Start();

                // 5秒後にボタンを再有効化するタイマー開始
                autoRestoreTimer = new Timer();
                autoRestoreTimer.Interval = 5000;
                autoRestoreTimer.Tick += AutoRestoreTimer_Tick;
                autoRestoreTimer.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("エラー: " + ex.Message);
                btnDisconnect.Enabled = true;
                btnDisconnect.BackColor = originalButtonBackColor;
            }
        }

        /// <summary>
        /// 0.5秒後に呼ばれる切断解除処理
        /// </summary>
        private void RestoreTimer_Tick(object sender, EventArgs e)
        {
            restoreTimer.Stop();
            restoreTimer.Tick -= RestoreTimer_Tick;
            restoreTimer.Dispose();
            restoreTimer = null;
        }

        /// <summary>
        /// 5秒後にボタンを再有効化するタイマーの Tick イベントハンドラ
        /// </summary>
        private void AutoRestoreTimer_Tick(object sender, EventArgs e)
        {
            autoRestoreTimer.Stop();
            autoRestoreTimer.Tick -= AutoRestoreTimer_Tick;
            autoRestoreTimer.Dispose();
            autoRestoreTimer = null;

            btnDisconnect.Enabled = true;
            // 元の背景色に復元
            btnDisconnect.BackColor = originalButtonBackColor;
        }

        /// <summary>
        /// TCP テーブルから対象の通信を切断する
        /// 正常系では切断対象のログのみ出力
        /// </summary>
        private void ForceDisconnectTargetConnections()
        {
            int buffSize = 0;
            uint ret = GetExtendedTcpTable(IntPtr.Zero, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL, 0);
            IntPtr tcpTablePtr = Marshal.AllocHGlobal(buffSize);
            try
            {
                ret = GetExtendedTcpTable(tcpTablePtr, ref buffSize, true, AF_INET, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL, 0);
                if (ret != 0)
                    throw new Exception("TCP テーブルの取得に失敗しました。エラーコード:" + ret);

                int rowCount = Marshal.ReadInt32(tcpTablePtr);
                IntPtr rowPtr = IntPtr.Add(tcpTablePtr, sizeof(int));
                int rowSize = Marshal.SizeOf(typeof(MIB_TCPROW_OWNER_PID));
                bool found = false;

                for (int i = 0; i < rowCount; i++)
                {
                    MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
                    
                    if (tcpRow.state == MIB_TCP_STATE_ESTAB)
                    {
                        int remotePort = ntohs((ushort)tcpRow.remotePort);
                        if (remotePort == targetRemotePort)
                        {
                            found = true;
                            // 正常系ログ(対象通信の切断のみ)
                            if (enableLogging)
                            {
                                try
                                {
                                    string logMessage = $"{DateTime.Now}: 切断対象 - リモートIP: {new IPAddress(tcpRow.remoteAddr)}, リモートポート: {remotePort}{Environment.NewLine}";
                                    string logFilePath = Path.Combine(Application.StartupPath, "HearthstoneDisconnect.log");
                                    File.AppendAllText(logFilePath, logMessage);
                                }
                                catch (Exception logEx)
                                {
                                    Debug.WriteLine("ログ出力エラー: " + logEx.Message);
                                }
                            }
                            // 対象通信を切断(DELETE_TCB 状態へ変更)
                            if (tcpRow.state != MIB_TCP_STATE_DELETE_TCB)
                            {
                                tcpRow.state = MIB_TCP_STATE_DELETE_TCB;
                                uint setRet = SetTcpEntry(ref tcpRow);
                            }
                        }
                    }
                    rowPtr = IntPtr.Add(rowPtr, rowSize);
                }

                if (!found)
                    MessageBox.Show("指定された通信が見つかりませんでした。");
            }
            finally
            {
                Marshal.FreeHGlobal(tcpTablePtr);
            }
        }

        /// <summary>
        /// ネットワークバイトオーダーからホストバイトオーダーへの変換(16bit)
        /// </summary>
        private ushort ntohs(ushort netshort)
        {
            return (ushort)(((netshort & 0xFF) << 8) | ((netshort >> 8) & 0xFF));
        }

        #region P/Invoke 定義

        private const int AF_INET = 2;

        public enum TCP_TABLE_CLASS
        {
            TCP_TABLE_BASIC_LISTENER,
            TCP_TABLE_BASIC_CONNECTIONS,
            TCP_TABLE_BASIC_ALL,
            TCP_TABLE_OWNER_PID_LISTENER,
            TCP_TABLE_OWNER_PID_CONNECTIONS,
            TCP_TABLE_OWNER_PID_ALL,
            TCP_TABLE_OWNER_MODULE_LISTENER,
            TCP_TABLE_OWNER_MODULE_CONNECTIONS,
            TCP_TABLE_OWNER_MODULE_ALL
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_TCPROW_OWNER_PID
        {
            public uint state;
            public uint localAddr;
            public uint localPort;
            public uint remoteAddr;
            public uint remotePort;
            public int owningPid;
        }

        [DllImport("iphlpapi.dll", SetLastError = true)]
        public static extern uint GetExtendedTcpTable(
            IntPtr pTcpTable,
            ref int dwOutBufLen,
            bool sort,
            int ipVersion,
            TCP_TABLE_CLASS tblClass,
            uint reserved
        );

        [DllImport("iphlpapi.dll", SetLastError = true)]
        public static extern uint SetTcpEntry(ref MIB_TCPROW_OWNER_PID pTcpRow);

        #endregion
    }
}

4. プロジェクトをビルド

Visual Studio の上部メニューから「ビルド」→「ソリューションのビルド」を選択します。
正常にビルドされると、VisualStudioの下部に「ビルド成功」と表示されます。

5. Reconnectorを実行

ビルドすると以下のようなフォルダ構成となり、DebugまたはReleaseフォルダ内に「HearthstoneRecconector.exe」が作成されています。

ビルドされたアプリケーションパス(プロジェクトフォルダがデスクトップの場合)
デスクトップ(プロジェクトフォルダの場所によって変わる)
└── HearthstoneRecconector
    └── HearthstoneRecconector
        └── bin
            ├── Debug
            │   └── HearthstoneRecconector.exe
            └── Release
                └── HearthstoneRecconector.exe

ビルドされたHearthstoneRecconector.exeを右クリックし、「管理者として実行」を選択します。
Windowsポップアップが表示されたら「はい」をクリックし、Reconnectorを起動しましょう。

アプリケーションウィンドウが表示され、中央に「Disconnect」ボタンが現れます。
バトルグラウンドをプレイ中に「Disconnect」をクリックすると、通信の切断・再接続が実施されます。

タスキルツールは通信を遮断するため管理者権限が必要です。必ず管理者として実行してください。

タスキルできない場合の対処法

簡易版ではタスキルできないケースがあります。

タスキルできないケース

ハースストーンのアップデートやパッチ更新直後に、ハースストーンの通信情報が変化し、タスキルできなくなるケースがあります。

対処法

時間経過とともに、ハースストーンの通信情報が元に戻りタスキルできるようになります。

すぐに必要な場合、以下の高機能版を使用してください。
高機能版は切断すべき通信を自動で特定するため、通信情報変更の影響を受けにくいです。

高機能版のタスキルツールをダウンロード

簡易版ツールの構築が難しい場合や、より確実にタスキルしたい場合は、高機能版をダウンロードしてください。

高機能版と簡易版の違い

  • ハースストーンのアニメーション通信を自動で特定するので、確実にタスキルできる
  • ダウンロードするだけで使える
  • ツールを最前面に表示するか選択可能

差分を表にまとめました。

スクロールできます
高機能簡易版
確実にタスキルできるハースストーンの通信情報が変わると機能しない場合がある
ダウンロードするだけですぐに使える自分で構築する必要がある
有料無料

高機能タスキルツールの画面

高機能版のUIは以下のようになっており、ログファイルの特定や簡単なUI設定が可能です。

高機能版のUI画面高機能版の設定画面

ツールのダウンロード方法

以下のGoogleDriveからダウンロードできます。

購入特典
・ツールのダウンロード
・ツールのマニュアル
・不明点や不具合サポート(コメント欄にて)

Ueda
フリーランスエンジニア
RPAエンジニアです。
UipathやVBAを使用した開発を得意としています。優れた可読性と効率的な設計を併せ持つRPA開発を心がけています。
RPA初心者向けの教育経験多数あり。RPAの開発サポートも承ります。

Wordpressを用いたHP制作のお仕事も経験があります。本サイトもWordpressを用いて制作しております。

ペットのチワプーと暮らしてます。
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (9件)

  • 対象portを1119にすることで動作確認できました。
    新環境のバトグラが再接続要求されることが多いので助かりました。

  • 初めまして。
    こちらの記事で紹介されている方法を試したところ、指定された通信が見つかりませんでした。
    と表示されタスクキルができなくて上の方のコメントを参考にさせてもらって
    private readonly int targetRemortPort = 3724の数字の部分を1119に書き換え(合っていますか?)
    た所、タスクキルができて画面が切り替わった後に、ゲームとの通信が切断されました。再接続中…
    と出てきてずっと操作ができない状態で手詰まりの状況です。
    もう一度ボタンを押すとゲームが落ちて普通の再起動をすることになっています。
    何か解決策があれば教えていただけませんか?

    • 初めまして!

      ■Port設定について
      Portの設定箇所は合っています!

      ■復帰できない原因
      切断した通信内に、復帰に必要な通信が含まれていたのが原因と推測します。(ファイアーウォール切断と同様の事象)
      簡易版はPort3724を前提としているため、動作確認時も1119はたまに復帰できないケースがありました。
      体感50%くらい、上手くできる場合もありますが。

      なおPort3724は動作確認では100%正常に動作していました。

      ■解決策
      1. Port3724の時だけツールを使う
      2. 高機能版(有料)を使う

      もう少し詳しく解説します。

      1. Port3724の時だけツールを使う
      Port3724では確実に動作するので、簡易版はPort3724で使うのがお勧めです。
      1119でも使えますが、100%ではないため注意が必要です。
      バトグラは傾向として、アプデ後はしばらく1119になり、落ち着いたら3724に戻ります。
      なので3724で使える期間の方が長いはずです。

      2. 高機能版(有料)を使う
      高機能版ではPort番号に関係なく、確実にタスキル→復帰が可能です。
      牛丼1杯分の価格で買い切りなので、常に100%確実にタスキルしたい場合はご検討ください。

  • お返事感謝いたします。
    Port3724でテストしてみたところ、やはり通信が見つかりませんでしたと表示され
    タスキル自体ができなかったので何が原因なんだろうと…

    分からなかったので有料版をDLさせていただいて、今2試合ほど使ってみました。
    すると序盤までは大変便利になって感動したのですが、2試合とも残り4人になってから使うと
    タスクキルできて画面が復帰した後に、ゲームとの通信が切断されました。再接続中…
    と出てきて待っても戻れなくてゲームを再起動すると対戦に復帰できず2試合とも
    結果が4位になってしまいました。
    2試合連続で発生したので、おそらく4人以下で使用すると復帰できないと思われます。

    忙しい後半こそ使いたいので、何かご教授頂けないでしょうか。

    • ありがとうございます!

      私のPCでは後半でも機能しており、事象が再現できておりません。。
      原因調査のため、以下の情報を共有いただけますでしょうか。

      1. ツールのLogファイル
       通常「C:\Program Files (x86)\Hearthstone\HearthstoneReconnector_Logs」にログファイルが格納されているかと思います。
       こちらの内容をコピペしてコメントに書き込みいただきたいです。
       当日分のみでOKです。

      2. ハースストーンのLogファイル
       通常「C:\Program Files (x86)\Hearthstone\Logs」に日付フォルダがあり、その中に「Hearthstone.log」があります。
       こちらもコピペしてコメントに書き込みいただきたいです。
       当日分のみでOKです。

      3. 状況確認
       ・ツールの切断ボタンを連続でクリックしたり、短いスパンでクリックしましたか?
       ・「待っても戻れない」とのことですが、どれくらい待ちましたか?

      ■注意
      1と2のログ情報については、確認後にコメントを削除しますので、単体でコメント送付いただけると助かります。

      いただいた情報をもとに調査してみます。
      お手数ですが、よろしくお願いします!

  • こんばんは。
    事象はお昼ごろ確認され、あの後もプレイしていたのですがその後2回中2回正常に動作いたしました。

    違いとしては、復帰できなかった時は上田さんのおっしゃる通り2試合とも前半のときに
    確認のためにタスキルをして戻ってきたらすぐタスキルを行う、という動作を
    何度も繰り返していました。
    その後の2回落ちなかったゲームの場合は4人になるまで1度くらいしかタスキルを
    していなかったので、それが原因だったと思われます。

    待っても戻れないというのは再接続中の画面を1分くらいでした。

    • 情報共有ありがとうございます!ログは控えたので削除しました。

      連続した頻繁なタスキルは通信再接続に支障をきたす可能性もあるため、適度に使用いただければと思います。
      通常の戦闘スキップ程度の頻度なら全く問題ないと思います。

      復帰できない事象について、調査いたします。
      事象の再発生の有無等、進展があればご連絡いただけますと幸いです!

  • 個人情報も結構乗っていたので削除ありがとうございます!

    そうですね、今ちょうど時間のほしい構成をやっていて怖かったのですが
    毎ターンタスキルできて非常に快適でした。
    ファイアウォールのタスキルより復帰早いですしね。

    ログがお役に立てると幸いです、ありがとうございました。

コメントする

目次