飞郁网络培训

9-10.FPS游戏自瞄透视之代码实现自瞄2

发布于:2018-12-23 19:38:03    |     197次阅读 作者:任鸟飞

所有的准备工作都完成了

那么我们就可以看看自瞄的代码是怎么写了

以下代码全部以中文标注


①首先是一个 人物和目标的结构

typedef struct T人物属性//人物属性结构

{

char* szpName;

DWORD d阵营;

FLOAT fHp;

FLOAT fMaxHp;

FLOAT fX;

FLOAT fY;

FLOAT fZ;

FLOAT f准星水平朝向;

FLOAT f准星高度朝向;

T人物属性* 初始化();

}_T人物属性;

typedef struct T怪物列表

{

T人物属性 列表[0x500];

DWORD nd数量;

void c初始化();

}_T怪物列表;


②然后我对结构进行初始化遍历

T人物属性*T人物属性::初始化() //获得人物数据

{

DWORD 模块句柄 = (DWORD)GetModuleHandleA("Crossout.exe");

DWORD Base = 0;

__try

{

d编号 = *(DWORD*)(模块句柄 + Base_角色编号);

szpName = (char*)(模块句柄 + Base_阵营数组 + d编号*Offset_阵营数组结构大小 + 0x8);

d阵营 = *(DWORD*)(模块句柄 + Base_阵营数组 + d编号*Offset_阵营数组结构大小 + 0x68);

ID = *(DWORD*)(模块句柄 + Base_阵营数组 + d编号*Offset_阵营数组结构大小 + 0xA0);

f准星水平朝向 = *(FLOAT*)(模块句柄 + Base_XY朝向基地址);

f准星高度朝向 = *(FLOAT*)(模块句柄 + Base_Z朝向基地址);

Base = *(DWORD*)(模块句柄 + Base_对象属性遍历基地址);

ID &= 0x0FFF;

ID += 0x2AAD;

ID *= 0xC;

Base += ID;

Base = *(DWORD*)Base;

Call_输出调试信息("创世战车 读取人物对象:%X\r\n",Base);

if (Base!=0)

{

fHp = *(FLOAT*)(Base + 0xC0);

fMaxHp = *(FLOAT*)(Base + 0xC4);

fX = *(FLOAT*)(Base + 0x2B0);

fZ = *(FLOAT*)(Base + 0x2B4);

fY = *(FLOAT*)(Base + 0x2B8);

b死亡标志位 = 1;

}

else

{

fHp = 0;

fMaxHp = 0;

fX = 0;

fY = 0;

fZ = 0;

b死亡标志位 = 0;

}

}

__except (1)

{

Call_输出调试信息("创世战车 读取人物信息异常\r\n");

return NULL;

}

return this;

}



void T怪物列表::c初始化() //获取怪物数据

{

DWORD 模块句柄 = (DWORD)GetModuleHandleA("Crossout.exe");

DWORD Base = 0;

__try

{

for (int i=0;i<32;i++)

{

列表[i].szpName = (char*)(模块句柄 + Base_阵营数组 + i*Offset_阵营数组结构大小 + 0x8);

列表[i].d阵营 = *(DWORD*)(模块句柄 + Base_阵营数组 + i*Offset_阵营数组结构大小 + 0x68);

列表[i].ID = *(DWORD*)(模块句柄 + Base_阵营数组 + i*Offset_阵营数组结构大小 + 0xA0);

Base = *(DWORD*)(模块句柄 + Base_对象属性遍历基地址);

列表[i].ID &= 0x0FFF;

列表[i].ID += 0x2AAD;

列表[i].ID *= 0xC;

Base += 列表[i].ID;

Base = *(DWORD*)Base;

Call_输出调试信息("创世战车 读取周围对象:%X\r\n",Base);

if (Base!=0)

{

列表[i].fHp = *(FLOAT*)(Base + 0xC0);

列表[i].fMaxHp = *(FLOAT*)(Base + 0xC4);

列表[i].fX = *(FLOAT*)(Base + 0x2B0);

列表[i].fZ = *(FLOAT*)(Base + 0x2B4);

列表[i].fY = *(FLOAT*)(Base + 0x2B8);

列表[i].b死亡标志位 = 1;

}

else

{

列表[i].fHp = 0;

列表[i].fMaxHp = 0;

列表[i].fX = 0;

列表[i].fY = 0;

列表[i].fZ = 0;

列表[i].b死亡标志位 = 0;

}

}

}

__except (1)

{

Call_输出调试信息("创世战车 读取怪物信息异常\r\n");

}

}


③筛选出最近的地方目标并把对其进行准星瞄准

void Call_自动瞄准(FLOAT 怪物X,FLOAT 怪物Y,FLOAT 怪物Z)

{

T人物属性 人物;

人物.初始化();

FLOAT 水平角;

if (怪物X > 人物.fX && 怪物Y > 人物.fY)//第一象限

{

Call_输出调试信息("创世战车 自瞄进入第一象限\r\n");

水平角=(FLOAT)(0 - atan2(怪物Y-人物.fY,怪物X-人物.fX)-3.1415926/2);

}

if (怪物X < 人物.fX && 怪物Y > 人物.fY)//第二象限

{

Call_输出调试信息("创世战车 自瞄进入第二象限\r\n");

水平角=(FLOAT)(atan2(怪物Y-人物.fY,人物.fX-怪物X)+3.1415926/2);

}

if (怪物X < 人物.fX && 怪物Y < 人物.fY)//第三象限

{

Call_输出调试信息("创世战车 自瞄进入第三象限\r\n");

水平角=(FLOAT)(3.1415926/2-atan2(人物.fY-怪物Y,人物.fX-怪物X));

}

if (怪物X > 人物.fX && 怪物Y < 人物.fY)//第四象限

{

Call_输出调试信息("创世战车 自瞄进入第四象限\r\n");

水平角=(FLOAT)(atan2(人物.fY-怪物Y,怪物X-人物.fX)-3.1415926/2);

}

Call_输出调试信息("创世战车 自瞄水平角%f\r\n",水平角);

FLOAT 俯视角;

FLOAT 水平距离;

水平距离 = sqrt((怪物X-人物.fX)*(怪物X-人物.fX)+(怪物Y-人物.fY)*(怪物Y-人物.fY));

if (怪物Z > 人物.fZ)

{

Call_输出调试信息("创世战车 自瞄进入抬头模式\r\n");

俯视角 = atan2(怪物Z-人物.fZ,水平距离);

}

if (怪物Z < 人物.fZ)

{

Call_输出调试信息("创世战车 自瞄进入低头模式\r\n");

俯视角 = 0 - atan2(人物.fZ-怪物Z,水平距离);

}

Call_输出调试信息("创世战车 自瞄俯视角%f\r\n",俯视角);

DWORD 模块句柄 = (DWORD)GetModuleHandleA("Crossout.exe");

*(FLOAT*)(模块句柄 + Base_XY朝向基地址) = 水平角; //计算出来的朝向值 写入内存

*(FLOAT*)(模块句柄 + Base_Z朝向基地址) = 俯视角; //计算出来的朝向值 写入内存

}


int Call_自动瞄准最近()

{

T人物属性 人物;

人物.初始化();

T怪物列表 List;

List.c初始化();

FLOAT 距离 = 222;

FLOAT X;

FLOAT Y;

FLOAT Z;

for (int i=0;i<32;i++) //筛选最近敌人

{

if (List.列表[i].fX > 0.1 || List.列表[i].fX < -0.1)

{

if (sqrt((List.列表[i].fX-人物.fX)*(List.列表[i].fX-人物.fX)+(List.列表[i].fY-人物.fY)*(List.列表[i].fY-人物.fY))< 距离 && i!=人物.d编号)

{

if (List.列表[i].d阵营 != 人物.d阵营)

{

Call_输出调试信息("创世战车 找到敌人!\r\n");

距离 = sqrt((List.列表[i].fX-人物.fX)*(List.列表[i].fX-人物.fX)+(List.列表[i].fY-人物.fY)*(List.列表[i].fY-人物.fY));

X = List.列表[i].fX;

Y = List.列表[i].fY;

Z = List.列表[i].fZ;

}

}

}

}

if (距离 < 222) //如果在我们攻击范围内才攻击

{

Call_自动瞄准(X,Y,Z-g_自减高度);

if (g_攻击标志位 == 0)

{

g_攻击标志位 = 1;

HANDLE handle_攻击线程=::CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)攻击线程,NULL,NULL,NULL);//创建线程

CloseHandle(handle_攻击线程);

}

return 1;

}

g_攻击标志位 = 0;

Sleep(300); // 确保彻底关闭

return 0;

}

最终实现自瞄效果