L2PacketHack Форум программы L2PacketHack, всё что с ней связано находится тут.
Правила раздела! Категорически запрещено:
* Просить пакеты/скрипты на шмот/адену/другие вещи;
* Просить (помочь) взломать/сломать сервак/аккаунт или раздеть/наказать кого-то на любом серваке;
* Просить научить работать с программой, если не понимаете элементарных вещей в отношениях клиент-сервер (так как, если вы их понимаете, то вопросов по основным возможностям программы быть недолжно);
* Все посты не удовлетворяющие этим запретам, а так же не относящиеся к теме будут удаляться при первой возможности.
* Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы.
* Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.
* Данные запреты неподлежат обсуждению.
Обсуждение багов Lineage ЗАПРЕЩЕНО!
12.04.2009, 01:00
#21
Новичок
Регистрация: 09.04.2009
Сообщений: 8
Сказал Спасибо: 4
Имеет 0 спасибок в 0 сообщенях
дык.....а я и не просил волкера для кача........меня интересует манор на данный момент...т.к. выкачал уже кучу чаров и саппортов сам в ФОГе
Спасибо конечно)
12.04.2009, 01:53
#22
Местный
Регистрация: 31.01.2008
Сообщений: 151
Сказал Спасибо: 25
Имеет 40 спасибок в 35 сообщенях
DashKAaa , ты экономику какого серва, еще не успел заставить работать на свой карман? xD
12.04.2009, 02:58
#23
Рыцарь
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
Проверил сегодня, что там с Абиссом. Все пакеты, я так понял, форматом от грации, только айди серверных пакетов почему то остались от интерлюда.
Поэтому, у кого есть желание, в скриптах для грации просто смените айди серверных пакетов с грации на интерлюд.
Для проверки исправил скрипт рыбалки для грации, теперь он записывает маршрут, бегает по нему в обе стороны, видит инвентарь.
За это сообщение NLObP нажился 3 спасибками от:
12.04.2009, 10:24
#24
Заблокирован
Регистрация: 10.03.2008
Адрес: Тула
Сообщений: 1,098
Сказал Спасибо: 188
Имеет 108 спасибок в 60 сообщенях
Цитата:
Сообщение от
NLObP
Проверил сегодня, что там с Абиссом. Все пакеты, я так понял, форматом от грации, только айди серверных пакетов почему то остались от интерлюда.
Поэтому, у кого есть желание, в скриптах для грации просто смените айди серверных пакетов с грации на интерлюд.
Для проверки исправил скрипт рыбалки для грации, теперь он записывает маршрут, бегает по нему в обе стороны, видит инвентарь.
Хмм... пойду помучаю... скрипт локомотива для интерлюда.. он то работает... но я его запустить не могу, т.к в чат команду Pos не воспринимает! хотя мобов вокруг видит.... хчоу перенастроить что бы не с пос команды понимал, а с социального действия.. так вот не получается(
Добавлено через 4 минуты
Цитата:
Сообщение от
dfackk
DashKAaa , ты экономику какого серва, еще не успел заставить работать на свой карман? xD
Да... я... не ботоводер, я так любитель......
Последний раз редактировалось DashKAaa, 12.04.2009 в 10:26 .
Причина: Добавлено сообщение
12.04.2009, 15:42
#25
Рыцарь
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
Цитата:
Сообщение от
DashKAaa
скрипт локомотива для интерлюда
Наоборот, возьми этот же скрипт для грации и серверные ID пакетов поменяй на ID от интерлюдии.
12.04.2009, 17:16
#26
Заблокирован
Регистрация: 10.03.2008
Адрес: Тула
Сообщений: 1,098
Сказал Спасибо: 188
Имеет 108 спасибок в 60 сообщенях
Угу.. сделал.. видит мобов, но все тажа проблема.. не понимает команды с чата((
т.е пишу команды (центра кача, а в ответ балда...) по этому и хотел переделать так что бы не писать надо было команду, а социальное действие нажимать... (мобов ид.. фиг с ними.. еще взять можно где либо, т.е 1.2.3.4.5.6 (забивать мобов не надо) вообщем.. вот такая вот задница ((
это если локомотив не работает... еще надо будет переделывать скрипт на лечение на буфф.. ппц, хотя бы с локомотивом разобраться бы (
12.04.2009, 21:35
#27
Новичок
Регистрация: 10.04.2009
Сообщений: 2
Сказал Спасибо: 0
Имеет 0 спасибок в 0 сообщенях
Кстати кто подскажет, из-за чего может пакет хак зависать ?никакие скрипты не включены
Добавлено через 10 минут
Кстати а как вариант не поможет, если скрипт для интерлюдии заменить клиентские интерлюдские пакеты на пакеты для грации ?
Последний раз редактировалось CKuMuHoK, 12.04.2009 в 21:35 .
Причина: Добавлено сообщение
12.04.2009, 21:46
#28
Рыцарь
Регистрация: 07.03.2009
Сообщений: 9,139
Сказал Спасибо: 70
Имеет 2,820 спасибок в 1,735 сообщенях
Зависать, из за циклов и дезлоков. в принципе как и все прилоежения.
а вот информацию чтобы люди смогли воспроизвести эти "зависания" и поправить по возможности, дать не судьба ?
__________________
L2Ext - project closed.
13.04.2009, 04:12
#29
Рыцарь
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
Пробуйте бота:
Бот Алексус для Абисса
delphi Код:
Const ProgramName =
'Бот - локомотив от Alexus ' +
'версия : 0.5.2 (for Abyss) ' +
'дата: 13.04.09' ;
{#############################################################################
Описание:
Бот для соло-кача в принципе любого война. По функциональности (в режиме кача) это еще не Волкер, но скрипт уже довольно умный :)
Охотиться только на заданных мобов.
Возможности:
- запоминает центр и радиус кача
- запоминает список мобов на которых надо охотиться!
- запоминает и затем подбирает дроп, упавший с убитых им мобов
- умеет лечиться банками (тип банки легко настраивается), ведется учет количества оставшихся банок
- управляется из окна чата в самом клиенте
- имеет окно для вывода всех параметров и статистики
- если моб по какой-то причине стал недосягаемым (стоит за деревом), то через 1 мин БОТ переключится на другого моба.
- если бот умирает, то не палимся и прекращаем рыпаться...(скоро появиться возможность логаута)
- пьет баф-банки
- работает под РУ-ОФФ Gracia, но для этого нужно обойти щит-консоль
- умеет спойлить (функция новая, нужно тестить)
Недостатки: (со временем будет исправлено)
- бот не умеет обходить препядствия
История версий:
0.1 - самое начало :)
0.2 - куча глюков, первая рабочая версия!
0.3 - первая стабильная безглючная версия, с минимальной функциональностью (самая стабильная, но очень простая)
0.4 - изменения:
- радиус кача можно задать в секции настройки
- бот теперь сразу видит всю локацию с самого запуска скрипта
- автоопределение размера инвентаря
- ID мобов можно теперь задавать в секции настройки
- ускорен процесс добавление мобов через клиент (теперь их не надо гасить)
- отключена ф-ция автоопределения своего ID и инвентаря, по этому запускать теперь бот надо до запуска клиента
- обновлено окно вывода информации (теперь его нельзя случайно закрыть!)
- на форму добавлены кнопки управления
- добавлена кнопка "Init" в окно управления, теперь бота можно запускать в любом месте, затем нажать эту кнопку
- добавлен механизм глотания баф-банок
- оптимизирован алгоритм выбора ближайшего моба
- скрипт доработан для новых версий пакетхака (данная версия разработана под пакетхак версии 3.4.1.69)
- в режиме кача, при отсутствии мобов в радиусе, бот возвращается в центр кача
- устранена ошибка, связянная с неправильным распознованием пакета 01 - MoveToLocation
0.5 - модификация под РУ-ОФФ Gracia
- добавлен споил
- убрана ошибка, вылезающая после нажатия кнопки Init
- немного подправлен алгоритм работы с инвентарем
Инструкция:
1. Внимательно НАСТРАИВАЕМ параметры в секции настройки
(90% ошибок и последующих глюков в скрипте вылезает именно отсюда!!!), жмем кнопку "Сохранить"
2. Запускаем ПакетХак, запускаем скрипт, запускаем игрового клиента.
либо запускаем скрипт после захода в игру, и жмем кнопку на форме "Init"
3. Добираемся до места кача
4. Выбираем в таргет моба на которого хотим охотится и отправляем в общий чат-> 1
5. Выбираем следующего моба отправляем в общий чат цифру 2, и т.д. можно выбрать до 10 разных тварей.
6. Либо просто в секции настройки задаем ID мобов
7. Становимся в центр кача и отправляем в общий чат-> pos , если все правильно то в чате будет выдано сообщение, что координаты заданы.
8. Бежим к краю радиуса кача и отправляем в общий чат-> dist, в чате вылезет сообщение от системы, что радиус задан.
9. Если радиус кача задан в секции настройки, то п.7 и 8 можно пропустить!!! становимся примерно в центр кача и отправляем в общий чат-> start ,
если все сделано верно, то будет выдано соответствующее сообщение.
10.Если бот поймал моба в таргет и побежал его атаковать, то можно свернуть окно игры
и смотреть на информационное окно скрипта.
В процессе кача, в общий чат можно посылать следующие управляющие команды:
pause - пауза, можно приостановить бота, повторная комманда pause запустит бота
stop - срочная остановка бота, и сброс всех настроек, повторный запуск возможен командой start
Также можно управлять ботом одноименными кнопками с формы.
#############################################################################}
//################### Сеция настройки бота ############################################
NickName = 'NLObP' ; // Твой ник в игре
CharNumber = 0 ; // если больше одного перса на аккаунте, то задаем его порядковый номер, нумерация начинается с нуля.
Radius_Kacha = 2000 ; // Радиус кача, если 0 - то задавать вручную через клиента (изменять от 100 до 9999). Проверил на практике, что максимум не более 2000.
Spoil = false ; // Споил false - откл, true - вкл. (только для гномов-спойлеров)
//-------------------------------------------------------------------------------------
HPLevel = 70 ; // Уровень жизни в %, при котором начинаем глотать банки
HPBottleID = 0 ; // ItemID 1060=Lesser Healing Potion; 1061=Healing Potion; 1539=Greater Healing Potion;
DrinkDelay = 14 ; // минимальное время задержки повторного питься HP-бутылки (10 - 20 сек).
//---------------------------------------------------------------------------------------
Bottle_1 _ID = 0 ; // ID номера баф-банок, 6036=Greater Magic Haste Potion, 6035=Magic Haste Potion, 1374=Greater Haste Potion, 1062=Haste Potion, 734=Haste Potion
Bottle_2 _ID = 0 ; // если 0 - то не использовать. 1375=Greater Swift Attack Potion, 735=Potion of Alacrity
Bottle_Interval = 19 ; // Время задержки повторного использования бутылей в минутах (изменять от 1 до 100)
//----------------------------------------------------------------------------------------
//############# Секция расширенной настройки для опытных ботоводеров :) ###################################
TimerCombat_Interval = 500 ; // частота срабатывания таймера атаки в милисекундах, чем меньше это число, тем быстрее бот будет думать.
TimerPickUp_Interval = 500 ; // частота срабатывания таймера сбора дропа, чем меньше это число, тем быстрее бот будет думать.
TimerForm_Interval = 2500 ; // частота срабатывания таймера обновления формы, чем меньше это число, тем быстрее будут обновляться данные в форме.
Attack_Time = 45 ; // Время на убивание моба в секундах.
PickUp_Time = 15 ; // Врямя на поднятие дропа в секундах.
Vertical = 1000 ; // Вертикальный радиус кача
//---------------------------------------------------------------------------------------
NpcTypeID1 = 0 ; // Если знаем, то задаем Type ID мобов, на которых будем охотиться
NpcTypeID2 = 0 ; // Если здесь одни нули, то задавать мобов будем через клиента
NpcTypeID3 = 0 ; // Для интерлюда задаем в формате 102xxxx , где xxxx - ID моба
NpcTypeID4 = 0 ; // Для С4 в формате 100хххх , где xxxx - ID моба
NpcTypeID5 = 0 ; // Для Gracia формат пока не смотрел...
NpcTypeID6 = 0 ;
NpcTypeID7 = 0 ;
NpcTypeID8 = 0 ;
NpcTypeID9 = 0 ;
NpcTypeID10 =0 ;
//########################################################################################
NpcTypeID_List_Razmer = 10 ; // Размер списка мобов (не трогать!)
OX = 1 ; OY = 2 ; OZ= 3 ; // Служебные константы
maximumItems = 500 ; // Размер базы мобов и дропа.
OblastVidimosti = 500000 ; // (не трогать!!!) Область видимости объектов (изменять от 1000 до 500000).
InvRazmer = 249 ; // Размер инвентаря (не трогать)
var
InitMode, RestartMode, PickUpMode : boolean ;
//-------------------------------------- БД --------------------------------------------------
MobsObjID : array [1 ..maximumItems ] of integer ; // ID моба
MobsNpcTypeID : array [1 ..maximumItems ] of integer ; // Тип моба
MobsDist : array [1 ..maximumItems ] of integer ; // Расстояние от центра кача до моба
MobsXYZ : array [1 ..maximumItems , 1 ..3 ] of integer ; // Координаты
MobsIsAttackable : array [1 ..maximumItems ] of boolean ; // Можно ли моба атаковать
MobsAgression : array [1 ..maximumItems ] of boolean ; // Моб атакует меня или стоит в сторонке...
MobsUpdated : array [1 ..maximumItems ] of boolean ; // Метка об обновлении моба
MobsLastIndex: integer ; // индекс последнего элемента базы
NpcTypeID_List : array [1 ..NpcTypeID_List_Razmer ] of integer ; // Список мобов (коды мобов)
NpcTypeID_List_Count : integer ; // Текущий размер списка
NpcTypeID_CurrentMob : integer ;
Items_ObjectID : array [1 ..maximumItems ] of integer ; // БД дропа с мобов
Items_ItemID : array [1 ..maximumItems ] of integer ;
Items_XYZ : array [1 ..maximumItems , 1 ..3 ] of integer ;
ItemsLastIndex: integer ;
Inventory: array[0 ..InvRazmer , 0 ..9 ] of integer ; // инвентарь (itemType1, ObjectID, ItemID, count, itemType2, CustType1, isEquipped, BodyPart, EnchantLevel, CustType2)
CurrentInvRazmer : integer ;
HPBottleObjID, HPBottleCount : integer ; // ObjID и количество HP-бутылей
Bottle_1 _ObjID, Bottle_1 _Count : integer ;
Bottle_2 _ObjID, Bottle_2 _Count : integer ;
TargetID, LastKilledMobObjID : integer ; // Текущая цель, последний убитый моб
MobsKilled : integer ; // счетчик убитых мобов
CenterX, CenterY, CenterZ : integer ; // Центр кача
CenterFixed : boolean ;
Radius: integer ; // Радиус кача
//--------------------------------------------------------
MyX, MyY, MyZ : integer ; // Мои статы
MyID, MyHP, MyMaxHP: integer ;
MyMP, MyMaxMP, MyCP, MyMaxCP: integer ;
HPlevelProcent : integer ; // уровень жизни в процентах
//--------------------------------------------------------
frm: TForm; // переменные описания формы
log, MobsDBscreen, ItemsDBScreen: TMemo;
panel: TPanel;
btnInit, btnStart, btnStop, btnPause: TButton;
frmParamIndex: byte ;
textX, textY, textZ, textMyID, textMyHP, textMyMaxHP: TEdit;
textMyMP, textMyMaxMP, textMyCP, textMyMaxCP: TEdit;
textCenterX, textCenterY, textCenterZ, textRadius : TEdit;
textTargetID, textMobX, textMobY, textMobZ : TEdit;
textAttackCycle, textMobsLastIndex, textMobsKilled: TEdit;
textHPBottleCount, textBottle_1 _Count, textBottle_2 _Count: TEdit;
cbFilterRadius : TCheckBox; l1: Tlabel;
//----------------------------------------------------------
TimerForm, TimerCombat, TimerPickUp, TimerBafBanka, TimerCheckDB : TTimer; // таймеры
time1: integer ;
Calculated_AttackTime, Calculated_PickUpTime : integer ;
AttackCycle: integer ; // Цикл атаки
Spoiled: boolean ;
//##############################################################################################
procedure Init; //Вызывается при включении скрипта
var
i,n : integer ;
begin
MyID:= 0 ; // обнуляем ВСЕ данные
MyX:= 0 ;
MyY:= 0 ;
MyZ:= 0 ;
MyID:= 0 ;
MyHP:= 0 ;
MyMaxHP:= 0 ;
MyMP:= 0 ;
MyMaxMP:= 0 ;
MyCP:= 0 ;
MyMaxCP:= 0 ;
time1:=1 ;
Calculated_AttackTime:= round ( 1000 / TimerCombat_Interval * Attack_Time) ;
Calculated_PickUpTime:= round ( 1000 / TimerPickUp_Interval * PickUp_Time) ;
HPlevelProcent:= 0 ;
HPBottleObjID:= 0 ;
HPBottleCount:= 0 ;
Bottle_1 _ObjID:= 0 ;
Bottle_1 _Count:= 0 ;
Bottle_2 _ObjID:= 0 ;
Bottle_2 _Count:= 0 ;
InitMode:= true ;
RestartMode:= false ;
MobsLastIndex:= 0 ;
for i:=1 to maximumItems do // Очищаем базу
begin
MobsObjID[i]:= 0 ;
MobsNpcTypeID[i]:=0 ;
MobsDist[i]:= 0 ;
MobsXYZ[i, OX]:= 0 ;
MobsXYZ[i, OY]:= 0 ;
MobsXYZ[i, OZ]:= 0 ;
MobsIsAttackable[i]:= false ;
MobsAgression[i]:= false ;
MobsUpdated[i]:=false ;
end ;
for i:=0 to InvRazmer do for n:=0 to 9 do Inventory[i, n]:= 0 ;
CurrentInvRazmer:=0 ;
TimerCombat:=TTimer.Create ( nil ) ; // создаем таймеры
TimerCombat.OnTimer :=@OnTimerCombat;
TimerCombat.enabled :=false ;
TimerCombat.interval := TimerCombat_Interval;
TimerForm:=TTimer.Create ( nil ) ;
TimerForm.OnTimer :=@OnTimerForm;
TimerForm.enabled :=true ;
TimerForm.interval := TimerForm_Interval;
TimerPickUp:=TTimer.Create ( nil ) ;
TimerPickUp.OnTimer :=@OnTimerPickUp;
TimerPickUp.enabled :=false ;
TimerPickUp.interval := TimerPickUp_Interval;
TimerBafBanka:=TTimer.Create ( nil ) ;
TimerBafBanka.OnTimer :=@OnTimerBafBanka;
TimerBafBanka.enabled :=false ;
TimerBafBanka.interval := 15000 ;
TimerCheckDB:=TTimer.Create ( nil ) ;
TimerCheckDB.OnTimer :=@OnTimerCheckDB;
TimerCheckDB.enabled :=true ;
TimerCheckDB.interval := 20 *60 *1000 ; // раз в 20 минут
frmParamIndex:=0 ; // создаем контролы в форме
frm:= TForm.Create ( nil ) ;
frm.Caption := ProgramName;
frm.BorderStyle := bsDialog;
frm.Position := poScreenCenter;
frm.Width :=650 ;
frm.Height :=700 ;
frm.OnClose := @FormClose;
MobsDBscreen:=TMemo.Create ( frm) ;
MobsDBscreen.parent :=frm;
MobsDBscreen.ReadOnly :=true ;
MobsDBscreen.ScrollBars :=0 ;
MobsDBscreen.Top :=157 ;
MobsDBscreen.Width :=457 ;
MobsDBscreen.Height :=385 ;
ItemsDBscreen:=TMemo.Create ( frm) ;
ItemsDBscreen.parent :=frm;
ItemsDBscreen.ReadOnly :=true ;
ItemsDBscreen.ScrollBars :=0 ;
ItemsDBscreen.Top :=1 ;
ItemsDBscreen.Width :=300 ;
ItemsDBscreen.Height :=155 ;
panel:=TPanel.Create ( frm) ;
panel.parent :=frm;
panel.align :=alRight;
log:=TMemo.Create ( panel) ;
log.parent :=frm;
log.align :=alBottom;
log.ReadOnly :=true ;
log.ScrollBars :=2 ;
log.Width :=570 ;
log.Height :=100 ;
log.Lines .Add ( 'Лог...' ) ;
btnInit:= TButton.Create ( frm) ;
btnInit.Name := 'btnInit' ;
btnInit.Parent := frm;
btnInit.SetBounds ( 370 , 10 , 75 , 25 ) ;
btnInit.Caption := 'Init' ;
btnInit.OnClick := @BtnInit_Click;
btnStart:= TButton.Create ( frm) ;
btnStart.Name := 'btnStart' ;
btnStart.Parent := frm;
btnStart.SetBounds ( 370 , 40 , 75 , 25 ) ;
btnStart.Caption := 'Start' ;
btnStart.OnClick := @btnStart_Click;
btnStop:= TButton.Create ( frm) ;
btnStop.Name := 'btnStop' ;
btnStop.Parent := frm;
btnStop.SetBounds ( 370 , 70 , 75 , 25 ) ;
btnStop.Caption := 'Stop' ;
btnStop.OnClick := @btnStop_Click;
btnPause:= TButton.Create ( frm) ;
btnPause.Name := 'btnPause' ;
btnPause.Parent := frm;
btnPause.SetBounds ( 370 , 100 , 75 , 25 ) ;
btnPause.Caption := 'Pause' ;
btnPause.OnClick := @btnPause_Click;
l1:= TLabel.Create ( frm) ;
l1.caption :='Фильтры:' ;
l1.parent :=frm;
l1.SetBounds ( 5 , 547 , 97 , 17 ) ;
cbFilterRadius := TCheckBox.Create ( frm) ;
cbFilterRadius.Name := 'cbFilterRadius' ;
cbFilterRadius.Parent := frm;
cbFilterRadius.SetBounds ( 60 , 545 , 97 , 17 ) ;
cbFilterRadius.Caption := 'Радиус' ;
// cbFilterRadius.OnClick := @CheckBoxFilterClick;
textMyID:= CreateTextBox( 'textMyID' ) ;
CreateLabel( 'Мой ID :' ) ;
textX:= CreateTextBox( 'textX' ) ;
CreateLabel( 'Мой X :' ) ;
textY:= CreateTextBox( 'textY' ) ;
CreateLabel( 'Мой Y :' ) ;
textZ:= CreateTextBox( 'textZ' ) ;
CreateLabel( 'Мой Z :' ) ;
textMyHP:= CreateTextBox( 'textMyHP' ) ;
CreateLabel( 'Мой HP :' ) ;
textMyMaxHP:= CreateTextBox( 'textMyMaxHP' ) ;
CreateLabel( 'Мой MaxHP :' ) ;
textMyMP:= CreateTextBox( 'textMyMP' ) ;
CreateLabel( 'Мой MP :' ) ;
textMyMaxMP:= CreateTextBox( 'textMyMaxMP' ) ;
CreateLabel( 'Мой MaxMP :' ) ;
// textMyCP:= CreateTextBox('textMyCP');
// CreateLabel('Мой CP :');
// textMyMaxCP:= CreateTextBox('textMyMaxCP');
// CreateLabel('Мой MaxCP :');
inc ( frmParamIndex) ;
textCenterX:= CreateTextBox( 'textCenterX' ) ;
CreateLabel( 'Ц. кач Х:' ) ;
textCenterY:= CreateTextBox( 'textCenterY' ) ;
CreateLabel( 'Ц. кач Y:' ) ;
textCenterZ:= CreateTextBox( 'textCenterZ' ) ;
CreateLabel( 'Ц. кач Z:' ) ;
textRadius:= CreateTextBox( 'Radius' ) ;
CreateLabel( 'Radius :' ) ;
inc ( frmParamIndex) ;
textTargetID:= CreateTextBox( 'TargetID' ) ;
CreateLabel( 'Цель ID :' ) ;
textAttackCycle:= CreateTextBox( 'AttackCycle' ) ;
CreateLabel( 'Цикл атаки:' ) ;
textMobsLastIndex:= CreateTextBox( 'MobsLastIndex' ) ;
CreateLabel( 'Мобов в БД:' ) ;
textMobsKilled:= CreateTextBox( 'MobsKilled' ) ;
CreateLabel( 'Убито моб:' ) ;
inc ( frmParamIndex) ;
textHPBottleCount:= CreateTextBox( 'HPBottleCount' ) ;
CreateLabel( 'HP бутылей:' ) ;
textBottle_1 _Count:= CreateTextBox( 'Bottle_1_Count' ) ;
CreateLabel( 'Баф-Банки 1:' ) ;
textBottle_2 _Count:= CreateTextBox( 'Bottle_2_Count' ) ;
CreateLabel( 'Баф-Банки 2:' ) ;
ClearDB;
frm.Show ; // выводим форму на экран
buf:=#$6E;
SendToServerEx( NickName) ;
end ;
procedure btnPause_Click( Sender: TButton) ;
begin
PauseGame;
end ;
procedure btnStop_Click( Sender: TButton) ;
begin
StopGame;
end ;
procedure btnStart_Click( Sender: TButton) ;
begin
StartGame;
end ;
procedure BtnInit_Click( Sender: TButton) ;
begin
RestartMode:= true ;
buf:= #$57 ; // авто релогин
// buf:= #$0F; // принудительно вызываем пакеты инвентаря и userinfo
SendToServerEx( NickName) ;
end ;
procedure AddtoNpcTypeID_List ( NpcTypeID: integer ) ;
begin
inc ( NpcTypeID_List_Count) ;
NpcTypeID_List[NpcTypeID_List_Count]:= NpcTypeID;
end ;
procedure ClearDB; // Очистка БД
var // Надо все занулять, иначе там хрень всякая вылезает или старые данные
i : integer ;
begin
ItemsLastIndex:= 0 ; // Очищаем переменные
TargetID:= 0 ;
LastKilledMobObjID:= 0 ;
MobsKilled:= 0 ;
CenterX:= 0 ;
CenterY:= 0 ;
CenterZ:= 0 ;
CenterFixed:= false ;
Radius:= Radius_Kacha;
TimerBafBanka.interval := 15000 ;
AttackCycle:= 0 ;
Spoiled:= false ;
NpcTypeID_List_Count:= 0 ;
if NpcTypeID1 <> 0 then AddtoNpcTypeID_List ( NpcTypeID1) ;
if NpcTypeID2 <> 0 then AddtoNpcTypeID_List ( NpcTypeID2) ;
if NpcTypeID3 <> 0 then AddtoNpcTypeID_List ( NpcTypeID3) ;
if NpcTypeID4 <> 0 then AddtoNpcTypeID_List ( NpcTypeID4) ;
if NpcTypeID5 <> 0 then AddtoNpcTypeID_List ( NpcTypeID5) ;
if NpcTypeID6 <> 0 then AddtoNpcTypeID_List ( NpcTypeID6) ;
if NpcTypeID7 <> 0 then AddtoNpcTypeID_List ( NpcTypeID7) ;
if NpcTypeID8 <> 0 then AddtoNpcTypeID_List ( NpcTypeID8) ;
if NpcTypeID9 <> 0 then AddtoNpcTypeID_List ( NpcTypeID9) ;
if NpcTypeID10<> 0 then AddtoNpcTypeID_List ( NpcTypeID10) ;
if NpcTypeID_List_Count = 0 then
for i:=1 to NpcTypeID_List_Razmer do NpcTypeID_List[i]:= 0 ;
NpcTypeID_CurrentMob:= 0 ;
for i:=1 to maximumItems do // Очищаем базу
begin
Items_ObjectID[i]:= 0 ;
Items_ItemID[i]:= 0 ;
Items_XYZ[i, OX]:= 0 ;
Items_XYZ[i, OY]:= 0 ;
Items_XYZ[i, OZ]:= 0 ;
end ;
btnStop.enabled :=false ;
btnPause.enabled := false ;
end ;
function Wait( var tick: integer ; Timewait: Integer ) : Boolean ; // сквозная проверка без остановки скрипта (c)dmitry501, modifed by Sh00rGo
var
t: integer ;
begin
result:=false ;
t:=Round ( Time *86400 ) ;
if t>( tick+Timewait) then begin
if tick>0 then result:=true ;
tick:=t;
end ;
end ;
//############################## Модуль работы с Инвентарем ###########################
procedure InventoryCreate;
var
i,k, offset : integer ;
begin
offset:= 76 ;
CurrentInvRazmer:=ReadH( 4 ) ;
for i:=0 to InvRazmer do
if i < CurrentInvRazmer then begin
Inventory[i,0 ]:=ReadH( i*offset+6 ) ; // itemType1
Inventory[i,1 ]:=ReadD( i*offset+8 ) ; // ObjectId
Inventory[i,2 ]:=ReadD( i*offset+12 ) ; // ItemID
Inventory[i,3 ]:=ReadD( i*offset+20 ) ; // count
Inventory[i,4 ]:=ReadH( i*offset+24 ) ; // itemType2
Inventory[i,5 ]:=ReadH( i*offset+26 ) ; // CustType1
Inventory[i,6 ]:=ReadH( i*offset+28 ) ; // isEquipped
Inventory[i,7 ]:=ReadD( i*offset+30 ) ; // BodyPart
Inventory[i,8 ]:=ReadH( i*offset+34 ) ; // EnchantLevel
Inventory[i,9 ]:=ReadH( i*offset+36 ) ; // CustType2
end else
for k:=0 to 9 do Inventory[i,k]:=0 ; // забиваем нулями
end ;
procedure InventoryUpdate;
var
i,j,k, offset: integer ;
begin
offset:= 82 ;
for j:=0 to ( ReadH( 2 ) -1 ) do
begin
case pck[j*offset+4 ] of
#$01 : k:=0 ; // add item, запишет на пустую ячейку
#$02 : k:=ReadD( j*offset+8 ) ; // mod item
#$03 : begin // remove item, обнулит ячейки удаленного предмета
k:=ReadD( j*offset+8 ) ;
for i:=0 to InvRazmer do if ( Inventory[i,1 ]=k) then
begin
for k:=0 to 9 do Inventory[i,k]:=0 ;
exit ;
end ;
end ;
end ;
for i:=0 to InvRazmer do if ( Inventory[i,1 ]=k) then
begin
Inventory[i,0 ]:=ReadH( j*offset+6 ) ; // itemType1
Inventory[i,1 ]:=ReadD( j*offset+8 ) ; // ObjectId
Inventory[i,2 ]:=ReadD( j*offset+12 ) ; // ItemID
Inventory[i,3 ]:=ReadD( j*offset+20 ) ; // count
Inventory[i,4 ]:=ReadH( j*offset+24 ) ; // itemType2
Inventory[i,5 ]:=ReadH( j*offset+26 ) ; // CustType1
Inventory[i,6 ]:=ReadH( j*offset+28 ) ; // isEquipped
Inventory[i,7 ]:=ReadD( j*offset+30 ) ; // BodyPart
Inventory[i,8 ]:=ReadH( j*offset+34 ) ; // EnchantLevel
Inventory[i,9 ]:=ReadH( j*offset+36 ) ; // CustType2
break ;
end ;
end ;
end ;
function GetInv( obj,up,down:integer ) : integer ; // up и down не проверяются
var // 0-itemType1, 1-ObjectId, 2-ItemID, 3-count, 4-itemType2, 5-CustType1, 6-isEquipped, 7-BodyPart, 8-EnchantLevel, 9-CustType2
i: integer ;
begin
for i:=0 to CurrentInvRazmer do if ( Inventory[i,up]=obj) then
begin
Result:=Inventory[i,down];
exit ;
end ;
Result:=-1 ;
end ;
{procedure UseItemID(ItemID:integer); //Использовать предмет с заданным ItemID
var
ObjItemID : integer;
begin
ObjItemID:= GetInv(ItemID,2,1);
if ObjItemID = -1 then exit;
buf:=#$14;
WriteD(ObjItemID);
WriteD(0);
SendToServerEx(NickName);;
end;}
procedure UseItemObjID( ItemObjID:integer ) ; //Использовать предмет с заданным ItemObjID
begin
buf:=#$19 ;
WriteD( ItemObjID) ;
WriteD( 0 ) ;
SendToServerEx( NickName) ;;
end ;
//############################################################################################
function rastoyanie( NpcX, NpcY, NpcZ : integer ) : longint ; // вычисление растояния между 2 точками
var
dx,dy,dz : integer ;
summa : longint ;
begin
try
dx:= NpcX-CenterX;
dy:= NpcY-CenterY;
dz:= NpcZ-CenterZ;
summa:= dx*dx+dy*dy; // мне кажется, что так будет быстрее считаться
if summa = 0 then result:= 0 else result:= Round ( sqrt ( summa) ) ; // обход возможной ошибки, если моб стоит прямо в центре кача
if abs ( dz) > vertical then result := result + OblastVidimosti; // добавляем коррекцию по вертикали
except
sendmsg( 'Ошибка вычисления расстояния' ) ;
sendmsg( 'dx= ' + inttostr ( dx) ) ;
sendmsg( 'dy= ' + inttostr ( dy) ) ;
sendmsg( 'dz= ' + inttostr ( dz) ) ;
sendmsg( 'summa= ' + inttostr ( summa) ) ;
result := OblastVidimosti;
end ;
end ;
function RastoyanieToMe( NpcX, NpcY : integer ) : integer ; // вычисление растояния между 2 точками
var
dx,dy, summa : integer ;
begin
dx:= NpcX-MyX;
dy:= NpcY-MyY;
summa:= dx*dx+dy*dy; // мне кажется, что так будет быстрее считаться
if summa = 0 then result:= 0 else result:= Round ( sqrt ( summa) ) ; // обход возможной ошибки, если моб стоит прямо в центре кача
end ;
procedure AddDroppedItem ( ObjID, ItemID, X, Y, Z: integer ) ; // Процедура добавляет дропнутую вещь в БД
begin
if ItemsLastIndex = maximumItems then ItemsLastIndex:=0 ; // обход переполнения базы предметов
inc ( ItemsLastIndex) ;
Items_ObjectID[ItemsLastIndex]:= ObjID;
Items_ItemID[ItemsLastIndex]:= ItemID;
Items_XYZ[ItemsLastIndex, OX]:= X;
Items_XYZ[ItemsLastIndex, OY]:= Y;
Items_XYZ[ItemsLastIndex, OZ]:= Z;
// log.Lines.Add('Вещь добавлена, индекс в БД: '+ inttostr(ItemsLastIndex));
end ;
procedure AddtoDB ( id, TypeID, x,y,z : integer ; IsAttackable : boolean ) ; // Процедура добавляет в БД нового моба
var
dist: integer ;
begin
if ( not initmode) then dist:= rastoyanie ( x,y,z) else dist := OblastVidimosti; // вычиляем расстояние от центра кача до моба
if dist > ( OblastVidimosti) then exit ; // если моб слишко далеко то ничего не делаем
inc ( MobsLastIndex) ; // увеличиваем размер БД
// log.Lines.Add('Моб добавлен, индекс в БД:'+ inttostr(MobsLastIndex));
// if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsObjID[MobsLastIndex]:= id; // Записываем моба
MobsNpcTypeID[MobsLastIndex]:= TypeID;
MobsDist[MobsLastIndex]:= dist;
MobsXYZ[MobsLastIndex, OX]:= x;
MobsXYZ[MobsLastIndex, OY]:= y;
MobsXYZ[MobsLastIndex, OZ]:= z;
MobsIsAttackable[MobsLastIndex]:= IsAttackable;
MobsAgression[MobsLastIndex]:= false ;
MobsUpdated[MobsLastIndex]:= true ;
end ;
procedure UpdateDB ( i, x,y,z : integer ; agression : boolean ) ; // Процедура обновляет данные в БД по мобу
var
dist: integer ;
begin
if ( not initmode) then dist:= rastoyanie ( x,y,z) else dist := OblastVidimosti;
if dist > ( OblastVidimosti) then DelDBItem( i) else // перепроверяем расстояние до моба, если он вышел за границу кача, то удаляем его
begin
// log.Lines.Add('Моб обновлен, индекс в БД:'+ inttostr(i));
// if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsDist[i]:= dist; // записываем данные
MobsXYZ[i, OX]:= x;
MobsXYZ[i, OY]:= y;
MobsXYZ[i, OZ]:= z;
if ( not MobsAgression[i]) then MobsAgression[i]:= agression;
MobsUpdated[i]:= true ;
end ;
end ;
procedure DelDBItem ( i: integer ) ; // процедура удалаяет моба из БД
begin
// log.Lines.Add('Моб удален, индекс в БД: '+ inttostr(i));
MobsObjID[i]:= 0 ;
MobsNpcTypeID[i]:= 0 ;
MobsDist[i]:= 0 ;
MobsXYZ[i, OX]:= 0 ;
MobsXYZ[i, OY]:= 0 ;
MobsXYZ[i, OZ]:= 0 ;
MobsAgression[i]:= false ;
MobsIsAttackable[i]:= false ;
MobsUpdated[i]:= false ;
if i < MobsLastIndex then // если надо, производим сдвиг данных в массивах
begin
MobsObjID[i]:= MobsObjID[MobsLastIndex];
MobsNpcTypeID[i]:= MobsNpcTypeID[MobsLastIndex];
MobsDist[i]:= MobsDist[MobsLastIndex];
MobsXYZ[i, OX]:= MobsXYZ[MobsLastIndex, OX];
MobsXYZ[i, OY]:= MobsXYZ[MobsLastIndex, OY];
MobsXYZ[i, OZ]:= MobsXYZ[MobsLastIndex, OZ];
MobsIsAttackable[i]:= MobsIsAttackable[MobsLastIndex];
MobsAgression[i]:= MobsAgression[MobsLastIndex];
MobsUpdated[i]:= MobsUpdated[MobsLastIndex];
end ;
dec ( MobsLastIndex) ; // уменьшаем размер БД
end ;
procedure DelDroppedItem ( i: integer ) ; // процедура удалаяет вещь из БД
begin
Items_ObjectID[i]:= 0 ;
Items_ItemID[i]:= 0 ;
Items_XYZ[i, OX]:= 0 ;
Items_XYZ[i, OY]:= 0 ;
Items_XYZ[i, OZ]:= 0 ;
// log.Lines.Add('Вещь удалена, индекс в БД: '+ inttostr(i));
if i < ItemsLastIndex then
begin
Items_ObjectID[i]:= Items_ObjectID[ItemsLastIndex];
Items_ItemID[i] := Items_ItemID[ItemsLastIndex];
Items_XYZ[i, OX]:= Items_XYZ[ItemsLastIndex, OX];
Items_XYZ[i, OY]:= Items_XYZ[ItemsLastIndex, OY];
Items_XYZ[i, OZ]:= Items_XYZ[ItemsLastIndex, OZ];
end ;
dec ( ItemsLastIndex) ;
end ;
function CheckItems ( id: integer ) : integer ; // функция проверяет наличие заданной вещи в БД
var
i: integer ;
begin
result:= 0 ;
for i:=1 to ItemsLastIndex do if Items_ObjectID[i] = id then
begin
result:=i; // И возвращаем его индекс по БД
break ;
end ;
end ;
function TestPovtor ( id: integer ) : integer ; // функция проверяет наличие заданного моба в БД
var
i: integer ;
begin
result:=0 ;
for i:=1 to MobsLastIndex do if MobsObjID[i] = id then // Ищем нужный ID в нашей БД
begin
result:=i; // И возвращаем его индекс по БД
break ;
end ;
end ;
function InMobsList ( NpcTypeID: integer ) : boolean ; // функция проверяет наличие заданного моба в списке на атаку
var
i: integer ;
begin
result:= false ;
for i:=1 to NpcTypeID_List_Count do if NpcTypeID_List[i] = NpcTypeID then result:= true ; // проверяем по списку
end ;
procedure SendMsg_to_CL( msg:string ) ; // отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD( 0 ) ;
WriteD( 10 ) ;
WriteS( '' ) ;
WriteS( msg) ;
SendToClientEx( NickName) ;
end ;
procedure OnTimerCheckDB ( Sender: TObject ) ;
var
i: integer ;
begin
i:=0 ;
while i <= MobsLastIndex do
begin
inc ( i) ;
if MobsUpdated[i] then MobsUpdated[i]:=false
else
begin
DelDBItem( i) ;
dec ( i) ;
end ;
end ;
end ;
procedure PrepareDB;
var
i: integer ;
//dist : double;
begin
i:=0 ;
while i <= MobsLastIndex do
begin
inc ( i) ;
if InMobsList( MobsNpcTypeID[i]) then MobsIsAttackable[i]:= true ;
MobsDist[i] := rastoyanie ( MobsXYZ[i, OX], MobsXYZ[i, OY], MobsXYZ[i, OZ]) ;
if MobsDist[i] >= OblastVidimosti then
begin
// DelDBItem(i);
// dec(i);
end ;
end ;
end ;
function ValidateData : boolean ; // функция проверки правильности задания всех параметров для начала кача
begin
if ( MyX <> 0 ) and ( MyY <> 0 ) and ( MyZ <> 0 ) and ( MyID <> 0 ) and ( MyHP > 0 ) and ( MyMaxHP > 0 ) and // верификация всех данных, чтобы потом в боевом режиме
( MyMP > 0 ) and ( MyMaxMP > 0 ) and {(MyCP <> 0) and (MyMaxCP <> 0) and } // не перепроверять все данные по 100 раз
( CenterX <> 0 ) and ( CenterY <> 0 ) and ( CenterZ <> 0 ) and ( Radius > 0 ) and ( NpcTypeID_List_Count > 0 ) then
begin
PrepareDB;
SendMsg_to_CL( 'Все начальные параметры заданы и проверены!' ) ;
log.Lines .Add ( 'Все начальные параметры заданы и проверены!' ) ;
result:= true ;
end
else
begin
SendMsg_to_CL( 'Ошибка задания начальных параметров!' ) ;
log.Lines .Add ( 'Ошибка задания начальных параметров!' ) ;
result:= false ;
end ;
end ;
procedure UserCommands; // комманды пользователя
var
i: integer ;
begin // если комманда обработана удачно, то в чат сообщение не попадет, а будет выдано системное сообщение прямо в клиент
if InitMode then case ( ReadS( 2 ) ) of
'pos' : if MyX <> 0 then // центр кача
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
CenterFixed:= true ;
SendMsg_to_CL( 'Центр кача задан успешно!' ) ;
log.Lines .Add ( 'Центр кача задан успешно!' ) ;
pck:='' ;
end ;
'dist' : if ( CenterX <> 0 ) and ( MyX <> 0 ) then // радиус кача
begin
CenterFixed:= true ;
Radius:= rastoyanie ( MyX,MyY,MyZ) ;
SendMsg_to_CL( 'Радиус кача задан успешно' ) ;
SendMsg_to_CL( 'R= ' + inttostr ( Radius) ) ;
log.Lines .Add ( 'Радиус кача задан успешно, R = ' + inttostr ( Radius) ) ;
pck:='' ;
end ;
'reset' : begin // сброс параметров
ClearDB;
SendMsg_to_CL( 'БД очищена, введите заново все параметры' ) ;
log.Lines .Add ( 'БД очищена!' ) ;
pck:='' ;
end ;
'1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' : // задаем мобов
begin
if ( NpcTypeID_List_Count+1 ) <> strtoint ( ReadS( 2 ) ) then
begin
SendMsg_to_CL( 'Добавлять мобов можно тока по очереди 1, 2, 3...' ) ;
pck:='' ;
exit ;
end ;
NpcTypeID_CurrentMob:= strtoint ( ReadS( 2 ) ) ;
SendMsg_to_CL( 'Добавляем моба № ' + ReadS( 2 ) ) ;
pck:='' ;
i:= TestPovtor ( TargetID) ;
if i > 0 then
begin
NpcTypeID_List[NpcTypeID_CurrentMob]:= MobsNpcTypeID[i];
SendMsg_to_CL( 'Моб №' + inttostr ( NpcTypeID_CurrentMob) + 'тип: ' +inttostr ( MobsNpcTypeID[i]) +' добавлен в базу' ) ;
log.Lines .Add ( 'Моб №' + inttostr ( NpcTypeID_CurrentMob) + 'тип: ' +inttostr ( MobsNpcTypeID[i]) +' добавлен в базу' ) ;
inc ( NpcTypeID_List_Count) ;
NpcTypeID_CurrentMob:= 0 ;
TargetID:= 0 ;
end ;
end ;
'start' : begin // собственно запуск бота
pck:='' ;
StartGame;
end ;
end ;
if ( not InitMode) then case ( ReadS( 2 ) ) of
'pause' : begin
pck:='' ;
PauseGame;
end ;
'stop' : begin
pck:='' ;
StopGame;
end ;
end ;
end ;
procedure PauseGame;
begin
TimerCombat.enabled := not ( TimerCombat.enabled ) ;
TimerBafBanka.enabled := not ( TimerBafBanka.enabled ) ;
if TimerCombat.enabled then
begin
btnPause.Caption :='Pause' ;
TimerBafBanka.interval := 15000 ;
SendMsg_to_CL( 'Искуственный интелект запущен!' ) ;
log.Lines .Add ( 'Искуственный интелект запущен!' ) ;
end
else
begin
btnPause.Caption :='Repeat' ;
SendMsg_to_CL( 'Искуственный интелект приостановлен.' ) ;
log.Lines .Add ( 'Искуственный интелект приостановлен.' ) ;
end ;
end ;
procedure StartGame;
begin
if ValidateData and InitMode then
begin
CenterFixed:= true ;
SendMsg_to_CL( 'ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!' ) ;
log.Lines .Add ( 'ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!' ) ;
TargetID:=0 ;
InitMode:= false ;
TimerCombat.enabled :=true ; // запускаем таймер
TimerBafBanka.interval := 15000 ;
TimerBafBanka.enabled := true ;
btnStart.enabled := false ;
btnStop.enabled := true ;
btnPause.enabled := true ;
end
else
begin
SendMsg_to_CL( 'Еще не все параметры заданы. Проверьте параметры...' ) ;
log.Lines .Add ( 'Еще не все параметры заданы. Проверьте параметры...' ) ;
end ;
end ;
procedure StopGame; // остановка кача
begin
TimerCombat.enabled := false ;
InitMode:= true ;
TimerPickUp.enabled :=false ;
TimerBafBanka.enabled :=false ;
TargetID:= 0 ;
ClearDB;
SendMsg_to_CL( 'Искуственный интелект остановлен.' ) ;
log.Lines .Add ( 'Искуственный интелект остановлен.' ) ;
btnStart.enabled := true ;
btnStop.enabled := false ;
btnPause.Caption := 'Pause' ;
btnPause.enabled :=false ;
end ;
function GetMinDistID : integer ; // функция поиска ближайшего моба в БД
var
i, Dist, MinDist : integer ;
begin
result:= 0 ;
if MobsLastIndex = 0 then exit ;
MinDist:=RastoyanieToMe( MobsXYZ[1 ,OX], MobsXYZ[1 ,OY]) ;
for i:=1 to MobsLastIndex do if ( MobsDist[i] <= Radius) and ( MobsIsAttackable[i]) then
begin
Dist:= RastoyanieToMe( MobsXYZ[i,OX], MobsXYZ[i,OY]) ;
if Dist <= MinDist then
begin
Dist:= MinDist;
result:= i;
end ; // если нашли хоть одного моба или несколько, товозращаем индекс ближайшего
end ;
end ;
function AgroTest : integer ; // функция проверяет, атакует ли меня кто-нибудь или нет
var
i: integer ;
begin
result:=0 ;
for i:=1 to MobsLastIndex do if MobsAgression[i] then // ищем первого попавшегося моба, который нас атакует
begin
result:= i; // возвращаем его индекс по БД
break ;
end ;
end ;
procedure PhisicalAttack; // команда атаки
begin
buf:=#$1F; //action
WriteD( TargetID) ;
WriteD( MyX) ;
WriteD( MyY) ;
WriteD( MyZ) ;
WriteC( 0 ) ;
SendToServerEx( NickName) ;
end ;
procedure RequestMagicSkillUse ( SkillID: integer ) ; // маг атака
begin
buf:=#$39 ;
WriteD( SkillID) ;
WriteD( 0 ) ;
WriteC( 0 ) ;
SendToServerEx( NickName) ;
end ;
procedure InitPickUpMode( mode: boolean ) ;
begin
if mode then
begin
PickUpMode:= true ;
TimerCombat.enabled := false ;
TimerPickUp.enabled := true ;
end
else
begin
PickUpMode:= false ;
TimerCombat.enabled := true ;
TimerPickUp.enabled := false ;
end ;
end ;
procedure OnTimerBafBanka ( Sender: TObject ) ; // таймер питья баф-банок
begin
if ( Bottle_1 _Count > 0 ) and ( Bottle_1 _ObjID > 0 ) then
begin
UseItemObjID( Bottle_1 _ObjID) ;
dec ( Bottle_1 _Count) ;
end ;
if ( Bottle_2 _Count > 0 ) and ( Bottle_2 _ObjID > 0 ) then
begin
UseItemObjID( Bottle_2 _ObjID) ;
dec ( Bottle_2 _Count) ;
end ;
TimerBafBanka.interval := Bottle_Interval*60 *1000 ;
end ;
procedure OnTimerPickUp ( Sender: TObject ) ; // таймер поднятия дропа
var
povtor: integer ;
begin
if ( AgroTest > 0 ) then
begin
TargetID:= 0 ;
InitPickUpMode( false ) ;
exit ;
end ;
if ( ItemsLastIndex > 0 ) and ( TargetID = 0 ) then
begin
TargetID:= Items_ObjectID[ItemsLastIndex];
AttackCycle:= 0 ;
PhisicalAttack;
exit ;
end ;
if ( ItemsLastIndex > 0 ) and ( TargetID > 0 ) then
begin
inc ( AttackCycle) ;
if ( ( AttackCycle mod 5 ) = 0 ) then PhisicalAttack;
if AttackCycle > Calculated_PickUpTime then
begin
Povtor:= CheckItems( TargetID) ;
if Povtor <> 0 then DelDroppedItem( Povtor) ;
TargetID:= 0 ;
end ;
exit ;
end ;
if ItemsLastIndex = 0 then InitPickUpMode( false ) ;
end ;
procedure OnTimerCombat ( Sender: TObject ) ; // боевой таймер, вся логика поведения бота находится именно здесь!!!
var
Agro, MinDistID, i: integer ;
begin
if TargetID > 0 then // если в прицеле есть моб, то
begin // валим вражину
if ( ( AttackCycle mod 5 ) = 0 ) then
begin
if Spoil and ( not Spoiled) then RequestMagicSkillUse( 254 ) // заспойлим моба если опция включена
else PhisicalAttack;
end ;
inc ( AttackCycle) ;
if AttackCycle > Calculated_AttackTime then // если валим моба больше минуты, значит это баг...
begin
i:= TestPovtor( TargetID) ;
if i > 0 then
begin
MobsIsAttackable[i]:= false ; //DelDBItem(i);
MobsAgression[i]:= false ;
end ;
TargetID:= 0 ;
end ;
exit ;
end ;
Agro:= AgroTest;
if Agro > 0 then // если нас кто-то атакует, то его и выбираем
begin
TargetID:= MobsObjID[Agro];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0 ;
exit ;
end ;
if ItemsLastIndex > 0 then // если чего-то валяется на земле, то
begin
InitPickUpMode( true ) ; // надо дроп подбирать
exit ;
end ;
MinDistID:= GetMinDistID; // запускаем алгоритм выбора цели
if MinDistID > 0 then // иначе ищем ближайшего
begin
TargetID:= MobsObjID[MinDistID];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0 ;
exit ;
end ;
if ( abs ( MyX-CenterX) > 20 ) and ( abs ( MyY-CenterY) > 20 ) then MoveTo ( CenterX, CenterY, CenterZ) ;
end ;
procedure MoveTo( TargetX,TargetY,TargetZ:integer ) ; //Идти в точку с координатами x,y,z
begin
buf:=#$0F; //01=MoveBackwardToLocation:d(targetX)d(targetY)d(targetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
WriteD( targetx) ; //куда
WriteD( targety) ;
WriteD( targetz) ;
WriteD( MyX) ; //откуда
WriteD( MyY) ;
WriteD( MyZ) ;
WriteD( 1 ) ; //используем 1-мышь 0-клавиатура
SendToServerEx( NickName) ;
end ;
procedure OnTimerForm ( Sender: TObject ) ; // таймер обновления данных в форме
var
i: integer ;
begin
textMyID.text := inttostr ( MyID) ; // обновляем данные в окне
textX.text := inttostr ( MyX) ;
textY.text := inttostr ( MyY) ;
textZ.text := inttostr ( MyZ) ;
textMyHP.text := inttostr ( MyHP) ;
textMyMaxHP.text := inttostr ( MyMaxHP) ;
textMyMP.text := inttostr ( MyMP) ;
textMyMaxMP.text := inttostr ( MyMaxMP) ;
// textMyCP.text:= inttostr(MyCP);
// textMyMaxCP.text:= inttostr(MyMaxCP);
textCenterX.text := inttostr ( CenterX) ;
textCenterY.text := inttostr ( CenterY) ;
textCenterZ.text := inttostr ( CenterZ) ;
textRadius.text := inttostr ( Radius) ;
textTargetID.text := inttostr ( TargetID) ;
textAttackCycle.text := inttostr ( AttackCycle) ;
textMobsLastIndex.text := inttostr ( MobsLastIndex) ;
textMobsKilled.text := inttostr ( MobsKilled) ;
textHPBottleCount.text := inttostr ( HPBottleCount) ;
textBottle_1 _Count.text := inttostr ( Bottle_1 _Count) ;
textBottle_2 _Count.text := inttostr ( Bottle_2 _Count) ;
MobsDBscreen.lines .Clear ;
for i:=1 to MobsLastIndex do // выводим БД мобов
begin
if ( TargetID = MobsObjID[i]) and MobsAgression[i] then
begin
MobsDBscreen.lines .add ( '<> ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if TargetID = MobsObjID[i] then
begin
MobsDBscreen.lines .add ( '-> ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if cbFilterRadius.checked then if MobsDist[i] <= Radius then
begin
MobsDBscreen.lines .add ( '-- ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if MobsAgression[i] then
begin
MobsDBscreen.lines .add ( '<- ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if ( not cbFilterRadius.checked ) then MobsDBscreen.lines .add ( '-- ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
end ;
ItemsDBscreen.lines .Clear ; // выводим БД дропа
for i:=1 to ItemsLastIndex do ItemsDBscreen.lines .add ( 'индекс в БД: ' +inttostr ( i) +' объект ID: ' +inttostr ( Items_ObjectID[i]) +' ID вещи: ' +inttostr ( Items_ItemID[i]) ) ;
if MobsLastIndex = 0 then MobsDBscreen.lines .add ( 'Мобы' ) ;
if ItemsLastIndex= 0 then ItemsDBscreen.lines .add ( 'Дроп' ) ;
end ;
procedure FormClose( Sender: TObject ; var Action: TCloseAction) ;
begin
Action:=caNone;
end ;
procedure CreateLabel ( text : string ) ; // процедура автоматизирует создание текстовых меток в форме
var
l: TLabel;
begin
l:= TLabel.Create ( panel) ;
l.caption :=text ;
l.parent :=panel;
l.left :=10 ;
l.top :=15 +20 *frmParamIndex;
inc ( frmParamIndex) ;
end ;
function CreateTextBox ( text :string ) :TEdit; // функция автоматизирует создание текстовых полей для вывода данных в форме
var
e: TEdit;
begin
e:= TEdit.Create ( panel) ;
e.text :=text ;
e.parent :=panel;
e.left :=80 ;
e.top :=10 +20 *frmParamIndex;
e.width := 95 ;
e.ReadOnly :=true ;
result:= e;
end ;
procedure Free; //Вызывается при выключении скрипта
begin
ClearDB;
TimerForm.free ;
TimerCombat.free ;
TimerPickUp.free ;
TimerBafBanka.free ;
TimerCheckDB.free ;
MobsDBscreen.free ;
ItemsDBscreen.free ;
log.free ;
frm.free ;
end ;
procedure UserInfo; // обновление данных о себе
var
i:word ;
begin
if InitMode then MyID:=ReadD( 18 ) ;
MyX:=ReadD( 2 ) ;
MyY:=ReadD( 6 ) ;
MyZ:=ReadD( 10 ) ;
i:=22 ;
ReadS( i) ;
i:=i+48 ;
MyMaxHP:=ReadD( i) ;
MyHP:=ReadD( i) ;
MyMaxMP:=ReadD( i) ; // чисто информативно
MyMP:=ReadD( i) ;
// i:=i+363; //пока не используется
// MyMaxCP:=ReadD(i);
// MyCP:=ReadD(i);
end ;
procedure StatusUpdate; // обновление данных о себе
var
i:integer ;
begin
for i:=0 to ReadD( 6 ) -1 do
case pck[i*8 +10 ] of
#$09 : MyHP:=ReadD( i*8 +14 ) ;
#$0A: MyMaxHP:=ReadD( i*8 +14 ) ;
#$0B: MyMP:=ReadD( i*8 +14 ) ;
#$0C: MyMaxMP:=ReadD( i*8 +14 ) ;
// #$21: MyCP:=ReadD(i*8+14); //пока не используется
// #$22: MyMaxCP:=ReadD(i*8+14);
end ;
if MyMaxHP > 0 then HPlevelProcent:= Round ( ( MyMaxHP/100 ) *HPLevel) ;
end ;
procedure DrinkBottle; // пьем бутылки и следим за их количеством
begin
if ( HPBottleCount > 0 ) and ( HPBottleObjID > 0 ) then
begin
UseItemObjID( HPBottleObjID) ;
dec ( HPBottleCount) ;
end ;
end ;
procedure MoveToLocation01;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then updateDB( i, ReadD( 06 ) , ReadD( 10 ) , ReadD( 14 ) , false ) ;
end ;
procedure NpcInfo16;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i = 0 then AddtoDB ( ReadD( 2 ) , ReadD( 6 ) , ReadD( 14 ) , ReadD( 18 ) , ReadD( 22 ) , InMobsList( ReadD( 6 ) ) )
else UpdateDB( i, ReadD( 14 ) , ReadD( 18 ) , ReadD( 22 ) , false ) ;
end ;
procedure Attack05;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i = 0 then log.Lines .Add ( 'Глюк, моб не найден, или нас утакует другой игрок!!!' )
else UpdateDB( i, ReadD( 15 ) , ReadD( 19 ) , ReadD( 23 ) , true ) ;
end ;
procedure Die06;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then
if MobsObjID[i] = TargetID then
begin
TimerCombat.enabled := false ;
if Spoil and Spoiled then
if ReadD( 22 ) = 1 then RequestMagicSkillUse( 42 ) ;
LastKilledMobObjID:=TargetID;
inc ( MobsKilled) ; // подводим статистику
MobsIsAttackable[i]:= false ;
MobsAgression[i]:= false ;
Spoiled:= false ;
TargetID:= 0 ;
TimerCombat.enabled := true ;
end ;
end ;
procedure DeleteObject12;
var
i: integer ;
begin
if LastKilledMobObjID = ReadD( 2 ) then
begin
LastKilledMobObjID:= 0 ;
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then DelDBItem( i) ;
exit ;
end ;
i:= CheckItems( ReadD( 2 ) ) ;
if i > 0 then
begin
if Items_ObjectID[i] = TargetID then TargetID:= 0 ;
DelDroppedItem( i) ;
exit ;
end ;
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then
begin
if TargetID = ReadD( 2 ) then TargetID:= 0 ;
DelDBItem( i) ;
exit ;
end ;
end ;
begin
if pck = '' then exit ;
if ( ConnectName = NickName) and FromServer then // разбор пакетов от сервера
case pck[1 ] of
#$01 : MoveToLocation01; // MoveToLocation:h(ObjectID)d(CurX)d(CurY)d(CurZ)d(DestX)d(DestY)d(DestZ)
// #$03: ; // CharInfo:d(X)d(Y)d(Z)-(4)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)-(4)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PvPFlag)d(Carma)d(MSpeed)d(PSpeed)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sitting)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(MountType)b(PrivateStoreType)
#$04 : if ReadS( 22 ) = NickName then // UserInfo:d(X)d(Y)d(Z)d(Heading)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)d(Level)d(Exp)d(STR)d(DEX)d(CON)d(INT)d(WIT)d(MEN)d(MaxHP)d(CurrentHP)d(MaxMP)d(CurrentMP)d(SP)d(CurrentLoad)d(MaxLoad)d(Unknown)d(Under)d(REar)d(LEar)d(Neck)d(RFinger)d(LFinger)d(Head)d(RHand)d(LHand)d(Gloves)d(Chest)d(Legs)d(Feet)d(Back)d(LRHand)d(Hair)i(Under)i(REar)i(LEar)i(Neck)i(RFinger)i(LFinger)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accuracy)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateStoreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cubics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLeft)b()b(RecomHave)b()
begin
UserInfo;
btnInit.enabled := false ;
if MyHP = 0 then // Проверка не убили ли нас...
begin
SendMsg_to_CL( 'Нас убили...' ) ;
log.Lines .Add ( 'Нас убили...' ) ;
StopGame;
end ;
end ;
#$05 : if ( ReadD( 6 ) = MyID) and ( not InitMode) then Attack05; // 05= Attack:d(AttackerID)d(TargetID)d(Damage)b(Flags)d(X)d(Y)d(Z)h(Hits)
#$48 : begin ; // 48= MagicSkillUse:h(CharID)h(targetID)d(skillID)d(skillLvl)d(hitTime)d(reuseDelay)d(X)d(Y)d(Z)w(count)d(d)d(d)d(d)
if ( ReadD( 2 ) = MyID) and ( ReadD ( 6 ) = TargetID) and ( ReadD( 10 ) = 254 ) then Spoiled:= true ;
end ;
#$06 : Die06; // Die:d(ChaID)
#$0C: if LastKilledMobObjID = ReadD( 2 ) then // DropItem:h(PlayerID)h(ObjectID)i(ItemID)d(X)d(Y)d(Z)d(Stackable)d(Count)
begin
AddDroppedItem( ReadD( 6 ) , ReadD( 10 ) , ReadD( 14 ) , ReadD( 18 ) , ReadD( 22 ) ) ;
end ;
#$0D: if TargetID = ReadD( 6 ) then // GetItem:d(PlayerID)h(ObjectID)d(X)d(Y)d(Z)
begin
TargetID:= 0 ;
end ;
#$0E: if MyID=ReadD( 2 ) then // StatusUpdate:h(ObjectID)d(Attributes)
begin
StatusUpdate;
if ( MyHP > 0 ) and ( MyHP < HPlevelProcent) then if Wait( time1,DrinkDelay) then DrinkBottle; // пьем бутылки
if MyHP > HPlevelProcent then time1:=1 ;
if MyHP = 0 then // Проверка не убили ли нас...
begin
SendMsg_to_CL( 'Нас убили...' ) ;
log.Lines .Add ( 'Нас убили...' ) ;
StopGame;
end ;
end ;
#$12 : DeleteObject12; // DeleteObject:h(ObjectID)
#$16 : if ( ReadD( 10 ) =1 ) and ( pck[121 ]=#$00 ) then NpcInfo16; // NpcInfo:h(ObjectID)d(NpcTypeID)d(IsAttackable)d(X)d(Y)d(Z)d(Heading)d(Unknown)d(MAtkSpd)d(PAtkSpd)d(RunSpd)d(WalkSpd)d(SwimRunSpd)d(SwimWalkSpd)d(FlRunSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(ProperMultiplier)f(PAtkSpd)f(CollisionRadius)f(CollisionHeight)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRunning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Name)s(Title)
#$1B: begin
InventoryCreate; // Инвентарь
if HPBottleID <> 0 then
begin
HPBottleObjID:= getinv( HPBottleID, 2 ,1 ) ;
HPBottleCount:= getinv( HPBottleID, 2 ,3 ) ;
end ;
if Bottle_1 _ID <> 0 then
begin
Bottle_1 _ObjID:=getinv( Bottle_1 _ID, 2 ,1 ) ;
Bottle_1 _Count:=getinv( Bottle_1 _ID, 2 ,3 ) ;
end ;
if Bottle_2 _ID <> 0 then
begin
Bottle_2 _ObjID:=getinv( Bottle_2 _ID, 2 ,1 ) ;
Bottle_2 _Count:=getinv( Bottle_2 _ID, 2 ,3 ) ;
end ;
end ;
#$27 : begin
InventoryUpdate;
if HPBottleID <> 0 then
begin
HPBottleObjID:= getinv( HPBottleID, 2 ,1 ) ;
HPBottleCount:= getinv( HPBottleID, 2 ,3 ) ;
end ;
if Bottle_1 _ID <> 0 then
begin
Bottle_1 _ObjID:=getinv( Bottle_1 _ID, 2 ,1 ) ;
Bottle_1 _Count:=getinv( Bottle_1 _ID, 2 ,3 ) ;
end ;
if Bottle_2 _ID <> 0 then
begin
Bottle_2 _ObjID:=getinv( Bottle_2 _ID, 2 ,1 ) ;
Bottle_2 _Count:=getinv( Bottle_2 _ID, 2 ,3 ) ;
end ;
end ;
#$13 : if RestartMode then // CharacterSelectionInfo
begin
buf:=#$12 ; // CharacterSelected
WriteD( CharNumber) ;
buf:= buf + hstr( '00 00 00 00 00 00 00 00 00 00 00 00 00 00' ) ;
SendToServerEx( NickName) ;
RestartMode:= false ;
end ;
end ;
if ( ConnectName = NickName) and FromClient then // разбор пакетов от клиента
case pck[1 ] of
#$1F: if InitMode then TargetID:= ReadD( 2 ) ; // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b(ActionID)
#$49 : UserCommands; // Say2:s(Text)d(Type)s(Target)
#$59 : begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD( 2 ) ;
MyY:= ReadD( 6 ) ;
MyZ:= ReadD( 10 ) ;
if ( not CenterFixed) and InitMode then
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
end ;
end ;
end ;
end .
За это сообщение NLObP нажился спасибкой от:
13.04.2009, 12:45
#30
Заблокирован
Регистрация: 10.03.2008
Адрес: Тула
Сообщений: 1,098
Сказал Спасибо: 188
Имеет 108 спасибок в 60 сообщенях
Цитата:
Сообщение от
NLObP
Пробуйте бота:
Бот Алексус для Абисса
delphi Код:
Const ProgramName =
'Бот - локомотив от Alexus ' +
'версия : 0.5.2 (for Abyss) ' +
'дата: 13.04.09' ;
{#############################################################################
Описание:
Бот для соло-кача в принципе любого война. По функциональности (в режиме кача) это еще не Волкер, но скрипт уже довольно умный :)
Охотиться только на заданных мобов.
Возможности:
- запоминает центр и радиус кача
- запоминает список мобов на которых надо охотиться!
- запоминает и затем подбирает дроп, упавший с убитых им мобов
- умеет лечиться банками (тип банки легко настраивается), ведется учет количества оставшихся банок
- управляется из окна чата в самом клиенте
- имеет окно для вывода всех параметров и статистики
- если моб по какой-то причине стал недосягаемым (стоит за деревом), то через 1 мин БОТ переключится на другого моба.
- если бот умирает, то не палимся и прекращаем рыпаться...(скоро появиться возможность логаута)
- пьет баф-банки
- работает под РУ-ОФФ Gracia, но для этого нужно обойти щит-консоль
- умеет спойлить (функция новая, нужно тестить)
Недостатки: (со временем будет исправлено)
- бот не умеет обходить препядствия
История версий:
0.1 - самое начало :)
0.2 - куча глюков, первая рабочая версия!
0.3 - первая стабильная безглючная версия, с минимальной функциональностью (самая стабильная, но очень простая)
0.4 - изменения:
- радиус кача можно задать в секции настройки
- бот теперь сразу видит всю локацию с самого запуска скрипта
- автоопределение размера инвентаря
- ID мобов можно теперь задавать в секции настройки
- ускорен процесс добавление мобов через клиент (теперь их не надо гасить)
- отключена ф-ция автоопределения своего ID и инвентаря, по этому запускать теперь бот надо до запуска клиента
- обновлено окно вывода информации (теперь его нельзя случайно закрыть!)
- на форму добавлены кнопки управления
- добавлена кнопка "Init" в окно управления, теперь бота можно запускать в любом месте, затем нажать эту кнопку
- добавлен механизм глотания баф-банок
- оптимизирован алгоритм выбора ближайшего моба
- скрипт доработан для новых версий пакетхака (данная версия разработана под пакетхак версии 3.4.1.69)
- в режиме кача, при отсутствии мобов в радиусе, бот возвращается в центр кача
- устранена ошибка, связянная с неправильным распознованием пакета 01 - MoveToLocation
0.5 - модификация под РУ-ОФФ Gracia
- добавлен споил
- убрана ошибка, вылезающая после нажатия кнопки Init
- немного подправлен алгоритм работы с инвентарем
Инструкция:
1. Внимательно НАСТРАИВАЕМ параметры в секции настройки
(90% ошибок и последующих глюков в скрипте вылезает именно отсюда!!!), жмем кнопку "Сохранить"
2. Запускаем ПакетХак, запускаем скрипт, запускаем игрового клиента.
либо запускаем скрипт после захода в игру, и жмем кнопку на форме "Init"
3. Добираемся до места кача
4. Выбираем в таргет моба на которого хотим охотится и отправляем в общий чат-> 1
5. Выбираем следующего моба отправляем в общий чат цифру 2, и т.д. можно выбрать до 10 разных тварей.
6. Либо просто в секции настройки задаем ID мобов
7. Становимся в центр кача и отправляем в общий чат-> pos , если все правильно то в чате будет выдано сообщение, что координаты заданы.
8. Бежим к краю радиуса кача и отправляем в общий чат-> dist, в чате вылезет сообщение от системы, что радиус задан.
9. Если радиус кача задан в секции настройки, то п.7 и 8 можно пропустить!!! становимся примерно в центр кача и отправляем в общий чат-> start ,
если все сделано верно, то будет выдано соответствующее сообщение.
10.Если бот поймал моба в таргет и побежал его атаковать, то можно свернуть окно игры
и смотреть на информационное окно скрипта.
В процессе кача, в общий чат можно посылать следующие управляющие команды:
pause - пауза, можно приостановить бота, повторная комманда pause запустит бота
stop - срочная остановка бота, и сброс всех настроек, повторный запуск возможен командой start
Также можно управлять ботом одноименными кнопками с формы.
#############################################################################}
//################### Сеция настройки бота ############################################
NickName = 'NLObP' ; // Твой ник в игре
CharNumber = 0 ; // если больше одного перса на аккаунте, то задаем его порядковый номер, нумерация начинается с нуля.
Radius_Kacha = 2000 ; // Радиус кача, если 0 - то задавать вручную через клиента (изменять от 100 до 9999). Проверил на практике, что максимум не более 2000.
Spoil = false ; // Споил false - откл, true - вкл. (только для гномов-спойлеров)
//-------------------------------------------------------------------------------------
HPLevel = 70 ; // Уровень жизни в %, при котором начинаем глотать банки
HPBottleID = 0 ; // ItemID 1060=Lesser Healing Potion; 1061=Healing Potion; 1539=Greater Healing Potion;
DrinkDelay = 14 ; // минимальное время задержки повторного питься HP-бутылки (10 - 20 сек).
//---------------------------------------------------------------------------------------
Bottle_1 _ID = 0 ; // ID номера баф-банок, 6036=Greater Magic Haste Potion, 6035=Magic Haste Potion, 1374=Greater Haste Potion, 1062=Haste Potion, 734=Haste Potion
Bottle_2 _ID = 0 ; // если 0 - то не использовать. 1375=Greater Swift Attack Potion, 735=Potion of Alacrity
Bottle_Interval = 19 ; // Время задержки повторного использования бутылей в минутах (изменять от 1 до 100)
//----------------------------------------------------------------------------------------
//############# Секция расширенной настройки для опытных ботоводеров :) ###################################
TimerCombat_Interval = 500 ; // частота срабатывания таймера атаки в милисекундах, чем меньше это число, тем быстрее бот будет думать.
TimerPickUp_Interval = 500 ; // частота срабатывания таймера сбора дропа, чем меньше это число, тем быстрее бот будет думать.
TimerForm_Interval = 2500 ; // частота срабатывания таймера обновления формы, чем меньше это число, тем быстрее будут обновляться данные в форме.
Attack_Time = 45 ; // Время на убивание моба в секундах.
PickUp_Time = 15 ; // Врямя на поднятие дропа в секундах.
Vertical = 1000 ; // Вертикальный радиус кача
//---------------------------------------------------------------------------------------
NpcTypeID1 = 0 ; // Если знаем, то задаем Type ID мобов, на которых будем охотиться
NpcTypeID2 = 0 ; // Если здесь одни нули, то задавать мобов будем через клиента
NpcTypeID3 = 0 ; // Для интерлюда задаем в формате 102xxxx , где xxxx - ID моба
NpcTypeID4 = 0 ; // Для С4 в формате 100хххх , где xxxx - ID моба
NpcTypeID5 = 0 ; // Для Gracia формат пока не смотрел...
NpcTypeID6 = 0 ;
NpcTypeID7 = 0 ;
NpcTypeID8 = 0 ;
NpcTypeID9 = 0 ;
NpcTypeID10 =0 ;
//########################################################################################
NpcTypeID_List_Razmer = 10 ; // Размер списка мобов (не трогать!)
OX = 1 ; OY = 2 ; OZ= 3 ; // Служебные константы
maximumItems = 500 ; // Размер базы мобов и дропа.
OblastVidimosti = 500000 ; // (не трогать!!!) Область видимости объектов (изменять от 1000 до 500000).
InvRazmer = 249 ; // Размер инвентаря (не трогать)
var
InitMode, RestartMode, PickUpMode : boolean ;
//-------------------------------------- БД --------------------------------------------------
MobsObjID : array [1 ..maximumItems ] of integer ; // ID моба
MobsNpcTypeID : array [1 ..maximumItems ] of integer ; // Тип моба
MobsDist : array [1 ..maximumItems ] of integer ; // Расстояние от центра кача до моба
MobsXYZ : array [1 ..maximumItems , 1 ..3 ] of integer ; // Координаты
MobsIsAttackable : array [1 ..maximumItems ] of boolean ; // Можно ли моба атаковать
MobsAgression : array [1 ..maximumItems ] of boolean ; // Моб атакует меня или стоит в сторонке...
MobsUpdated : array [1 ..maximumItems ] of boolean ; // Метка об обновлении моба
MobsLastIndex: integer ; // индекс последнего элемента базы
NpcTypeID_List : array [1 ..NpcTypeID_List_Razmer ] of integer ; // Список мобов (коды мобов)
NpcTypeID_List_Count : integer ; // Текущий размер списка
NpcTypeID_CurrentMob : integer ;
Items_ObjectID : array [1 ..maximumItems ] of integer ; // БД дропа с мобов
Items_ItemID : array [1 ..maximumItems ] of integer ;
Items_XYZ : array [1 ..maximumItems , 1 ..3 ] of integer ;
ItemsLastIndex: integer ;
Inventory: array[0 ..InvRazmer , 0 ..9 ] of integer ; // инвентарь (itemType1, ObjectID, ItemID, count, itemType2, CustType1, isEquipped, BodyPart, EnchantLevel, CustType2)
CurrentInvRazmer : integer ;
HPBottleObjID, HPBottleCount : integer ; // ObjID и количество HP-бутылей
Bottle_1 _ObjID, Bottle_1 _Count : integer ;
Bottle_2 _ObjID, Bottle_2 _Count : integer ;
TargetID, LastKilledMobObjID : integer ; // Текущая цель, последний убитый моб
MobsKilled : integer ; // счетчик убитых мобов
CenterX, CenterY, CenterZ : integer ; // Центр кача
CenterFixed : boolean ;
Radius: integer ; // Радиус кача
//--------------------------------------------------------
MyX, MyY, MyZ : integer ; // Мои статы
MyID, MyHP, MyMaxHP: integer ;
MyMP, MyMaxMP, MyCP, MyMaxCP: integer ;
HPlevelProcent : integer ; // уровень жизни в процентах
//--------------------------------------------------------
frm: TForm; // переменные описания формы
log, MobsDBscreen, ItemsDBScreen: TMemo;
panel: TPanel;
btnInit, btnStart, btnStop, btnPause: TButton;
frmParamIndex: byte ;
textX, textY, textZ, textMyID, textMyHP, textMyMaxHP: TEdit;
textMyMP, textMyMaxMP, textMyCP, textMyMaxCP: TEdit;
textCenterX, textCenterY, textCenterZ, textRadius : TEdit;
textTargetID, textMobX, textMobY, textMobZ : TEdit;
textAttackCycle, textMobsLastIndex, textMobsKilled: TEdit;
textHPBottleCount, textBottle_1 _Count, textBottle_2 _Count: TEdit;
cbFilterRadius : TCheckBox; l1: Tlabel;
//----------------------------------------------------------
TimerForm, TimerCombat, TimerPickUp, TimerBafBanka, TimerCheckDB : TTimer; // таймеры
time1: integer ;
Calculated_AttackTime, Calculated_PickUpTime : integer ;
AttackCycle: integer ; // Цикл атаки
Spoiled: boolean ;
//##############################################################################################
procedure Init; //Вызывается при включении скрипта
var
i,n : integer ;
begin
MyID:= 0 ; // обнуляем ВСЕ данные
MyX:= 0 ;
MyY:= 0 ;
MyZ:= 0 ;
MyID:= 0 ;
MyHP:= 0 ;
MyMaxHP:= 0 ;
MyMP:= 0 ;
MyMaxMP:= 0 ;
MyCP:= 0 ;
MyMaxCP:= 0 ;
time1:=1 ;
Calculated_AttackTime:= round ( 1000 / TimerCombat_Interval * Attack_Time) ;
Calculated_PickUpTime:= round ( 1000 / TimerPickUp_Interval * PickUp_Time) ;
HPlevelProcent:= 0 ;
HPBottleObjID:= 0 ;
HPBottleCount:= 0 ;
Bottle_1 _ObjID:= 0 ;
Bottle_1 _Count:= 0 ;
Bottle_2 _ObjID:= 0 ;
Bottle_2 _Count:= 0 ;
InitMode:= true ;
RestartMode:= false ;
MobsLastIndex:= 0 ;
for i:=1 to maximumItems do // Очищаем базу
begin
MobsObjID[i]:= 0 ;
MobsNpcTypeID[i]:=0 ;
MobsDist[i]:= 0 ;
MobsXYZ[i, OX]:= 0 ;
MobsXYZ[i, OY]:= 0 ;
MobsXYZ[i, OZ]:= 0 ;
MobsIsAttackable[i]:= false ;
MobsAgression[i]:= false ;
MobsUpdated[i]:=false ;
end ;
for i:=0 to InvRazmer do for n:=0 to 9 do Inventory[i, n]:= 0 ;
CurrentInvRazmer:=0 ;
TimerCombat:=TTimer.Create ( nil ) ; // создаем таймеры
TimerCombat.OnTimer :=@OnTimerCombat;
TimerCombat.enabled :=false ;
TimerCombat.interval := TimerCombat_Interval;
TimerForm:=TTimer.Create ( nil ) ;
TimerForm.OnTimer :=@OnTimerForm;
TimerForm.enabled :=true ;
TimerForm.interval := TimerForm_Interval;
TimerPickUp:=TTimer.Create ( nil ) ;
TimerPickUp.OnTimer :=@OnTimerPickUp;
TimerPickUp.enabled :=false ;
TimerPickUp.interval := TimerPickUp_Interval;
TimerBafBanka:=TTimer.Create ( nil ) ;
TimerBafBanka.OnTimer :=@OnTimerBafBanka;
TimerBafBanka.enabled :=false ;
TimerBafBanka.interval := 15000 ;
TimerCheckDB:=TTimer.Create ( nil ) ;
TimerCheckDB.OnTimer :=@OnTimerCheckDB;
TimerCheckDB.enabled :=true ;
TimerCheckDB.interval := 20 *60 *1000 ; // раз в 20 минут
frmParamIndex:=0 ; // создаем контролы в форме
frm:= TForm.Create ( nil ) ;
frm.Caption := ProgramName;
frm.BorderStyle := bsDialog;
frm.Position := poScreenCenter;
frm.Width :=650 ;
frm.Height :=700 ;
frm.OnClose := @FormClose;
MobsDBscreen:=TMemo.Create ( frm) ;
MobsDBscreen.parent :=frm;
MobsDBscreen.ReadOnly :=true ;
MobsDBscreen.ScrollBars :=0 ;
MobsDBscreen.Top :=157 ;
MobsDBscreen.Width :=457 ;
MobsDBscreen.Height :=385 ;
ItemsDBscreen:=TMemo.Create ( frm) ;
ItemsDBscreen.parent :=frm;
ItemsDBscreen.ReadOnly :=true ;
ItemsDBscreen.ScrollBars :=0 ;
ItemsDBscreen.Top :=1 ;
ItemsDBscreen.Width :=300 ;
ItemsDBscreen.Height :=155 ;
panel:=TPanel.Create ( frm) ;
panel.parent :=frm;
panel.align :=alRight;
log:=TMemo.Create ( panel) ;
log.parent :=frm;
log.align :=alBottom;
log.ReadOnly :=true ;
log.ScrollBars :=2 ;
log.Width :=570 ;
log.Height :=100 ;
log.Lines .Add ( 'Лог...' ) ;
btnInit:= TButton.Create ( frm) ;
btnInit.Name := 'btnInit' ;
btnInit.Parent := frm;
btnInit.SetBounds ( 370 , 10 , 75 , 25 ) ;
btnInit.Caption := 'Init' ;
btnInit.OnClick := @BtnInit_Click;
btnStart:= TButton.Create ( frm) ;
btnStart.Name := 'btnStart' ;
btnStart.Parent := frm;
btnStart.SetBounds ( 370 , 40 , 75 , 25 ) ;
btnStart.Caption := 'Start' ;
btnStart.OnClick := @btnStart_Click;
btnStop:= TButton.Create ( frm) ;
btnStop.Name := 'btnStop' ;
btnStop.Parent := frm;
btnStop.SetBounds ( 370 , 70 , 75 , 25 ) ;
btnStop.Caption := 'Stop' ;
btnStop.OnClick := @btnStop_Click;
btnPause:= TButton.Create ( frm) ;
btnPause.Name := 'btnPause' ;
btnPause.Parent := frm;
btnPause.SetBounds ( 370 , 100 , 75 , 25 ) ;
btnPause.Caption := 'Pause' ;
btnPause.OnClick := @btnPause_Click;
l1:= TLabel.Create ( frm) ;
l1.caption :='Фильтры:' ;
l1.parent :=frm;
l1.SetBounds ( 5 , 547 , 97 , 17 ) ;
cbFilterRadius := TCheckBox.Create ( frm) ;
cbFilterRadius.Name := 'cbFilterRadius' ;
cbFilterRadius.Parent := frm;
cbFilterRadius.SetBounds ( 60 , 545 , 97 , 17 ) ;
cbFilterRadius.Caption := 'Радиус' ;
// cbFilterRadius.OnClick := @CheckBoxFilterClick;
textMyID:= CreateTextBox( 'textMyID' ) ;
CreateLabel( 'Мой ID :' ) ;
textX:= CreateTextBox( 'textX' ) ;
CreateLabel( 'Мой X :' ) ;
textY:= CreateTextBox( 'textY' ) ;
CreateLabel( 'Мой Y :' ) ;
textZ:= CreateTextBox( 'textZ' ) ;
CreateLabel( 'Мой Z :' ) ;
textMyHP:= CreateTextBox( 'textMyHP' ) ;
CreateLabel( 'Мой HP :' ) ;
textMyMaxHP:= CreateTextBox( 'textMyMaxHP' ) ;
CreateLabel( 'Мой MaxHP :' ) ;
textMyMP:= CreateTextBox( 'textMyMP' ) ;
CreateLabel( 'Мой MP :' ) ;
textMyMaxMP:= CreateTextBox( 'textMyMaxMP' ) ;
CreateLabel( 'Мой MaxMP :' ) ;
// textMyCP:= CreateTextBox('textMyCP');
// CreateLabel('Мой CP :');
// textMyMaxCP:= CreateTextBox('textMyMaxCP');
// CreateLabel('Мой MaxCP :');
inc ( frmParamIndex) ;
textCenterX:= CreateTextBox( 'textCenterX' ) ;
CreateLabel( 'Ц. кач Х:' ) ;
textCenterY:= CreateTextBox( 'textCenterY' ) ;
CreateLabel( 'Ц. кач Y:' ) ;
textCenterZ:= CreateTextBox( 'textCenterZ' ) ;
CreateLabel( 'Ц. кач Z:' ) ;
textRadius:= CreateTextBox( 'Radius' ) ;
CreateLabel( 'Radius :' ) ;
inc ( frmParamIndex) ;
textTargetID:= CreateTextBox( 'TargetID' ) ;
CreateLabel( 'Цель ID :' ) ;
textAttackCycle:= CreateTextBox( 'AttackCycle' ) ;
CreateLabel( 'Цикл атаки:' ) ;
textMobsLastIndex:= CreateTextBox( 'MobsLastIndex' ) ;
CreateLabel( 'Мобов в БД:' ) ;
textMobsKilled:= CreateTextBox( 'MobsKilled' ) ;
CreateLabel( 'Убито моб:' ) ;
inc ( frmParamIndex) ;
textHPBottleCount:= CreateTextBox( 'HPBottleCount' ) ;
CreateLabel( 'HP бутылей:' ) ;
textBottle_1 _Count:= CreateTextBox( 'Bottle_1_Count' ) ;
CreateLabel( 'Баф-Банки 1:' ) ;
textBottle_2 _Count:= CreateTextBox( 'Bottle_2_Count' ) ;
CreateLabel( 'Баф-Банки 2:' ) ;
ClearDB;
frm.Show ; // выводим форму на экран
buf:=#$6E;
SendToServerEx( NickName) ;
end ;
procedure btnPause_Click( Sender: TButton) ;
begin
PauseGame;
end ;
procedure btnStop_Click( Sender: TButton) ;
begin
StopGame;
end ;
procedure btnStart_Click( Sender: TButton) ;
begin
StartGame;
end ;
procedure BtnInit_Click( Sender: TButton) ;
begin
RestartMode:= true ;
buf:= #$57 ; // авто релогин
// buf:= #$0F; // принудительно вызываем пакеты инвентаря и userinfo
SendToServerEx( NickName) ;
end ;
procedure AddtoNpcTypeID_List ( NpcTypeID: integer ) ;
begin
inc ( NpcTypeID_List_Count) ;
NpcTypeID_List[NpcTypeID_List_Count]:= NpcTypeID;
end ;
procedure ClearDB; // Очистка БД
var // Надо все занулять, иначе там хрень всякая вылезает или старые данные
i : integer ;
begin
ItemsLastIndex:= 0 ; // Очищаем переменные
TargetID:= 0 ;
LastKilledMobObjID:= 0 ;
MobsKilled:= 0 ;
CenterX:= 0 ;
CenterY:= 0 ;
CenterZ:= 0 ;
CenterFixed:= false ;
Radius:= Radius_Kacha;
TimerBafBanka.interval := 15000 ;
AttackCycle:= 0 ;
Spoiled:= false ;
NpcTypeID_List_Count:= 0 ;
if NpcTypeID1 <> 0 then AddtoNpcTypeID_List ( NpcTypeID1) ;
if NpcTypeID2 <> 0 then AddtoNpcTypeID_List ( NpcTypeID2) ;
if NpcTypeID3 <> 0 then AddtoNpcTypeID_List ( NpcTypeID3) ;
if NpcTypeID4 <> 0 then AddtoNpcTypeID_List ( NpcTypeID4) ;
if NpcTypeID5 <> 0 then AddtoNpcTypeID_List ( NpcTypeID5) ;
if NpcTypeID6 <> 0 then AddtoNpcTypeID_List ( NpcTypeID6) ;
if NpcTypeID7 <> 0 then AddtoNpcTypeID_List ( NpcTypeID7) ;
if NpcTypeID8 <> 0 then AddtoNpcTypeID_List ( NpcTypeID8) ;
if NpcTypeID9 <> 0 then AddtoNpcTypeID_List ( NpcTypeID9) ;
if NpcTypeID10<> 0 then AddtoNpcTypeID_List ( NpcTypeID10) ;
if NpcTypeID_List_Count = 0 then
for i:=1 to NpcTypeID_List_Razmer do NpcTypeID_List[i]:= 0 ;
NpcTypeID_CurrentMob:= 0 ;
for i:=1 to maximumItems do // Очищаем базу
begin
Items_ObjectID[i]:= 0 ;
Items_ItemID[i]:= 0 ;
Items_XYZ[i, OX]:= 0 ;
Items_XYZ[i, OY]:= 0 ;
Items_XYZ[i, OZ]:= 0 ;
end ;
btnStop.enabled :=false ;
btnPause.enabled := false ;
end ;
function Wait( var tick: integer ; Timewait: Integer ) : Boolean ; // сквозная проверка без остановки скрипта (c)dmitry501, modifed by Sh00rGo
var
t: integer ;
begin
result:=false ;
t:=Round ( Time *86400 ) ;
if t>( tick+Timewait) then begin
if tick>0 then result:=true ;
tick:=t;
end ;
end ;
//############################## Модуль работы с Инвентарем ###########################
procedure InventoryCreate;
var
i,k, offset : integer ;
begin
offset:= 76 ;
CurrentInvRazmer:=ReadH( 4 ) ;
for i:=0 to InvRazmer do
if i < CurrentInvRazmer then begin
Inventory[i,0 ]:=ReadH( i*offset+6 ) ; // itemType1
Inventory[i,1 ]:=ReadD( i*offset+8 ) ; // ObjectId
Inventory[i,2 ]:=ReadD( i*offset+12 ) ; // ItemID
Inventory[i,3 ]:=ReadD( i*offset+20 ) ; // count
Inventory[i,4 ]:=ReadH( i*offset+24 ) ; // itemType2
Inventory[i,5 ]:=ReadH( i*offset+26 ) ; // CustType1
Inventory[i,6 ]:=ReadH( i*offset+28 ) ; // isEquipped
Inventory[i,7 ]:=ReadD( i*offset+30 ) ; // BodyPart
Inventory[i,8 ]:=ReadH( i*offset+34 ) ; // EnchantLevel
Inventory[i,9 ]:=ReadH( i*offset+36 ) ; // CustType2
end else
for k:=0 to 9 do Inventory[i,k]:=0 ; // забиваем нулями
end ;
procedure InventoryUpdate;
var
i,j,k, offset: integer ;
begin
offset:= 82 ;
for j:=0 to ( ReadH( 2 ) -1 ) do
begin
case pck[j*offset+4 ] of
#$01 : k:=0 ; // add item, запишет на пустую ячейку
#$02 : k:=ReadD( j*offset+8 ) ; // mod item
#$03 : begin // remove item, обнулит ячейки удаленного предмета
k:=ReadD( j*offset+8 ) ;
for i:=0 to InvRazmer do if ( Inventory[i,1 ]=k) then
begin
for k:=0 to 9 do Inventory[i,k]:=0 ;
exit ;
end ;
end ;
end ;
for i:=0 to InvRazmer do if ( Inventory[i,1 ]=k) then
begin
Inventory[i,0 ]:=ReadH( j*offset+6 ) ; // itemType1
Inventory[i,1 ]:=ReadD( j*offset+8 ) ; // ObjectId
Inventory[i,2 ]:=ReadD( j*offset+12 ) ; // ItemID
Inventory[i,3 ]:=ReadD( j*offset+20 ) ; // count
Inventory[i,4 ]:=ReadH( j*offset+24 ) ; // itemType2
Inventory[i,5 ]:=ReadH( j*offset+26 ) ; // CustType1
Inventory[i,6 ]:=ReadH( j*offset+28 ) ; // isEquipped
Inventory[i,7 ]:=ReadD( j*offset+30 ) ; // BodyPart
Inventory[i,8 ]:=ReadH( j*offset+34 ) ; // EnchantLevel
Inventory[i,9 ]:=ReadH( j*offset+36 ) ; // CustType2
break ;
end ;
end ;
end ;
function GetInv( obj,up,down:integer ) : integer ; // up и down не проверяются
var // 0-itemType1, 1-ObjectId, 2-ItemID, 3-count, 4-itemType2, 5-CustType1, 6-isEquipped, 7-BodyPart, 8-EnchantLevel, 9-CustType2
i: integer ;
begin
for i:=0 to CurrentInvRazmer do if ( Inventory[i,up]=obj) then
begin
Result:=Inventory[i,down];
exit ;
end ;
Result:=-1 ;
end ;
{procedure UseItemID(ItemID:integer); //Использовать предмет с заданным ItemID
var
ObjItemID : integer;
begin
ObjItemID:= GetInv(ItemID,2,1);
if ObjItemID = -1 then exit;
buf:=#$14;
WriteD(ObjItemID);
WriteD(0);
SendToServerEx(NickName);;
end;}
procedure UseItemObjID( ItemObjID:integer ) ; //Использовать предмет с заданным ItemObjID
begin
buf:=#$19 ;
WriteD( ItemObjID) ;
WriteD( 0 ) ;
SendToServerEx( NickName) ;;
end ;
//############################################################################################
function rastoyanie( NpcX, NpcY, NpcZ : integer ) : longint ; // вычисление растояния между 2 точками
var
dx,dy,dz : integer ;
summa : longint ;
begin
try
dx:= NpcX-CenterX;
dy:= NpcY-CenterY;
dz:= NpcZ-CenterZ;
summa:= dx*dx+dy*dy; // мне кажется, что так будет быстрее считаться
if summa = 0 then result:= 0 else result:= Round ( sqrt ( summa) ) ; // обход возможной ошибки, если моб стоит прямо в центре кача
if abs ( dz) > vertical then result := result + OblastVidimosti; // добавляем коррекцию по вертикали
except
sendmsg( 'Ошибка вычисления расстояния' ) ;
sendmsg( 'dx= ' + inttostr ( dx) ) ;
sendmsg( 'dy= ' + inttostr ( dy) ) ;
sendmsg( 'dz= ' + inttostr ( dz) ) ;
sendmsg( 'summa= ' + inttostr ( summa) ) ;
result := OblastVidimosti;
end ;
end ;
function RastoyanieToMe( NpcX, NpcY : integer ) : integer ; // вычисление растояния между 2 точками
var
dx,dy, summa : integer ;
begin
dx:= NpcX-MyX;
dy:= NpcY-MyY;
summa:= dx*dx+dy*dy; // мне кажется, что так будет быстрее считаться
if summa = 0 then result:= 0 else result:= Round ( sqrt ( summa) ) ; // обход возможной ошибки, если моб стоит прямо в центре кача
end ;
procedure AddDroppedItem ( ObjID, ItemID, X, Y, Z: integer ) ; // Процедура добавляет дропнутую вещь в БД
begin
if ItemsLastIndex = maximumItems then ItemsLastIndex:=0 ; // обход переполнения базы предметов
inc ( ItemsLastIndex) ;
Items_ObjectID[ItemsLastIndex]:= ObjID;
Items_ItemID[ItemsLastIndex]:= ItemID;
Items_XYZ[ItemsLastIndex, OX]:= X;
Items_XYZ[ItemsLastIndex, OY]:= Y;
Items_XYZ[ItemsLastIndex, OZ]:= Z;
// log.Lines.Add('Вещь добавлена, индекс в БД: '+ inttostr(ItemsLastIndex));
end ;
procedure AddtoDB ( id, TypeID, x,y,z : integer ; IsAttackable : boolean ) ; // Процедура добавляет в БД нового моба
var
dist: integer ;
begin
if ( not initmode) then dist:= rastoyanie ( x,y,z) else dist := OblastVidimosti; // вычиляем расстояние от центра кача до моба
if dist > ( OblastVidimosti) then exit ; // если моб слишко далеко то ничего не делаем
inc ( MobsLastIndex) ; // увеличиваем размер БД
// log.Lines.Add('Моб добавлен, индекс в БД:'+ inttostr(MobsLastIndex));
// if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsObjID[MobsLastIndex]:= id; // Записываем моба
MobsNpcTypeID[MobsLastIndex]:= TypeID;
MobsDist[MobsLastIndex]:= dist;
MobsXYZ[MobsLastIndex, OX]:= x;
MobsXYZ[MobsLastIndex, OY]:= y;
MobsXYZ[MobsLastIndex, OZ]:= z;
MobsIsAttackable[MobsLastIndex]:= IsAttackable;
MobsAgression[MobsLastIndex]:= false ;
MobsUpdated[MobsLastIndex]:= true ;
end ;
procedure UpdateDB ( i, x,y,z : integer ; agression : boolean ) ; // Процедура обновляет данные в БД по мобу
var
dist: integer ;
begin
if ( not initmode) then dist:= rastoyanie ( x,y,z) else dist := OblastVidimosti;
if dist > ( OblastVidimosti) then DelDBItem( i) else // перепроверяем расстояние до моба, если он вышел за границу кача, то удаляем его
begin
// log.Lines.Add('Моб обновлен, индекс в БД:'+ inttostr(i));
// if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsDist[i]:= dist; // записываем данные
MobsXYZ[i, OX]:= x;
MobsXYZ[i, OY]:= y;
MobsXYZ[i, OZ]:= z;
if ( not MobsAgression[i]) then MobsAgression[i]:= agression;
MobsUpdated[i]:= true ;
end ;
end ;
procedure DelDBItem ( i: integer ) ; // процедура удалаяет моба из БД
begin
// log.Lines.Add('Моб удален, индекс в БД: '+ inttostr(i));
MobsObjID[i]:= 0 ;
MobsNpcTypeID[i]:= 0 ;
MobsDist[i]:= 0 ;
MobsXYZ[i, OX]:= 0 ;
MobsXYZ[i, OY]:= 0 ;
MobsXYZ[i, OZ]:= 0 ;
MobsAgression[i]:= false ;
MobsIsAttackable[i]:= false ;
MobsUpdated[i]:= false ;
if i < MobsLastIndex then // если надо, производим сдвиг данных в массивах
begin
MobsObjID[i]:= MobsObjID[MobsLastIndex];
MobsNpcTypeID[i]:= MobsNpcTypeID[MobsLastIndex];
MobsDist[i]:= MobsDist[MobsLastIndex];
MobsXYZ[i, OX]:= MobsXYZ[MobsLastIndex, OX];
MobsXYZ[i, OY]:= MobsXYZ[MobsLastIndex, OY];
MobsXYZ[i, OZ]:= MobsXYZ[MobsLastIndex, OZ];
MobsIsAttackable[i]:= MobsIsAttackable[MobsLastIndex];
MobsAgression[i]:= MobsAgression[MobsLastIndex];
MobsUpdated[i]:= MobsUpdated[MobsLastIndex];
end ;
dec ( MobsLastIndex) ; // уменьшаем размер БД
end ;
procedure DelDroppedItem ( i: integer ) ; // процедура удалаяет вещь из БД
begin
Items_ObjectID[i]:= 0 ;
Items_ItemID[i]:= 0 ;
Items_XYZ[i, OX]:= 0 ;
Items_XYZ[i, OY]:= 0 ;
Items_XYZ[i, OZ]:= 0 ;
// log.Lines.Add('Вещь удалена, индекс в БД: '+ inttostr(i));
if i < ItemsLastIndex then
begin
Items_ObjectID[i]:= Items_ObjectID[ItemsLastIndex];
Items_ItemID[i] := Items_ItemID[ItemsLastIndex];
Items_XYZ[i, OX]:= Items_XYZ[ItemsLastIndex, OX];
Items_XYZ[i, OY]:= Items_XYZ[ItemsLastIndex, OY];
Items_XYZ[i, OZ]:= Items_XYZ[ItemsLastIndex, OZ];
end ;
dec ( ItemsLastIndex) ;
end ;
function CheckItems ( id: integer ) : integer ; // функция проверяет наличие заданной вещи в БД
var
i: integer ;
begin
result:= 0 ;
for i:=1 to ItemsLastIndex do if Items_ObjectID[i] = id then
begin
result:=i; // И возвращаем его индекс по БД
break ;
end ;
end ;
function TestPovtor ( id: integer ) : integer ; // функция проверяет наличие заданного моба в БД
var
i: integer ;
begin
result:=0 ;
for i:=1 to MobsLastIndex do if MobsObjID[i] = id then // Ищем нужный ID в нашей БД
begin
result:=i; // И возвращаем его индекс по БД
break ;
end ;
end ;
function InMobsList ( NpcTypeID: integer ) : boolean ; // функция проверяет наличие заданного моба в списке на атаку
var
i: integer ;
begin
result:= false ;
for i:=1 to NpcTypeID_List_Count do if NpcTypeID_List[i] = NpcTypeID then result:= true ; // проверяем по списку
end ;
procedure SendMsg_to_CL( msg:string ) ; // отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD( 0 ) ;
WriteD( 10 ) ;
WriteS( '' ) ;
WriteS( msg) ;
SendToClientEx( NickName) ;
end ;
procedure OnTimerCheckDB ( Sender: TObject ) ;
var
i: integer ;
begin
i:=0 ;
while i <= MobsLastIndex do
begin
inc ( i) ;
if MobsUpdated[i] then MobsUpdated[i]:=false
else
begin
DelDBItem( i) ;
dec ( i) ;
end ;
end ;
end ;
procedure PrepareDB;
var
i: integer ;
//dist : double;
begin
i:=0 ;
while i <= MobsLastIndex do
begin
inc ( i) ;
if InMobsList( MobsNpcTypeID[i]) then MobsIsAttackable[i]:= true ;
MobsDist[i] := rastoyanie ( MobsXYZ[i, OX], MobsXYZ[i, OY], MobsXYZ[i, OZ]) ;
if MobsDist[i] >= OblastVidimosti then
begin
// DelDBItem(i);
// dec(i);
end ;
end ;
end ;
function ValidateData : boolean ; // функция проверки правильности задания всех параметров для начала кача
begin
if ( MyX <> 0 ) and ( MyY <> 0 ) and ( MyZ <> 0 ) and ( MyID <> 0 ) and ( MyHP > 0 ) and ( MyMaxHP > 0 ) and // верификация всех данных, чтобы потом в боевом режиме
( MyMP > 0 ) and ( MyMaxMP > 0 ) and {(MyCP <> 0) and (MyMaxCP <> 0) and } // не перепроверять все данные по 100 раз
( CenterX <> 0 ) and ( CenterY <> 0 ) and ( CenterZ <> 0 ) and ( Radius > 0 ) and ( NpcTypeID_List_Count > 0 ) then
begin
PrepareDB;
SendMsg_to_CL( 'Все начальные параметры заданы и проверены!' ) ;
log.Lines .Add ( 'Все начальные параметры заданы и проверены!' ) ;
result:= true ;
end
else
begin
SendMsg_to_CL( 'Ошибка задания начальных параметров!' ) ;
log.Lines .Add ( 'Ошибка задания начальных параметров!' ) ;
result:= false ;
end ;
end ;
procedure UserCommands; // комманды пользователя
var
i: integer ;
begin // если комманда обработана удачно, то в чат сообщение не попадет, а будет выдано системное сообщение прямо в клиент
if InitMode then case ( ReadS( 2 ) ) of
'pos' : if MyX <> 0 then // центр кача
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
CenterFixed:= true ;
SendMsg_to_CL( 'Центр кача задан успешно!' ) ;
log.Lines .Add ( 'Центр кача задан успешно!' ) ;
pck:='' ;
end ;
'dist' : if ( CenterX <> 0 ) and ( MyX <> 0 ) then // радиус кача
begin
CenterFixed:= true ;
Radius:= rastoyanie ( MyX,MyY,MyZ) ;
SendMsg_to_CL( 'Радиус кача задан успешно' ) ;
SendMsg_to_CL( 'R= ' + inttostr ( Radius) ) ;
log.Lines .Add ( 'Радиус кача задан успешно, R = ' + inttostr ( Radius) ) ;
pck:='' ;
end ;
'reset' : begin // сброс параметров
ClearDB;
SendMsg_to_CL( 'БД очищена, введите заново все параметры' ) ;
log.Lines .Add ( 'БД очищена!' ) ;
pck:='' ;
end ;
'1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '10' : // задаем мобов
begin
if ( NpcTypeID_List_Count+1 ) <> strtoint ( ReadS( 2 ) ) then
begin
SendMsg_to_CL( 'Добавлять мобов можно тока по очереди 1, 2, 3...' ) ;
pck:='' ;
exit ;
end ;
NpcTypeID_CurrentMob:= strtoint ( ReadS( 2 ) ) ;
SendMsg_to_CL( 'Добавляем моба № ' + ReadS( 2 ) ) ;
pck:='' ;
i:= TestPovtor ( TargetID) ;
if i > 0 then
begin
NpcTypeID_List[NpcTypeID_CurrentMob]:= MobsNpcTypeID[i];
SendMsg_to_CL( 'Моб №' + inttostr ( NpcTypeID_CurrentMob) + 'тип: ' +inttostr ( MobsNpcTypeID[i]) +' добавлен в базу' ) ;
log.Lines .Add ( 'Моб №' + inttostr ( NpcTypeID_CurrentMob) + 'тип: ' +inttostr ( MobsNpcTypeID[i]) +' добавлен в базу' ) ;
inc ( NpcTypeID_List_Count) ;
NpcTypeID_CurrentMob:= 0 ;
TargetID:= 0 ;
end ;
end ;
'start' : begin // собственно запуск бота
pck:='' ;
StartGame;
end ;
end ;
if ( not InitMode) then case ( ReadS( 2 ) ) of
'pause' : begin
pck:='' ;
PauseGame;
end ;
'stop' : begin
pck:='' ;
StopGame;
end ;
end ;
end ;
procedure PauseGame;
begin
TimerCombat.enabled := not ( TimerCombat.enabled ) ;
TimerBafBanka.enabled := not ( TimerBafBanka.enabled ) ;
if TimerCombat.enabled then
begin
btnPause.Caption :='Pause' ;
TimerBafBanka.interval := 15000 ;
SendMsg_to_CL( 'Искуственный интелект запущен!' ) ;
log.Lines .Add ( 'Искуственный интелект запущен!' ) ;
end
else
begin
btnPause.Caption :='Repeat' ;
SendMsg_to_CL( 'Искуственный интелект приостановлен.' ) ;
log.Lines .Add ( 'Искуственный интелект приостановлен.' ) ;
end ;
end ;
procedure StartGame;
begin
if ValidateData and InitMode then
begin
CenterFixed:= true ;
SendMsg_to_CL( 'ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!' ) ;
log.Lines .Add ( 'ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!' ) ;
TargetID:=0 ;
InitMode:= false ;
TimerCombat.enabled :=true ; // запускаем таймер
TimerBafBanka.interval := 15000 ;
TimerBafBanka.enabled := true ;
btnStart.enabled := false ;
btnStop.enabled := true ;
btnPause.enabled := true ;
end
else
begin
SendMsg_to_CL( 'Еще не все параметры заданы. Проверьте параметры...' ) ;
log.Lines .Add ( 'Еще не все параметры заданы. Проверьте параметры...' ) ;
end ;
end ;
procedure StopGame; // остановка кача
begin
TimerCombat.enabled := false ;
InitMode:= true ;
TimerPickUp.enabled :=false ;
TimerBafBanka.enabled :=false ;
TargetID:= 0 ;
ClearDB;
SendMsg_to_CL( 'Искуственный интелект остановлен.' ) ;
log.Lines .Add ( 'Искуственный интелект остановлен.' ) ;
btnStart.enabled := true ;
btnStop.enabled := false ;
btnPause.Caption := 'Pause' ;
btnPause.enabled :=false ;
end ;
function GetMinDistID : integer ; // функция поиска ближайшего моба в БД
var
i, Dist, MinDist : integer ;
begin
result:= 0 ;
if MobsLastIndex = 0 then exit ;
MinDist:=RastoyanieToMe( MobsXYZ[1 ,OX], MobsXYZ[1 ,OY]) ;
for i:=1 to MobsLastIndex do if ( MobsDist[i] <= Radius) and ( MobsIsAttackable[i]) then
begin
Dist:= RastoyanieToMe( MobsXYZ[i,OX], MobsXYZ[i,OY]) ;
if Dist <= MinDist then
begin
Dist:= MinDist;
result:= i;
end ; // если нашли хоть одного моба или несколько, товозращаем индекс ближайшего
end ;
end ;
function AgroTest : integer ; // функция проверяет, атакует ли меня кто-нибудь или нет
var
i: integer ;
begin
result:=0 ;
for i:=1 to MobsLastIndex do if MobsAgression[i] then // ищем первого попавшегося моба, который нас атакует
begin
result:= i; // возвращаем его индекс по БД
break ;
end ;
end ;
procedure PhisicalAttack; // команда атаки
begin
buf:=#$1F; //action
WriteD( TargetID) ;
WriteD( MyX) ;
WriteD( MyY) ;
WriteD( MyZ) ;
WriteC( 0 ) ;
SendToServerEx( NickName) ;
end ;
procedure RequestMagicSkillUse ( SkillID: integer ) ; // маг атака
begin
buf:=#$39 ;
WriteD( SkillID) ;
WriteD( 0 ) ;
WriteC( 0 ) ;
SendToServerEx( NickName) ;
end ;
procedure InitPickUpMode( mode: boolean ) ;
begin
if mode then
begin
PickUpMode:= true ;
TimerCombat.enabled := false ;
TimerPickUp.enabled := true ;
end
else
begin
PickUpMode:= false ;
TimerCombat.enabled := true ;
TimerPickUp.enabled := false ;
end ;
end ;
procedure OnTimerBafBanka ( Sender: TObject ) ; // таймер питья баф-банок
begin
if ( Bottle_1 _Count > 0 ) and ( Bottle_1 _ObjID > 0 ) then
begin
UseItemObjID( Bottle_1 _ObjID) ;
dec ( Bottle_1 _Count) ;
end ;
if ( Bottle_2 _Count > 0 ) and ( Bottle_2 _ObjID > 0 ) then
begin
UseItemObjID( Bottle_2 _ObjID) ;
dec ( Bottle_2 _Count) ;
end ;
TimerBafBanka.interval := Bottle_Interval*60 *1000 ;
end ;
procedure OnTimerPickUp ( Sender: TObject ) ; // таймер поднятия дропа
var
povtor: integer ;
begin
if ( AgroTest > 0 ) then
begin
TargetID:= 0 ;
InitPickUpMode( false ) ;
exit ;
end ;
if ( ItemsLastIndex > 0 ) and ( TargetID = 0 ) then
begin
TargetID:= Items_ObjectID[ItemsLastIndex];
AttackCycle:= 0 ;
PhisicalAttack;
exit ;
end ;
if ( ItemsLastIndex > 0 ) and ( TargetID > 0 ) then
begin
inc ( AttackCycle) ;
if ( ( AttackCycle mod 5 ) = 0 ) then PhisicalAttack;
if AttackCycle > Calculated_PickUpTime then
begin
Povtor:= CheckItems( TargetID) ;
if Povtor <> 0 then DelDroppedItem( Povtor) ;
TargetID:= 0 ;
end ;
exit ;
end ;
if ItemsLastIndex = 0 then InitPickUpMode( false ) ;
end ;
procedure OnTimerCombat ( Sender: TObject ) ; // боевой таймер, вся логика поведения бота находится именно здесь!!!
var
Agro, MinDistID, i: integer ;
begin
if TargetID > 0 then // если в прицеле есть моб, то
begin // валим вражину
if ( ( AttackCycle mod 5 ) = 0 ) then
begin
if Spoil and ( not Spoiled) then RequestMagicSkillUse( 254 ) // заспойлим моба если опция включена
else PhisicalAttack;
end ;
inc ( AttackCycle) ;
if AttackCycle > Calculated_AttackTime then // если валим моба больше минуты, значит это баг...
begin
i:= TestPovtor( TargetID) ;
if i > 0 then
begin
MobsIsAttackable[i]:= false ; //DelDBItem(i);
MobsAgression[i]:= false ;
end ;
TargetID:= 0 ;
end ;
exit ;
end ;
Agro:= AgroTest;
if Agro > 0 then // если нас кто-то атакует, то его и выбираем
begin
TargetID:= MobsObjID[Agro];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0 ;
exit ;
end ;
if ItemsLastIndex > 0 then // если чего-то валяется на земле, то
begin
InitPickUpMode( true ) ; // надо дроп подбирать
exit ;
end ;
MinDistID:= GetMinDistID; // запускаем алгоритм выбора цели
if MinDistID > 0 then // иначе ищем ближайшего
begin
TargetID:= MobsObjID[MinDistID];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0 ;
exit ;
end ;
if ( abs ( MyX-CenterX) > 20 ) and ( abs ( MyY-CenterY) > 20 ) then MoveTo ( CenterX, CenterY, CenterZ) ;
end ;
procedure MoveTo( TargetX,TargetY,TargetZ:integer ) ; //Идти в точку с координатами x,y,z
begin
buf:=#$0F; //01=MoveBackwardToLocation:d(targetX)d(targetY)d(targetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
WriteD( targetx) ; //куда
WriteD( targety) ;
WriteD( targetz) ;
WriteD( MyX) ; //откуда
WriteD( MyY) ;
WriteD( MyZ) ;
WriteD( 1 ) ; //используем 1-мышь 0-клавиатура
SendToServerEx( NickName) ;
end ;
procedure OnTimerForm ( Sender: TObject ) ; // таймер обновления данных в форме
var
i: integer ;
begin
textMyID.text := inttostr ( MyID) ; // обновляем данные в окне
textX.text := inttostr ( MyX) ;
textY.text := inttostr ( MyY) ;
textZ.text := inttostr ( MyZ) ;
textMyHP.text := inttostr ( MyHP) ;
textMyMaxHP.text := inttostr ( MyMaxHP) ;
textMyMP.text := inttostr ( MyMP) ;
textMyMaxMP.text := inttostr ( MyMaxMP) ;
// textMyCP.text:= inttostr(MyCP);
// textMyMaxCP.text:= inttostr(MyMaxCP);
textCenterX.text := inttostr ( CenterX) ;
textCenterY.text := inttostr ( CenterY) ;
textCenterZ.text := inttostr ( CenterZ) ;
textRadius.text := inttostr ( Radius) ;
textTargetID.text := inttostr ( TargetID) ;
textAttackCycle.text := inttostr ( AttackCycle) ;
textMobsLastIndex.text := inttostr ( MobsLastIndex) ;
textMobsKilled.text := inttostr ( MobsKilled) ;
textHPBottleCount.text := inttostr ( HPBottleCount) ;
textBottle_1 _Count.text := inttostr ( Bottle_1 _Count) ;
textBottle_2 _Count.text := inttostr ( Bottle_2 _Count) ;
MobsDBscreen.lines .Clear ;
for i:=1 to MobsLastIndex do // выводим БД мобов
begin
if ( TargetID = MobsObjID[i]) and MobsAgression[i] then
begin
MobsDBscreen.lines .add ( '<> ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if TargetID = MobsObjID[i] then
begin
MobsDBscreen.lines .add ( '-> ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if cbFilterRadius.checked then if MobsDist[i] <= Radius then
begin
MobsDBscreen.lines .add ( '-- ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if MobsAgression[i] then
begin
MobsDBscreen.lines .add ( '<- ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
continue ;
end ;
if ( not cbFilterRadius.checked ) then MobsDBscreen.lines .add ( '-- ' +inttostr ( i) +' МобID: ' +inttostr ( MobsObjID[i]) +' ТипID: ' +inttostr ( MobsNpcTypeID[i]) +' дистанция ' +inttostr ( MobsDist[i]) ) ;
end ;
ItemsDBscreen.lines .Clear ; // выводим БД дропа
for i:=1 to ItemsLastIndex do ItemsDBscreen.lines .add ( 'индекс в БД: ' +inttostr ( i) +' объект ID: ' +inttostr ( Items_ObjectID[i]) +' ID вещи: ' +inttostr ( Items_ItemID[i]) ) ;
if MobsLastIndex = 0 then MobsDBscreen.lines .add ( 'Мобы' ) ;
if ItemsLastIndex= 0 then ItemsDBscreen.lines .add ( 'Дроп' ) ;
end ;
procedure FormClose( Sender: TObject ; var Action: TCloseAction) ;
begin
Action:=caNone;
end ;
procedure CreateLabel ( text : string ) ; // процедура автоматизирует создание текстовых меток в форме
var
l: TLabel;
begin
l:= TLabel.Create ( panel) ;
l.caption :=text ;
l.parent :=panel;
l.left :=10 ;
l.top :=15 +20 *frmParamIndex;
inc ( frmParamIndex) ;
end ;
function CreateTextBox ( text :string ) :TEdit; // функция автоматизирует создание текстовых полей для вывода данных в форме
var
e: TEdit;
begin
e:= TEdit.Create ( panel) ;
e.text :=text ;
e.parent :=panel;
e.left :=80 ;
e.top :=10 +20 *frmParamIndex;
e.width := 95 ;
e.ReadOnly :=true ;
result:= e;
end ;
procedure Free; //Вызывается при выключении скрипта
begin
ClearDB;
TimerForm.free ;
TimerCombat.free ;
TimerPickUp.free ;
TimerBafBanka.free ;
TimerCheckDB.free ;
MobsDBscreen.free ;
ItemsDBscreen.free ;
log.free ;
frm.free ;
end ;
procedure UserInfo; // обновление данных о себе
var
i:word ;
begin
if InitMode then MyID:=ReadD( 18 ) ;
MyX:=ReadD( 2 ) ;
MyY:=ReadD( 6 ) ;
MyZ:=ReadD( 10 ) ;
i:=22 ;
ReadS( i) ;
i:=i+48 ;
MyMaxHP:=ReadD( i) ;
MyHP:=ReadD( i) ;
MyMaxMP:=ReadD( i) ; // чисто информативно
MyMP:=ReadD( i) ;
// i:=i+363; //пока не используется
// MyMaxCP:=ReadD(i);
// MyCP:=ReadD(i);
end ;
procedure StatusUpdate; // обновление данных о себе
var
i:integer ;
begin
for i:=0 to ReadD( 6 ) -1 do
case pck[i*8 +10 ] of
#$09 : MyHP:=ReadD( i*8 +14 ) ;
#$0A: MyMaxHP:=ReadD( i*8 +14 ) ;
#$0B: MyMP:=ReadD( i*8 +14 ) ;
#$0C: MyMaxMP:=ReadD( i*8 +14 ) ;
// #$21: MyCP:=ReadD(i*8+14); //пока не используется
// #$22: MyMaxCP:=ReadD(i*8+14);
end ;
if MyMaxHP > 0 then HPlevelProcent:= Round ( ( MyMaxHP/100 ) *HPLevel) ;
end ;
procedure DrinkBottle; // пьем бутылки и следим за их количеством
begin
if ( HPBottleCount > 0 ) and ( HPBottleObjID > 0 ) then
begin
UseItemObjID( HPBottleObjID) ;
dec ( HPBottleCount) ;
end ;
end ;
procedure MoveToLocation01;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then updateDB( i, ReadD( 06 ) , ReadD( 10 ) , ReadD( 14 ) , false ) ;
end ;
procedure NpcInfo16;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i = 0 then AddtoDB ( ReadD( 2 ) , ReadD( 6 ) , ReadD( 14 ) , ReadD( 18 ) , ReadD( 22 ) , InMobsList( ReadD( 6 ) ) )
else UpdateDB( i, ReadD( 14 ) , ReadD( 18 ) , ReadD( 22 ) , false ) ;
end ;
procedure Attack05;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i = 0 then log.Lines .Add ( 'Глюк, моб не найден, или нас утакует другой игрок!!!' )
else UpdateDB( i, ReadD( 15 ) , ReadD( 19 ) , ReadD( 23 ) , true ) ;
end ;
procedure Die06;
var
i: integer ;
begin
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then
if MobsObjID[i] = TargetID then
begin
TimerCombat.enabled := false ;
if Spoil and Spoiled then
if ReadD( 22 ) = 1 then RequestMagicSkillUse( 42 ) ;
LastKilledMobObjID:=TargetID;
inc ( MobsKilled) ; // подводим статистику
MobsIsAttackable[i]:= false ;
MobsAgression[i]:= false ;
Spoiled:= false ;
TargetID:= 0 ;
TimerCombat.enabled := true ;
end ;
end ;
procedure DeleteObject12;
var
i: integer ;
begin
if LastKilledMobObjID = ReadD( 2 ) then
begin
LastKilledMobObjID:= 0 ;
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then DelDBItem( i) ;
exit ;
end ;
i:= CheckItems( ReadD( 2 ) ) ;
if i > 0 then
begin
if Items_ObjectID[i] = TargetID then TargetID:= 0 ;
DelDroppedItem( i) ;
exit ;
end ;
i:= TestPovtor( ReadD( 2 ) ) ;
if i > 0 then
begin
if TargetID = ReadD( 2 ) then TargetID:= 0 ;
DelDBItem( i) ;
exit ;
end ;
end ;
begin
if pck = '' then exit ;
if ( ConnectName = NickName) and FromServer then // разбор пакетов от сервера
case pck[1 ] of
#$01 : MoveToLocation01; // MoveToLocation:h(ObjectID)d(CurX)d(CurY)d(CurZ)d(DestX)d(DestY)d(DestZ)
// #$03: ; // CharInfo:d(X)d(Y)d(Z)-(4)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)-(4)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PvPFlag)d(Carma)d(MSpeed)d(PSpeed)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sitting)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(MountType)b(PrivateStoreType)
#$04 : if ReadS( 22 ) = NickName then // UserInfo:d(X)d(Y)d(Z)d(Heading)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)d(Level)d(Exp)d(STR)d(DEX)d(CON)d(INT)d(WIT)d(MEN)d(MaxHP)d(CurrentHP)d(MaxMP)d(CurrentMP)d(SP)d(CurrentLoad)d(MaxLoad)d(Unknown)d(Under)d(REar)d(LEar)d(Neck)d(RFinger)d(LFinger)d(Head)d(RHand)d(LHand)d(Gloves)d(Chest)d(Legs)d(Feet)d(Back)d(LRHand)d(Hair)i(Under)i(REar)i(LEar)i(Neck)i(RFinger)i(LFinger)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accuracy)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateStoreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cubics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLeft)b()b(RecomHave)b()
begin
UserInfo;
btnInit.enabled := false ;
if MyHP = 0 then // Проверка не убили ли нас...
begin
SendMsg_to_CL( 'Нас убили...' ) ;
log.Lines .Add ( 'Нас убили...' ) ;
StopGame;
end ;
end ;
#$05 : if ( ReadD( 6 ) = MyID) and ( not InitMode) then Attack05; // 05= Attack:d(AttackerID)d(TargetID)d(Damage)b(Flags)d(X)d(Y)d(Z)h(Hits)
#$48 : begin ; // 48= MagicSkillUse:h(CharID)h(targetID)d(skillID)d(skillLvl)d(hitTime)d(reuseDelay)d(X)d(Y)d(Z)w(count)d(d)d(d)d(d)
if ( ReadD( 2 ) = MyID) and ( ReadD ( 6 ) = TargetID) and ( ReadD( 10 ) = 254 ) then Spoiled:= true ;
end ;
#$06 : Die06; // Die:d(ChaID)
#$0C: if LastKilledMobObjID = ReadD( 2 ) then // DropItem:h(PlayerID)h(ObjectID)i(ItemID)d(X)d(Y)d(Z)d(Stackable)d(Count)
begin
AddDroppedItem( ReadD( 6 ) , ReadD( 10 ) , ReadD( 14 ) , ReadD( 18 ) , ReadD( 22 ) ) ;
end ;
#$0D: if TargetID = ReadD( 6 ) then // GetItem:d(PlayerID)h(ObjectID)d(X)d(Y)d(Z)
begin
TargetID:= 0 ;
end ;
#$0E: if MyID=ReadD( 2 ) then // StatusUpdate:h(ObjectID)d(Attributes)
begin
StatusUpdate;
if ( MyHP > 0 ) and ( MyHP < HPlevelProcent) then if Wait( time1,DrinkDelay) then DrinkBottle; // пьем бутылки
if MyHP > HPlevelProcent then time1:=1 ;
if MyHP = 0 then // Проверка не убили ли нас...
begin
SendMsg_to_CL( 'Нас убили...' ) ;
log.Lines .Add ( 'Нас убили...' ) ;
StopGame;
end ;
end ;
#$12 : DeleteObject12; // DeleteObject:h(ObjectID)
#$16 : if ( ReadD( 10 ) =1 ) and ( pck[121 ]=#$00 ) then NpcInfo16; // NpcInfo:h(ObjectID)d(NpcTypeID)d(IsAttackable)d(X)d(Y)d(Z)d(Heading)d(Unknown)d(MAtkSpd)d(PAtkSpd)d(RunSpd)d(WalkSpd)d(SwimRunSpd)d(SwimWalkSpd)d(FlRunSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(ProperMultiplier)f(PAtkSpd)f(CollisionRadius)f(CollisionHeight)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRunning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Name)s(Title)
#$1B: begin
InventoryCreate; // Инвентарь
if HPBottleID <> 0 then
begin
HPBottleObjID:= getinv( HPBottleID, 2 ,1 ) ;
HPBottleCount:= getinv( HPBottleID, 2 ,3 ) ;
end ;
if Bottle_1 _ID <> 0 then
begin
Bottle_1 _ObjID:=getinv( Bottle_1 _ID, 2 ,1 ) ;
Bottle_1 _Count:=getinv( Bottle_1 _ID, 2 ,3 ) ;
end ;
if Bottle_2 _ID <> 0 then
begin
Bottle_2 _ObjID:=getinv( Bottle_2 _ID, 2 ,1 ) ;
Bottle_2 _Count:=getinv( Bottle_2 _ID, 2 ,3 ) ;
end ;
end ;
#$27 : begin
InventoryUpdate;
if HPBottleID <> 0 then
begin
HPBottleObjID:= getinv( HPBottleID, 2 ,1 ) ;
HPBottleCount:= getinv( HPBottleID, 2 ,3 ) ;
end ;
if Bottle_1 _ID <> 0 then
begin
Bottle_1 _ObjID:=getinv( Bottle_1 _ID, 2 ,1 ) ;
Bottle_1 _Count:=getinv( Bottle_1 _ID, 2 ,3 ) ;
end ;
if Bottle_2 _ID <> 0 then
begin
Bottle_2 _ObjID:=getinv( Bottle_2 _ID, 2 ,1 ) ;
Bottle_2 _Count:=getinv( Bottle_2 _ID, 2 ,3 ) ;
end ;
end ;
#$13 : if RestartMode then // CharacterSelectionInfo
begin
buf:=#$12 ; // CharacterSelected
WriteD( CharNumber) ;
buf:= buf + hstr( '00 00 00 00 00 00 00 00 00 00 00 00 00 00' ) ;
SendToServerEx( NickName) ;
RestartMode:= false ;
end ;
end ;
if ( ConnectName = NickName) and FromClient then // разбор пакетов от клиента
case pck[1 ] of
#$1F: if InitMode then TargetID:= ReadD( 2 ) ; // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b(ActionID)
#$49 : UserCommands; // Say2:s(Text)d(Type)s(Target)
#$59 : begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD( 2 ) ;
MyY:= ReadD( 6 ) ;
MyZ:= ReadD( 10 ) ;
if ( not CenterFixed) and InitMode then
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
end ;
end ;
end ;
end .
хмм, это с пакетами отредактированный ?
домой приду проверю... просто вчера пробовал все передал, но команды из чата не воспринимал (
Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
Часовой пояс GMT +4, время: 03:59 .
vBulletin style designed by
MSC Team .
Powered by vBulletin® Version 3.6.11
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод:
zCarot
Вы хотите чувствовать себя в безопасности? чоп Белган обеспечит её!