当前位置: 首页 > article >正文

35.第二阶段x86游戏实战2-C++遍历技能

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

本次游戏没法给

内容参考于:微尘网络安全

本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要盲目相信。

工具下载:

链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3

提取码:6tw3

复制这段内容后打开百度网盘手机App,操作更方便哦

上一个内容:34.第二阶段x86游戏实战2-游戏数据保存与定位(特征码定位基址)

上一个内容里使用特征码进行定位了基址偏移,本次就来使用C++把技能数据遍历出来

首先新加一个按钮

遍历技能按钮的点击事件,也是遍历技能入口代码

遍历技能二叉树代码

结构.cpp文件:主要新加 技能二叉数函数、AsmGetMonsterData函数

#include "pch.h"
#include "结构.h"

DWORD R_rwjz = *(DWORD*)((DWORD)GetModuleHandleA("Game.exe") + 0x5A6AF4);//人物基地址
DWORD R_jnecs2 = *(DWORD*)(JNECS2);
DWORD R_jnecs = *(DWORD*)(JNECS);
DWORD R_jnlq = *(DWORD*)(JNLQ);

void R_人物属性::初始化()
{
	__try {
		/**
			GetModuleHandleA("Game.exe")返回Game.exe模块的模块基址
		*/
		//DWORD 状态基址 = (DWORD)GetModuleHandleA("Game.exe") + 0x59EF6C;
		/**
			(DWORD*)状态基址 的意思是把 状态基址 的值当成内存地址
			*(DWORD*)状态基址 意思把内存地址里的值取出来
		*/
	/*	DWORD 状态偏移 = *(DWORD*)状态基址 + 0x60;
		DWORD 状态偏移1 = *(DWORD*)状态偏移 + 0x14C;
		状态 = *(DWORD*)状态偏移1;*/

		DWORD RW偏移 = ReadDword(R_rwjz + 0xc);
		M_通用包 = ReadWord(RW偏移 + 0x2c);
		M_走路包 = ReadWord(RW偏移 + 0x30);
		//状态 = ReadDword(状态偏移1);
		fX = ReadFloat(RW偏移 + 0x3C);
		fY = ReadFloat(RW偏移 + 0x44);
		pName = "";
		pName = ReadStr((char*)(ReadDword(ReadDword(RW偏移 + 0x148) + 0x10) + 0x2c));
		血量 = ReadFloat(ReadDword(ReadDword(RW偏移 + 0x148) + 0x10) + 0x8);

	}
	__except (1) {
		Call_输出调试信息("读物人物信息异常\r\n");
	}
}

void R_遍历背包::遍历背包()
{
	try {
		DWORD s = 0;
		//DWORD JZ = (DWORD)GetModuleHandleA("Game.exe") + 0x59F458;
		DWORD JZ = (DWORD)GetModuleHandleA("Game.exe") + 0x59F490;
		DWORD JZpy = ReadDword(ReadDword(JZ) + 0x181C4);
		背包[0].背包数量 = ReadDword(ReadDword(JZ) + 0x181C4 + 0x14); // 道具背包数量
		背包[1].背包数量 = ReadDword(ReadDword(JZ) + 0x181C4 + 0x15); // 材料背包数量
		背包[2].背包数量 = ReadDword(ReadDword(JZ) + 0x181C4 + 0x16);// 任务背包数量
		for (int i = 0; i < 3; i++)
		{
			CString str;
			str.Format(L"数量2:%d %d %d", 背包[0].背包数量, 背包[1].背包数量, 背包[2].背包数量);
			//AfxMessageBox(str);
			for (int  j = 0; j < 背包[i].背包数量; j++)
			{
				if (i == 0) {
					s = j;
				}
				if (i == 1)
					s = j + 背包[0].背包数量;
				if (i == 2)
					s = j + 背包[0].背包数量 + 背包[1].背包数量;
				列表[s].dwObject = ReadDword(JZpy + j * 4);
				if (列表[s].dwObject != 0) {
					DWORD 值 = ReadDword(列表[s].dwObject + 0x2C);
					列表[s].pName = ReadStr((char*)ReadDword(值 + 0x18));
					列表[s].p使用等级 = ReadDword(值 + 0x20);
					列表[s].简介 = ReadStr((char*)ReadDword(值 + 0x1c));;
					列表[s].p数量 = (BYTE)ReadByte(ReadDword(列表[s].dwObject + 0x14) + 0x58);
				}
				else
				{

					列表[s].pName = "";
					列表[s].p数量 = 0;
					列表[s].简介 = "";
					列表[s].p使用等级 = 0;
				}

				d数量++;

			}
			JZpy = JZpy + 0x80;// 扩展背包大小,写死0x80,扩展背包大小0x80/0x47=十进制的32
		}
	}
	catch (...)
	{
		Call_输出调试信息("tlhj   返回背包信息异常\r\n");
	}

}

void R_周围遍历::周围二叉数(DWORD Tree, R_人物属性 rw)
{
	try
	{

		int ss = 0;
		ss++;
		if (ss < 5000)
		{


			BYTE data = -1;
			data = ReadByte(Tree + 0xd);
			DWORD 左子树 = ReadDword(Tree + 0x0);
			DWORD 右子树 = ReadDword(Tree + 0x8);
			if (data == 0)
			{
				列表[d数量].dwObject = ReadDword(Tree + 0x14);
				列表[d数量].id = ReadDword(列表[d数量].dwObject + 0x2c);
				列表[d数量].fX = ReadFloat(列表[d数量].dwObject + 0x3c);//坐标X
				列表[d数量].fY = ReadFloat(列表[d数量].dwObject + 0x44);
				列表[d数量].PType = ReadByte(ReadDword(列表[d数量].dwObject + 0x24) + 0x14);

				if ((int)列表[d数量].fX == 100 && (int)列表[d数量].fY == 100)
				{

				}
				else
				{
					// 计算最近距离的公式,所有游戏通用,看不懂死记住就行,小学的公式
					列表[d数量].距离 = sqrt((rw.fX - 列表[d数量].fX)*(rw.fX - 列表[d数量].fX) + (rw.fY - 列表[d数量].fY)*(rw.fY - 列表[d数量].fY));
					列表[d数量].pName = "";
					//Call_输出调试信息("-----r2-------%x", AA);
					列表[d数量].pName = ReadStr((char *)(ReadDword(ReadDword(列表[d数量].dwObject + 0x148) + 0x10) + 0x2c));

					列表[d数量].血量 = ReadFloat(ReadDword(ReadDword(列表[d数量].dwObject + 0x148) + 0x10) + 0x8);
					d数量++;
				}

				周围二叉数(左子树, rw);
				周围二叉数(右子树, rw);

			}
		}

	}
	catch (...)
	{

		Call_输出调试信息("tlhj   遍历二叉数异常\r\n");
	}
}
DWORD R_blzw = *(DWORD*)((DWORD)GetModuleHandleA("Game.exe") + 0x59F008);
void R_周围遍历::AsmGetMonsterData()
{
	Sleep(10);
	try
	{
		
		DWORD dwTreeBase = *(DWORD*)(R_blzw + 0x54);
		dwTreeBase = *(DWORD*)(dwTreeBase + 0x4);
		DWORD dwEnvTreeBase = dwTreeBase;
		Call_输出调试信息("-----q-------");
		if (dwEnvTreeBase) {
			R_人物属性 rw;
			rw.初始化();
			d数量 = 0;
			周围二叉数(dwEnvTreeBase, rw);//遍历二叉树


		}//正确取到二叉树基址

	}
	catch (...)
	{
		Call_输出调试信息("tlhj   得到二叉数根结点异常\r\n");
	}
}

R_人物属性 R_周围遍历::遍历最近怪物()
{
	this->AsmGetMonsterData();
	R_人物属性 a;
	R_人物属性 人物;
	人物.初始化();
	try
	{
		if (this->d数量 > 0)
		{
			for (int i = 0; i < (int)this->d数量; i++)
			{

				for (int j = i + 1; j < (int)this->d数量; j++)
				{
					if (this->列表[i].距离 > this->列表[j].距离)
					{
						a = this->列表[j];
						this->列表[j] = this->列表[i];
						this->列表[i] = a;
					}
				}




			}

			if (d数量 >= 1)
			{
				return this->列表[d数量 - 2];
			}
			else
			{
				return 人物;
			}


		}

		return 人物;

	}
	catch (...)
	{
		Call_输出调试信息("tlhj   返回最近怪物信息异常\r\n");
	}
}

void R_遍历技能::技能二叉数2(DWORD Tree)
{
	try
	{


		BYTE data = 0;
		data = ReadByte(Tree + 0xd);
		DWORD 左子树 = ReadDword(Tree + 0x0);
		DWORD 右子树 = ReadDword(Tree + 0x8);
		if (data == 0)
		{
			列表[d数量].dwObject = ReadDword(Tree + 0x14);
			列表[d数量].pName = ReadStr((char *)ReadDword(Tree + 0x14) + 0x8);
			d数量++;
			技能二叉数2(左子树);
			技能二叉数2(右子树);
		}

	}
	catch (...)
	{

		Call_输出调试信息("天龙怀旧   遍历二叉数异常\r\n");
	}
}

void R_遍历技能::AsmGetMonster()
{
	try
	{
		DWORD dwTreeBase = ReadDword(R_jnecs2 + 0x28);
		dwTreeBase = ReadDword(dwTreeBase + 0x4);
		DWORD dwEnvTreeBase = dwTreeBase;

		if (dwEnvTreeBase) {
			d数量 = 0;
			技能二叉数2(dwEnvTreeBase);//遍历二叉树

		}//正确取到二叉树基址

	}
	catch (...)
	{
		Call_输出调试信息("天龙怀旧   得到二叉数根结点异常\r\n");
	}
}

void R_遍历技能::技能二叉数(DWORD Tree)
{
	try
	{

		BYTE data = 0;
		data = ReadByte(Tree + 0xd);
		DWORD 左子树 = ReadDword(Tree + 0x0);
		DWORD 右子树 = ReadDword(Tree + 0x8);
		if (data == 0)
		{
			列表[d数量].dwObject = Tree;
			列表[d数量].pID = ReadByte(Tree + 0x10);
			列表[d数量].pName = ReadStr((char *)ReadDword(ReadDword(Tree + 0x18) + 0xc));
			列表[d数量].冷却ID = ReadDword(ReadDword(Tree + 0x18) + 0x40);

			DWORD dwTreeBase = ReadDword(R_jnlq + 0x18164);
			DWORD 冷却时间 = ReadDword(dwTreeBase + 列表[d数量].冷却ID * 3 * 4);
			char* a = "";
			if (冷却时间 == 0 || 冷却时间 == 0xffffffff) {
				a = "未冷却";

			}
			else {
				a = "冷却";

			}
			列表[d数量].冷却 = a;
			d数量++;
			技能二叉数(左子树);
			技能二叉数(右子树);

		}

	}
	catch (...)
	{

		Call_输出调试信息("天龙怀旧   遍历二叉数异常\r\n");
	}
}

void R_遍历技能::AsmGetMonsterData()
{
	try
	{

		DWORD	dwTreeBase = ReadDword(R_jnecs + 0x60);
		dwTreeBase = ReadDword(dwTreeBase + 0x148);
		dwTreeBase = ReadDword(dwTreeBase + 0x10);
		dwTreeBase = ReadDword(dwTreeBase + 0x2A44);
		dwTreeBase = ReadDword(dwTreeBase + 0x4);
		DWORD dwEnvTreeBase = dwTreeBase;

		if (dwEnvTreeBase) {
			d数量 = 0;
			技能二叉数(dwEnvTreeBase);//遍历二叉树

		}//正确取到二叉树基址

	}
	catch (...)
	{
		Call_输出调试信息("天龙怀旧   得到二叉数根结点异常\r\n");
	}
}

结构.h文件:新加 R_技能属性结构、R_遍历技能结构

#pragma once
#include <string>

#define  BLZW (DWORD)GetModuleHandleA("Game.exe") + 0x59EFA4//遍历周围 和人物状态同一个
using namespace std;
struct R_人物属性
{
	DWORD 状态;
	FLOAT 血量;
	DWORD 最大血量;
	FLOAT fX;
	FLOAT fY;
	DWORD id;
	DWORD dwObject;
	DWORD PType;
	DWORD M_走路包;
	FLOAT 距离;
	DWORD M_通用包;
	PCHAR pName = "";

	void 初始化();
};

struct R_背包属性 {
	DWORD dwObject;
	string pName;
	BYTE p数量;
	string 简介;
	DWORD p使用等级;
};

struct R_背包类
{
	BYTE 背包数量 = 0;
};

struct R_遍历背包 {
	R_背包类 背包[0x3];
	R_背包属性 列表[0x100];
	DWORD d数量 = 0;
	void 遍历背包();
};

struct 坐标 {
	FLOAT x;
	FLOAT y;
};

struct R_周围遍历
{

	R_人物属性 列表[0x100];
	DWORD d数量 = 0;
	void 周围二叉数(DWORD Tree, R_人物属性 dw);
	void AsmGetMonsterData();
	R_人物属性 遍历最近怪物();

};

struct R_技能属性
{
	DWORD dwObject;
	string pName;
	DWORD 冷却ID;
	DWORD pID;
	string 冷却;
};

struct R_遍历技能
{
	R_技能属性 列表[0x100];
	DWORD d数量 = 0;
	void 技能二叉数2(DWORD Tree);
	void AsmGetMonster();
	void 技能二叉数(DWORD Tree);
	void AsmGetMonsterData();
};
#define  JNLQ (DWORD)GetModuleHandleA("Game.exe") + 0x59F4F8//技能冷却数组
#define  JNECS (DWORD)GetModuleHandleA("Game.exe") + 0x59F008//技能二叉数
#define  JNECS2 (DWORD)GetModuleHandleA("Game.exe") + 0x34cb88//技能二叉数2

CM.cpp文件:新加 OnBnClickedButton5函数(遍历技能按钮的点击事件处理函数)

// CM.cpp: 实现文件
//

#include "pch.h"
#include "tl.h"
#include "CM.h"
#include "afxdialogex.h"


// CM 对话框

IMPLEMENT_DYNAMIC(CM, CDialogEx)

CM::CM(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG1, pParent)
	, edi_x(_T(""))
{

}

CM::~CM()
{
}

void CM::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, edi_x);
	DDX_Text(pDX, IDC_EDIT2, edi_y);
}


BEGIN_MESSAGE_MAP(CM, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON1, &CM::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CM::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &CM::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &CM::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &CM::OnBnClickedButton5)
END_MESSAGE_MAP()


// CM 消息处理程序


void CM::OnBnClickedButton1()
{
	R_人物属性 a;
	a.初始化();
	Call_输出调试信息("人物信息:人物状态%d",a.状态);
}


void CM::OnBnClickedButton2()
{
	UpdateData(TRUE);
	CString str1 = edi_x;
	CString str2 = edi_y;
	// strtol((const char*)CW2A(str1.GetBuffer(0)), NULL, 10);把字符串转成int数字类型
	int x = strtol((const char*)CW2A(str1.GetBuffer(0)), NULL, 10);
	int y = strtol((const char*)CW2A(str2.GetBuffer(0)), NULL, 10);
	Call_xunlu(x, y);
}


void CM::OnBnClickedButton3()
{
	R_遍历背包 a;
	a.遍历背包();// 遍历背包
	CString str;
	str.Format(L"a数量 %d", a.d数量);
	AfxMessageBox(str);

	for (int i = 0; i < a.d数量; i++)
	{
		Call_输出调试信息("tl怀旧   背包信息 dwObject -------------%X----------------\r\n", a.列表[i].dwObject);
		Call_输出调试信息("tl怀旧   背包信息 名字:%s\r\n", a.列表[i].pName.c_str());
		Call_输出调试信息("tl怀旧   背包信息 使用等级:%d\r\n", a.列表[i].p使用等级);
		Call_输出调试信息("tl怀旧   背包信息 简介:%s\r\n", a.列表[i].简介.c_str());
		Call_输出调试信息("tl怀旧   背包信息 数量:%d\r\n", a.列表[i].p数量);


	}

}


void CM::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	R_周围遍历 a;

	a.遍历最近怪物();// 让怪物重新排列
	for (int i = 0; i < a.d数量; i++)
	{
		Call_输出调试信息("人物信息:---------------------%s-----%x---------------------", a.列表[i].pName, a.列表[i].dwObject);
		Call_输出调试信息("人物信息:人物id:%x", a.列表[i].id);
		Call_输出调试信息("人物信息:人物X:%f 人物Y:%f", a.列表[i].fX, a.列表[i].fY);
		Call_输出调试信息("人物信息:人物类型:%x  人物距离:%f", a.列表[i].PType, a.列表[i].距离);


	}
}


void CM::OnBnClickedButton5()
{
	// TODO: 在此添加控件通知处理程序代码
	R_遍历技能 a;
	a.AsmGetMonsterData();// 遍历技能

	for (int i = 0; i < a.d数量; i++)
	{

		Call_输出调试信息("tl怀旧   技能信息 名字:---------------%s-----------------------\r\n", a.列表[i].pName.c_str());
		Call_输出调试信息("tl怀旧   技能信息 ID:%d\r\n", a.列表[i].pID);
			Call_输出调试信息("tl怀旧   技能信息 是否冷却:%s\r\n", a.列表[i].冷却.c_str());
			Call_输出调试信息("tl怀旧   技能信息 冷却ID:%x\r\n", a.列表[i].冷却ID);
		Call_输出调试信息("tl怀旧   技能信息 对象地址:%x\r\n", a.列表[i].dwObject);

	}
}

上方的代码不全,只有手写的代码

完整代码:

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg?pwd=q9n5

提取码:q9n5

复制这段内容后打开百度网盘手机App,操作更方便哦


img


http://www.kler.cn/news/365138.html

相关文章:

  • 请简述同步和异步的区别。
  • 人工智能的未来:重塑生活与工作的变革者
  • Spring Cloud:构建高可用分布式系统的利器
  • 怎么区分主谓宾I love you与主系表I am fine? 去掉宾语看句子完整性 主系表结构则侧重于描述主语的状态、特征或性质
  • 一起搭WPF架构之LiveCharts.Wpf的简单了解与安装
  • MoeCTF 2024 ---Misc方向WP
  • CPRI与eCPRI的区别
  • 每天5分钟玩转C#/.NET之C#语言详细介绍
  • python-PyQt项目实战案例:制作一个视频播放器
  • 双十一送你一份购物攻略,绿联NAS DXP2800评测
  • 借老系统重构我给jpa写了个mybatis风格的查询模块
  • 【笔记】apt源设置为阿里云源
  • 19.面试算法-树的深度优先遍历(一)
  • Nginx15-Lua扩展模块
  • Zookeeper面试整理-Zookeeper集群管理
  • 简单走近ChatGPT
  • 信息安全工程师(55)网络安全漏洞概述
  • 解决 PHP 上传数据超时 504 错误:
  • 为微信小程序换皮肤之配置vant
  • 流批一体计算引擎-17-[Flink]中的Table API常用算子
  • 【Hive实战】Hive MetaStore升级调研
  • 金融工程--pine-script 入门
  • 软考:缓存击穿和缓存穿透
  • bitpoke- mysql-operator cluster
  • Python学习路线:从新手到专家
  • 低代码开发详解与行业应用指南