53.第二阶段x86游戏实战2-c++实现自动打怪2

发布于:2025-03-26 ⋅ 阅读:(27) ⋅ 点赞:(0)

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

本次游戏没法给

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

工具下载:

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

提取码:6tw3

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

上一个内容:52.第二阶段x86游戏实战2-c++实现自动打怪1

CMeLua.cpp文件的修改,修改了 Lua_lu函数,Lua_lu函数也是当前代码查看的入口

#include "pch.h"
#include "CMeLua.h"

extern CMessage* pMsg; // 前面带 extern 说明是全局变量,也就是说在其它文件中对 pMsg 这个名字的变量进行的修改那么这里也会被影响到

int CMeLua::LUA_Xulu(LuaState * pState)
{
	LuaStack args(pState);
	DWORD x = args[1].GetInteger();
	DWORD y = args[2].GetInteger();
	Msg_xl(x, y);


	return 0;
}

void Lua_lu(int x, int y, string Scene)
{
	// 寻路目的地的地图id
	int SceneId = FUN_GetSceneID(Scene.c_str());
	// 获取当前角色所在的地图id,之前找地图id的时候找的的GetSceneID函数
	int id = pMsg->msg_getnumber("g_GetValue = GetSceneID()");

	/**
		如果目的地地图id和寻路的目的地地图id一样说明是当前地图寻路,就调用短寻路
		两个id不一样说明是跨地图寻路就调用长寻路	
	*/
	if (SceneId == id)
	{
		pMsg->msg_dostring("AutoRunToTarget(%d, %d)", (int)x, (int)y);

	}
	else
	{
		pMsg->msg_dostring("AutoRunToTargetEx(%d, %d, %d)", (int)x, (int)y, SceneId);
	}
}

Hook.cpp文件的修改,新加 pMsg变量,修改了 Call_主线程回调函数函数

#include "pch.h"

// 获取全局变量pMsg,它是在CM.cpp文件中声明的
extern CMessage* pMsg;

HHOOK g_Hook返回;
const DWORD g_My消息ID = RegisterWindowMessageA("MyMsyCode");// 注册一个消息号
HWND Call_获取窗口句柄()
{
	// 获取游戏存放的窗口句柄,通过CE搜索spy++的句柄找到的
	//HWND hGame = (HWND)((DWORD)GetModuleHandleA("CEGUIBase.dll") + 0x251030);
	HWND hGame = (HWND)((DWORD)GetModuleHandleA("Game.exe") + 0x73AD98);
	hGame = *(HWND*)hGame;
	return hGame;
}

void Msg_xl(DWORD X, DWORD Y)
{
	T寻路参数 寻路;
	寻路.X = X;
	寻路.Y = Y;
	::SendMessageA(Call_获取窗口句柄(), g_My消息ID, ID_寻路, (LPARAM)&寻路);
}

//主线程回调函数
LRESULT CALLBACK Call_主线程回调函数(int nCode, WPARAM wParam, LPARAM lparam)
{
	/*
		::SendMessageA(Call_获取窗口句柄(), g_My消息ID, ID_寻路, (LPARAM)&寻路);

		CWPSTRUCT类型的参数分别对应SendMessageA函数的入参,如下
			LPARAM  lParam =  (LPARAM)&寻路
			WPARAM  wParam = ID_寻路
			UINT    message = g_My
			HWND    hwnd = Call_获取窗口句柄()
	*/
	CWPSTRUCT *lpArg = (CWPSTRUCT*)lparam;//结构  hwnd message wParam lParam
	if (nCode == HC_ACTION)//自己进程的消息
	{
		if (lpArg->hwnd == Call_获取窗口句柄() && lpArg->message == g_My消息ID)//我们自己的消息  
		{
			string luaText;

			switch (lpArg->wParam)
			{
				T寻路参数*寻路;
				T参数*get;
			case ID_寻路:
				寻路 = (T寻路参数*)lpArg->lParam;
				Call_xunlu(寻路->X, 寻路->Y);
				return 1;
				//break;
			case LUA_GETVALUE:
				get = (T参数*)lpArg->lParam;
				pMsg->telua_getnumber((char*)get->Y, (PVOID)get->X);
				return 1;
				//break;
			}
		}
	}
	return CallNextHookEx(g_Hook返回, nCode, wParam, lparam);
}

DWORD Call_Hook主线程()
{
	HWND hGame = Call_获取窗口句柄();
	// 通过句柄获取窗口的线程id
	DWORD ndThreadId = GetWindowThreadProcessId(hGame, NULL);
	if (ndThreadId != 0)
	{
		// 注册窗口HOOK,SetWindowsHookEx是微软提供
		g_Hook返回 = SetWindowsHookEx(WH_CALLWNDPROC, Call_主线程回调函数, NULL, ndThreadId);
	}
	return 1;
}

Message.h文件的修改,新加 CriticalSectionLock类、T参数结构体、LUA_GETVALUE宏

#pragma once
#include "pch.h"
// 专门用来处理lua的类
typedef int(*Glua_dostring)(int, const char *);//do_string
typedef int(*Glua_pushstring)(int, const char *);//pushstring
typedef void(*Glua_gettable)(int, int);//gettable
typedef double(*Glua_tonumber)(int, double);//tonumber
typedef int(*Glua_settop)(int, int);//settop
typedef const char*(*Glua_tostring)(int, int);//tostring
typedef int(*Glua_pushcclosure)(int, int, int);//
typedef void(*Glua_settable)(int, int);
typedef int(*Glua_loadfile)(int, const char*);
typedef int(*Gplua_call)(int, int, int, int);
typedef int(*Glua_type)(int, int);
typedef int(*Glua_dofile)(int, const char*);

class CMessage
{
public:
	CMessage() {};
	~CMessage() {};
	void Init() {
		//初始化游戏lua函数,lua状态机
		InitLuaFun();//初始化游戏lua库函数
		lua_state = getlua_state();//获取游戏lua状态机指针

		LUAInitialize();
	};
public:
	void msg_dostring(const char* _Format, ...);
	const char* telua_tostring(int n);
private:
	int getlua_state();

	BOOL LUAInitialize();
	int InitLuaFun();//获取lua库函数
	CCriticalSection m_State;
public:
	/************************************************************************/
	/* 游戏的lua函数接口定义                                                                     */
	/************************************************************************/
	int  telua_loadfile(const char*file);
	bool telua_register(const char *FuncName, int pFun);
	bool telua_dostring(const char * args);
	bool telua_getglobal(const char*name);
	double telua_tonumber(int n);
	bool CMessage::call_dostring(const char * buf);
	void telua_pop(int n);
	int msg_getnumber(char* _Format, ...);
	/************************************************************************/
	/* 游戏的lua函数指针定义                                                                     */
	/************************************************************************/
	Glua_dostring GLua_Dostring = nullptr;
	Glua_pushstring GLua_Pushstring = nullptr;
	Glua_gettable GLua_Gettable = nullptr;
	Glua_tonumber GLua_Tonumber = nullptr;
	Glua_settop   GLua_Settop = nullptr;
	Glua_tostring GLua_Tostring = nullptr;
	Glua_pushcclosure GLua_Pushcclosure = nullptr;
	Glua_settable	GLua_Settable = nullptr;
	Glua_loadfile	GLua_Loadfile = nullptr;
	Gplua_call	  GpLua_Call = nullptr;
	Glua_type   Gplua_type = nullptr;
	Glua_dofile Gplua_dofile = nullptr;
	int lua_state = 0;//lua状态机指针
	/************************************************************************/
	/* lua取值的函数                                                                     */
	/************************************************************************/
	bool telua_getnumber(const char* buf, PVOID  out);
	bool telua_getstring(const char* buf, const char* want_get_string);
	string msg_getstring(const char * str_arg, char * _Format, ...);
	typedef int(*lplua_dostring)(int, const char *);
	lplua_dostring g_lplua_dostring;
};

//封装的临界区线程同步的类
class CriticalSectionLock
{
public:
	CriticalSectionLock(CCriticalSection* cs)
	{
		m_cs = cs;
		m_cs->Lock();
	}
	~CriticalSectionLock()
	{
		m_cs->Unlock();
	}
private:
	CCriticalSection* m_cs;
};

struct T参数
{
	WPARAM X;
	LPARAM Y;
};


// 获取当前地图id
#define  LUA_GETVALUE     WM_USER + 801

Message.cpp文件的修改,新加 telua_getnumber函数、telua_pop函数、msg_getnumber函数、telua_dostring函数、telua_getglobal函数、telua_tonumber函数、call_dostring函数

#include "pch.h"
#include "Message.h"
#include "stringex.h"

HMODULE hDll;
extern CMessage* pMsg;

void CMessage::msg_dostring(const char * _Format, ...)
{
}

int CMessage::getlua_state()
{
	return 0;
}

int CMessage::InitLuaFun()
{

	HMODULE LuaPlus = GetModuleHandleA("LuaPlus.dll");
	if (LuaPlus)
	{

		g_lplua_dostring = (lplua_dostring)GetProcAddress(GetModuleHandleA("LuaPlus.dll"), "lua_dostring");

		GLua_Dostring = (Glua_dostring)GetProcAddress(LuaPlus, "lua_dostring");
		GLua_Gettable = (Glua_gettable)GetProcAddress(LuaPlus, "lua_gettable");
		GLua_Pushstring = (Glua_pushstring)GetProcAddress(LuaPlus, "lua_pushstring");
		GLua_Tonumber = (Glua_tonumber)GetProcAddress(LuaPlus, "lua_tonumber");
		GLua_Tostring = (Glua_tostring)GetProcAddress(LuaPlus, "lua_tostring");
		GLua_Settop = (Glua_settop)GetProcAddress(LuaPlus, "lua_settop");
		GpLua_Call = (Gplua_call)GetProcAddress(LuaPlus, "lua_pcall");
		GLua_Settable = (Glua_settable)GetProcAddress(LuaPlus, "lua_settable");
		GLua_Pushcclosure = (Glua_pushcclosure)GetProcAddress(LuaPlus, "lua_pushcclosure");
		GLua_Loadfile = (Glua_loadfile)GetProcAddress(LuaPlus, "luaL_loadfile");
		Gplua_type = (Glua_type)GetProcAddress(LuaPlus, "lua_type");
		Gplua_dofile = (Glua_dofile)GetProcAddress(LuaPlus, "lua_dofile");

		if (GLua_Dostring && GLua_Gettable && GLua_Pushstring
			&& GLua_Tonumber && GLua_Tostring &&GLua_Settop)
		{
			return 1;//获取lua函数地址成功
		}
		else
		{
			return 0;//获取地址失败,模块句柄获取成功
		}
	}
	return -1;//无效模块句柄
}

BOOL CMessage::LUAInitialize()
{
	LuaStateOwner*  pState = new LuaStateOwner(true);
	// 在自定义资源中释放出sys


	//HRSRC hResc = FindResource(hDll, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA);
	//if (hResc == NULL)
	//{
	//	Call_输出调试信息("hResc=%d,getlasterorr=%d", hResc, GetLastError());
	//	//dbgPrint("system.luaGetLastError  ==   %d pMe->hDll=%s MAKEINTRESOURCE(IDR_RCDATA2)=%d", ::GetLastError(), pMe->hDll, MAKEINTRESOURCE(IDR_RCDATA2));
	//	return FALSE;
	//}

	//Call_输出调试信息("hResc=%d,getlasterorr=%d", hResc, GetLastError());
	//DWORD dwImageSize = SizeofResource(hDll, hResc);

	//HGLOBAL hResourecImage = LoadResource(hDll, hResc);
	//Call_输出调试信息("hResourecImageetlasterorr=%d", GetLastError());
	//if (hResourecImage == NULL)
	//{
	//	return FALSE;
	//}
	//string luaText = (char*)hResourecImage;
	//PVOID pMemory = LockResource(hResourecImage);//<<<<<quchu dizhi
	//Call_输出调试信息("pMemorygetlasterorr=%d", GetLastError());

	//pMsg->msg_dostring(luaText.c_str());
	//if (pMemory == NULL)
	//{
	//	Call_输出调试信息("pMemory=NULL");
	//	return FALSE;
	//}

	return TRUE;
}

bool CMessage::telua_getnumber(const char* buf, PVOID out)
{
	__try {
		// telua_dostring执行lua代码
		if (telua_dostring(buf))
		{
			// 获取 g_GetValue的值
			if (telua_getglobal("g_GetValue"))
			{
				Call_输出调试信息("g_GetValue无异常");
				/**
					从栈里获取一个数据,-1表示从栈顶获得一个数据,现在也就是获取g_GetValue的值
					获取之后把它的值强制转成一个数字
				*/ 
				*(int*)out = (int)telua_tonumber(-1);
				// 从栈中删除一个数据,telua_pop(1)这意思是删除栈顶的数据
				telua_pop(1);
				return true;
			}
			else
			{
				Call_输出调试信息("%s telua_getglobal erro", __FUNCTION__);
				return false;
			}
		}
		else
		{
			Call_输出调试信息("%s telua_dostring erro", __FUNCTION__);
			return false;
		}
	}
	__except (1) {
		Call_输出调试信息(__FUNCTION__); return false;
	}

}

void CMessage::telua_pop(int n)
{
	__try {
		/**
			这是lua的api,意思是:
				GLua_Settop 用来调整 lua 栈的栈顶位置
				也就是从栈里删除一个数据,删除的位置是n
				它实际的作用是修改lua栈顶的位置
				正数:如果 index 是正数,那么栈会被调整为该索引位置。若 index 大于当前栈顶索引,会在栈顶填充 nil;
					若 index 小于当前栈顶索引,栈会被截断,高于该索引的元素会被移除。
				负数:当 index 为负数时,它表示相对于栈顶的位置。例如,-1 代表当前栈顶,-2 代表栈顶下面的元素。
					栈会被调整到相对于栈顶 index 位置处。
				零:若 index 为 0,栈会被清空,所有元素都会被移除。
		*/
		GLua_Settop(lua_state, -(n)-1);
	}
	__except (1) {
		Call_输出调试信息(__FUNCTION__);
	}
}


int CMessage::msg_getnumber(char* _Format, ...)//获取整形值
{
	// 创建一个临界区,防止其它线程写东西导致执行代码有问题
	CriticalSectionLock lock(&m_State);

	int nValue = 0;
	try
	{
		char getnumberBuf[2048] = { 0 };//用于存放getnumber的字符串缓冲区
		/**
			va_list list;
			va_start(list, _Format);
			vsprintf(getnumberBuf, _Format, list);
			va_end(list);
			这一段的意思是获取可变参数
			就是获取 int CMessage::msg_getnumber(char* _Format, ...) 这里的...
		*/
		va_list list;
		va_start(list, _Format);
		vsprintf(getnumberBuf, _Format, list);
		va_end(list);
		//dbgPrint(getnumberBuf);
		/**
			struct T参数
			{
				WPARAM X;
				LPARAM Y;
			};
		*/
		T参数 getnumber;
		getnumber.X = (WPARAM)&nValue;
		getnumber.Y = (LPARAM)getnumberBuf;
		/**
			使用游戏的线程调用游戏的函数
			如果不用游戏的线程调用游戏的函数,游戏有时候会崩溃退出
		*/
		::SendMessageA(Call_获取窗口句柄(), RegisterWindowMessageA("MyMsyCode"), LUA_GETVALUE, (LPARAM)&getnumber);
	}
	catch (...)
	{
		Call_输出调试信息(__FUNCTION__);
	}

	return nValue;
}

bool CMessage::telua_dostring(const char * buf)
{
	stringex a = buf;
	// 执行lua代码
	if (call_dostring(a.c_str()))
		return 1;

	return 0;
}

bool CMessage::telua_getglobal(const char*name)
{
	__try {
		// 这是lua的api,意思是将一个参数放到lua的栈顶
		GLua_Pushstring(lua_state, name);
		/**
			这是lua的api,意思是:
				-10001是lua中的一个常量值,表示_G,_G的意思是全局表
				GLua_Gettable(lua_state, -10001);这一行代码的意思
				从栈顶获取一个值(键,或者说一个变量名,数据的名字),然后使用这个值(名字)
				去全局表里找它对应的数据,找到数据之后把数据放到lua的栈顶
		*/ 
		GLua_Gettable(lua_state, -10001);
		return true;
	}
	__except (1) { Call_输出调试信息("telua_getglobal异常"); return false; }
}

double CMessage::telua_tonumber(int n)
{
	__try {
		/**
			这是lua的api,意思是:
				GLua_Tonumber函数的作用是从栈里获取一个数据
				GLua_Tonumber(lua_state, n)意思是n是一个序号,如果n是3,那就获取栈中第三个数据
		*/
		return GLua_Tonumber(lua_state, n);
	}
	__except (1) {
		Call_输出调试信息(__FUNCTION__);
		return 1.234567;
	}
}

bool CMessage::call_dostring(const char * buf)
{
	__try {
		//Call_输出调试信息("GLua_Dostring%s", buf);
		// 接收一个字符串参数并当成lua代码执行
		GLua_Dostring(lua_state, buf);
		return true;
	}
	__except (1) {
		Call_输出调试信息("GLua_Dostring异常");


		return false;
	}
}

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

完整代码:以 52.第二阶段x86游戏实战2-c++实现自动打怪1 它的代码为基础进行修改

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

提取码:q9n5

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


img