close
呵呵,所以這一節我們就來設計下界面和最基本的讀取人物其他信息。 我們的目的是把界面設計成如下圖片所示的樣子,當然怎麼排列還是看自己喜歡,呵呵。 一個按鈕,一個時鐘控件,其他都是標籤,按著一定的排列畫在窗口上。 按鈕可以在上方 Standard 欄找到,時鐘控件可以在 System 欄找到。 我們利用時鐘控件,就可以實現循環讀取遊戲的數據了,這一次的代碼將會和上一次的有點改變。 下面我們開始寫代碼: 首先,選擇時鐘控件,將 Interval 屬性設置為 100 ,意思就是1秒鐘讀取10次數據。Enabled 屬性設置為False 。 雙擊按鈕,進入代碼界面,寫下如下代碼 FirstAdr= 0x930014; GameFormHwnd=FindWindow("QElementClient Window", "Element Client"); if(!GameFormHwnd) { ShowMessage("遊戲沒有啟動,請先啟動遊戲並完全進入遊戲!"); return ; } GetWindowThreadProcessId(GameFormHwnd,&hProcId); Timer1->Enabled=true; 和上一次的差別是,我們把讀取數據的代碼放到時鐘控件裡,這裡只做遊戲的開啟判斷和數據初始化。 然後雙擊時鐘控件,由於所有的數據都在時鐘控件裡面讀取,所以代碼有點多: HANDLE mProcID; DWORD eax,ecx, mex,tmp1,tmp2; AnsiString ms; //byte dcode; WCHAR mname[64]; mProcID = OpenProcess(PROCESS_ALL_ACCESS, false, hProcId); ReadProcessMemory(mProcID, LPVOID(0x930014), &eax, 4, 0); ReadProcessMemory(mProcID, LPVOID(eax + 0x1C), &ecx, 4, 0); ReadProcessMemory(mProcID, LPVOID(ecx + 0x24), &eax, 4, 0); ReadProcessMemory(mProcID, LPVOID(eax + 0x25C), &HP, 4, 0); ReadProcessMemory(mProcID, LPVOID(eax + 0x250), &ManLv, 4, 0); //0x24C 人物等級 ReadProcessMemory(mProcID, LPVOID(eax + 0x398), &mex, 4, 0); //怪物名字 ReadProcessMemory(mProcID, LPVOID(mex), mname, 64, 0); ManName=mname; ReadProcessMemory( mProcID, LPVOID(eax + 0x244), &ManID, 4, 0); //人物 ID ReadProcessMemory(mProcID, LPVOID(eax + 0x25C), &HP, 4, 0); //596 當前體力 紅 ReadProcessMemory(mProcID, LPVOID(eax + 0x260), &MP, 4, 0); //600 當前內力 藍 ReadProcessMemory(mProcID, LPVOID(eax + 0x274), &MaxHP, 4, 0); //620 最大血值 ReadProcessMemory(mProcID, LPVOID(eax + 0x278), &MaxMP, 4, 0); //624 最大內力值 ReadProcessMemory(mProcID, LPVOID(eax + 0x2DC), &Money, 4, 0); //724 當前金錢值 ReadProcessMemory(mProcID, LPVOID(eax + 0x7D4), &GWID, 4, 0); //120版 偏移加 8 或地址 0x0354AF44 當前目標怪物ID ,為負就是怪,為正就是NPC或玩家,為0則怪物死亡,或沒有選擇怪物. ReadProcessMemory(mProcID, LPVOID(eax + 0x264), &Exp, 4, 0); //0x25C 當前經驗值,十進制 ReadProcessMemory( mProcID, LPVOID(eax + 0x3C), &Mx, 4, 0); //人物坐標 x float 4字節 ReadProcessMemory( mProcID, LPVOID(eax + 0x44), &My, 4, 0); //人物坐標 y float 4字節 //怪物信息 //--------------------------------------------------------- if( GWID > 0x80000000) //大於0x80000000為怪物或NPC { WCHAR Buff[64]; ReadProcessMemory( mProcID, LPVOID(FirstAdr), &eax, 4, 0); ReadProcessMemory( mProcID, LPVOID(eax + 0x1C), &ecx, 4, 0); ReadProcessMemory( mProcID, LPVOID(ecx + 0x8), &eax, 4, 0); ReadProcessMemory( mProcID, LPVOID(eax + 0x20), &ecx, 4, 0); ReadProcessMemory( mProcID, LPVOID(ecx + 0x24), &tmp1, 4, 0); //讀出怪物數組的最大值 ReadProcessMemory( mProcID, LPVOID(ecx + 0x18), &tmp2, 4, 0); //讀出怪物列表的首地址 if(GWID!=0) eax = tmp2 + (GWID % tmp1) * 0x4; ReadProcessMemory( mProcID, LPVOID(eax), &ecx, 4, 0); ReadProcessMemory( mProcID, LPVOID(ecx + 0x4), &eax, 4, 0); ReadProcessMemory( mProcID, LPVOID(eax + 0x134), &GWHP, 4, 0); //怪物當前血值 ReadProcessMemory( mProcID, LPVOID(eax + 0x14C), &GWMaxHP, 4, 0); //怪物血值上限 //ReadProcessMemory( mProcID, LPVOID(eax + 0xB4), &GWType, 4, 0); //選中類型 //ReadProcessMemory( mProcID, LPVOID(eax + 0x120), &GWTypeID, 4, 0); //怪物類 ReadProcessMemory( mProcID, LPVOID(eax + 0x128), &GWLv, 2, 0); ReadProcessMemory( mProcID, LPVOID(eax + 0x3C), &GWMx, 4, 0); //怪物X坐標 ReadProcessMemory( mProcID, LPVOID(eax + 0x44), &GWMy, 4, 0); //怪物Y坐標 ReadProcessMemory( mProcID, LPVOID(eax + 0x234), &MtoG, 4, 0); //怪物距離 //怪物名稱部分------------------------------------ ReadProcessMemory( mProcID, LPVOID(eax + 0x210), &ecx, 4, 0); //怪物名字 ReadProcessMemory( mProcID, LPVOID(ecx), Buff, 64, 0); GWName = Buff; } else if(GWID < 0x80000000 && GWID >0) //玩家 { WCHAR Buff2[64]; ReadProcessMemory( mProcID, LPVOID(FirstAdr), &eax, 4, 0); ReadProcessMemory( mProcID, LPVOID(eax + 0x1C), &ecx, 4, 0); ReadProcessMemory( mProcID, LPVOID(ecx + 0x24), &eax, 4, 0); //------------------------------------------------------- ReadProcessMemory( mProcID, LPVOID(eax + 0x138), &ecx, 4, 0); //------------------------------------------------------- ReadProcessMemory( mProcID, LPVOID(ecx + 0x24), &tmp1, 4, 0); //讀出怪物數組的最大值 ReadProcessMemory( mProcID, LPVOID(ecx + 0x18), &tmp2, 4, 0); //讀出怪物列表的首地址 if(GWID!=0) eax = tmp2 + (GWID % tmp1) * 0x4; ReadProcessMemory( mProcID, LPVOID(eax), &ecx, 4, 0); ReadProcessMemory( mProcID, LPVOID(ecx + 0x4), &eax, 4, 0); ReadProcessMemory( mProcID, LPVOID(eax + 0x25C), &GWHP, 4, 0); //選中人物當前血值 ReadProcessMemory( mProcID, LPVOID(eax + 0x274), &GWMaxHP, 4, 0); //選中人物血值上限 ReadProcessMemory( mProcID, LPVOID(eax + 0x250), &GWLv, 2, 0); //ReadProcessMemory( mProcID, LPVOID(eax + 0xB4), &GWType, 4, 0); //選中類型 ReadProcessMemory( mProcID, LPVOID(eax + 0x3C), &GWMx, 4, 0); //怪物X坐標 ReadProcessMemory( mProcID, LPVOID(eax + 0x44), &GWMy, 4, 0); //怪物Y坐標 ReadProcessMemory( mProcID, LPVOID(eax + 0x4D0), &MtoG, 4, 0); //人與人距離 if( GWID == ManID && GWID!=0) { GWHP = HP; GWMaxHP = MaxHP; GWMx = Mx; GWMy = My; } //選擇人物名字部分---------------------------------------- ReadProcessMemory( mProcID, LPVOID(eax + 0x398), &ecx, 4, 0); ReadProcessMemory( mProcID, LPVOID(ecx), Buff2, 64, 0); GWName = Buff2; } //下面開始顯示數據 LbName->Caption="人物: " + ManName; LbLv->Caption = "等級: " + AnsiString(ManLv); LbId->Caption = "ID: " + AnsiString(ManID); LbManPos->Caption = "坐標: X: " + ms.FormatFloat("0.0",Mx) + " Y: " + ms.FormatFloat("0.0",My); LbHP->Caption= "HP: " + IntToStr(HP) + " / " + IntToStr(MaxHP); LbMP->Caption= "MP: " + IntToStr(MP) + " / " + IntToStr(MaxMP); LbExp->Caption = "Exp: " + IntToStr(Exp); LbMon->Caption = "金錢: " + AnsiString(Money / 10000) + "金 " + AnsiString((Money % 10000) / 100) + "銀 " + AnsiString(Money % 100) + "銅"; if( GWID > 0) { if( GWID == ManID) Form1->LbObj->Caption = "目標: " + AnsiString(ManLv) + "級 ID:" + AnsiString(ManID) + " " + ManName; else Form1->LbObj->Caption = "目標: " + AnsiString(GWLv) + "級 ID:" + AnsiString(GWID) + " " + GWName; } else Form1->LbObj->Caption = "目標: "; LbObjHP->Caption="目標HP: " + IntToStr(GWHP) + " / " + IntToStr(GWMaxHP); LbObjPos->Caption = "坐標: X: " + ms.FormatFloat("0.0",GWMx) + " Y: " + ms.FormatFloat("0.0",GWMy) + " 距離: " + ms.FormatFloat("0.0",MtoG); //顯示段完 CloseHandle(mProcID); 以上就是在時鐘控件裡的代碼。 另外,我們需要定義一些全局變量,在 #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; 這些代碼下面,加入以下代碼 DWORD FirstAdr; DWORD ShutTime,hProcId,ManID,HP,MaxHP,MP,MaxMP,Money; DWORD GWID,GWMaxHP,GWHP,ObjHP,ObjMaxHP,ObjID,Exp,MaxExp,ExpLvUp; HWND GameFormHwnd; long ManLv,GWLv; float MtoG,AreaMtoG,GWMx,GWMy,Mx,My; AnsiString ManName,GWName; 到這裡,完成讀取基本信息的製作。 |
全站熱搜
留言列表