farmwl

 Admin
  • Content count

    824
  • Joined

  • Last visited


Everything posted by farmwl

  1. farmwl added a topic in Script repository   

    Управление окнами - синхронное ТП в нужную локацию
    Если вам приходится управлять большим кол-вом окон одновременно, то данный скрипт будет как нельзя кстати. С его помощью Вы, например, сможете отдать команду всем окнам телепортироваться за Вами (либо записаться на олимп, либо зайти в инсту и тд - немного изменив код можно заставить их делать все что угодно).
    Как использовать:
    Предполагается, чтобы боты бегают за мейн чаром прицепом (настраивается в интерфейсе)В скрипте указываем либо управлять всеми ботами сразу, либо указываем ники каждого ботаЗапускаем скрипт на мейн чареПодбегаем к ГК, берем его в таргетПишем в пати чат tp_5 - и окна заговорят с ГК, и выберут 5ую строчку в списке телепортов (можно писать TP_7, Tp_10 и тд - регистр не важен)В это время сами так же ТПшимся вместе с нашими окнами вручнуюuses SysUtils, Classes; var Control_All_Bots: boolean = true; // управлять всеми ботами сразу (true) или только никами, перечисленными ниже (false) Control_Nicknames: array of string = ['nick1', 'nick2']; // перечисляем ники ботов, которыми нужно управлять procedure Chat_Control_Thread(); // поток, который и будет управлять окнами var dlg: integer; begin while (Engine.Status <> lsOnline) do delay(555); // ожидаем входа в игру while delay(55) do begin // запускаем бесконечный цикл if (ChatMessage.Unread) // если сообщение не прочитано and (ChatMessage.Time < 3333) // и было отправлено < 3 сек назад and (ChatMessage.ChatType = mtParty) // и написано в пати чате and (ChatMessage.Sender = User.Name) // и его написали мы сами and (Pos('tp_', AnsiLowerCase(ChatMessage.Text)) > 0) then begin // и в нем содержится "tp_", тогда dlg:= StrToInt(Trim(Copy(ChatMessage.Text, Pos('tp_', ChatMessage.Text)+3, 2))); // запоминаем номер телепорта if (Control_All_Bots) then Control_All(dlg) // если нужно управлять всеми ботами, то вызываем одну функцию else Control_By_Nicks(dlg); // если же нужно управлять только указанными никами, то другую end; end; end; procedure Control_All(dlg: integer); // функция для управления всеми запущенными ботами var i: integer; begin // всеми окнами берем в таргет нашу текущую цель i:= 0; while (GetControlByIndex(i) <> nil) do begin // пока TL2Control по i-ому индексу не нулевой if (GetControlByIndex(i).Status <> lsOnline) then continue; // если окно не в игре, то переходим к следующему GetControlByIndex(i).SetTarget(User.Target); // i-ым окном выделяем того, кого держим в таргете мейн окном inc(i); // увеличиваем индекс (для перехода к следующему окну) end; delay(999); // немного ждем после того, как все окна выбрали цель // всеми окнами подбегаем к нашей цели, если нужно i:= 0; while (GetControlByIndex(i) <> nil) do begin if (GetControlByIndex(i).Status <> lsOnline) then continue; if (GetControlByIndex(i).GetUser.DistTo(User.Target) > 200) then GetControlByIndex(i).MoveTo(User.Target, -70); inc(i); end; delay(999); // всеми окнами открываем диалог i:= 0; while (GetControlByIndex(i) <> nil) do begin if (GetControlByIndex(i).Status <> lsOnline) then continue; GetControlByIndex(i).DlgOpen; inc(i); end; delay(999); // всеми окнами выбираем Телепорт i:= 0; while (GetControlByIndex(i) <> nil) do begin if (GetControlByIndex(i).Status <> lsOnline) then continue; GetControlByIndex(i).DlgSel('Телепорт'); // можно заменить на 'Teleport' или 1 inc(i); end; delay(999); // всеми окнами выбираем куда телепортироваться i:= 0; while (GetControlByIndex(i) <> nil) do begin if (GetControlByIndex(i).Status <> lsOnline) then continue; GetControlByIndex(i).DlgSel(dlg); inc(i); end; delay(999); end; procedure Control_By_Nicks(dlg: integer); // функция для управления определенными никами var i: integer; begin // всеми окнами берем в таргет нашу текущую цель for i:= 0 to Length(Control_Nicknames)-1 do begin if (GetControl(Control_Nicknames[ i ]).Status <> lsOnline) then continue; GetControl(Control_Nicknames[ i ]).SetTarget(User.Target); end; delay(999); // всеми окнами подбегаем к нашей цели, если нужно for i:= 0 to Length(Control_Nicknames)-1 do begin if (GetControl(Control_Nicknames[ i ]).Status <> lsOnline) then continue; if (GetControl(Control_Nicknames[ i ]).GetUser.DistTo(User.Target) > 200) then GetControl(Control_Nicknames[ i ]).MoveTo(User.Target, -70); end; delay(999); // всеми окнами открываем диалог for i:= 0 to Length(Control_Nicknames)-1 do begin if (GetControl(Control_Nicknames[ i ]).Status <> lsOnline) then continue; GetControl(Control_Nicknames[ i ]).DlgOpen; end; delay(999); // всеми окнами выбираем Телепорт for i:= 0 to Length(Control_Nicknames)-1 do begin if (GetControl(Control_Nicknames[ i ]).Status <> lsOnline) then continue; GetControl(Control_Nicknames[ i ]).DlgSel('Телепорт'); // можно заменить на 'Teleport' или 1 end; delay(999); // всеми окнами выбираем куда телепортироваться for i:= 0 to Length(Control_Nicknames)-1 do begin if (GetControl(Control_Nicknames[ i ]).Status <> lsOnline) then continue; GetControl(Control_Nicknames[ i ]).DlgSel(dlg);     end;   delay(999); end; begin   Script.NewThread(@Chat_Control_Thread);   // code end.
    • 1 reply
    • 593 views
  2. farmwl added a post in a topic Как пользоваться Script_Recorder'ом для Адреналина?   

    Тебе следует для начала основы скриптописания освоить видимо, базовую инфу можно найти тут: http://asiwin.com/forum/53-scripting/
    А то, по-моему, ты не очень представляешь как оно вообще должно выглядеть и работать)
     
  3. farmwl added a post in a topic Как пользоваться Script_Recorder'ом для Адреналина?   

    что там объяснять то? в инструкции описано подробно как запустить.
    если выдает ошибки при запуске - скачай последнюю версию, она там 1.3.1
  4. farmwl added a topic in Script repository   

    Сканирование игрового чата [ChatMessage]
    Простой пример, который выводит в хистори все сообщения чата:
    uses SysUtils; procedure chat_scaner(); var chat_sender: TL2Char; ans_type: byte; begin while true do begin delay(111); if (ChatMessage.Unread) and (ChatMessage.Time < 3333) then begin engine.msg(ChatMessage.Sender, ChatMessage.text, 0); end; end; end; begin Script.NewThread(@chat_scaner); delay(-1); end.

    • 0 replies
    • 251 views
  5. farmwl added a post in a topic Проблемы \ решения   

    а ты уверен, что у тебя версия с волкером?
    оконка за 300р - это именно оконка, без волкера. для волкера ключи пооконные от адреналина подходят если что
  6. farmwl added a topic in L2Adrenalin   

    Как узнать свои координаты? Запись маршрута в L2Adrenaline боте
    Существует 2 способа записи маршрута:
    Запись текущих (своих) координат.
    Тут все просто - Вы становитесь активным персонажем в нужную точку, переходите в многооконку, ставите курсор мыши в нужное место (в скрипте) и нажимаете сочетание клавиш Alt + V (это работает как с Ctrl+V, только Alt+V). Все, ASI записала текущие координаты туда, где был установлен курсор мыши.Запись маршрута встроенным рекордером.  
    Вы должны поставить курсор мыши в нужное место в скрипте и активировать функцию записи (красный кружок, расположен в закладке скрипт).
    Теперь Вам остается просто кликать мышкой в игре, каждый клик будет записываться рекордером, преобразуя координаты в готовые MoveTo. 
    • 0 replies
    • 957 views
  7. farmwl added a topic in Script repository   

    Как сделать передвижение бота более человечным
    Очень палевно выглядят боты, если их много и они бегают по одним и тем же координатам целыми трейнами. Чтобы избежать этого достаточно добавить в каждую команду 
    Engine.MoveTo(X, Y, Z) добавить немного рандома:
    Engine.MoveTo(X+random(200)-100, Y+random(200)-100, Z); // отклонение от финальной точки будет +\-100м по каждой из координат, это значение можно менять на любоеТак же можно написать процедуру, которая бы имитировала поведение среднестатистического игрока, когда тому нечего делать:
    procedure Neurotic_Clicks_Thread(d: integer); // поток, имитирующий нервное кликальнье мышкой по земле рядом с персонажем begin while delay(555) do begin // запускаем бесконечный цикл if (Engine.Status = lsOnline) then begin // если мы в игре, то if (not User.Moved) and (not User.InCombat) and (User.Cast.EndTime = 0) // если мы не движемся, не в бою, ничего не кастуем and ((User.Target = nil) or (User.Target.Dead)) then // и у нас нет таргета или цель мертва, то if Engine.DMoveTo(User.X+random(2*d)-d, User.Y+random(2*d)-d, User.Z) then // делаем рандомный шаг в сторону delay(555+random(4444)); // и ждем рандомное кол-во времени end; end; end; begin Script.NewThread(@Neurotic_Clicks_Thread(100)); // запускаем поток, в скобках указываем как сильно отбегать в стороны end.Условий можно добавить под свои нужды и побольше, например проверять время, прошедшее с последнего нашего ТП. В любом случае подобный поток добавляет человечности боту, когда тот например стоит на споте и ждет респа мобов
    • 7 replies
    • 604 views
  8. farmwl added a topic in L2Adrenalin   

    Работа с динамическими bypass'ами. Парсинг. Регулярные выражения.
    Сейчас админы серверов изобретают различные методы противодействия ботам. В этой статье будет рассмотрено, какие методы защиты применяются в диалогах, направленные на то, чтобы затруднить ботам их работу, в то время как для обычных игроков подобные меры защиты скорей всего будут даже не заметны.
    Пока я разрабатывал и тестировал скрипт для Adrenalin'a на прохождение квестов на ТТ рецепты, я встретил несколько способов, которые и будут описаны ниже. Для удобства я буду рассматривать диалог с Джереми, у которого берутся эти квесты. Для удобного просмотра диалогов в процессе работы можно воспользоваться Script Recorder'ом.
    Динамически меняющийся bypass (например, на euro-pvp.com). Самый простой случай - сама фраза, которую мы хотим выбрать не меняется, но с каждым новым открытием диалога меняется bypass, который нужно отправить. Обычно данный способ комбинируют с каким-нибудь еще.
    <a action="bypass -h 0-739772929">[Доставка ликера (In progress)]</a><br> // 0-739772929 <a action="bypass -h 01784106480">[Доставка яиц (In progress)]</a><br> // 01784106480<a action="bypass -h 0-739859206">[Доставка ликера (In progress)]</a><br> // 0-739859206 <a action="bypass -h 01784133759">[Доставка яиц (In progress)]</a><br> // 01784133759 Замена одной или нескольких букв в строчке (например, на emerial.ru). Длина строки при этом не меняется. Как правило, в исходной строке заменяют пару букв, так что бегло взглянув это можно даже не заметить. Например, вместо "Доставка яиц" будет "Досrавка яиц". Этот способ как раз и используется в дополнение к предыдущему, т.е. при каждом новом открытии диалога меняется и строка ответа и bypass. Данный способ мешает нам искать bypass по заранее известной подстроке, <a action="bypass -h 01736714927">[Доставка ликdра]</a><br> // 01736714927 <a action="bypass -h 0-1931249600">[Дeставка яиц]</a><br> // 0-1931249600<a action="bypass -h 01736767322">[Доставка лdкера]</a><br> // 01736767322 <a action="bypass -h 0-1931186782">[Доставка aиц]</a><br> // 0-1931186782Использование "невидимых" нам спец. символов. Причем как внутри диалога, так и внутри bypass'a (например, на ketrawars.net). Фактически они присутствуют в диалоге, но при экранировании (т.е. когда нам показывают этот диалог) они не отображаются. Это связано с нестандартными кодировками, кому сильно интересно можете погуглить. По этой же причине я не могу, например, выложить на форум код этих строк (эти спец символы будут автоматически удалены), поэтому любуемся скриншотами:В обычном блокноте:

    В Sublime:

    Таким образом, длина искомой подстроки меняется каждый раз, однако последовательность символов в этой подстроке целиком сохранятся.
    Возможно есть еще другие виды защит именно на уровне всевозможных модификаций диалогов (вылезающие при открытии диалога каптчи - это отдельный разговор), но мне пока другие не встречались.
    Итак, теперь, когда ясна задача, можно думать над тем, как находить заветные bypass's для отправки. Вариантов опять таки несколько, можно решить это, не выходя за рамки функций Pos, Copy, Delete, Trim и тд. Однако проще и красивее будет использовать регулярные выражения (regular expressions). О том, что это и как они составляются можете погуглить. Если кратко, то это поиск по шалблонам, который позволяет нам парсить диалоги в разы проще.
    Как пользоваться регулярными выражениями?
    Тут все просто, подключаете модуль RegExpr в раздел uses и пользуетесь.
    Пример:
    uses SysUtils, Classes, RegExpr; // подключили модуль RegExpr procedure PrintAllTags(); // распечатать все конструкции с bypass'ами var RegExp: TRegExpr; begin RegExp:= TRegExpr.Create; RegExp.Expression:= '(<a *(.+?)</a>)|(<button *(.+?)>)'; if RegExp.Exec(Engine.DlgText) then repeat Print(RegExp.Match[0]); until (not RegExp.ExecNext); RegExp.Free; end; begin PrintAllTags(); end.Этот простой код найдет и распечатает нам все интересующие bypass'ы:

     
    uses SysUtils, Classes, RegExpr; // подключили модуль RegExpr function Bypass(dlg: string): boolean; var RegExp: TRegExpr; SL: TStringList; i: integer; bps: string; begin Result:= true; // задаем результат по умолчанию RegExp:= TRegExpr.Create; // инициализируем объекты для дальнейшей работы SL:= TStringList.Create; RegExp.Expression:= '(<a *(.+?)</a>)|(<button *(.+?)>)'; // задаем регэксп на поиск всех возможных bypass'ов if RegExp.Exec(Engine.DlgText) then // если нашлелся нужный шаблон, то repeat SL.Add(RegExp.Match[0]); // заполняем наш список такими совпадениями until (not RegExp.ExecNext); // пока не закончатся шаблоны for i:= 0 to SL.Count-1 do begin // теперь пробегаемся по нашему списку if (Pos(dlg, SL[ i ]) > 0) then begin // если в i-ой строке нашелся искомый текст, то RegExp.Expression:= '"bypass -h *(.+?)"'; // ищем шаблон текста c bypass'ом if RegExp.Exec(SL[ i ]) then // и если нашли, то копирем из него интересующий нас кусок bps:= TrimLeft(Copy(RegExp.Match[0], 12, Length(RegExp.Match[0])-12)); end; end; Print(bps); // распечатываем конечный вариант bypass'а if (Length(bps) > 0) then Engine.BypassToServer(bps); // если его длина > 0, то отправляем на сервер RegExp.Free; // не забываем освобождать память SL.Free; end; begin Bypass('Набор воина'); end.О правилах составления регулярных выражений полно инфы в инете, например тут
    Возможностей много, можете почитать исходники: RegExpr.txt
    Надеюсь, что распарсить полученные строчки не составит труда
    • 2 replies
    • 3,946 views
  9. farmwl added a post in a topic Проблемы \ решения   

     > Бот не пакетный и не изменяет данные (c) http://asiwin.com/buy/adrenalin/
    Принцип работы бота иной, ему все равно на пакеты и изменение шифраций
  10. farmwl added a topic in ArcheBox   

    Как запустить скрипт \ плагин в ASI WIN?
    Очень часто мне задают вопрос: "А как запустить скрипт?".
    Максимально наглядный ответ:

    • 2 replies
    • 2,186 views
  11. farmwl added a topic in L2Adrenalin   

    Как запустить скрипт в Adrenaline bot без запуска клиента L2
    В Adrenaline для открытия \ редактирования \ запуска скрипта необходимо, чтобы в списке аккаунтов появился хотя бы 1 аккаунт.
    Как правило многие запускают клиент игры ради этого, но можно сделать проще. достаточно выделить поле редактирования скрипта и нажать сочетание Ctrl + P - появится "пустой" аккаунт. Теперь его можно выделить и работать со скриптами не прибегая к запуску игры.

    • 2 replies
    • 1,710 views
  12. farmwl added a topic in Script repository   

    Отправка SMS сриптом. Работа с TCP
    Благодаря возможности работы с TCP, мы, например, можем отправлять себе смс'ки прямо из скрипта с помощью сторонних сервисов.
    Для этого разумеется нужно на этом сервисе сначала зарегаться, получить свой уникальный API ключ и пополнить счет. В данном примере использован sms.ru, тут есть возможность бесплатно отправлять смс на свой номер (указанный при регистрации). Однако, не думаю что стоит этим злоупотреблять, благо стоимость отправки там что-то около 25 копеек
    uses Classes, TCP; function Send_SMS(text, api_key, mob_number: string): string; var Head: TStringList; Socket: TTCPBlockSocket; begin Head:= TStringList.Create; text:= StringReplace(text, ' ', '+', [rfReplaceAll]); // преобразумем текст сообщения - заменяем пробелы на + // формируем запрос, который пошлем серверу Head.Add('GET /sms/send?api_id='+api_key+'&to='+mob_number+'&text='+text+' HTTP/1.1'); Head.Add('Accept: */*'); Head.Add('Accept-Encoding: gzip, deflate'); Head.Add('Host: sms.ru'); Head.Add('Connection: Keep-Alive'); Head.Add(#10#13); Socket:= TTCPBlockSocket.Create; // создаем сокет Socket.Connect('sms.ru', '80'); // подключаемся к sms.ru if (Socket.LastError = 0) then // если нет никаких ошибок, то   Socket.SendString(Head.Text); // отправляем наш запрос  Head.Free; // не забываем очищать память Socket.Free; end; begin Send_SMS('АК реснулась!', '21****2D-****-****-****-****BA****40', '79210000000'); end.Возможности использования ограничены лишь вашей фантазией.
    • 2 replies
    • 217 views
  13. farmwl added a post in a topic Реакция на появление Capthca, События   

    можно и самому распознавать. нейросети нынче учат даже в игры играть, не то что простенькие каптчи разгадывать
  14. farmwl added a post in a topic Проблемы \ решения   

    конечно ведется, пока тестируем, еще немножко терпения)
  15. farmwl added a topic in Script repository   

    TCP Socket
    Класс TTCPBlockSocket в модуле TCP (доступен начиная с версии 1.96).
    Теперь Вы можете создавать TCP соединения как клиентские так и быть сервером.
    Можете отправлять и получать данные в любые другие приложения, почту и т.д. (куда угодно)
    Например можно запустить 2 бота на разных компах один будет сервером, а второй клиентом, и они смогут общаться между собой с помощью TCP соединения.
    Качать пример во вложении (с форума работать не будет, из за ссылок на гугл в примере)
    Описание класса:
    constructor Create; destructor Destroy; override; procedure CloseSocket; override; function WaitingData: integer; override; procedure Listen; override; function Accept: integer; override; procedure Connect(IP, Port: string); override; function SendBuffer(Buffer: pointer; Len: integer): integer; override; function RecvBuffer(Buffer: pointer; Len: integer; Timeout: integer): integer; virtual; procedure SendByte(Data: byte); virtual; function RecvByte(Timeout: integer): byte; virtual; procedure SendString(Data: ansistring); virtual; function RecvString(Timeout: integer): ansistring; virtual; procedure SendInteger(Data: integer); virtual; function RecvInteger(Timeout: integer): integer; property LastError: integer;Пример использования:
    В данном примере создается сокет, соединяется с http://www.google.ru отправляет данные (эмулирует запрос HTTP) и получает ответ от сервера:
    uses Classes, TCP; var Head: TStringList; Socket: TTCPBlockSocket; i: integer; procedure OnFree; begin Head.Free; Socket.Free; end; begin Head:= TStringList.Create; Head.Add('GET / HTTP/1.1'); //Создаем запрос, который пошлем серверу Head.Add('Accept: */*'); Head.Add('Accept-Encoding: gzip, deflate'); Head.Add('Host: www.google.ru'); Head.Add('Connection: Keep-Alive'); Head.Add(#10#13); Socket := TTCPBlockSocket.Create; //Создаем сокет Socket.connect('173.194.71.94', '80'); //конектим www.google.ru if Socket.LastError <> 0 then Exit; //Если произошла ошибка, выходим Socket.SendString(Head.text); //Отправляем наши данные Head.Clear; Head.DelimitedText := Socket.RecvString(5000); //Получаем ответ for i := 0 to Head.Count-1 do //Показываем ответ print(Head.Strings); end.
    • 5 replies
    • 421 views
  16. farmwl added a post in a topic Каталог готовых скриптов, примеров и полезных статей   

    Проверить, готов ли скил к применению:
    var skill: TL2Skill; // объявляем переменную skill типа TL2Skill, т.е. "умение" begin SkillList.ByID(176, skill); // ищем скил по ID и помещаем его в переменную Print(skill.EndTime); // распечатать время отката умения if (skill.EndTime = 0) then ... // если скил откатился, то end.
  17. farmwl added a post in a topic Каталог готовых скриптов, примеров и полезных статей   

    Проверка на смерть:
    function Check_Death(): boolean; begin result:= false; // указываем результат по умолчанию if (User.Dead) then begin // если мы мертвы, то result:= true; // задаем реузльтат функции - истина Engine.Msg('', 'Умер, воскрешаюсь...', 128); // печатаем инфу в логи Engine.FaceControl(0, false); // выключаем интерфейс while (User.Dead) and delay(999) do Engine.GoHome; // пока мы метрвы, раз в 1 секунду пытаемся воскреситься delay(5555); // ждем дополнительное время для прогрузки (на слабых ПК стоит увеличить) end; end;
  18. farmwl added a post in a topic Каталог готовых скриптов, примеров и полезных статей   

    Проверка стадии квеста:
    В L2Walker'e раньше была функция: QuestStage(ИД квеста, условие, стадия квеста) - Считает степень прохождения текущего квеста.
    Сейчас в L2Adrenaline боте есть только: function QuestStatus(QuestID: Cardinal; Step: Integer): Boolean;  // Проверяет выполнен указанный шаг квеста или нет
    Напишем аналог QuestStage для Adrenalin:
    function QuestStage(quest_id: integer): integer; // возвращает текущую стадию квеста по ID var i: byte; begin result:= 0; for i:= 1 to 32 do if Engine.QuestStatus(quest_id, i) then result:= i; end; begin Print(QuestStage(622)); // распечатать стадию квеста end.
  19. farmwl added a topic in Script repository   

    Поддержание курицы в боевом режиме (пример для ЕЕшек)
    Простой поток, который будет поддерживать именно Вашу курицу в боевом режиме (а не пытаться бить любую, которую найдет), чтобы та заливала МП. Можно с легкостью добавить в Ваш скрипт:
    procedure Kookaburra_Thread(mp: byte); begin   while delay(555) do begin                                // запускаем бесконечный цикл     if (Engine.Status = lsOnline) then begin               // если мы в игре, то       if (not User.InCombat) and (User.MP < mp) then begin // если мы не в боевом режиме и у нас мало МП, то         if (PetList.Count > 0) and (User.DistTo(PetList(0)) < 500) then begin  // если у нас призван пет и дистанция до него < 500, то             Engine.FaceControl(0, false);                    // выключаем интерфейс (чтобы не конфликтовало)           if Engine.SetTarget(PetList(0)) then delay(111); // берем в таргет нашего пета           if Engine.UseSkill(1177, true) then              // используем на него атакующий скил: Удар ветра [id: 1177]             while (User.Cast.EndTime <> 0) do delay(111);  // и ждем окончания его каста           Engine.FaceControl(0, true);                     // включаем обратно интерфейс         end;       end;     end;   end; end; begin Script.NewThread(@Kookaburra_Thread(50)); // аргументом подаем % MP, на котором нужно бить курицу   // code end.
    • 0 replies
    • 283 views
  20. farmwl added a topic in Script repository   

    Проверка на застревание персонажа
    Бывают случаи, когда персонаж во время выполнения скрипта застревает в геодате \  упирается в стены и тд. Такие случаи можно обрабатывать отдельным потоком и предпринимать какие-нибудь меры. Будет полезно для тех, кто пишет свои скрипты:
    uses SysUtils; procedure Sticking_Thread(sec: integer); var Timer: int64; X, Y, Z: integer; begin while (Engine.Status <> lsOnline) do delay(555); // ожидаем входа в игру X:= User.X; Y:= User.Y; Z:= User.Z; // запоминаем текущие координаты Timer:= GetTickCount + sec*1000; // запоминаем время while delay(555) do begin // запускаем бесконечный цикл if (Engine.Status = lsOnline) then begin // если мы в игре, то if (User.Cast.EndTime = 0) // если мы ничего не кастуем в данный момент and (Abs(User.X-X) < 50) // (значение 50 можно менять) and (Abs(User.Y-Y) < 50) then begin // и наши координаты почти не изменились, тогда Print('Похоже, что я стою на месте'); // пишем в логи (эту строчку можно закоментировать) if (GetTickCount > Timer) then begin // если прошло больше указанного времени, то Script.Suspend; // тормозим скрипт Print('Кажется я застрял'); // пишем в логи (эту строчку можно закоментировать) if Engine.UseItem(736) then begin // используем SoE while (User.Cast.EndTime <> 0) do delay(555); // ждем окончания каста delay(5555); // и ждем еще немного, чтобы прогрузиться end; Script.Replace; // перезапускаем скрипт (или делаем чтобы-нибудь еще) end; end else begin // если же мы ничего не кастуем, и наши координаты поменялись, то X:= User.X; Y:= User.Y; Z:= User.Z; // запоминаем новые координаты Timer:= GetTickCount + sec*1000; // обновляем таймер Print('Все в порядке, я двигаюсь'); // пишем в логи (эту строчку можно закоментировать) end; end; end; end; begin Script.NewThread(@Sticking_Thread(30)); // параметром указываем время (в сек), после которого юзать СОЕ end.Общая логика такова:
    Мы дожидаемся входа в игру, запоминаем свои координаты, и далее каждые пол секунды сравниваем свои координаты с теми, которые запомнили до этого: если координаты не изменились + мы ничего не кастуем в данный момент и это длится больше указанного времени (30 секунд в нашем случае), то тормозим скрипт, используем СОЕ и перезапускаем скрипт. Если же наши координаты хоть немного изменились или мы что-то кастуем (например то же СОЕ), то обнуляем таймер и запоминаем текущие координаты (с ними будем сравнивать дальше)
    • 3 replies
    • 290 views
  21. farmwl added a topic in Interface set up examples   

    Список тем по настройке интерфейса L2 Adrenalin
    В данной теме будут собраны ответы на часто возникающие вопросы, которые можно решить с помощью интерфейса:
    Не забывайте, у нас есть подробнейшая инструкция по настройке интерфейса в текстовом формате
    Настройка кайта \ дистанционной атаки (для лучников и магов)Ребафф через Alt+B (работает не везде) Авто использование банок душ камаэлей \ камней зарядок гладов и тировНастройка спойла \ свипаНастройка крафта сосок \ ресурсовНастройка рыбалкиПример полной настройки коневода на АОЕ фармНастройка скилов пета \ сумонаНастройка реса в патиНастройка Toogle-скилов (Vicious Stance, Arcane Power и тд)
    • 0 replies
    • 3,999 views
  22. farmwl added a topic in L2Adrenalin   

    Autorun script (Обновление от 11.02.2015)
    В обновлении от 11.02.2015 появилась новая функция - Автозапуск скрипта.
    Как работает:
    Задается 1 скрипт, который будет автоматически запускаться на любом новом аккаунте, в который заинжектится бот.

    Как настроить:
    Запускаете 1 любой акк. открываете нужный Вам скрипт () и затем нажимаете кнопку .
    Все, теперь все новые запускаемые аккаунты автоматически будут загружать этот скрипт при запуске

    • 0 replies
    • 3,959 views
  23. farmwl added a topic in L2Adrenalin   

    Немного инфы об Engine.BypassToServer
    Вопросов поступает много и они, как правило, все однотипные, поэтому давайте прольем свет на команду Adrenalin'a Engine.BypassToServer
    Итак, для начала самый важный вопрос - зачем она нужна?
    Она нужна для выбора ответов во всевозможных диалогах (разговоры с NPC, Alt+B, ответы на некоторые капчи и тд). Более простая для использования функция Engine.DlgSel, куда мы подаем номер строки или текст - по сути своей просто враппер (обертка) над Engine.BypassToServer. Но Engine.DlgSel не ограничивается лишь функционалом Engine.BypassToServer !
    Следующий вопрос, который возникает - так почему тогда не использовать всегда Engine.DlgSel ?
    На некоторых фри серверах Engine.DlgSel может просто не работать в силу предпринятых администрацией мер. Так же Engine.BypassToServer необходим в случаях использования диалогов через Alt+B и ему подобных.
    Ну и наконец - как пользоваться Engine.BypassToServer ?
    Для начала немного теории: В Lineage II диалоги как правило представлены в формате html документов. Текст текущего открытого диалога можно узнать с помощью Engine.DlgText - его можно просто распечатать. Для простоты просмотра можно так же использовать готовый плагин Script Recorder. Ну а еще в самом Adrenalin'e есть снифер: https://youtu.be/qMHKAXsZsa8 (пример для бафа через Alt+B), но об этом чуть ниже
    Например диалог с ГК в Годдарте:
    <html>     <body>         Хранитель Портала Татьяна:<br>         Очень приятно. Татьяна, Хранитель Портала Годдарда. Портал позволяет перемещаться на большие расстояния за считанные мгновения. Но чтобы овладеть искусством управления порталом, нужно провести в Башне Слоновой Кости десятки лет. <br>         Ну же! Назовите место, куда Вы хотите отправиться!<br>         <a action="bypass -h teleport_request">Телепортироваться</a><br>         <a action="bypass -h menu_select?ask=-303&reply=518">Обменять Алмазы Иных Миров</a><br>         <a action="bypass -h menu_select?ask=-19&reply=0">[Для Дворян] Телепортироваться</a><br>         <a action="bypass -h menu_select?ask=255&reply=10" msg="811;Ипподром">Переместиться на Арену и Ипподром (Бесплатно)</a><br>         <a action="bypass -h menu_select?ask=-1816&reply=3" msg="811;Остров Грез">Переместиться на Остров Грез (Бесплатно)</a><br>         <a action="bypass -h menu_select?ask=20003&reply=1">Призвать Аллегрию</a><br>         <a action="bypass -h talk_select">Квест</a>     </body> </html> Обратим внимание на теги <a> внутри которых есть то самое слово bypass, остановимся на первой же строке: 
    <a action="bypass -h teleport_request">Телепортироваться</a><br>Данный диалог может быть выбран тремя различными способами:
    Engine.DlgSel(1); // по номеру строки Engine.DlgSel('Телепортироваться'); // по тексту в строке Engine.BypassToServer('teleport_request'); // с помощью bypassС первыми двумя надеюсь всем понятно, рассмотрим что же происходит в 3ем случае?
    <a action="bypass -h teleport_request"> - как видно, при выборе этой строки произойдет некоторое дейсвтие типа bypass, которое условно говоря "несет в себе суть" teleport_request.
    Рассмотрим еще случай, когда диалог представлен в виде кнопок, у нас будут строчки вида:
    <button action="bypass -h npc_268448112_Olympiad 1" value="Наблюдать" width=200 height=31 back="L2UI_CT1.OlympiadWnd_DF_Watch_Down" fore="L2UI_CT1.OlympiadWnd_DF_Watch">Несмотря на чуть более сложную структуру, суть абсолютно та же самая: есть некая кнопка (до этого была ссылка), которой приписано action="bypass -h npc_268448112_Olympiad 1". Название строки теперь хранится в свойстве value, собственно это единственное отличие. Забегая наперед, отмечу, что свойство action не всегда располагается левее свойства value.
     
    Таким образом, для того, чтобы использовать Engine.BypassToServer, нужно запомнить пару пунктов:
    для отправки подходят только сообщения, в которых есть слово bypass -h копировать не нужнокопировать нужно все что после -h и вплоть до закрывающей двойной кавычкиесли на конце bypass'а есть .htm, то необходимо вторым параметром подавать true:Engine.BypassToServer('Quest 621_EggDelivery 31521-1.htm', true);Как говорил выше, в самом боте есть снифер, на видео показано, как можно получать прям готовые значения подаваемых в функцию аргументов.
    Таким образом, для максимально эффективного использования данной функции будет полезно уметь парсить текст, возвращаемый в Engine.DlgText - так можно будет обойти проблемы и с динамически меняющимися диалогами и некоторыми капчами.
    • 2 replies
    • 4,104 views
  24. farmwl added a topic in L2Adrenalin   

    Коротко о PostMessage \ SendMessage
    Вообще SendMessage и PostMessage - две Win API функции, которые доступны не только в скрипт движке бота.
    В нашем случае речь пойдет об их врапперах (обертках): Engine.SendMessage и Engine.PostMessage
    Начнем как обычно с вопроса - что они делают?
    Данные функции посылают некоторое сообщение одному или нескольким окнам. Важен тот факт, что отправлять сообщения можно и в свернутые окна! Разница между ними в том, что SendMessage отправляет сообщение и ждет, пока целевое окно это сообщение обработает, а PostMessage просто помещает сообщение в очередь и программа работает дальше. В случае, когда в сообщении задействованы указатели на динамически размещаемые данные, предпочтительно использовать SendMessage, т.к. иначе возможна ситуация, когда целевое окно начнет обрабатывать сообщение, указатели уже окажутся освобождены. Вообще, в обеих функциях требуется дескриптор (HWND) целевого окна, но т.к. у мы рассматриваем обертки в виде команд скрипт движка - то там автоматически будет указан дескриптор текущего окна с игрой.
    Что такое сообщение?
    Это информация о некотором изменении в пользовательском интерфейсе, например перемещение окна или нажатие клавиши на клавиатуре\мышке. Сообщения также уведомляют программу, что истек заданный отрезок времени. Сообщения используются для операций с совместным использованием данных. С точки зрения программирования, сообщение - это целое значение без знака (Cardinal).
    Сообщение можно представить следующей записью:
    Message = record msg : longint; // номер сообщения lParam : longint; // информационные wParam : longint; // поля end;В полях lParam и wParam содержится дополнительная информация о происшедшем событии, например, для сообщения wm_lbuttondown (нажатие ЛКМ) в lParam содержатся координаты указателя мыши момент нажатия кнопки мыши, в wParam содержатся сведения были ли нажаты клавиши Ctrl или Shift в момент нажатия кнопки мыши.
    Зачем это все нужно?
    С помощью этих команд можно реализовать свой кликер, например для заточки вещей и подобных задач. Кроме того можно вводить текст с клавиатуры, хотя для этого есть более удобная команда Engine.EnterText
    Как это использовать?
    Для того, чтобы послать сообщение, нужно знать что именно ты посылаешь, поэтому читаем документацию, гуглим и напрягаемся.
    Сразу стоит отметить, что в скрипте нужно будет указывать именно код сообщения, т.е. число:
    Engine.SendMessage($102, 65, 0);Здесь $102 - это WM_CHAR message, 65 - код кнопки A, 0 - в зависимости от значения третьего параметра, он может иметь разный смысл, об этом как правило пишут там же, где и описание сообщения
    • 0 replies
    • 2,229 views
  25. farmwl added a post in a topic Проблемы \ решения   

    обычно, при установке новых хроник требуется чуть больше времени на обновление, больше ничего принципиального