美服疯狂坦克辅助瞄准外挂C#版开发(四)程序使用说明和完成源代码及其下载

来源:互联网 发布:淘宝卖家质量问题范围 编辑:程序博客网 时间:2024/05/14 02:59

到现在为止,我们已经将疯狂坦克外挂所需相关的功能点及解决方案完成。

先说说常规的使用方法:

1、编译发布程序后,先运行程序(默认不可见),然后进入美服疯狂坦克。

2、在游戏中按(Pause)键启动各种辅助线。

3、在游戏中按(Scroll Lock)键切换你当前所用的坦克。

4、在游戏中鼠标放到你坦克所在的位置(小地图上圆点中心),按下(PrScrn SysRq)键确定曲线起点。

5、通过(Insert)和(Delete)键调节角度标识与游戏中坦克实际角度线端点重合。

6、通过(Home)和(End)键调节风力标识与游戏中风力线边缘重合。

7、通过(PgUp)和(PgDn)建调节力度,直到小地图上的抛物线穿过你要命中的目标。

8、按一下键盘上的左边的(Control)键,将会按照预先设定的抛物线发射炮弹命中目标。

PS:所有调节按键,同时按下(Shift)键为粗调,放开(Shift)键后为精调。

由于游戏中不同的坦克的风力系统、推力系数、重力系数、满力时间不一样,所以请使用各种坦克经过多次测试得出系数。

具体测试各种坦克的相关系数方法:

1、选中某一款坦克,然后多次测试,根据炮弹的落点与小地图上曲线落点的误差调节该坦克的风力系统、推力系数、重力系数,直到精确。

2、多次测试根据推力标识与实际力度边缘线的误差调节该坦克的满力时间这一系数。

3、将各种测量后的系数写入配置文件中保存。

截止到目前为止,一个疯狂坦克辅助瞄准外挂的基本功能就完成了。但是这样的外挂其实是存在一些功能缺陷的,如下:

1、不能够直接读取游戏内存中的数据,来获取当前的角度、风力和力度等值,而是通过绘制和调节辅助线来获取。

2、不能够直接识别出当前正在使用的坦克的名称和加载相关参数,需要通过手动切换坦克。

3、未将各种坦克的四个系数都预设好,因为我真的没有这个时间和耐性。

以上的功能缺陷,最大的一个技术障碍就是不能够在游戏运行过程中从内存中获取相关的数据。

这也是为什么美服没有瞄准外挂而且当初国服的外挂在美服用不了的原因把。

个人推测是因为在某一次游戏更新过程中,将原来直接写到动态内存中的这些相关数据改为加密后再写入内存。

所以不管用FPE或者金山游侠等内存查询工具,均不能够在内存中发现任何的相关数据明文。

如果有朋友对其加密方式有研究,或者能够提供获取这些数据的解决方法,请与我联系指正。

如果能够获取到这些数据,这个外挂功能就算比较完整了,使用起来也没这么麻烦,如国服当年的坦克猎手4.1。

下面是程序的所有源码,稍后我会放到CSDN下载中心一份完整的源码,不知道是否能通过审核。

本程序仅限用于学习研究,请不要破坏游戏平衡,谢谢。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Xml;
  8. using System.Windows.Forms;
  9. using System.Runtime.InteropServices;
  10. using System.Diagnostics;
  11. using GlobalMouseKeyBoardHook;
  12. namespace BBTankAssistant
  13. {
  14.     public partial class Form1:Form
  15.     {
  16.         #region ====变量定义====
  17.         //全局鼠标钩子
  18.         private KeyboardHook KH;
  19.         //全局键盘钩子
  20.         private MouseHook MH;
  21.         //炮弹初始位置(坦克所在位置坐标)
  22.         private Point PrimaryCoordinate;
  23.         //炮弹运行位置(某一时刻炮弹所在位置坐标)
  24.         private Point MovementCoordinate;
  25.         //炮弹运行轨迹(炮弹可能出现的所有位置坐标)
  26.         private IList<Point> MoveKeyCoordinates;
  27.         //风力大小
  28.         private float WindPower;
  29.         //推力大小
  30.         private float PushPower;
  31.         //推力角度
  32.         private double PushAngle;
  33.         //当前坦克编号
  34.         private int TankNumberNowPlay;
  35.         //当前坦克
  36.         private Tank TankNowPlay; 
  37.         //计时器
  38.         private Stopwatch SW;
  39.         #endregion
  40.         #region ====外部方法====
  41.         //外部方法:获取DC
  42.         [DllImport("User32.dll")]
  43.         public extern static System.IntPtr GetDC(System.IntPtr hWnd);
  44.         //外部方法:释放DC
  45.         [DllImport("User32.dll")]
  46.         static extern int ReleaseDC(IntPtr hWnd,IntPtr hDC);
  47.         //外部方法:刷新区域
  48.         [DllImport("user32.dll",CharSet = CharSet.Auto)]
  49.         public static extern bool InvalidateRect(IntPtr hWnd,IntPtr lpRect,bool bErase); 
  50.         #endregion
  51.         public Form1()
  52.         {
  53.             InitializeComponent();
  54.         }
  55.         private void Form1_Shown(object sender,EventArgs e)
  56.         {
  57.             this.Hide();
  58.         }
  59.         private void Form1_Load(object sender,EventArgs e)
  60.         {
  61.             #region ====变量初始化====
  62.             KH = new KeyboardHook();
  63.             MH = new MouseHook();
  64.             KH.Start();
  65.             MH.Start();
  66.             KH.KeyDown += new KeyEventHandler(KeyBoardHook_KeyDown);
  67.             KH.KeyUp += new KeyEventHandler(KeyBoardHook_KeyUp);
  68.             KH.KeyPress += new KeyPressEventHandler(KeyBoardHook_KeyPress);
  69.             MH.MouseDown += new MouseEventHandler(MouseHook_MouseDown);
  70.             MH.MouseUp += new MouseEventHandler(MouseHook_MouseUp);
  71.             PrimaryCoordinate = new Point(487,56);
  72.             WindPower = 0;
  73.             PushPower = 0;
  74.             PushAngle = 30;
  75.             TankNumberNowPlay = 0;
  76.             TankNowPlay = Common.GetAllTanks()[0];
  77.             SW = new Stopwatch();
  78.             #endregion
  79.         }
  80.         private void timer1_Tick(object sender,EventArgs e)
  81.         {
  82.             DrawAssistantLine();
  83.         }
  84.         private void timer2_Tick(object sender,EventArgs e)
  85.         {
  86.             if(SW.ElapsedMilliseconds <  TankNowPlay.MaxPowerTime * PushPower / 322)
  87.             {
  88.                 KeyboardSimulator.KeyDown(Keys.Space);
  89.             }
  90.             else
  91.             {
  92.                 KeyboardSimulator.KeyUp(Keys.Space);
  93.                 SW.Reset();
  94.                 timer2.Enabled = false;
  95.             }
  96.         }
  97.         public void KeyBoardHook_KeyDown(object sender,KeyEventArgs e)
  98.         {
  99.             #region ====按键绑定====
  100.             switch(e.KeyCode)
  101.             {
  102.                 case Keys.Pause:
  103.                     timer1.Enabled = true;
  104.                     break;
  105.                 case Keys.Scroll:
  106.                     ChangeNextTank();
  107.                     break;
  108.                 case Keys.Insert:
  109.                     PushAngle += e.Shift ? 10 : 1; 
  110.                     break;
  111.                 case Keys.Delete:
  112.                     PushAngle -= e.Shift ? 10 : 1;
  113.                     break;
  114.                 case Keys.Home:
  115.                     if(WindPower < 36)
  116.                     {
  117.                         WindPower += e.Shift ? 10 : 1; 
  118.                     }
  119.                     break;
  120.                 case Keys.End:
  121.                     if(WindPower > -36)
  122.                     {
  123.                         WindPower -= e.Shift ? 10 : 1;
  124.                     }
  125.                     break;
  126.                 case Keys.PageUp:
  127.                     if(PushPower < 322)
  128.                     {
  129.                         PushPower += e.Shift ? 10 : 1; 
  130.                     }
  131.                     break;
  132.                 case Keys.PageDown:
  133.                     if(PushPower > 0)
  134.                     {
  135.                         PushPower -= e.Shift ? 10 : 1; 
  136.                     }
  137.                     break;
  138.                 case Keys.PrintScreen:
  139.                     PrimaryCoordinate = MouseSimulator.Position;
  140.                     break;
  141.                 case Keys.LControlKey:
  142.                     SW.Start();
  143.                     timer2.Enabled = true;
  144.                     break;
  145.                 default:
  146.                     break;
  147.             } 
  148.             #endregion
  149.         }
  150.         public void KeyBoardHook_KeyUp(object sender,KeyEventArgs e)
  151.         {
  152.         }
  153.         public void KeyBoardHook_KeyPress(object sender,KeyPressEventArgs e)
  154.         {
  155.         }
  156.         public void MouseHook_MouseDown(object sender,MouseEventArgs e)
  157.         {
  158.         }
  159.         public void MouseHook_MouseUp(object sender,MouseEventArgs e)
  160.         {
  161.         }
  162.         //切换下一坦克
  163.         public void ChangeNextTank()
  164.         {
  165.             IList<Tank> ILT = new List<Tank>();
  166.             ILT = Common.GetAllTanks();
  167.             if((ILT !=null)&&(ILT.Count > 0))
  168.             {
  169.                 if(TankNumberNowPlay < ILT.Count -1 )
  170.                 {
  171.                     TankNumberNowPlay += 1;
  172.                 }
  173.                 else
  174.                 {
  175.                     TankNumberNowPlay = 0;
  176.                 }
  177.                 TankNowPlay = ILT[TankNumberNowPlay];
  178.             }
  179.             else
  180.             {
  181.                 TankNowPlay = null;
  182.             }
  183.         }
  184.         //绘图
  185.         public void DrawAssistantLine()
  186.         {
  187.             #region ====绘图准备====
  188.             Pen Pe = new Pen(Color.Red,1);
  189.             SolidBrush SB = new SolidBrush(Color.Green);
  190.             IntPtr ScreenHandle = GetDC(IntPtr.Zero);
  191.             Graphics G = Graphics.FromHdc(ScreenHandle); 
  192.             #endregion
  193.             #region ====绘制坦克名称====
  194.             G.DrawString(TankNowPlay.Name,new Font("宋体",12),SB,PrimaryCoordinate); 
  195.             #endregion
  196.             #region ====绘制参考线====
  197.             //绘制角度线条
  198.             G.DrawLine(Pe,74,427,74 + float.Parse((37 * Math.Cos(PushAngle * Math.PI / 180)).ToString()),427 - float.Parse((37 * Math.Sin(PushAngle * Math.PI / 180)).ToString()));
  199.             //绘制角度端点
  200.             G.FillEllipse(SB,72 + float.Parse((37 * Math.Cos(PushAngle * Math.PI / 180)).ToString()),425 - float.Parse((37 * Math.Sin(PushAngle * Math.PI / 180)).ToString()),4,4);
  201.             //绘制风力线
  202.             G.DrawLine(Pe,74 + WindPower,469,74 + WindPower,477);
  203.             //绘制推力线
  204.             G.DrawLine(Pe,224 + PushPower,438,224 + PushPower,454); 
  205.             #endregion
  206.             #region ====绘制辅助线====
  207.             ////绘制角度边框
  208.             //G.DrawEllipse(Pe,35,388,74,74);
  209.             ////绘制推力边框
  210.             //G.DrawRectangle(Pe,224,438,322,16);
  211.             ////绘制风力边框
  212.             //G.DrawRectangle(Pe,38,469,72,8);
  213.             ////绘制地图边框
  214.             //G.DrawRectangle(Pe,482,5,153,95); 
  215.             #endregion
  216.             #region ====计算运行轨迹====
  217.             MovementCoordinate = PrimaryCoordinate;
  218.             MoveKeyCoordinates = new List<Point>();
  219.             double MoveTime = 0;
  220.             while(((MovementCoordinate.X > Parabola.GraphRangeXmin) && (MovementCoordinate.X < Parabola.GraphRangeXmax)) && ((MovementCoordinate.Y > Parabola.GraphRangeYmin) && (MovementCoordinate.Y < Parabola.GraphRangeYmax)))
  221.             {
  222.                 MovementCoordinate = new Point();
  223.                 MovementCoordinate.X = int.Parse(Math.Round(PrimaryCoordinate.X + TankNowPlay.PushCoefficient * PushPower * Math.Cos(PushAngle * Math.PI / 180) * MoveTime + (TankNowPlay.WindCoefficient * WindPower * MoveTime * MoveTime) / 2,0).ToString());
  224.                 MovementCoordinate.Y = int.Parse(Math.Round(PrimaryCoordinate.Y - TankNowPlay.PushCoefficient * PushPower * Math.Sin(PushAngle * Math.PI / 180) * MoveTime + (TankNowPlay.GravityCoefficient * MoveTime * MoveTime) / 2,0).ToString());
  225.                 MoveKeyCoordinates.Add(MovementCoordinate);
  226.                 MoveTime += Parabola.GraphFreq;
  227.             } 
  228.             #endregion
  229.             #region ====绘制弹道曲线====
  230.             Point[] Ps = new Point[MoveKeyCoordinates.Count];
  231.             MoveKeyCoordinates.CopyTo(Ps,0);
  232.             //绘制弹道曲线
  233.             G.DrawLines(Pe,Ps);  
  234.             #endregion
  235.             #region ====释放所有资源====
  236.             //InvalidateRect(System.IntPtr.Zero,System.IntPtr.Zero,false); 
  237.             Pe.Dispose();
  238.             SB.Dispose();
  239.             G.Dispose();
  240.             ReleaseDC(IntPtr.Zero,ScreenHandle); 
  241.             #endregion
  242.         }
  243.     }
  244.     #region ====通用函数====
  245.     public static class Common
  246.     {
  247.         //读取配置文件内容
  248.         public static string GetConfigValue(string XmlPath)
  249.         {
  250.             XmlDocument XD = new XmlDocument();
  251.             XD.Load(AppDomain.CurrentDomain.BaseDirectory + "../..../../BBTankAssistant.config");
  252.             XmlNode XN = XD.SelectSingleNode(XmlPath);
  253.             if(XN != null)
  254.             {
  255.                 return XN.InnerText;
  256.             }
  257.             else
  258.             {
  259.                 return null;
  260.             }
  261.         }
  262.         //更新配置文件内容
  263.         public static void SetConfigValue(string XmlPath,string ConfigValue)
  264.         {
  265.             XmlDocument XD = new XmlDocument();
  266.             XD.Load(AppDomain.CurrentDomain.BaseDirectory + "../../BBTankAssistant.config");
  267.             XmlNode XN = XD.SelectSingleNode(XmlPath);
  268.             if(XN != null)
  269.             {
  270.                 XN.InnerText = ConfigValue;
  271.                 XD.Save(AppDomain.CurrentDomain.BaseDirectory + "../../BBTankAssistant.config");
  272.             }
  273.         }
  274.         //获取所有坦克对象
  275.         public static IList<Tank> GetAllTanks()
  276.         {
  277.             XmlDocument XD = new XmlDocument();
  278.             XD.Load(AppDomain.CurrentDomain.BaseDirectory + "../../BBTankAssistant.config");
  279.             XmlNodeList XNL = XD.SelectNodes("//Tank");
  280.             if(XNL.Count > 0 )
  281.             {
  282.                 IList<Tank> ILT = new List<Tank>();
  283.                 foreach(XmlNode XN in XNL)
  284.                 {
  285.                     Tank T = new Tank(XN.FirstChild.InnerText);
  286.                     ILT.Add(T);
  287.                 }
  288.                 return ILT;
  289.             }
  290.             else
  291.             {
  292.                 return null;
  293.             }
  294.         }
  295.     } 
  296.     #endregion
  297.     #region ====弹道模型====
  298.     public static class Parabola
  299.     {
  300.         //Xmin
  301.         public static int GraphRangeXmin
  302.         {
  303.             get
  304.             {
  305.                 return int.Parse(Common.GetConfigValue("//ParabolaGraphRange").Split(',')[0]);
  306.             }
  307.         }
  308.         //Xmax
  309.         public static int GraphRangeXmax
  310.         {
  311.             get
  312.             {
  313.                 return int.Parse(Common.GetConfigValue("//ParabolaGraphRange").Split(',')[1]);
  314.             }
  315.         }
  316.         //Ymin
  317.         public static int GraphRangeYmin
  318.         {
  319.             get
  320.             {
  321.                 return int.Parse(Common.GetConfigValue("//ParabolaGraphRange").Split(',')[2]);
  322.             }
  323.         }
  324.         //Ymax
  325.         public static int GraphRangeYmax
  326.         {
  327.             get
  328.             {
  329.                 return int.Parse(Common.GetConfigValue("//ParabolaGraphRange").Split(',')[3]);
  330.             }
  331.         }
  332.         //Freq
  333.         public static double GraphFreq
  334.         {
  335.             get
  336.             {
  337.                 return double.Parse(Common.GetConfigValue("//ParabolaGraphFreq"));
  338.             }
  339.             set
  340.             {
  341.                 Common.SetConfigValue("//ParabolaGraphFreq",value.ToString());
  342.             }
  343.         }
  344.     } 
  345.     #endregion
  346.     #region ====坦克模型====
  347.     public class Tank
  348.     {
  349.         #region ====字段====
  350.         //名称
  351.         private string m_Name;
  352.         #endregion
  353.         #region ====属性====
  354.         //名称
  355.         public string Name
  356.         {
  357.             get
  358.             {
  359.                 return m_Name;
  360.             }
  361.             set
  362.             {
  363.                 m_Name = value;
  364.             }
  365.         }
  366.         //风力系数
  367.         public double WindCoefficient
  368.         {
  369.             get
  370.             {
  371.                 return double.Parse(Common.GetConfigValue("//Tank[@Name='"+m_Name+"']/WindCoefficient"));
  372.             }
  373.             set
  374.             {
  375.                 Common.SetConfigValue("//Tank[@Name='" + m_Name + "']/WindCoefficient",value.ToString());
  376.             }
  377.         }
  378.         //推力系数
  379.         public double PushCoefficient
  380.         {
  381.             get
  382.             {
  383.                 return double.Parse(Common.GetConfigValue("//Tank[@Name='" + m_Name + "']/PushCoefficient"));
  384.             }
  385.             set
  386.             {
  387.                 Common.SetConfigValue("//Tank[@Name='" + m_Name + "']/PushCoefficient",value.ToString());
  388.             }
  389.         }
  390.         //重力系数
  391.         public double GravityCoefficient
  392.         {
  393.             get
  394.             {
  395.                 return double.Parse(Common.GetConfigValue("//Tank[@Name='" + m_Name + "']/GravityCoefficient"));
  396.             }
  397.             set
  398.             {
  399.                 Common.SetConfigValue("//Tank[@Name='" + m_Name + "']/GravityCoefficient",value.ToString());
  400.             }
  401.         }
  402.         //满力时间
  403.         public double MaxPowerTime
  404.         {
  405.             get
  406.             {
  407.                 return double.Parse(Common.GetConfigValue("//Tank[@Name='" + m_Name + "']/MaxPowerTime"));
  408.             }
  409.             set
  410.             {
  411.                 Common.SetConfigValue("//Tank[@Name='" + m_Name + "']/MaxPowerTime",value.ToString());
  412.             }
  413.         }
  414.         #endregion
  415.         #region ====构造函数====
  416.         public Tank(string Name)
  417.         {
  418.             m_Name = Name;
  419.         }
  420.         #endregion
  421.     } 
  422.     #endregion
  423. }
原创粉丝点击