PDA

Просмотр полной версии : Использование функций автопилота.


vogel
27.04.2012, 22:06
Решил вот поделиться с сообществом функциями управления игровым автопилотом.
Он, к сожалению, не настолько хорош как в JD или FW, но тем не менее мне нравится его использовать вместо стандартной функции движения.

Для начала определим необходимые константы :

Const
PW_BASE_ADDRESS = $00A571E0;
PW_DYNAMIC_BASE_OFFSET = $001c; // [base] + 1c = CECGameRun
PW_ROLE_BASE_OFFSET = $0034; // [base] + 1c + 34

AutoRouteAddr = $00478ED0; //$004551D0; //$00452B60;


и напишем функцию, которую будем инжектить :

procedure AutoRouteCall(cmd : Pointer); stdcall;
var
addr: Pointer;
begin
addr := Pointer(AutoRouteAddr);
asm
pushad
mov eax, dword ptr [PW_BASE_ADDRESS]
mov eax, dword ptr [eax + PW_DYNAMIC_BASE_OFFSET]
mov ecx, dword ptr [eax + PW_ROLE_BASE_OFFSET]
push cmd
call addr
popad
end;
end;


Это - единственная точка входа для управления всем, что связано с автопилотом в игре.
Управление осуществляется передачей ей массива параметров :

Вот так, для того, чтобы начать движение к точке с координатами (x, y) :

procedure AutoRouteStart(x, y : integer);
var
buf : array[0..6] of integer;
begin
buf[0] := 330;
buf[1] := 0;
buf[2] := 0;
buf[3] := 0; // Команда на взлёт
buf[4] := x;
buf[5] := y;
buf[6] := 0;
InjectFunc(@AutoRouteCall, @buf, SizeOf(buf));
end;


Вот так, чтобы начать плавный подъём к указанной высоте :

procedure AutoRouteAltitude(z : integer);
var
buf : array[0..6] of integer;
begin
buf[0] := 330;
buf[1] := 0;
buf[2] := 0;
buf[3] := 1; // Команда сменить высоту
buf[4] := z;
buf[5] := 0; // Хз что, но может быть 0 или 1
buf[6] := 0;
InjectFunc(@AutoRouteCall, @buf, SizeOf(buf));
end;


И вот так, чтобы прекратить движение :

procedure AutoRouteStop();
var
buf : array[0..6] of integer;
begin
buf[0] := 330;
buf[1] := 0;
buf[2] := 0;
buf[3] := 2; // Команда стоп
buf[4] := 0; buf[5] := 0; buf[6] := 0;
InjectFunc(@AutoRouteCall, @buf, SizeOf(buf));
end;


Использовать это можно вот так :


AutoRouteStart(1350, 345);
AutoRouteAltitude(75);


Комментируем, задаём вопросы, ставим спасибы...

Lermontov
28.04.2012, 18:41
Куда "вставлять" эту функцию? В смысле перед чем или после чего?
procedure AutoRouteCall(cmd : Pointer); stdcall;
var
addr: Pointer;
begin
addr := Pointer(AutoRouteAddr);
asm
pushad
mov eax, dword ptr [PW_BASE_ADDRESS]
mov eax, dword ptr [eax + PW_DYNAMIC_BASE_OFFSET]
mov ecx, dword ptr [eax + PW_ROLE_BASE_OFFSET]
push cmd
call addr
popad
end;
end;

x3max
28.04.2012, 21:46
Куда "вставлять" эту функцию? В смысле перед чем или после чего?

повнимательнее на строку:
InjectFunc(@AutoRouteCall, @buf, SizeOf(buf));

Lermontov
28.04.2012, 22:17
повнимательнее на строку:
InjectFunc(@AutoRouteCall, @buf, SizeOf(buf));

На этой строчке и выбивает ошибку :cry:

Dinmaite
28.04.2012, 22:39
procedure AutoPathCall(aPParams:PParams); stdcall;
var
addr:pointer;
x,y:dword;
begin
x:=aPParams^.param1;
y:=aPParams^.Param2;
z:=aPParams^.Param3;
addr := Pointer($00438770);
asm
pushad
MOV EDI,y
MOV ESI,x
MOV EAX,DWORD PTR DS:[$9C0E6C] // base_addr
PUSH 0 // ; /Arg7 = 00000000
PUSH EDI // ; |Arg6
MOV ECX,DWORD PTR DS:[EAX+$1C] // ; |
PUSH ESI // ; |Arg5
PUSH 0 // ; |Arg4 = 00000000
PUSH 0 // ; |Arg3 = 00000000
PUSH 0 // ; |Arg2 = 00000000
PUSH $14A // ; |Arg1 = 0000014A
call addr // ; \elementc.00438770


MOV EDX,DWORD PTR DS:[$9C0E6C] //; elementc.009C14F8
XOR EAX,EAX
MOV AL,0
PUSH 0 //; /Arg7 = 00000000
MOV ECX,DWORD PTR DS:[EDX+$1C] //; |
MOV EDX,z //; |
PUSH EAX //; |Arg6 = 00000000
PUSH EDX //; |Arg5 = Высота полета
PUSH 1 //; |Arg4 = 00000001
PUSH 0 //; |Arg3 = 00000000
PUSH 0 //; |Arg2 = 00000000
PUSH $14A //; |Arg1 = 0000014A
CALL addr //; \elementc.00438770
popad
end;
end;


procedure AutoPath(realcoord_X,realcoord_Y,realcoord_Z:singl e);
begin
aParams.Param1:=round(realcoord_X);
aParams.Param2:=round(realcoord_Y);
aParams.Param3:=round(realcoord_Z); // высота полета
InjectFunc(aHandle,@AutoPathCall,@aParams,SizeOf(a Params));
end;


Молодец что поделился.

vogel
29.04.2012, 14:05
На этой строчке и выбивает ошибку :cry:

Вот она, вотонаотонааа ([Ссылки могут видеть только зарегистрированные и активированные пользователи]) процедура инжекта моей мечты.

samosi
30.04.2012, 14:44
хм... После инжекта он хрен пойми куда летит... Почему так?

vogel
02.05.2012, 00:18
Он летит туда, куда посылаешь. Ровно в указанные координаты.

samosi
02.05.2012, 11:52
хм не могли бы вы дать мне код? Так как у меня он летит всегда в правый верхний угл за картой.

vogel
02.05.2012, 16:24
Просьба не путать - куда он летит и куда показывает пунктирная линия.
Летит он куда послал из функции AutoRouteStart(х. у);
А пунктирную линию рисует либо к предыдущей точке, куда ты летел вручную либо в правый верхний угол.
За корректную отрисовку отвечает другая (хз какая) функция - я её пока не нашёл.

samosi
02.05.2012, 17:01
Спс все пашет. Но линию надо доделать.
P.S. Dinmaite твоя функу почему то не пашет...(Офсеты были поменяны.)

BritishColonist
02.05.2012, 17:39
samosi, он привёл старый пример со старыми оффсетами.

Lermontov
06.05.2012, 22:34
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;

procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
KlientWindow:HWND; //Handle клиента
ProcessId:Integer;
hProcess:Integer;

implementation

{$R *.dfm}




Const
PW_BASE_ADDRESS = $00A571E0;
PW_DYNAMIC_BASE_OFFSET = $001c; // [base] + 1c = CECGameRun
PW_ROLE_BASE_OFFSET = $0034; // [base] + 1c + 34

AutoRouteAddr = $00478ED0; //$004551D0; //$00452B60;


procedure TForm1.Button1Click(Sender: TObject);
begin

ProcessId:= FindWindow(nil, PChar('Perfect World')); //Находим Handle окна
GetWindowThreadProcessId(KlientWindow,@ProcessId); //Получаем Ид.П.
hProcess := OpenProcess(PROCESS_ALL_ACCESS,False,KlientWindow) ;
end;





procedure InjectFunc(Func: Pointer; aParams: Pointer; aParamsSize: DWORD);
var
hThread: THandle;
lpNumberOfBytes: DWORD;

ThreadAddr, ParamAddr: Pointer;
begin
if ProcessId<>0 then
begin
// ---- Выделим место в памяти процесса и запишем туда нашу функцию
ThreadAddr := VirtualAllocEx(ProcessId, nil, 256, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(ProcessId, ThreadAddr, Func, 256, lpNumberOfBytes);

// ---- Также запишем параметры к ней
ParamAddr := VirtualAllocEx(ProcessId, nil, aParamsSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(ProcessId, ParamAddr, aParams, aParamsSize, lpNumberOfBytes);

// ---- Создадим поток, в котором это всё будет выполняться
hThread := CreateRemoteThread(ProcessId, nil, 0, ThreadAddr, ParamAddr, 0, lpNumberOfBytes);

// ---- Ожидаем, пока функция отработает
WaitForSingleObject(hThread, INFINITE);

// ---- Подчищаем за собой
CloseHandle(hThread);
VirtualFreeEx(ProcessId, ParamAddr, 0, MEM_RELEASE);
VirtualFreeEx(ProcessId, ThreadAddr, 0, MEM_RELEASE);
end
end;
procedure AutoRouteCall(cmd : Pointer); stdcall;
var
addr: Pointer;
begin
addr := Pointer(AutoRouteAddr);
asm
pushad
mov eax, dword ptr [PW_BASE_ADDRESS]
mov eax, dword ptr [eax + PW_DYNAMIC_BASE_OFFSET]
mov ecx, dword ptr [eax + PW_ROLE_BASE_OFFSET]
push cmd
call addr
popad
end;
end;

procedure AutoRouteStart(x, y : integer);
var
buf : array[0..6] of integer;
begin
buf[0] := 330;
buf[1] := 0;
buf[2] := 0;
buf[3] := 0; // Команда на взлёт
buf[4] := x;
buf[5] := y;
buf[6] := 0;
InjectFunc(@AutoRouteCall, @buf, SizeOf(buf));
end;









procedure TForm1.Button2Click(Sender: TObject);

begin

AutoRouteStart(1350, 345);
end;



Что не так в моем бреде?/kidding

vogel
07.05.2012, 00:33
А что не работает-то ?

Lermontov
13.05.2012, 20:29
Как заставить программу лететь по координатам указанных в, допустим, Edit1 и Edit2?

vogel
13.05.2012, 20:41
допустим, считать эти координаты из полей Text контролозв Edit1 и Edit2.
перевести их из строк в цифры, допустим StrToInt
и вызвать AutoRouteStart(x, y);

Lermontov
13.05.2012, 20:45
допустим, считать эти координаты из полей Text контролозв Edit1 и Edit2.
перевести их из строк в цифры, допустим StrToInt
и вызвать AutoRouteStart(x, y);

Можно пример, не могу понять....

dwa83
14.05.2012, 17:12
Можно пример, не могу понять....
int x=StrToInt(Form1->Edit1->Text);
int y=StrToInt(Form1->Edit2->Text);
AutoRouteStart(x, y);
[c++]

IntToStr - преобразует число в строку
FloatToStr - преобразует дробное чесло в строку
StrToFloat, StrToInt - соответственно обратное действие.

Lermontov
14.05.2012, 17:38
int x=StrToInt(Form1->Edit1->Text);
int y=StrToInt(Form1->Edit2->Text);
AutoRouteStart(x, y);
[c++]

IntToStr - преобразует число в строку
FloatToStr - преобразует дробное чесло в строку
StrToFloat, StrToInt - соответственно обратное действие.


Спасибо сам разобрался )

procedure TForm1.Button1Click(Sender: TObject);
var A: Integer;
begin
A:=StrToInt(Edit1.Text);
end;

Choochoo
07.06.2012, 08:46
ProcessId:Integer;
hProcess:Integer;
Что не так в моем бреде?/kidding
Почему Integer? нужен DWORD или Cardinal

A:=StrToInt(Edit1.Text);
Не забудте что кординаты которые надо указывать отличаются от тех которые мы видим на карте.

samosi
07.06.2012, 11:03
Del.

Lermontov
04.10.2012, 08:48
Const
PW_BASE_ADDRESS = $00A571E0;
PW_DYNAMIC_BASE_OFFSET = $001c; // [base] + 1c = CECGameRun
PW_ROLE_BASE_OFFSET = $0034; // [base] + 1c + 34

AutoRouteAddr = $00478ED0; //$004551D0; //$00452B60;


Прошу прощения! Какие оффсеты в новом обновлении, интересует AutoRouteAddr PW_DYNAMIC_BASE_OFFSET PW_ROLE_BASE_OFFSET. Заранее спасибо!

АпАпАпчих
30.10.2012, 12:05
Я вот давным давно писал бота, правда по старым методам банального нажатия клавиш и используя обычные чтение и запись в памяти игры, инжектами функциями не страдал, но вот хочется уже догнать прогресс)) Хочу сделать возвращение персонажа на определенную точку, если он далеко выбегает.. В общем хотелось бы задать пару вопросов по этому поводу:

1. Координаты которые указываются в данной функции, как говорилось выше, не совпадают с координатами карты мира. А какие совпадают? что считывать?

2. Что хранится по этому AutoRouteAddr = $00478ED0; адресу?

3. Есть ли еще какие-нибудь способы перемещения персонажа? (если есть , просто на словах объяснить, это так, для общего развития)

Надеюсь на вашу помощь, а то надоело видеть как чар выбегает хрен пойми куда и застревает в камнях или вообще агрится на мобов выше себя на 30 уровней)

Jok3r666
28.12.2012, 06:22
buf[0] := 330;
Почему именно 330? за что отвечает? и как было определенно что 330?

vogel
28.12.2012, 15:59
Почему 220 - я не знаю. Знают, очевидно, китайские разработчики.
Определено было в отладчике.