Эта программа написанна на Delphi(Pascal), в ней используется скриптовый движек под названием Fast Script , к теме я прикрепил файл , в котором подробно описан этот движек со всеми его возможностями , я рекомендую вам прочитать этот файл , прежде чем читать тему далее.
1.скачать эту программку L2 Phx - Управляем Ла2 2. Запустить программу 3. Запустить ла2 4. По умолчаюнию сниффер в программе включен , можешь выключить , если ты собрался отправлять уже готовые пакеты 5.в Нужном разделе отправляешь готовый или свой отснифанный пакет!
Итак, я думаю вы уже прочитали информацию о FS , приступим к изучению синтаксиса скриптов с примерами.
Переменные
Цитата:
pck (string) - текущий обрабатываемый пакет (без первых двух байт с размером) FromClient (boolean) - пакет (pck) пришел от клиента (всёравно что not FromServer) FromServer (boolean) - пакет (pck) пришел от сервера (всёравно что not FromClient) buf (string) - буфер, используемый некоторыми функциями ConnectName (string) - имя чара от или к которому идёт пакет (v. 3.1.3+) ConnectID (integer) - номер соединения для которого выполняется скрип
Функции
Цитата:
ShowTab и HideTab - для отображения/скрытия панели (UserTab), управлять которой можно из скрипта Для рисования на ней контролов надо указывать UserTab в качестве родителя SendToClient - отправляет клиенту содержимое переменной buf SendToServer - отправляет серверу содержимое переменной buf SendToClientEx(CharName: string) - отправляет клиенту с именем CharName содержимое переменной buf (v. 3.1.3+) SendToServerEx(CharName: string) - отправляет серверу с именем CharName содержимое переменной buf (v. 3.1.3+) (к пакету buf автоматически добавляются 2 байта длины)
NoFreeOnClientDisconnect - запрещает закрытие соединения при дисконекте клиента (v. 3.1.9+) NoFreeOnServerDisconnect - запрещает закрытие соединения при дисконекте сервера (v. 3.1.9+) YesFreeOnClientDisconnect - разрешает закрытие соединения при дисконекте клиента (v. 3.1.9+) YesFreeOnServerDisconnect - разрешает закрытие соединения при дисконекте сервера (v. 3.1.9+) (по умолчанию закрытия разрешены)
ReadC(var index:integer):byte - читает из переменной pck байт ReadH(var index:integer):word - читает из переменной pck число (2 байта) (v. 3.1.8+) ReadD(var index:integer):integer - читает из переменной pck число (4 байта) ReadF(var index:integer):double - читает из переменной pck число c плавающей запятой(8 байт) (v. 3.1.8+) ReadS(var index:integer):string - читает из переменной pck строку (в пакете строка unicode нультерминированная, а результирующая строка обычная паскалевская) Index - начальная позиция чтения, которая модифицируется функцией (сдвигается на число считанных байт)
HStr(h:string):string - преобразует строку в HEX-последовательность К примеру, HStr('AA 00 BB 00 CC 00') вернёт цепочку байт #$AA#$00#$BB#$00#$CC#$00. Можно передавать строку как с пробелами, так и без них; регистр символов не имеет значения.
WriteC(v:byte; ind:integer=0) - пишет в переменную buf один байт WriteH(v:word; ind:integer=0) - пишет в переменную buf число (2 байта) (v. 3.1.8+) WriteD(v:integer; ind:integer=0) - пишет в переменную buf число (4 байта) WriteF(v:double; ind:integer=0) - пишет в переменную buf число c плавающей запятой(8 байт) (v. 3.1.8+) WriteS(v:string) - пишет в переменную buf строку (автоматический перевод в unicode) В первых четырёх процедурах присутствует необязательный параметр ind. Если параметр не указан, то переменная buf дополняется байтом/числом, иначе модифицируется часть буфера.
LoadLibrary(LibName:String):Integer - подгружает к программе библиотеку LibName и возвращает указатель на неё (v. 3.1.8+) FreeLibrary(LibHandle:Integer):Boolean - выгружает из памяти программы библиотеку (v. 3.1.8+) CallFunction(LibHandle:integer;FunctionName:String;Count:Integ er;Params:array of variant):variant - вызывает функцию FunctionName из зарание подгруженной библиотеки с указателем LibHandle и параметрами перечисленными в Params (v. 3.1.8+)
Вкладка скрипты
Цитата:
Процедура OnConnect(WithClient: Boolean) вызывается при установке соединения, флаг WithClient указывает с клиентом ли произошло соединение (v. 3.1.9+) Процедура OnDisconnect(WithClient: Boolean) вызывается при потере соединения (v. 3.1.9+) Процедура Init вызывается когда вы устанавливаете рядом со скриптом галочку. Процедура Free вызывается когда вы убираете рядом со скриптом галочку. Основное тело скрипта (между begin и end) вызывается каждый раз при получении пакета от сервера или клиента если скрипт отмечен галочкой.
Вкладка дополнительно
Цитата:
Основное тело скрипта (между begin и end) вызывается по нажатию кнопки Выполнить, и прекращается либо по нажатию Стоп, либо по окончанию работы скрипта.
Рассмотрим пример простого скрипта
Итак , например, мы имеем двух чаров (2 окна) char1 и char2 , постараемся написать скрипт, который бы при определенном действии char1 сделал бы так , чтобы char2 повторил действие , не разворачивая окна. Пусть char1 должен будет выполнить действие Victory и после чего char2 повторит его. Пакет социального действия Victory - 1b 04 00 00 00 , а значит , исходя из изложенного выше мы можем написать простой скрипт:
Цитата:
begin if FromClient and (ConnectName='char1') and (pck=HStr('1b 04 00 00 00')) then begin buf:=HStr('1b 04 00 00 00'); SendToServerEx('char2'); pck:=''; end; end.
Все просто , не правда ли?
Вот и все , пора заканчивать гайд , спасибо за внимание , права на гайд частично принадлежат Mmoworld.info и частично создателю программы Xkor.
Предлагаю пользователям выкладывать интересные скрипты , начну , Скрипт на AutoTarget игрока , бьющего вас , хоть на некоторых клиентах он , похоже , встроен , но плохо работает ..
Цитата:
const Name='mmoworld.info'; //Пишите сюда свой ник ( вместо моего mmoworld.info)
//************************************************** ************* // вызывается при приходе каждого пакета, если скрипт включен //************************************************** ************* begin //************************************************** ************************** if (ConnectName=Name) and FromServer thenbegin case pck[1] of #$04: begin //пакет с инфой о моём чаре i:=2; MyXpos:=ReadD(i); //получаю координату х моего чара MyYpos:=ReadD(i); //получаю координату у моего чара MyZpos:=ReadD(i); //получаю координату z моего чара //Запоминаем ИД i:=18; MyID:=ReadD(i); //получаю ид моего чара end; //************************************************** ************* //05=Attack:d(AttackerID)h(targetID)d(Damage)b(Flags )d(X)d(Y)d(Z)d(ListHits)h(targetID)d(damage)b(flag s) //48=MagicSkillUse:h(CharID)h(targetID)h(skillID)d(s killLvl)d(hitTime)d(reuseDelay)d(X)d(Y)d(Z)w(count )d(d)d(d)d(d) #$05,#$48: begin if Status=1 thenbegin AttackerID:=ReadD(2); TargetID:=ReadD(6); if (AttackerID<>TargetID) and (MyID=TargetID) then TargetAttacker(AttackerID); end; end; end; end; //************************************************** ************************** if (ConnectName=Name) and FromClient thenbegin case pck[1] of #$1B: begin //C>Пакет RequestSicialAction #$1B case ReadD(2) of //социальное действие Yes для начала ловли 6: begin Status:=1; SendMsg('Автоматическое взятие в цель включено!'); //не передаем серверу pck:=''; end; //социальное действие No для окончания 5: begin Status:=0; SendMsg('Автоматическое взятие в цель включено!'); //не передаем серверу pck:=''; end; end; end; //ValidatePosition пакет от клиента с моими кординатами #$48: begin MyXpos:=ReadD(2); //получаю координату х моего чара MyYpos:=ReadD(6); //получаю координату у моего чара MyZpos:=ReadD(10); //получаю координату z моего чара end; end; end; end.
оо , вот этот скрипт просто супер для ПВП серверов , работает таким образом: 1) Вам кидают трейд - пакетхак его принимает 2)Если положили больше 5кк , то он бафает , если нет то жмет отмена
Естественно 5кк вы можете изменить хоть на 1 адену , порывшись в скрипте , или , скажем , бафф за 1 Stone Of Purity , дерзайте , непосредственно скрипт:
var Target: string; prof,x: integer; timer1: TTimer;
procedure Init; begin timer1:=TTimer.Create(nil); timer1.OnTimer:=@OnTimer; timer1.enabled:=true; timer1.interval:=2000; end;
procedure OnTimer(Sender: TObject); begin case x of 1: begin buf:=hstr(b1); sendtoserver; x:=x+1; end; 2: begin buf:=hstr(b2); sendtoserver; x:=x+1; end; 3: begin buf:=hstr(b3); sendtoserver; x:=x+1; end; 4: begin buf:=hstr(b4); sendtoserver; x:=0; end; end; end;
procedure Free; begin timer1.Free; end; /////////////////////////////////////////////////////////////////// begin
if FromServer and (pck[1]=#$5E) and (x=0) then //подкорректил немного, что б бот не принимал трэйд когда кого-то уже баффает 06.08.07 begin Target:=#$04+pck[2]+pck[3]+pck[4]+pck[5]; buf:=hstr('44 01 00 00 00'); sendtoserver; //если кидают трэйд, то принимать end; if fromclient and (pck[1]=#$44) then pck:=''; {клиент почему-то иногда автоматом отылает кэнсл трэйд, поэтому убиватю этот пакет} if fromserver and (pck[1]=#$21) then begin if pck[14]+pck[15]+pck[16]=#$40#$4B#$4C then {если в трэйд положили 5кк} begin buf:=hstr('17 01 00 00 00');//подтвердить трэйд prof:=1; end; if prof=0 then buf:=hstr('17 00 00 00 00');//отмена трэйда sendtoserver; end;
if FromServer and (pck[1]+pck[2]=#$22#$01) then begin buf:=target; sendtoserver;
Предлагаю пользователям выкладывать интересные скрипты , начну. Скрипт на сдачу манора
Продолжим вкусным , "100% сдача манора" , что дает отличный доход , ваща задача всего лишь запустить скрипт минут за 5 до начала олимпиады , все остальное он сделает сам , вы будите довольно , не палится Гмом , хотя после N-ного количества сдач игроки могут расстроится и попросить проверить ГМа проверить логи , если он увидет , что все время сдаете только вы , может заподозрит чего .. ну да ладно , что-то я заговорился , скрипт:
var PaketManora: string; //Пакет на сдачу манора, который мы отправим серваку зараннее с помощью клиента // и запомним его для того чтобы вручную не формировать его кодом. //важно что оправлять его нужно после после объявления об олимпиаде. //так как в пакете манора используются ИД сессии, которые изменяются //каждый ровный час.
timer1: TTimer; //таймер контролирующий системное время
StartTime: TDateTime; EndTime: TDateTime;
x:integer;
procedure Init; //Вызывается при включении скрипта begin timer1:=TTimer.Create(nil); timer1.OnTimer:=@OnTimer; // timer1.enabled:=false; // таймер по умолчанию выключен timer1.interval:=400; // через каждые 0,4сек будем засекать контрольное время сдачи манора
x:=0; end;
procedure Free; //Вызывается при выключении скрипта begin timer1.Free; //освобождаем занимаемую память таймером end;
//вызывается при срабатывании таймера procedure OnTimer(Sender: TObject); begin //если наступило время сдавать манор и скрипт пока еще не отправил 30 попыток его сдать то if (time >= EndTime) and (x<30) then begin // отправляем пакет на сдачу манора. buf:=PaketManora; SendToServer; //счетчик попыток x:=x+1; end; end;
begin
//если перехвачен пакет на сдачу манора то if FromClient and (pck[1]=#$D0) and (pck[2]=#$09) and (pck[3]=#$00) then begin //запоминаем его полностью PaketManora:=pck; end;
//если получен пакет об начале олимпиады то if FromServer and (pck[1]=#$64) and (pck[2]=#$69) and (pck[3]=#$06) then begin //засекаем текущее время StartTime:=time; //вычисляем время сдачи манора (прибавляем нужное время которое нужно засеч после получения сообщения об илимпиаде) EndTime:=StartTime + EncodeTime(0,5,49,0); // изменяем и корректируем ето число в формате (ЧЧ,ММ,СС,МС) //активируем таймер timer1.enabled:=true;