C#簡單遊戲外掛製做(以Warcraft Ⅲ爲例)

網上有不少外掛製做的教程,大可能是講針對大型網絡遊戲的,主要包含一些抓包、反彙編、C++的知識綜合。事實也如此,常見的外掛都是使用VC++寫的,歷來沒有過C#或者其餘.NET語言編寫的外掛。windows

    做爲微軟.NET技術的忠實粉絲,這不免是一種遺憾。不過沒關係,下面流牛木馬就教你們兩招,包教包會,免收學費。 :)網絡

    其實做爲遊戲外掛來講,主要就是三個功能:模擬鍵盤操做、模擬鼠標操做、修改內存數據。修改內存數據比較難,但模擬鼠標鍵盤的操做卻很簡單。不少流行遊戲的外掛,均可以只經過模擬鼠標鍵盤來實現,例如:勁舞團、QQ音速、連連看、各種網頁遊戲,以及各種大型網遊中的自動打怪、自動吃藥等等。函數

    Warcraft Ⅲ,學名魔獸爭霸之冰封王座,俗稱魔獸,簡稱war3,在最近六七年風靡全球。最近兩年,war3在中國又掀起了玩DOTA的新高潮。.net

    本文製做DOTA遊戲中的顯血、改鍵外掛爲例,簡單地介紹如何使用C#語言製做遊戲外掛。線程

    最終界面以下:指針

image    本示例包含兩個功能:顯血;將Q鍵改成小鍵盤的7鍵。玩war3的同窗都知道,這兩個功能對於war3(尤爲是DOTA)至關重要。code

     首先簡單介紹一下,外掛程序模擬鍵盤的原理。htm

     外掛程序與遊戲程序是兩個不一樣的進程。外掛程序使用Windows提供的API找到遊戲程序的進程,並設置鍵盤鉤子(什麼叫作鉤子?你不知道,但百度知道。)設置完鉤子後,咱們再監控遊戲進程中用戶的按鍵,並根據用戶需求進行處理,完成某些模擬鍵盤動做。 blog

     瞭解了這個過程以後,咱們就能夠開始整理思路了。完成外掛一共須要如下四個步驟:教程

1、聲明Windows API 中的函數和常量

      //鍵盤Hook結構函數
        [StructLayout(LayoutKind.Sequential)]
        public class KeyBoardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        #region DllImport
        //設置鉤子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        //抽掉鉤子
        public static extern bool UnhookWindowsHookEx(int idHook);
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        //調用下一個鉤子
        public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
        //取得模塊句柄 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        //尋找目標進程窗口
        [DllImport("USER32.DLL")]
        public static extern IntPtr FindWindow(string lpClassName,
            string lpWindowName);
         //設置進程窗口到最前 
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
       //模擬鍵盤事件 
        [DllImport("User32.dll")]
        public static extern void keybd_event(Byte bVk, Byte bScan, Int32 dwFlags, Int32 dwExtraInfo);
//釋放按鍵的常量
   private const int KEYEVENTF_KEYUP =2;
       本例所使用的函數比較少,它們都在系統的USER32.dll裏,包括:設置和取消鉤子、調用下一個鉤子、導入進程、模擬鍵盤等等。咱們依次導入它們。
       這些函數的命名規範合理,幾乎只根據函數名就能知道其功能。
       若是讀者對於其中的某些函數不熟悉,請自行搜索MSDN。

2、使用Windows API設置鉤子  

          有了以上windows API函數的聲明,下一步就是設置鉤子了。

          寥寥兩行代碼,但包含了至關豐富的內容。

//委託
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
 
public void Hook_Start()
    {
        // 安裝鍵盤鉤子
        if (hHook == 0)
        {
            KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);

            hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
                     
        }
    }
 
    先介紹一下設置鉤子的明星函數:SetWindowsHookEx 。它的參數說明以下。

SetWindowsHookEx(
idHook: Integer;   {鉤子類型}
lpfn: TFNHookProc; {函數指針}
hmod: HINST;       {包含鉤子函數的模塊(EXE、DLL)句柄; 通常是 HInstance; 若是是當前線程這裏能夠是 0}
  dwThreadId: DWORD  {關聯的線程; 可用 GetCurrentThreadId 獲取當前線程; 0 表示是系統級鉤子}
): HHOOK;            {返回鉤子的句柄; 0 表示失敗}

 

    請注意lpfn這個參數。上面的解釋是「函數指針」。在C#中,是不能直接使用指針的,更不要說函數指針了。咱們能夠採用C#中的委託(delegate)來實現函數指針的功能。

    因而乎,在上面的代碼中,咱們定義了一個處理鍵盤消息函數的委託KeyBoardHookProcedure = new HookProc(KeyBoardHookProc),並將它做爲參數傳入SetWindowsHookEx 內。KeyBoardHookProc就是被委託的具體函數。

 

3、監控用戶操做

   設置好鉤子後,咱們能夠在被委託的函數中寫入監控用戶操做與模擬鍵盤的代碼。

public static int KeyBoardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
       //監控用戶鍵盤輸入
         KeyBoardHookStruct input = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));

            //截獲Home  鍵          
            if (input.vkCode == (int)Keys.Home)
            {
              //此處寫入其餘操做邏輯                
            }
       
           // 繼續執行下一個鉤子程序
            return CallNextHookEx(hHook, nCode, wParam, lParam);

        }

 

4、根據用戶須要模擬鍵盤操做

        顯血功能:玩war3的都知道,war3自帶的顯血快捷鍵有3個。Alt鍵是顯示全部單位生命,[ 鍵顯示友方單位生命,] 鍵顯示地方單位生命。外掛須要作的事情僅僅是模擬一直按着某個鍵不鬆手而已。因爲Alt鍵與其餘不少鍵構成組合鍵,故咱們不能模擬長按Alt,不然會影響正常遊戲。咱們的解決方案應該是模擬長按 [ 鍵和 ] 鍵。代碼以下:

              //得到魔獸程序的句柄
                IntPtr wcHandle = FindWindow(null, "Warcraft III");

                //若是鉤子有效
                if (wcHandle != IntPtr.Zero)
                {
                    //設置遊戲窗口到最前
                    SetForegroundWindow(wcHandle);
                byte VK_NUM1 = 219;   //鍵盤上 [ 鍵的代碼。按[可顯示友方單位生命值。
                  byte VK_NUM2 = 221;   // 鍵盤上] 鍵的代碼。按]可顯示敵方單位生命值。
                  keybd_event(VK_NUM1, 0, 0, 0); //長按[
                keybd_event(VK_NUM2, 0, 0, 0);  //長按]
               }

        改鍵: 小鍵盤(Numpad)上的快捷鍵很不方便按,因此不少玩家喜歡把小鍵盤上的鍵改到左邊的字母鍵盤。玩DOTA的同窗都知道,沒有任何英雄的技能使用"Q」這個快捷鍵(召喚師有一種球是"Q"(不是技能))。因而咱們把小鍵盤上的7鍵改到Q上,也不會形成任何衝突。方法也很簡單:若是監控到用戶按"Q」鍵,則像遊戲進程發送小鍵盤上的"7"鍵。代碼以下:

        //若是用戶按了Q鍵
          if (input.vkCode == (int)Keys.Q)
          {
              //得到魔獸程序的句柄
              IntPtr wcHandle = FindWindow(null, "Warcraft III");

              //若是鉤子有效
              if (wcHandle != IntPtr.Zero)
              {
                  //設置遊戲窗口到最前
                  SetForegroundWindow(wcHandle);
                  byte VK_Q = (byte)Keys.NumPad7;
                  keybd_event(VK_Q, 0, 0, 0);//按下小鍵盤7
                  keybd_event(VK_Q, 0, KEYEVENTF_KEYUP, 0); //鬆開小鍵盤7
              }
              return 1;
          }

好了,到這裏就把模擬鍵盤的外掛介紹完了。模擬鼠標與之很是相似,請用戶自行揣摩。本文僅作拋磚引玉,歡迎感興趣的朋友來流牛木馬的博客進行討論。

附件:外掛成品下載(運行須要.net 2.0以上環境)

相關文章
相關標籤/搜索