Просмотр полной версии : ДА БУДЕТ БOT!
Объясните для тупых для чего этот скрипт???
Объсняю это заготовка которую можно юзать для определяния зарания зану кача. мозг боту надо есчё написать.
Взгляните, что то нр не пьются*(
viewtopic.php?f=8&t=264&p=5166#p5166 (http://www.forum.coderx.ru/viewtopic.php?f=8&t=264&p=5166#p5166)
прошу не хамить*))))
Хочу вот попробовать убить РБ в 1 окно.
1- может пакетно увеличить скорость атаки или как бы атаковать много раз за 1-2 сек.
2- может для етого пакет юзеринфо или атаки брать???
печаль вызывает на моём лице такое.. скока раз еще говорить можно! нельзя обмануть сервер с помощью КЛИЕНТА! НЕЛЬЗЯ! можно баги найти в сервере тока, и ченить автоматизировать...
[quote="Agat"]1. За минуту до объявления Олимпиады ставишь галочку напротив скрипта "сдача манора". :wink:
2. Сразу у нпц пытаешься сдать манор. Выдаст ошибку. :shock: Это нормально.
Сдаешь не сразу :ROFL: А после получения сообщения сообщения "Отчет начат"!
VORON, ВороН пожалуйста объясни попорядку как запустить твой бот что именно надо делать и какие переменные надо вбивать и каким способом твой скрипт запускается...чтото я не могу его запустить и понять как он запускается! зараннее спасибо!!!
Я про автокач бота твоегО! и еще просьбочка если появилось чтото более легко настраиваемое либо модернизированое рабочее то выкладывайте не жалейте свои русурсы!
хм а чё там настраивать Name='ник' в константы записать и везде ник на Name заменить
VORON, ВороН пожалуйста объясни попорядку как запустить твой бот что именно надо делать и какие переменные надо вбивать и каким способом твой скрипт запускается...чтото я не могу его запустить и понять как он запускается! зараннее спасибо!!!
если ты про КАЧБОТ-"ЛОКОМАТИВ!" то.. я его сделал и забыл про него уже почти на пол года.. не усовершенствовал его с тех пор как выложил.. но сегодня уже будучи на другом сервере и с чаром другой профой и другим именем захотелось его доделать.. запустил за 5 сек.. проблем вапще не возникло.. все имена исправил на реальные.. (имена ника персонажа).. включил галочку.. побегал туда сюда 5 сек (для захвата координат) потом прибежал на место кача (жэлательно круглую), встал в центр и написал в чат "х1" (по английски), потом добежал до граници предполагаемой области кача и написал в чат "х2".. потом чтоб база заполнилась нужными мобами убежал оттуда метров на 100 чтоб мобы за горизонтом исчезли с того места где я кач буду.. и вернулся назад чтоб мобы заного отобразились и запомнились в базу данных с мобами.. написал в чат "хх" и вуаля.. перс сам стал охотиться за мобами..
правда тупо так-)) но работает... одного убьет- бежит к новому-) убьет- к новому-).. весело-)
в ближайшее время доделаю скрипт.. чтоб он мог сам лут собирать, и оперативней новую цель выбирал.. а то в етом варианте он над трупом стоит до полного его исчезновеня (делет обжэкт пакет, нужно переделать на ДАЙ-пакет) еще хачу объединить 2 линии скриптоводства в одно.. первая линия ето баферы- ассисты, бафают, хилят, регенят.. я почти сделал такой скрипт который управляет ШЕ+ПП+БИШОП одновременно.. но его изюменкой является то что его можно не коректируя применять в ситуации даже если одного или 2-х участников нету (типа 1 ПП тока, или 1 ШЕ, или 1 БИШ).. т.е. более менее универсальный скрипт.. вторая линия скриптоводства ето создания бота с мозгами на скрипте - типа етого скрипта.. я хачу научить етого бота управлять ботами баферами.. большинство функций у ботов баферов ассистов- автоматизировано, но приказы на РЕБАФ или на что то другое нестандартное- должен отдовать бот командир типа- "ЛОКОМАТИВА" вопщем хачу в итоге получить 2 скрипта, для сапортов и для главного перса, по возможности универсально.. щас просто стал танкера качать.. а кач его дело очень утомительное.. поетому хачу на бота ету праблу переложить.. но в общем.. я тебе объяснил как запускать.. я буквально седня проверял- он отлично запускается..
Всем привет.
У меня есть несколько вопросов.
Вообще дело обстоит так. Недавно попробовал в Брандадах спойлить сопы при помощи полеарма.Тоесть собрать паровозик, испльзовать wild spoil, убить всю толпу и потом sweep'ать. И пока бьешь моба который на таргете может погибнуть несколько других в паровозе, нужных для спола->свипа. Беда заключается в том, что очень сложно взять этих мертвых мобов на таргет в результате чего они пропадают непросвипаные. И я подумал что можно было бы для таргета отлавливать пакеты дайд и брать оттуда IDI для дальнейшего таргета, но , во-первых, там не указывается вид моба (требуется свипать тока один или два вида мобов, зависит от недели), а во-вторых, этих пакетов (дайд) просто куча и не представляется возможным выбрать из них тех трупов которых сделал я)).
Так вот не могли бы вы мне помочь по данному вопросу. Не судите строго, если где-то глупость написал. Я пока мало чего знаю и умею, но пытаюсь понять. Заранее спасибо.
dmitry501
27.02.2008, 13:32
Вопроса не увидел. Как помочь если не понятно что ты хочешь. Ты описал факты и всё. Учись формулировать мысли.
Реально в игре спойлить то толпу можно, но свипить можно только того кто в таргете - потерял таргет после смерти моба - потерял дроп.
Я думаю, что полиарма - это не та пушка в данном случае.
Это я не по скрипту написал, а по игровому процессу.
VORON, ВороН пожалуйста объясни попорядку как запустить твой бот что именно надо делать и какие переменные надо вбивать и каким способом твой скрипт запускается...чтото я не могу его запустить и понять как он запускается! зараннее спасибо!!!
если ты про КАЧБОТ-"ЛОКОМАТИВ!" то.. я его сделал и забыл про него уже почти на пол года.. не усовершенствовал его с тех пор как выложил.. но сегодня уже будучи на другом сервере и с чаром другой профой и другим именем захотелось его доделать.. запустил за 5 сек.. проблем вапще не возникло.. все имена исправил на реальные.. (имена ника персонажа).. включил галочку.. побегал туда сюда 5 сек (для захвата координат) потом прибежал на место кача (жэлательно круглую), встал в центр и написал в чат "х1" (по английски), потом добежал до граници предполагаемой области кача и написал в чат "х2".. потом чтоб база заполнилась нужными мобами убежал оттуда метров на 100 чтоб мобы за горизонтом исчезли с того места где я кач буду.. и вернулся назад чтоб мобы заного отобразились и запомнились в базу данных с мобами.. написал в чат "хх" и вуаля.. перс сам стал охотиться за мобами..
правда тупо так-)) но работает... одного убьет- бежит к новому-) убьет- к новому-).. весело-)
в ближайшее время доделаю скрипт.. чтоб он мог сам лут собирать, и оперативней новую цель выбирал.. а то в етом варианте он над трупом стоит до полного его исчезновеня (делет обжэкт пакет, нужно переделать на ДАЙ-пакет) еще хачу объединить 2 линии скриптоводства в одно.. первая линия ето баферы- ассисты, бафают, хилят, регенят.. я почти сделал такой скрипт который управляет ШЕ+ПП+БИШОП одновременно.. но его изюменкой является то что его можно не коректируя применять в ситуации даже если одного или 2-х участников нету (типа 1 ПП тока, или 1 ШЕ, или 1 БИШ).. т.е. более менее универсальный скрипт.. вторая линия скриптоводства ето создания бота с мозгами на скрипте - типа етого скрипта.. я хачу научить етого бота управлять ботами баферами.. большинство функций у ботов баферов ассистов- автоматизировано, но приказы на РЕБАФ или на что то другое нестандартное- должен отдовать бот командир типа- "ЛОКОМАТИВА" вопщем хачу в итоге получить 2 скрипта, для сапортов и для главного перса, по возможности универсально.. щас просто стал танкера качать.. а кач его дело очень утомительное.. поетому хачу на бота ету праблу переложить.. но в общем.. я тебе объяснил как запускать.. я буквально седня проверял- он отлично запускается..
кстате работаю над темже :) тока намного хуже чем у тебя дела :) пакет на смерть моба 06(Mobid)00 00 00 00... ну что б привязать дрын из трупа или удалить быстро из таргета :) ну разумей как хочешь помоему лутьше удалять из масива с объжект делета, но таргет менят или если надо использовать скилы дрына из трупа и призыв самона :) с 06
Хм, ну извините что не понятно объяснил.
Вопрос в том как сделать автосвип, а в частности, как сделать таргет по убитым мною мобам определенного вида до того как они исчезнут?
По игровому процессу:
Спойлить целую толпу реально выгоднее. Свипать безспорно сложно и требует много внимания ловкости и сноровки.
Но по личным наблюдения, с учетом всех оговорок, куда гораздо выгоднее чем по одному.
dmitry501
28.02.2008, 07:11
Как сделать автосвип. Как обычно. Садишься и пишешь скрипт.Пиши что конкретно непонятно. Твой вопрос подобен - "Как сделать работу".
Сначала разрабатываешь алкгоритм. например
Запомнить ID мобов, которых проспоилил.
При смерти моба смотреть на расстояние до него, попал ли он в нашу таблицу споила и попадает ли в требования по нужности его свипа.
Если моб по всем параметрам подходит, то добежать до него и просвипать.
При получении пакета удаления нпц удалять строку в таблице спойла.
Затем начинаешь писать уже конкретнй скрипт по реализации алгоритма - непостредственно кодить.
Затем все отлаживаешь, находишь косяки в исходном алгоритме, перерабатываешь алгоритм и все заново....
Суть надеюсь ясна?
Принцип понятен.
Но например, как запомнить ID моба, если ты его на таргет не брал, но проспойлил?
Я отслеживал пакеты и не нашел ни одиного в котором указывалось что моб такой-то, проспойлен.
Принцип понятен.
Но например, как запомнить ID моба, если ты его на таргет не брал, но проспойлил?
Я отслеживал пакеты и не нашел ни одиного в котором указывалось что моб такой-то, проспойлен.
Вот кусок кода с проверкой, что моб проспойлен от skymanrus
#$06: begin
//06=Die:h(CharID)d(d)d(HAsHideout)d(HasCastle)d(fla gs)d(sweepable)d(access)
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
if (pck[22]=#$01) then begin //моб проспойлен?
mlk.Lines.Add(' свипаю!');
buf:=hstr('04')+spoilid+hstr('00');
SendToServerEx(Name);
buf:=hstr('2F 2A 00 00 00 00 00 00 00 00');
SendToServerEx(Name);
spoilid:='';
//// mlk.Lines.Add(' ТОРМОЗ! ОН УМЕР!!!');
//delay(700);
end;
Создавай массив со всеми мобами какие есть, а потом по пакету #06 Die пробегая по массиву и сверяя ObjID будешь проверять свипать или не.
06=Die:h(CharID)d(d)d(HAsHideout)d(HasCastle)d(fla gs)d(sweepable)d(access)
вот за ето спс :) очень помогло
я делал иначе.. в базу данных запоминал всех мобов которые нас меня или моих чаров (ид известны) били.. все кто их били автоматом считаются проспойлеными.. для создания такой базы я использовал примитивный пакет- АТАК (кто то камуто нанес урон..) далее при любом ДАЕ я смотрел кто из етих даев посинел.. и если синяя сучка оказалась среди тех кто меня бил или моих друзей- то надо ее полюбасу просвипать..
Добавлено спустя 12 минут 1 секунду:
Re: Стоит ответить
кстате работаю над темже :) тока намного хуже чем у тебя дела :) пакет на смерть моба 06(Mobid)00 00 00 00... ну что б привязать дрын из трупа или удалить быстро из таргета :) ну разумей как хочешь помоему лутьше удалять из масива с объжект делета, но таргет менят или если надо использовать скилы дрына из трупа и призыв самона :) с 06
я склоняюсь к одному что в любом варианте (предложенном) (покачто тока мной) - есть моск у бота .. который срабатывает (в моем варианте) 1 раз в 5 секунд (чем чаще тем тормозов больше) мой моск бота 1 раз в 5 сек- очень приметивен- он очень мало чего умеет.. его можно юзать и в каждый сек по 2-3 раза.. но по мере наростания его функциональности вопрос об быстродействие встанет все чаше..
скажу также что я неслова не понял из того что ты написал..
ето я понял..
"кстате работаю над темже :) тока намного хуже чем у тебя дела :) пакет на смерть моба 06(Mobid)00 00 00 00... "
это я непонял
"ну что б привязать дрын из трупа или удалить быстро из таргета :)"
это я тожэ не понял..
"ну разумей как хочешь помоему лутьше удалять из масива с объжект делета, но таргет менят или если надо использовать скилы дрына из трупа и призыв самона :) с 06"
давайте общаться на языке общедоступном...
Тут всказно - не просить скрипты, а как тогда быть человеку которому
нужен несложный скрипт, но он дуб в програминге (да и времени нет на это)?
Может всетаки кто-то сможет мне помочь, за плату в 5-10вебмани?
Что надо.. несложный скрипт - манор бот (соло без доп персов)
1 чтоб определял область кача
2 сканировал область кача и запоминал определеных мобов
3 вычислял оперделенного ближайшего моба
4 манорил его семенем
5 бил
6 собирал манор (если выпали деньги подбирал)
7 и снова с 2 пункта
Главное чтоб я не разбирал что там в скрипте - пришел,поменял ид на нужного моба, запустил и все.
Понимаю что нарушаю правило, но я же не бесплатно - надеюсь строго не накажете :)
p.s. если мало денег то определити цену попрашу народ на другом форуме - за такое скинутся
(ведь если исключить манор со скрипта то простенький скриптбот очень неплохо раскупят)
думаю даже Вороновски подошел бы тока достроить его до манора и тока на соло
(кчему лишнее) и растолковать по пунктам что надо делать...вот за это и хочу платить..
выкладываю более менее универсальный скрипт на баферов.. у вас ШЕ ПП БИШ ЕЕ?
впринципе независимо от сотава- скрипт переделок не требует.. запускаете и всё работет..
но! ваши пожелания в (когда и каму хилить и каким скилом ) учитываются там.. я коменты вставил- где править надо..
скрипт хорош тем что нетребует переделок если увас нет ШЕ ПП БИШ и ЕЕ одновременно а есть кто то 1..
етот скрипт исползует и баф и реген и хил.. для любого состава бафера точнее он написан для состава БИШ+ПП+ШЕ+ЕЕ- но подрузумевает в себе что их нет одновременно..
var
Bot1X,Bot1Y,Bot1Z,Bot2X,Bot2Y,Bot2Z,Bot3X,Bot3Y,Bo t3Z,Bot4X,Bot4Y,Bot4Z:string; //координаты баферов
IDAssistTarget:string; //таргет командира
rnd:integer; // вспомогательная для случайного события
bafSE: array [1..100] of string; //список бафов ШЕ
bafPP: array [1..100] of string; //список бафов ПП
bafEE: array [1..100] of string; //список бафов ЕЕ
BafSEApplyChar: array [1..100] of string; //указывает ИД чара на которого нужно наложить баф с помощью ШЕ
BafSEApplyBaf: array [1..100] of string; //указывает какой баф наложить на чара с помощью ШЕ
BafPPApplyChar: array [1..100] of string; //указывает ИД чара на которого нужно наложить баф с помощью ПП
BafPPApplyBaf: array [1..100] of string; //указывает какой баф наложить на чара с помощью ПП
BafEEApplyChar: array [1..100] of string; //указывает ИД чара на которого нужно наложить баф с помощью ЕЕ
BafEEApplyBaf: array [1..100] of string; //указывает какой баф наложить на чара с помощью ЕЕ
NameKom,NameBot1,NameBot2,NameBot3,NameBot4:string ; //имена чаров учавствующих в процессе
MaxHPKom,MaxHPBot1,MaxHPBot2,MaxHPBot3,MaxHPBot4:i nteger; //максимальные уровни ХП (лимиты)
MaxMPKom,MaxMPBot1,MaxMPBot2,MaxMPBot3,MaxMPBot4:i nteger; //максимальные уровни МП (лимиты)
//текущее значение ХП и МП
CurHPKom,CurMPKom,CurHPbot1,CurMPbot1,CurHPbot2,Cu rMPbot2,CurHPbot3,CurMPbot3,CurHPbot4,CurMPbot4:in teger;
IDKomandos,IDbot1,IDbot2,IDbot3,IDbot4:string; // идешники всех
timer3: TTimer; //для создания пати
timer4: TTimer; //мульти-баф, общий как для физика так и для мага.. нужные бафы указываются заранее в конце скрипта
BufEndSE,BufEndPP,BufEndEE:boolean;// используется в таймере (мультибаф) для указания на то что 1 из баферов закончил бафать
tick3,tick4:integer; // используется в таймере бафа для тиков.. каждый тик- новый баф..
i:integer;
tempD:integer;
tempS:String;
//**********************МУЛЬТИБАФ******************* ****************************************
procedure OnTimer4(Sender: TObject);
begin
//если очередной баф в списке бафов для бафера = '' (окончание процесса бафа) то значит бафер уже отбафал всё что нужно, хватит бафать..
if (BafPPApplyChar[tick4]='') then BufEndPP:=True;
if (BafSEApplyChar[tick4]='') then BufEndSE:=True;
if (BafEEApplyChar[tick4]='') then BufEndEE:=True;
//если все баферы закончили бафать то выключаем таймер мультибафа
//ну и счетчик тиков ставим в исходное положение
if (BufEndPP=True) and (BufEndSE=True) and (BufEndEE=True) then
begin
tick4:=1;
timer4.enabled:=false;
BufEndSE:=False;
BufEndPP:=False;
BufEndEE:=False;
//раз закончили бафать то не допускаем выполнение нижеследущего кода
exit;
end;
//бафаем чара.. используется переменные BafPPApplyChar[tick4],BafPPApplyBaf[tick4] для ПП и аналогичные для ШЕ и ЕЕ указывающие на то какому баферу ково бафать и каким бафом в текущий ТИК.
//ТИК- (tick4) - ето счетчик, который изменяется на 1 с каждым новым бафом.. т.е. каждые 4 секунды (интервал таймера) тик увеличивается на 1
//ТИКИ нужны чтоб каждый раз новый баф кастовать..
buf:=hstr('04') + BafPPApplyChar[tick4] + Bot2X + Bot2Y + Bot2Z + hstr('00');
if (BufEndPP=False) and (IDbot2<>'') then SendToServerEX(NameBot2);
buf:=BafPPApplyBaf[tick4];
if (BufEndPP=False) and (IDbot2<>'') then SendToServerEX(NameBot2);
buf:=hstr('04') + BafSEApplyChar[tick4] + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (BufEndSE=False) and (IDbot3<>'') then SendToServerEX(NameBot3);
buf:=BafSEApplyBaf[tick4];
if (BufEndSE=False) and (IDbot3<>'') then SendToServerEX(NameBot3);
buf:=hstr('04') + BafEEApplyChar[tick4] + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (BufEndEE=False) and (IDbot4<>'') then SendToServerEX(NameBot4);
buf:=BafEEApplyBaf[tick4];
if (BufEndEE=False) and (IDbot4<>'') then SendToServerEX(NameBot4);
tick4:=tick4+1;
end;
//****************************РАЗДАЧА ПРИГЛАШЕНИЙ НА ВСТУПЛЕНИЕ В ПАТИ*******************
procedure OnTimer3(Sender: TObject);
begin
if tick3 = 1 then
begin
buf:=hstr('2B');
//этот код закоментирован , для того чтобы не разрывать пати.. впринципе хз каму как.. если надо четко стабиильно пати создать быстро из своих ботов-баферов то раскоментить
//а если ты с баферами + другие чары с тобой бегают- то ненадо раскоменчивать.. хотя можно тока баферов раскоментить тогда они свою пати порвут и снова вступят к командиру (если он лидер пати)
// if IDKomandos<>'' then SendToServerEX(NameKom);
// if IDBot1<>'' then SendToServerEX(NameBot1);
// if IDBot2<>'' then SendToServerEX(NameBot2);
// if IDBot3<>'' then SendToServerEX(NameBot3);
// if IDBot4<>'' then SendToServerEX(NameBot4);
end;
if tick3 = 2 then
begin
buf:=hstr('29');
writeS(namebot1);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
if tick3 = 3 then
begin
buf:=hstr('29');
writeS(namebot2);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
if tick3 = 4 then
begin
buf:=hstr('29');
writeS(namebot3);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
if tick3 = 5 then
begin
buf:=hstr('29');
writeS(namebot4);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
tick3:=tick3+1;
//ну когда всем баферам приглашение отправили то вырубаем таймер
if tick3=6 then
begin
tick3:=1;
timer3.enabled:=false;
end;
end;
//*************************БЕЖИМ ЗА ЛИДЕРОМ*******************************************
//процедура заставляет бежать ботов за лидером
procedure BotBeg;
begin
//проверяем условие чтоб координаты ботов небыли равными '' и ИД был перехвачен
if IDKomandos <> '' then
begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot2X + Bot2Y + Bot2Z + hstr('00');
if IDBot2<>'' then SendToServerEX(NameBot2);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot2X + Bot2Y + Bot2Z + hstr('00');
if IDBot2<>'' then SendToServerEX(NameBot2);
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if IDBot3<>'' then SendToServerEX(NameBot3);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if IDBot3<>'' then SendToServerEX(NameBot3);
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if IDBot4<>'' then SendToServerEX(NameBot4);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if IDBot4<>'' then SendToServerEX(NameBot4);
end;
end;
procedure Init; //Вызывается при включении скрипта
begin
NameKom:='ИМЯ КОМАНДИРА';
NameBot1:='ИМЯ БИША'; //биш
NameBot2:='ИМЯ ПП'; //пп
NameBot3:='ИМЯ ШЕ'; //ше
NameBot4:='ИМЯ ЕЕ'; //ее
//список бафов:
bafPP[1]:=hstr('2F 0B 04 00 00 00 00 00 00 00'); // ментал
bafPP[2]:=hstr('2F 10 04 00 00 00 00 00 00 00'); // пд
bafPP[3]:=hstr('2F 2C 04 00 00 00 00 00 00 00'); // па
bafPP[4]:=hstr('2F 35 04 00 00 00 00 00 00 00'); // фокус
bafPP[5]:=hstr('2F 36 04 00 00 00 00 00 00 00'); // кон
bafPP[6]:=hstr('2F 3D 04 00 00 00 00 00 00 00'); // акумен
bafPP[7]:=hstr('2F A7 04 00 00 00 00 00 00 00'); // резист к огню
bafPP[8]:=hstr('2F B4 04 00 00 00 00 00 00 00'); // вв
bafPP[9]:=hstr('2F 26 04 00 00 00 00 00 00 00'); // берс
bafPP[10]:=hstr('2F 14 04 00 00 00 00 00 00 00'); // ХП реген
bafPP[12]:=hstr('2F 3E 04 00 00 00 00 00 00 00'); // хаст
bafPP[13]:=hstr('2F 15 04 00 00 00 00 00 00 00'); // блесс ХП
bafPP[14]:=hstr('2F 0C 04 00 00 00 00 00 00 00'); // маджик барьер
bafPP[15]:=hstr('2F 6C 05 00 00 00 00 00 00 00'); // гритер ПА
bafPP[16]:=hstr('2F 6D 05 00 00 00 00 00 00 00'); // гритер ПД
bafPP[17]:=hstr('2F 70 05 00 00 00 00 00 00 00'); // скаред атак резист
bafPP[18]:=hstr('2F 71 05 00 00 00 00 00 00 00'); // дарк атак резист
bafPP[19]:=hstr('2F A5 04 00 00 00 00 00 00 00'); // резист к ветру
bafPP[20]:=hstr('2F 9E 04 00 00 00 00 00 00 00'); // резист к воде
bafPP[21]:=hstr('2F DA 04 00 00 00 00 00 00 00'); // деф виспер
bafPP[22]:=hstr('2F D8 04 00 00 00 00 00 00 00'); // гвиданс
bafPP[23]:=hstr('2F 18 04 00 00 00 00 00 00 00'); // блесс МП
bafPP[24]:=hstr('2F DB 04 00 00 00 00 00 00 00'); // ЩИТ РЕЙТ
bafSE[1]:=hstr('2F 0B 04 00 00 00 00 00 00 00'); // ментал
bafSE[2]:=hstr('2F 10 04 00 00 00 00 00 00 00'); // ПД
bafSE[3]:=hstr('2F 2C 04 00 00 00 00 00 00 00'); // ПА
bafSE[4]:=hstr('2F F4 04 00 00 00 00 00 00 00'); // ВАМП
bafSE[5]:=hstr('2F 23 04 00 00 00 00 00 00 00'); // ЕМП
bafSE[6]:=hstr('2F 17 05 00 00 00 00 00 00 00'); // М.КРИТ
bafSE[7]:=hstr('2F 35 04 00 00 00 00 00 00 00'); // ФОКУС
bafSE[8]:=hstr('2F DA 04 00 00 00 00 00 00 00'); // ДЕФ ВИСПЕР
bafSE[9]:=hstr('2F D8 04 00 00 00 00 00 00 00'); // гвиданс
bafSE[10]:=hstr('2F B4 04 00 00 00 00 00 00 00'); // ВВ
bafEE[1]:=hstr('2F EB 04 00 00 00 00 00 00 00'); // резист ШОК
bafEE[2]:=hstr('2F 3F 04 00 00 00 00 00 00 00'); // ЭВЕЙШН
CurHPKom:=15000;
CurHPBot1:=15000;
CurHPBot2:=15000;
CurHPBot3:=15000;
CurHPBot4:=15000;
CurMPKom:=15000;
CurMPBot1:=15000;
CurMPBot2:=15000;
CurMPBot3:=15000;
CurMPBot4:=15000;
MaxHPKom:=10;
MaxHPBot1:=10;
MaxHPBot2:=10;
MaxHPBot3:=10;
MaxHPBot4:=10;
tick3:=1;
tick4:=1;
BufEndSE:=False;
BufEndPP:=False;
BufEndEE:=False;
timer4:=TTimer.Create(nil);
timer4.OnTimer:=@OnTimer4; //
timer4.enabled:=false; //
timer4.interval:=4000;
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3; //
timer3.enabled:=false; //
timer3.interval:=1000;
// ЗАПРОС НА ОТКРЫТИЕ ИНВЕНТОРЯ!!!! ДЛЯ ЗАХВАТА ИДЕШНИКА!
// чтобы принудительно вызвать от сервера пакет ЮЗЕР ИНФО в котором ИД указан
buf:=hstr('0F');
SendToServerEX(NameKom);
SendToServerEX(NameBot1);
SendToServerEX(NameBot2);
SendToServerEX(NameBot3);
SendToServerEX(NameBot4);
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer3.Free;
timer4.Free;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//для тго чтоб 2-3 скрипта коректно работали одновременно..
if pck='' then exit;
//******************************АВТОСОГЛАШЕНИЕ НА ВСТУПЛЕНИЕ В ПАТИ************************
//******************************ПРИ УСЛОВИИ ЧТО ПАТИ ДАЕТ- КОМАНДИР************************
//ну тут тупо считываем имя кто нам шлет пати из пакета на предложение в него вступить
//ну и если имя- командир то вступаем в ету пати автоматом..
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot1);
end;
if FromServer then
if ConnectName=NameBot2 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot2);
end;
if FromServer then
if ConnectName=NameBot3 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot3);
end;
if FromServer then
if ConnectName=NameBot4 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot4);
end;
//*******************ЗАХВАТ КООРДИНАТ***************************************** **********
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot1 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot1X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot1Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot1Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot2 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot2X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot2Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot2Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot3 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot3X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot3Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot3Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot4 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot4X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot4Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot4Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//********************ОСТСЛЕЖИВАЕМ ТРУПАКИ******************************************* *************
//если кто то умер то приходит пакет DIE.. то хилить его ненадо...
//нефиг трупы хилить...
//для того чтоб трупяков боты не хилили ставим кодом то что ХП (текущее) у них до жопы... т.е. 15к
if FromServer then
if ConnectName=NameKom then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDKomandos then
CurHPKom:=15000;
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot1 then
CurHPBot1:=15000;
if FromServer then
if ConnectName=NameBot2 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot2 then
CurHPBot2:=15000;
if FromServer then
if ConnectName=NameBot3 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot3 then
CurHPBot3:=15000;
if FromServer then
if ConnectName=NameBot4 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot3 then
CurHPBot4:=15000;
//*************************УЗНАЕМ ЛИМИТЫ ХП и МП и ИД***********************************************
//из пакета UserInfo который приходит во время бафа и не только
//как тока скрипт начинает свою работу то он на все аки отправляет запрос на открытие ИНВЕНТОРЯ
//вместе с ответом сервера всегда приходит пакет ЮЗЕР ИНФО.. из етого замечательного пакета мы считываем максимальные значения ХП и МП
//а так жэ ИД чара (бота- бафера)
//КОМАНДИР
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$04 then
begin
IDKomandos:=pck[18]+pck[19]+pck[20]+pck[21]; //тут выдергиваем ИД чара
i:=22;
tempS:=readS(i); // ето используем для удобства.. имя типа пропускаем.. потому как каждый раз оно из разного кол-ва букв состоит.. в скобках переменная автоматом увеличивается на кол-во букв (ну там по формуле.. в юникоде 1 буква=2 байта, и символ окончания строки еще 00 00)
i:=i+48; // через 48 байтофъ после имени указывается лимиты и текущие значения для ХП и МП
//запоминаем их.. тут нам не особо важны текущие значения.. хотя лишний раз не помешают
//но важно- максимальное значение- ЛИМИТЫ
MaxHPKom:=readD(i);
CurHPKOM:=readD(i);
MaxMPKom:=readD(i);
CurMPKOM:=readD(i);
end;
//1-й бот
if FromServer then
if ConnectName = NameBot1 then
if pck[1]=#$04 then
begin
IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot1:=readD(i);
CurHPBot1:=readD(i);
MaxMPBot1:=readD(i);
CurMPBot1:=readD(i);
end;
//2-й бот
if FromServer then
if ConnectName = NameBot2 then
if pck[1]=#$04 then
begin
IDBot2:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot2:=readD(i);
CurHPBot2:=readD(i);
MaxMPBot2:=readD(i);
CurMPBot2:=readD(i);
end;
//3-й бот
if FromServer then
if ConnectName = NameBot3 then
if pck[1]=#$04 then
begin
IDBot3:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot3:=readD(i);
CurHPBot3:=readD(i);
MaxMPBot3:=readD(i);
CurMPBot3:=readD(i);
end;
//4-й бот
if FromServer then
if ConnectName = NameBot4 then
if pck[1]=#$04 then
begin
IDBot4:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot4:=readD(i);
CurHPBot4:=readD(i);
MaxMPBot4:=readD(i);
CurMPBot4:=readD(i);
end;
//*************************СЛЕДИМ ЗА ХП и МП******************************************
//а ету часть кода требуется под ваши жэлания настроить..
//тут указываются значения при которых ПП ШШ ЕЕ БИШ будут вам ману лить и ХП заливать и каким именно скилом
//следим за ХП КОМАНДИРА
//отлавливаем СТАТУС АПДЕЙТ!!!!!
//как выяснилось статус апдейта бывает 2 разных..
//1 для ХП, 2 для МП
//етот пакет приходит при любом изменении ХП и МП у чара..
//чтоб их отличить сервак использует индекс.. в 6-м байте присылает либо 4 либо 2..
//если в 6-м байте СТАТУС АПДЕЙТ цифра #$04 то значит реч в етом пакете про ХП
//а если #$02 то реч в етом пакете про МП..
//возможно что для ЦП есть еще другой указатель но скрипт не учитывает ЦП никак..
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$0e then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$04) then
begin
//считываем текущее состояние ХП!!-)
CurHPKom:=ReadD(14);
//ну собственно ето уже можно править под желания каждого:
//если жизни текущие меньше 0,7 от шкалы (70%) и при етом больше (0,25 = 25%)25% от шкалы то..
//то биш использует свой любимый скил МАЖОР ХИЛ за спирит оре (в интерлюде) (для ц4 такого скила нету)
if (CurHPKom < round(MaxHPKom*0.7)) and (CurHPKom > round(MaxHPKom*0.25)) then
begin
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00'); // МАЖОР ХИЛ
if (IDBot1 <> '') then SendToServerEX(NameBot1);
end;
//если жизни опустились меньше чем 25% то надо хилить бишем очень быстро поетому используем БЕТЛ ХИЛ
//(чтоб из жопы вытащить)
if (CurHPKom < round(MaxHPKom*0.2)) then
begin
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F C2 04 00 00 00 00 00 00 00'); // БЭТЛ ХИЛ
if (IDBot1 <> '') then SendToServerEX(NameBot1);
end;
// при желании можно еще чтоб ПП хилил.. лимит при котором он будет хилить БЕТЛ ХИЛОМ устанавливаем..
if (CurHPKom < round(MaxHPKom*0.7)) then
begin
buf:=hstr('04') + IDKomandos + Bot2X + Bot2Y + Bot2Z + hstr('00');
if (IDBot2 <> '') then SendToServerEX(NameBot2);
buf:=hstr('2F F7 03 00 00 00 00 00 00 00'); //ПП ХИЛИТ
if (IDBot2 <> '') then SendToServerEX(NameBot2);
end;
//ШЕ НЕ ХИЛИТ но вставивив сюда 6 строк аналогичных предыдущим будет и ШЕ хилить..
//но зато хилит ЕЕ.. смотрите.. аналогично может и ШЕ хилить...
//вы уже поняли что ЕЕ включит хил на 50% ХП командира
if (CurHPKom < round(MaxHPKom*0.5)) then
begin
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
buf:=hstr('2F C1 04 00 00 00 00 00 00 00 '); //ЕЕ ХИЛИТ
if (IDBot4 <> '') then SendToServerEX(NameBot4);
end;
end;
//следим за ХП у БОТ1
//если злой хренко решит наших баферов бить, а потом нас- то мы просто так не сдадимся..
//баферам ХИЛ дадим.. чтоб хренко били били и не убили...
//я сделал тупо- чтоб тока сам себя хилял бафер.. добавьте аналогичные строки сюда и будет так что все баферы будут хилить баф-бота
//ето надо полюбасу- но пока руки не дошли.. и вам немного задачи- доделать скрипт..
//но я етого не сделал еще по одной причине.. в реальных условиях мой командир бегает оч шустро..
//баферы отстают.. если 1 бафер на пвп отстанет- да и хер с ним.. а если етого отстающего бьют..
//и все мои баферы кинутся его хилить (если его бьют) то я через 15 сек буду оч далеко и меня уже баферы не догонят
//и я буду- (командир пати) без хила.. поетому если бафера атакуют то я сделал чтоб он сам себя лечил..
// но чтоб другие не лечили, чтоб другие за мной бежали..
if FromServer then
if ConnectName = NameBot1 then
if pck[1]=#$0e then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot1 + #$04) then
begin
CurHPbot1:=ReadD(14);
//на 70% шкалы хилит бафер сам себя (бишоп) скилом мажор хил
if (CurHPbot1 < round(MaxHPBot1*0.7)) then
begin
buf:=hstr('04') + IDbot1 + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00'); //скил бишопа: можор хил
if (IDBot1 <> '') then SendToServerEX(NameBot1);
end;
end;
//следим за ХП у БОТ2
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot2 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot2 + #$04) then
begin
CurHPbot2:=ReadD(14);
if (CurHPbot2 < round(MaxHPBot2*0.7)) then
begin
buf:=hstr('04') + IDbot2 + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') and (IDBot2 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00');
if (IDBot1 <> '') and (IDBot2 <> '') then SendToServerEX(NameBot1);
end;
end;
//следим за ХП у БОТ3
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot3 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot3 + #$04) then
begin
CurHPbot3:=ReadD(14);
if (CurHPbot3 < round(MaxHPBot3*0.7)) then
begin
buf:=hstr('04') + IDbot3 + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F C1 04 00 00 00 00 00 00 00');
if (IDBot3 <> '') then SendToServerEX(NameBot1);
end;
end;
//следим за ХП у БОТ4
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot4 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot4 + #$04) then
begin
CurHPbot4:=ReadD(14);
if (CurHPbot4 < round(MaxHPBot4*0.7)) then
begin
buf:=hstr('04') + IDbot4 + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (IDBot4 <> '') and (IDBot4 <> '') then SendToServerEX(NameBot4);
buf:=hstr('2F C1 04 00 00 00 00 00 00 00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
end;
end;
//следим за МП у КОМАНДИРА (ШЕ следит)
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameKom then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$02) then
begin
CurMPkom:=ReadD(14);
if (CurMPkom < round(MaxMPkom*0.5)) then
begin
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F F5 03 00 00 00 00 00 00 00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
end;
end;
//следим за МП у КОМАНДИРА (ЕЕ следит)
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameKom then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$02) then
begin
CurMPkom:=ReadD(14);
if (CurMPkom < round(MaxMPkom*0.5)) then
begin
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
buf:=hstr('2F F5 03 00 00 00 00 00 00 00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
end;
end;
//следим за МП у БИША
//этот кусок кода вполне альтернативный..
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot1 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot1 + #$02) then
begin
CurMPBot1:=ReadD(14);
if (CurMPBot1 < round(MaxMPBot1*0.9)) then
begin
buf:=hstr('04') + IDBot1 + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F F5 03 00 00 00 00 00 00 00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
end;
end;
//**********************СЛЕДИМ ЗА ТАРГЕТАМИ****************************************
//КОМАНДИР
//если принят пакет со сменой таргета у командира то
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$A6 then
begin
//запоминаем ИД таргета командира для ассиста
IDAssistTarget:= pck[2]+pck[3]+pck[4]+pck[5];
end;
//**********************САЖАЕМ ВСЮ ПАТИ ЧЕРЕЗ КОНТРОЛ****************************************
//если принят пакет на сажание с контролом то сажаем всю пати
if FromClient then
if (ConnectName = NameKom) then
if (pck[1]+pck[2]+pck[6]=hstr('45 00 01')) then
begin
buf:=hstr('45 00 00 00 00 01 00 00 00 00');
if IDBot1<>'' then SendToServerEX(NameBot1);
if IDBot2<>'' then SendToServerEX(NameBot2);
if IDBot3<>'' then SendToServerEX(NameBot3);
if IDBot4<>'' then SendToServerEX(NameBot4);
end;
//*******************БЕЖИМ ЗА КОМАНДИРОМ ПОСЛЕ ИСПОЛЬЗОВАНИЯ СКИЛА***************************
//ловим пакет МАДЖИКСКИЛЮЗ
if FromServer then
if pck[1] = #$48 then
if (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT1) or (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT2) or (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT3) then
begin
BotBeg;
end;
//**************************УПРАВЛЕНИЕ************** **********************************
//"Bow" (ПОКЛОН)- БЕЖАТЬ за КОМАНДИРОМ
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 07') then
begin
pck:='';
BotBeg;
exit;
end;
//ADVANCE- В АТАКУ - пати быстрое создание (3-я кнопка)
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 04') then
begin
pck:='';
//сразу рвем пати у всех чаров и командир раздает пати поновому
//чары автоматически принимают пати
//используется таймер т.к. одновременно 2-м чарам пати кинуть нельзя
timer3.enabled:=true;
exit;
end;
//YES- РУТ ПО АССИСТУ (4-я кнопка) либо переделать в какойто дебаф от каждого бафера он свой.. по ассисту все баферы какуюто куйню кинут на цель по ассисту..
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 06') then
begin
pck:='';
buf:=hstr('04') + IDAssistTarget + Bot1X + Bot1Y + Bot1Z + hstr('00');
if NameBot1<>'' then SendToServerEX(NameBot1);
buf:=hstr('04') + IDAssistTarget + Bot2X + Bot2Y + Bot2Z + hstr('00');
if NameBot2<>'' then SendToServerEX(NameBot2);
buf:=hstr('04') + IDAssistTarget + Bot3X + Bot3Y + Bot3Z + hstr('00');
if NameBot3<>'' then SendToServerEX(NameBot3);
buf:=hstr('2F 72 05 00 00 01 00 00 00 00');
if NameBot1<>'' then SendToServerEX(NameBot1);
buf:=hstr('2F B1 04 00 00 01 00 00 00 00');
if NameBot2<>'' then SendToServerEX(NameBot2);
buf:=hstr('2F B1 04 00 00 00 00 00 00 00');
if NameBot3<>'' then SendToServerEX(NameBot3);
exit;
end;
//NO буф МАГА по ассисту
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 05') then
begin
BafPPApplyChar[1]:=IDAssistTarget;
BafPPApplyBaf[1]:=bafPP[1];
BafPPApplyChar[2]:=IDAssistTarget;
BafPPApplyBaf[2]:=bafPP[2];
BafPPApplyChar[3]:=IDAssistTarget;
BafPPApplyBaf[3]:=bafPP[5];
BafPPApplyChar[4]:=IDAssistTarget;
BafPPApplyBaf[4]:=bafPP[6];
BafPPApplyChar[5]:=IDAssistTarget;
BafPPApplyBaf[5]:=bafPP[7];
BafPPApplyChar[6]:=IDAssistTarget;
BafPPApplyBaf[6]:=bafPP[8];
BafPPApplyChar[7]:=IDAssistTarget;
BafPPApplyBaf[7]:=bafPP[9];
BafPPApplyChar[8]:=IDAssistTarget;
BafPPApplyBaf[8]:=bafPP[23];
BafPPApplyChar[9]:=IDAssistTarget;
BafPPApplyBaf[9]:=bafPP[13];
BafPPApplyChar[10]:=IDAssistTarget;
BafPPApplyBaf[10]:=bafPP[14];
BafPPApplyChar[11]:=IDAssistTarget;
BafPPApplyBaf[11]:=bafPP[16];
BafPPApplyChar[12]:=IDAssistTarget;
BafPPApplyBaf[12]:=bafPP[18];
BafPPApplyChar[13]:=IDAssistTarget;
BafPPApplyBaf[13]:=bafPP[19];
BafPPApplyChar[14]:=IDAssistTarget;
BafPPApplyBaf[14]:=bafPP[20];
BafPPApplyChar[15]:='';
BafPPApplyBaf[15]:='';
BafSEApplyChar[1]:=IDAssistTarget;
BafSEApplyBaf[1]:=bafSE[5];
BafSEApplyChar[2]:=IDAssistTarget;
BafSEApplyBaf[2]:=bafSE[6];
BafSEApplyChar[3]:='';
BafSEApplyBaf[3]:='';
BafEEApplyChar[1]:=IDAssistTarget;
BafEEApplyBaf[1]:=bafEE[1];
BafEEApplyChar[2]:=IDAssistTarget;
BafEEApplyBaf[2]:=bafEE[2];
BafEEApplyChar[3]:='';
BafEEApplyBaf[3]:='';
timer4.enabled:=true;
pck:='';
exit;
end;
//UNAWARE буф ФИЗИКА по ассисту
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 08') then
begin
BafPPApplyChar[1]:=IDAssistTarget;
BafPPApplyBaf[1]:=bafPP[1];
BafPPApplyChar[2]:=IDAssistTarget;
BafPPApplyBaf[2]:=bafPP[2];
BafPPApplyChar[3]:=IDAssistTarget;
BafPPApplyBaf[3]:=bafPP[3];
BafPPApplyChar[4]:=IDAssistTarget;
BafPPApplyBaf[4]:=bafPP[4];
BafPPApplyChar[5]:=IDAssistTarget;
BafPPApplyBaf[5]:=bafPP[7];
BafPPApplyChar[6]:=IDAssistTarget;
BafPPApplyBaf[6]:=bafPP[8];
BafPPApplyChar[7]:=IDAssistTarget;
BafPPApplyBaf[7]:=bafPP[9];
BafPPApplyChar[8]:=IDAssistTarget;
BafPPApplyBaf[8]:=bafPP[22];
BafPPApplyChar[9]:=IDAssistTarget;
BafPPApplyBaf[9]:=bafPP[12];
BafPPApplyChar[10]:=IDAssistTarget;
BafPPApplyBaf[10]:=bafPP[13];
BafPPApplyChar[11]:=IDAssistTarget;
BafPPApplyBaf[11]:=bafPP[14];
BafPPApplyChar[12]:=IDAssistTarget;
BafPPApplyBaf[12]:=bafPP[15];
BafPPApplyChar[13]:=IDAssistTarget;
BafPPApplyBaf[13]:=bafPP[18];
BafPPApplyChar[14]:=IDAssistTarget;
BafPPApplyBaf[14]:=bafPP[19];
BafPPApplyChar[15]:=IDAssistTarget;
BafPPApplyBaf[15]:=bafPP[20];
BafPPApplyChar[16]:=IDAssistTarget;
BafPPApplyBaf[16]:=bafPP[21];
BafPPApplyChar[17]:='';
BafPPApplyBaf[17]:='';
BafSEApplyChar[1]:=IDAssistTarget;
BafSEApplyBaf[1]:=bafSE[4];
BafSEApplyChar[2]:='';
BafSEApplyBaf[2]:='';
BafEEApplyChar[1]:=IDAssistTarget;
BafEEApplyBaf[1]:=bafEE[1];
BafEEApplyChar[2]:=IDAssistTarget;
BafEEApplyBaf[2]:=bafEE[2];
BafEEApplyChar[3]:='';
BafEEApplyBaf[3]:='';
timer4.enabled:=true;
pck:='';
exit;
end;
end.
Бот для кача ТК 64+ лвл
Достоинства:
- миникарта;
- панель с инфой;
- бафает себя:
- юзает кубики;
- юзает пошин алакрити;
- лечит себя хил пошинами и элементал хилом;
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
//************************************************** *************
const
name='NLObP'; //имя чара для которого включен скрипт
//установить константу в зависимости от типа игры (С4 или Интерлюд)
IL=false; //true - IL, false - C4
max=50; //максимальное значение массива
buff1=91; //бафф defense aura
buff2=77; //бафф attack aura
buff3=112; //бафф deflect arrow
buff4=230; //бафф sprint
buff5=123; //бафф spirit barrier
cubicstorm=10;
cubiclife=67;
elementalheal=58;
//************************************************** *************
var
info, msg, stats : TMemo;
frm : TForm;
map : Tform; //виртуальная карта
offs1, xm, ym : integer;
heal, kill : string;
MaxHP, MyZpos, cvaZ, CurHP, ID, xpos, ypos, skill, MyID, PercentHP, MEsit: integer;
MEup, but, sud, bst, Radius, cvaX, attackIDMinID, attackk, attackID, cvaY, zpos: integer;
Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc : Boolean;
bfi, atck, hpi, i, ii: integer;
last : integer; //последняя запись в массиве, для ускорения скрипта
MobsID: array[1..max] of integer;
MobsRAS: array[1..max] of integer;
MobsX: array[1..max] of integer;
MobsY: array[1..max] of integer;
MobsZ: array[1..max] of integer;
NPCid: array[1..max] of integer;
Aggro: array[1..max] of Boolean;
Shape: array [0..max] of Tshape; //виртуальная карта
timer1: TTimer;
timer2: TTimer;
timer3: TTimer;
//************************************************** *************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
var
i: integer;
begin
if il then begin
//CharInfo
offs1:=48; //44 для С4, 48 для IL
end else begin
offs1:=44;
end;
atck:=0; //кол-во неуспешных атак после которых пробуем сместиться
hpi:=0;
bfi:=60; //60 сек, чтобы бафы не пропустить
ii:=1;
last:=1; //начальное значение
Radius:=1500; // радиус круга кача! Можно под место править.
PercentHP:=70; // при каком количестве хп в % юзать бутылку лечения
MEsit:=55; // при каком количестве хп в % надо сесть и подкопить хп
MEup:=90; // при каком количестве хп в % надо встать после отдыха
frm := TForm.Create(nil);
frm.Caption := 'BOT '+name;
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=520;
frm.Height:=700;
info:=TMemo.Create(frm);
info.parent:=frm;
info.align:=alLeft;
info.ReadOnly:=true;
info.ScrollBars:=0;
info.Width:=470;
info.Height:=370;
info.Lines.Add('БОТ НЕ ПОДКЛЮЧЁН К СЕРВЕРУ!');
msg:=TMemo.Create(frm);
msg.parent:=frm;
msg.align:=alBottom;
msg.ReadOnly:=true;
msg.ScrollBars:=0;
msg.Width:=570;
msg.Height:=100;
msg.Lines.Add('...');
stats:=TMemo.Create(frm);
stats.parent:=frm;
stats.align:=alRight;
stats.ReadOnly:=true;
stats.ScrollBars:=0;
stats.Width:=140;
stats.Height:=100;
frm.Show;
map := TForm.Create(nil);
map.Caption := 'MiniMap: '+name;
map.BorderStyle := bsSizeable;
map.Position := poScreencenter;
map.Width:=300;
map.Height:=300;
map.FormStyle:=FsStayOnTop;
map.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!
//атака и прочее
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1; //
timer1.enabled:=false; // таймер по умолчанию выключен
timer1.interval:=1000; // через каждые 1сек будем обновлять
//вывод в форму
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2; //
timer2.enabled:=true; // таймер по умолчанию включен
timer2.interval:=1000; // через каждые 1сек будем обновлять
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3; //
timer3.enabled:=true; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
for i:= 1 to max do begin
Aggro[i]:=false;
Shape[i]:=Tshape.create(nil); //для мобов
Shape[i].parent:=map;
Shape[i].Brush.Color:=clGreen; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
Shape[i].left:=-7; //координаты
Shape[i].top:=-7;
Shape[i].width:=7; //размеры
Shape[i].height:=7;
end;
shape[0]:=Tshape.create(nil); //для моего чара
shape[0].parent:=map;
//shape[0].Brush.Color:= clBlack ;
shape[0].left:=-5; //координаты
shape[0].top:=-5;
shape[0].width:=5; //размеры
shape[0].height:=5;
end;
//************************************************** *************
procedure GameToMap(x, y : integer);
//преобразуем игровые координаты в координаты карты
//никак не сделаю нормальные преобразования =(
var
masshtabx, masshtaby : extended;
begin
masshtabx:=radius*2/map.Width;
masshtaby:=radius*2/map.Height;
xm:=Round((x-cvaX+map.Width/2)/masshtabx); //координата X на карте
ym:=Round((y-cvaY+map.Height/2)/masshtaby); //координата Y на карте
end;
//************************************************** *************
procedure ViewInfo;
var
i: integer;
begin
info.Lines.Clear;
stats.Lines.Clear;
stats.Lines.Add('MaxHP :'+IntToStr(MaxHP));
stats.Lines.Add('CurHP :'+IntToStr(CurHP));
stats.Lines.Add('MyID :'+IntToStr(MyID));
stats.Lines.Add('MyXpos :'+IntToStr(MyXpos));
stats.Lines.Add('MyYpos :'+IntToStr(MyYpos));
stats.Lines.Add('MyZpos :'+IntToStr(MyZpos));
stats.Lines.Add('Radius :'+IntToStr(RADIUS));
stats.Lines.Add('cvaX :'+IntToStr(cvaX));
stats.Lines.Add('cvaY :'+IntToStr(cvaY));
stats.Lines.Add('cvaZ :'+IntToStr(cvaZ));
stats.Lines.Add('skill :'+IntToStr(skill)+' юзал скил');
stats.Lines.Add('but :'+IntToStr(but)+' бутылки');
stats.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
stats.Lines.Add('bst :'+IntToStr(bst)+' встать');
stats.Lines.Add('ID :'+IntToStr(ID)+' кто ходит');
stats.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
stats.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
stats.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
stats.Lines.Add('sit :'+VarToStr(sit));
stats.Lines.Add('PercentHP :'+IntToStr(PercentHP)+' %хп');
stats.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
stats.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
stats.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
stats.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
stats.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
stats.Lines.Add('atck :'+IntToStr(atck)+' цикл неудачных атак');
stats.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
stats.Lines.Add('SummaAR :'+IntToStr(Summ(MobsID))+' всего в бд');
stats.Lines.Add('rezu :'+IntToStr(delta(MyXpos, MyYpos, xpos, ypos))+' рез ближ');
stats.Lines.Add('MaxX :'+IntToStr(MaxX));
stats.Lines.Add('MaxID :'+IntToStr(MaxID));
stats.Lines.Add('MinX :'+IntToStr(MinX));
stats.Lines.Add('MinID :'+IntToStr(MinID));
stats.Lines.Add('povtor :'+VarToStr(povtor));
stats.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
stats.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
stats.Lines.Add('Hpotion: '+inttostr(Hpotion));
stats.Lines.Add('Apotion: '+inttostr(Apotion));
// if (MaxHP<>0) then begin
info.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
info.Lines.Add('HP:'+IntToStr(CurHP)+' из '+IntToStr(MaxHP)+' Цикл1='+IntToStr(attackk)+' Цикл2='+IntToStr(atck)+' Цикл бафа='+IntToStr(bfi));
if (Hpotion=0) then info.Lines.Add('Юзать HP бутылки?: НЕТ!');
if (Hpotion<>0) then info.Lines.Add('Юзать HP бутылки?: ДА!');
if (Apotion=0) then info.Lines.Add('Юзать AP бутылки?: НЕТ!');
if (Apotion<>0) then info.Lines.Add('Юзать AP бутылки?: ДА!');
if (sit=false) then info.Lines.Add('Бот стоит!');
if (sit=true) then info.Lines.Add('Бот сидит!');
for i:= 1 to last do begin
if (MobsID[i]<>0) then begin
if (attackIDMinID<>i) then info.Lines.Add('--'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
if (attackIDMinID=i) then info.Lines.Add('->'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
end;
end;
for i:= 1 to last do begin
if (MobsID[i]<>0) then begin
GameToMap(MobsX[i],MobsY[i]);
Shape[i].left:=xm; //координаты моба
Shape[i].top:=ym;
if Aggro[i]=true then Shape[i].Brush.Color:=clPurple;
end;
end;
// end;
if (MaxHP=0) then info.Lines.Add(' Для инициализации Бота используй аптечку!');
end;
//************************************************** *************
procedure Free;
begin
DelALL;
end;
//************************************************** *************
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
end;
end;
if (MaxHP<>0) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*PercentHP); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
end;
end;
//************************************************** *************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$01;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyXpos); //откуда
WriteD(MyYpos);
WriteD(MyZpos);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(Name);
msg.Lines.Add('MoveTo('+inttostr(targetx)+','+intt ostr(targety)+','+inttostr(targetz)+')');
end;
//************************************************** *************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:exte nded):boolean;
begin
if delta(targetx, targety, MyXpos, MyYpos)<=distanciya
then result:=true else result:=false;
end;
//************************************************** *************
function delta(xpos1, ypos1, xpos2, ypos2:extended):integer; //возвращает переменную rezu которая является растоянием между 2 точками
begin
result:= Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;
//************************************************** *************
procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsID[ele]:=0;
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
Aggro[ele]:=false;
Shape[ele].left:=-7; //координаты, чтобы небыло видно на карте
Shape[ele].top:=-7;
Shape[i].Brush.Color:=clGreen;
end;
//************************************************** *************
procedure DelALL; //обнуляем всю базу!
var
i: integer;
begin
for i:= 1 to max do begin
NPCid[i]:=0;
MobsID[i]:=0;
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
Aggro[i]:=false;
shape[i].free;
end;
shape[0].free;
timer1.Free;
timer2.Free;
timer3.Free;
info.Free;
msg.Free;
frm.Free;
map.Free;
end;
//************************************************** *************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
var
i: integer;
begin
MinX:=5000;
MinID:=0;
MaxX:=0;
MaxID:=0;
for i:= 1 to last do begin
if (arra[i]<=MinX) and (arra[i]<>0) then begin
MinX:=arra[i];
MinID:=i;
end;
if (arra[i]>=MaxX) then begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;
//************************************************** *************
function ETOpovtor(chislo: integer; arra:array of integer):boolean;
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
var
i: integer;
begin
Result:=false;
for i:= 1 to last do begin
if (arra[i]=chislo) then Result:=true;
end;
end;
//************************************************** *************
procedure attackt(mobus:integer);
begin
buf:=#$04; //action
WriteD(MobsID[mobus]);
WriteD(MyXpos);
WriteD(MyYpos);
WriteD(MyZpos);
WriteC(0);
SendToServerEx(Name);
end;
//************************************************** *************
function Summ(sum:array of integer):integer;
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
i: integer;
begin
Result:=0;
for i:= 1 to max do begin
if (sum[i]<>0) then inc(Result);
end;
end;
//************************************************** *************
procedure OnTimer1(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!!!!!!!!!!!!!
begin
//не всегда атакует по двойному клику, поэтому клики с задержкой в 1 сек.
//повторяем через 6 сек. двойной клик
if (MinID>0) then begin
if (sit=false) then begin
case attackk of
0: begin
msg.Lines.Add('Атакую! '+IntToStr(ID));
attackID:=MobsID[MinID];
attackIDMinID:=MinID;
attackt(attackIDMinID); //target
end;
//делаем паузу
1: begin
attackt(attackIDMinID); //attack
end;
6: begin
attackt(attackIDMinID); //target
end;
//делаем паузу
7: begin
attackt(attackIDMinID); //attack
attackk:=-1;
inc(atck);
end;
end;
//если стоим 35 сек ((attackk=7)*5), убираем текущий таргет и пробуем другой, вдруг поможет =)
case atck of
5: begin
MobsRAS[attackIDMinID]:=5000;
// GetMinMaxX(MobsRAS);
attackk:=-1;
atck:=0;
end;
end;
inc(attackk);
end;
end;
end;
//************************************************** *************
procedure OnTimer2(Sender: TObject); //
begin
//контролируем бафы, если время бафов, то пытаемся бафаться каждую секунду
dec(bfi);
if bfi<0 then begin
timer3.interval:=1000; //каждые 1 сек
bfi:=1200; //20 мин
end;
//выводим в форму
ViewInfo;
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
//идем в центр если нет мобов. Это можно включить при желании,
//только будет мешать при управлении мобом
{
if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
end;
}
//лечимся в промежутках между битвами
if (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Баффаюсь elemental heal!');
MagicSkillUse(elementalheal);
end;
//лечимся бутылками все время
if (CurHP<but) and (Hpotion<>0) then begin
if hpi=5 then begin
UseItem(Hpotion);
hpi:=0;
end else inc(hpi);
end;
//сидим если надо
if (CurHP<sud) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add(' все блин я отдыхаю!');
buf:=heal;
SendToServerEx(Name);
sit:=true;
end;
//встаем
if (CurHP>bst) and (sit=true) then begin
msg.Lines.Add(' пора за работу!');
buf:=heal;
SendToServerEx(Name);
attackk:=0;
atck:=0;
sit:=false;
end;
end;
//************************************************** *************
procedure OnTimer3(Sender: TObject); //баффы
begin
//если никого не бъем, то надо бафаться
if (Summ(Aggro)=0) and (sit=false) then begin
case ii of
1: begin
timer1.enabled:=false; //откл. атаку
msg.Lines.Add('Баффаюсь Defense aura!');
//бафф
MagicSkillUse(buff1);
inc(ii);
timer3.interval:=6000; //каждые 6 сек
end;
2: begin
msg.Lines.Add('Баффаюсь Attack aura!');
MagicSkillUse(buff2);
inc(ii);
end;
3: begin
msg.Lines.Add('Баффаюсь Deflect arrow!');
MagicSkillUse(buff3);
inc(ii);
end;
4: begin
msg.Lines.Add('Баффаюсь Sprint!');
MagicSkillUse(buff4);
inc(ii);
end;
5: begin
msg.Lines.Add('Баффаюсь Spirit barrier!');
MagicSkillUse(buff5);
inc(ii);
timer3.interval:=10000; //каждые 10 сек
end;
6: begin
msg.Lines.Add('Баффаюсь Storm cubic!');
MagicSkillUse(cubicstorm);
inc(ii);
end;
7: begin
msg.Lines.Add('Баффаюсь Life cubic!');
MagicSkillUse(cubiclife);
inc(ii);
end;
8: begin
if Hpotion<>0 then begin
msg.Lines.Add('Potion of Alacrity!');
UseItem(Apotion);
end;
inc(ii);
end;
9: begin
ii:=1;
timer3.interval:=1150000; //каждые 20 мин
bfi:=1150;
timer1.enabled:=true; //вкл. атаку
end;
end;
end;
end;
//************************************************** *************
procedure AddBD(id, posx, posy, posz:integer;); //добавляем моба в базу данных
var
i: integer;
begin
for i:=1 to last do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(id, MobsID)=false) then begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=delta(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
GameToMap(posx,posy);
shape[i].left:=xm; //координаты моба
shape[i].top:=ym;
break;
end;
end;
end;
//если нет свободного места ищем дальше
for i:=last+1 to max do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(id, MobsID)=false) then begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=delta(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
last:=i;
GameToMap(posx,posy);
shape[i].left:=xm; //координаты моба
shape[i].top:=ym;
break;
end;
end;
end;
end;
//************************************************** *************
function ISnpc(id: integer;): boolean;
var
i: integer;
begin
result:=false;
for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;
//************************************************** *************
procedure UseItem(ObjID:integer);
begin
buf:=#$14;
WriteD(ObjID);
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(S hiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
buf:=#$2F;
WriteD(MagicID);
WriteD(00);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
if (ConnectName=Name) and FromServer then begin
case pck[1] of
#$76: begin
msg.Lines.Add('S>C $76');
if (ReadD(2)=MyID) then begin //я юзнул какой то скилл
msg.Lines.Add(' юзнул скилл!');
skill:=1;
end;
end;
#$0E: begin
msg.Lines.Add('S>C $0E StatsUpdate');
if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
end;
//MagicSkillUse 48, Attack 05
#$05: begin
msg.Lines.Add('S>C $05 Attack');
if (ReadD(6)=MyID) then begin
//меня ударили
sit:=false;
if (ETOpovtor(ReadD(2),MobsID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
for i:=1 to last do begin
if (MobsID[i]=ReadD(2)) then begin //если моб записан в базе данных
msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(attackIDMinID));
MobsRAS[i]:=1;
Aggro[i]:=true; // стал агрессор
if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
attackIDMinID:=i;
timer1.enabled:=true;
end;
if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
break;
end;
end;
end;
end;
#$0C: begin
msg.Lines.Add('S>C $0C DropItem');
if (MyXpos<>0) then begin
if (delta(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
msg.Lines.Add('Выпала вещь!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
WriteC(0);
SendToServerEx(Name);
msg.Lines.Add(' Пробую поднять!!!');
delay(1000);
timer1.enabled:=true;
end;
end;
end;
#$04: begin
msg.Lines.Add('S>C $04 CharInfo');
//пакет с инфой о моём чаре
i:=2;
MyXpos:=ReadD(i); //получаю координату х моего чара
MyYpos:=ReadD(i); //получаю координату у моего чара
MyZpos:=ReadD(i); //получаю координату z моего чара
GameToMap(MyXpos,MyYpos);
shape[0].left:=xm; //координаты моего чара
shape[0].top:=ym;
//Запоминаем ИД
i:=18;
MyID:=ReadD(i); //получаю ид моего чара
//смещение переменное, зависит от имени (LenName*2+2)
i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
if (gdo=false) then begin //задаем центр окружности кача
cvaX:=MyXpos;
cvaY:=MyYpos;
gdo:=true;
end;
end;
#$01: begin
msg.Lines.Add('S>C $01 Move');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
i:=2;
ID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
xpos:=ReadD(i);
ypos:=ReadD(i);
zpos:=ReadD(i);
if not ISnpc(ID) and (delta(cvaX,cvaY,xpos,ypos)<=Radius) then AddBD(ID,xpos,ypos,zpos);
end;
end;
//принят пакет Die
#$06: begin
msg.Lines.Add('S>C $06 Die');
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
for i:=1 to last do begin
if (MobsID[i]=ReadD(2)) then begin
DelElArr(i);
attackk:=0;
atck:=0;
msg.Lines.Add('БОБИК СДОХ!! :'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
//принят пакет DeleteObject
#$12: begin
msg.Lines.Add('S>C $12 DeleteObject');
//выкидываем из базы
for i:=1 to last do begin
if (MobsID[i]=ReadD(2)) then begin
DelElArr(i);
msg.Lines.Add('Удаляю из базы!! :'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
#$03: begin
msg.Lines.Add('S>C $03 Char');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(18),NPCid)=false) then begin
NPCid[i]:=ReadD(18);
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
#$16: begin
msg.Lines.Add('S>C $16 NPC');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
msg.Lines.Add('Вижу NPC!');
if (ReadD(10)=0) then begin //если нельзя атаковать
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(2), NPCid)=false) then begin
NPCid[i]:=ReadD(2);
msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
break;
end;
end;
end;
end;
if (ReadD(10)=1) and (pck[120]=#$00) then begin //если можно атаковать
if (delta(cvaX, cvaY, ReadD(14), ReadD(18))<=RADIUS) then begin
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
end
else msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' вне радиуса действия!');
end;
end;
end;
//InventoryUpdate
#$27: begin
msg.Lines.Add('S>C $27 InventoryUpdate');
if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
Hpotion:=ReadD(8);
msg.Lines.Add('ID бутылок Hpotion:'+inttostr(Hpotion));
end;
if ReadD(12)=735 then begin //Potion of Alacrity
Apotion:=ReadD(8);
msg.Lines.Add('ID бутылок Apotion:'+inttostr(Apotion));
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=Name) and FromClient then begin
case pck[1] of
#$1B: begin
msg.Lines.Add('C>S $1B ');
case ReadD(2) of
//социальное действие Yes для начала
$06: begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
attackk:=0;
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты ОБНОВЛЕНЫ!!');
// GetMinMaxX(MobsRAS);
timer1.enabled:=true;
timer3.enabled:=true;
end;
//социальное действие No для окончания
$05: begin
timer1.enabled:=false;
timer3.enabled:=false;
msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
end;
{ //социальное действие Applaud
$0B: begin
if timer2.enabled=false
then timer2.enabled:=true
else timer2.enabled:=false;
attackk:=0;
atck:=0;
msg.Lines.Add('! ВКЛ/ВЫКЛ!!!');
end;
} //социальное действие Sorrow - удаляем текущую запись в базе
$0D: begin
ID:=MobsID[attackIDMinID];
DelElArr(attackIDMinID);
attackk:=0;
atck:=0;
msg.Lines.Add('Удаляем текущую запись в базе!!!');
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=ID;
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
//ValidatePosition пакет от клиента с моими кординатами
#$48: begin
msg.Lines.Add('C>S $48 ValidatePosition');
//обновляем ВСЕ растояния в BD если мы сошли с места
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
GameToMap(MyXpos,MyYpos);
shape[0].left:=xm; //координаты моего чара
shape[0].top:=ym;
for i:=1 to last do begin
if (MobsID[i]<>0) then begin
if (true<>Aggro[i]) then begin
MobsRAS[i]:=delta(MyXpos,MyYpos,MobsX[i],MobsY[i]);
end;
end;
end;
end;
end;
end;
end.
ппц слов нет это =@ :O: :Yahoo!:
да.. скажу вам честно- "ЛЁД ТРОНУЛСЯ- ГОСПОДА ПРИСЯЖНЫЕ!" .. а то на месте буксовали-)
NLObP:=+1
надо вникнуть протестить.. если не лень добавь еще коментов плиз.. некоторые куски при беглом осмотре непонятны.. чтоб не вникая в код было понятно как ето всё пашет.. если не трудно плиз сделай и закрепим тогда к первому посту.. хотя и в таком варианте тожэ прикрепим но хочется еще более доступный вид.. -)
пока не проверял в работе но вижу работа огромная проделана-) даже миникарта создана-)) супер.. и лог действий-)..
можно какнить обощить всех физиков в 1 скрипт? чтоб было несколько строк тока для переделки.. чтоб скрипт улавливал какието параметры (ХП,МП,состояние атаки, скока противников нас бьют одновременно) и от в зависимости от них инициализировался запуск процедуру- в теле которой что хатим то сами под себя и напишем, под каждую профу.. ну например: мало ХП, нас атакуют сразу 3= запускаем процедуру, в теле которой ТАНКИ- пропишут себе УД, СПЕЛСИНГЕР- пропишет ФЛЕШ- массовый что все убежали, ну чета такое например бы сделать.. хотя в любом случае твой скрипт надо брать за основу.. и доделывать уж его под жэлания каждого.. то что выкладывал я давным давно конечножэ в сравнение не идет с етим-)..
также в идеале, в качестве готового решения, надо сделать 2 скрипта 1 из которых управляет баферами, второй- мозг- управляет командиром.. впринципе сыровато пока но уже есть то что будет работать.. то что я выложил для баферов- неможет автоматом перебафывать командира.. но добавив 5 строк (в управляющий блок кода , в конце скрипта) можно заставить скрипт реагировать и выполнять ребаф по каманде в приват сообщение, присланное от бота- командира типа твоего.. вот ето будет савсем уж весело тогда-).. чтоб командир следил- каму и что делать в какихто неординарных случаях приказывал ботам неординарные приказы..-) а боты- баферы чтоб в своём скрипте неукаснительно их выполняли-)..
спасибо еще раз-) буду изучать терь то что ты напрогал..
при беглом просмотре понял что львиная часть скрипта это панельки и карты, которые я не как не могу понять ктонить популярно логику отображения в окошке может объяснить? :) а в целом за пару дней можно переделать для сумонера :) блага логика простая тока надо проверку добавить на хп сумона и проверку кто кого атакует + ко всему этому задержку между атакой сумона и сомонером ну что б сумонер первым не атакавал.
NLObP, поставь плиз побольше коментариев :oops: плизз, а то очень трудно понять что куда и откуда т.к. некоторые переменые я так и не нашёл где забиваются :( не сочти дебилом меня, но за 3 часа я не понял откуда взялся центр зоны кача %)
За основу взят бот из темы ОТПТИМИЗАЦИЯ БОТА! от skymanrus. Мне там особенно понравилась панель с инфой. До этого я все сообщения по отладке в чать кидал. С панелью намного удобнее отлаживать скрипт.
Панель состои из трех частей. Слева информация по базе мобов и атаках на них (стрелкой указывается цель). Справа информация о переменных. Снизу лог сообщений. Первым делом исправляем имя чара (в 3.1.8. выскакивала ошибка, в 3.2.0 ошибка не выскакивает и можно долго непонимать почему скрипт не работает). Включаем скрипт (через 1 мин включаются бафы). Пьем бутылкы Хил и Алакрити пошин. Можно не пить, тогда в скрипте не используются. Ставим нужный радиус: Radius:=1500; // радиус круга кача! Идем на место кача, жмем YES, вот код:
//социальное действие Yes для начала
$06: begin
cvaX:=MyXpos; //запоминаем центр кача
cvaY:=MyYpos;
cvaZ:=MyZpos;
attackk:=0; //
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты ОБНОВЛЕНЫ!!');
timer1.enabled:=true; //включаем охоту на мобов
timer3.enabled:=true; //включаем работу бафов
end;
Бот готов к работе. Он видит мобов после того как они начнут двигаться или респавнящихся, неподвижных не видит. Ближайшего начинает атаковать. Если в базу попал NPC или рейд босс его можно принудительно убрать из списка - соц.действием Sorrow.
NLObP, поставь плиз побольше коментариев :oops: плизз, а то очень трудно понять что куда и откуда т.к. некоторые переменые я так и не нашёл где забиваются :( не сочти дебилом меня, но за 3 часа я не понял откуда взялся центр зоны кача %)
За основу взят бот из темы ОТПТИМИЗАЦИЯ БОТА! от skymanrus. Мне там особенно понравилась панель с инфой. До этого я все сообщения по отладке в чать кидал. С панелью намного удобнее отлаживать скрипт.
Панель состои из трех частей. Слева информация по базе мобов и атаках на них (стрелкой указывается цель). Справа информация о переменных. Снизу лог сообщений. Первым делом исправляем имя чара (в 3.1.8. выскакивала ошибка, в 3.2.0 ошибка не выскакивает и можно долго непонимать почему скрипт не работает). Включаем скрипт (через 1 мин включаются бафы). Пьем бутылкы Хил и Алакрити пошин. Можно не пить, тогда в скрипте не используются. Ставим нужный радиус: Radius:=1500; // радиус круга кача! Идем на место кача, жмем YES, вот код:
//социальное действие Yes для начала
$06: begin
cvaX:=MyXpos; //запоминаем центр кача
cvaY:=MyYpos;
cvaZ:=MyZpos;
attackk:=0; //
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты ОБНОВЛЕНЫ!!');
timer1.enabled:=true; //включаем охоту на мобов
timer3.enabled:=true; //включаем работу бафов
end;
Бот готов к работе. Он видит мобов после того как они начнут двигаться или респавнящихся, неподвижных не видит. Ближайшего начинает атаковать. Если в базу попал NPC или рейд босс его можно принудительно убрать из списка - соц.действием Sorrow.
спс помог очень прям :) терь переделаю думаю... :) и выложу свой вариант, но уже как мне кажется более верный зона кача 4-х угольник, скрипт работает всегда для того что б можно было хотя б убежать подальше возрат в точку ребафа, постараюсь что б он делал это не приводя парик, но пока слабо представляю как это сделать, начну с зоны там увидим
Бот для кача ТК 64+ лвл
Достоинства:
- миникарта;
- панель с инфой;
- бафает себя:
- юзает кубики;
- юзает пошин алакрити;
- лечит себя хил пошинами и элементал хилом;
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
//************************************************** *************
const
name='NLObP'; //имя чара для которого включен скрипт
//установить константу в зависимости от типа игры (С4 или Интерлюд)
IL=false; //true - IL, false - C4
max=50; //максимальное значение массива
buff1=91; //бафф defense aura
buff2=77; //бафф attack aura
buff3=112; //бафф deflect arrow
buff4=230; //бафф sprint
buff5=123; //бафф spirit barrier
cubicstorm=10;
cubiclife=67;
elementalheal=58;
//************************************************** *************
var
info, msg, stats : TMemo;
frm : TForm;
map : Tform; //виртуальная карта
offs1, xm, ym : integer;
heal, kill : string;
MaxHP, MyZpos, cvaZ, CurHP, ID, xpos, ypos, skill, MyID, PercentHP, MEsit: integer;
MEup, but, sud, bst, Radius, cvaX, attackIDMinID, attackk, attackID, cvaY, zpos: integer;
Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc : Boolean;
bfi, atck, hpi, i, ii: integer;
last : integer; //последняя запись в массиве, для ускорения скрипта
MobsID: array[1..max] of integer;
MobsRAS: array[1..max] of integer;
MobsX: array[1..max] of integer;
MobsY: array[1..max] of integer;
MobsZ: array[1..max] of integer;
NPCid: array[1..max] of integer;
Aggro: array[1..max] of Boolean;
Shape: array [0..max] of Tshape; //виртуальная карта
timer1: TTimer;
timer2: TTimer;
timer3: TTimer;
//************************************************** *************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
var
i: integer;
begin
if il then begin
//CharInfo
offs1:=48; //44 для С4, 48 для IL
end else begin
offs1:=44;
end;
atck:=0; //кол-во неуспешных атак после которых пробуем сместиться
hpi:=0;
bfi:=60; //60 сек, чтобы бафы не пропустить
ii:=1;
last:=1; //начальное значение
Radius:=1500; // радиус круга кача! Можно под место править.
PercentHP:=70; // при каком количестве хп в % юзать бутылку лечения
MEsit:=55; // при каком количестве хп в % надо сесть и подкопить хп
MEup:=90; // при каком количестве хп в % надо встать после отдыха
frm := TForm.Create(nil);
frm.Caption := 'BOT '+name;
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=520;
frm.Height:=700;
info:=TMemo.Create(frm);
info.parent:=frm;
info.align:=alLeft;
info.ReadOnly:=true;
info.ScrollBars:=0;
info.Width:=470;
info.Height:=370;
info.Lines.Add('БОТ НЕ ПОДКЛЮЧЁН К СЕРВЕРУ!');
msg:=TMemo.Create(frm);
msg.parent:=frm;
msg.align:=alBottom;
msg.ReadOnly:=true;
msg.ScrollBars:=0;
msg.Width:=570;
msg.Height:=100;
msg.Lines.Add('...');
stats:=TMemo.Create(frm);
stats.parent:=frm;
stats.align:=alRight;
stats.ReadOnly:=true;
stats.ScrollBars:=0;
stats.Width:=140;
stats.Height:=100;
frm.Show;
map := TForm.Create(nil);
map.Caption := 'MiniMap: '+name;
map.BorderStyle := bsSizeable;
map.Position := poScreencenter;
map.Width:=300;
map.Height:=300;
map.FormStyle:=FsStayOnTop;
map.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!
//атака и прочее
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1; //
timer1.enabled:=false; // таймер по умолчанию выключен
timer1.interval:=1000; // через каждые 1сек будем обновлять
//вывод в форму
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2; //
timer2.enabled:=true; // таймер по умолчанию включен
timer2.interval:=1000; // через каждые 1сек будем обновлять
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3; //
timer3.enabled:=true; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
for i:= 1 to max do begin
Aggro[i]:=false;
Shape[i]:=Tshape.create(nil); //для мобов
Shape[i].parent:=map;
Shape[i].Brush.Color:=clGreen; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
Shape[i].left:=-7; //координаты
Shape[i].top:=-7;
Shape[i].width:=7; //размеры
Shape[i].height:=7;
end;
shape[0]:=Tshape.create(nil); //для моего чара
shape[0].parent:=map;
//shape[0].Brush.Color:= clBlack ;
shape[0].left:=-5; //координаты
shape[0].top:=-5;
shape[0].width:=5; //размеры
shape[0].height:=5;
end;
//************************************************** *************
procedure GameToMap(x, y : integer);
//преобразуем игровые координаты в координаты карты
//никак не сделаю нормальные преобразования =(
var
masshtabx, masshtaby : extended;
begin
masshtabx:=radius*2/map.Width;
masshtaby:=radius*2/map.Height;
xm:=Round((x-cvaX+map.Width/2)/masshtabx); //координата X на карте
ym:=Round((y-cvaY+map.Height/2)/masshtaby); //координата Y на карте
end;
//************************************************** *************
procedure ViewInfo;
var
i: integer;
begin
info.Lines.Clear;
stats.Lines.Clear;
stats.Lines.Add('MaxHP :'+IntToStr(MaxHP));
stats.Lines.Add('CurHP :'+IntToStr(CurHP));
stats.Lines.Add('MyID :'+IntToStr(MyID));
stats.Lines.Add('MyXpos :'+IntToStr(MyXpos));
stats.Lines.Add('MyYpos :'+IntToStr(MyYpos));
stats.Lines.Add('MyZpos :'+IntToStr(MyZpos));
stats.Lines.Add('Radius :'+IntToStr(RADIUS));
stats.Lines.Add('cvaX :'+IntToStr(cvaX));
stats.Lines.Add('cvaY :'+IntToStr(cvaY));
stats.Lines.Add('cvaZ :'+IntToStr(cvaZ));
stats.Lines.Add('skill :'+IntToStr(skill)+' юзал скил');
stats.Lines.Add('but :'+IntToStr(but)+' бутылки');
stats.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
stats.Lines.Add('bst :'+IntToStr(bst)+' встать');
stats.Lines.Add('ID :'+IntToStr(ID)+' кто ходит');
stats.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
stats.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
stats.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
stats.Lines.Add('sit :'+VarToStr(sit));
stats.Lines.Add('PercentHP :'+IntToStr(PercentHP)+' %хп');
stats.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
stats.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
stats.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
stats.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
stats.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
stats.Lines.Add('atck :'+IntToStr(atck)+' цикл неудачных атак');
stats.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
stats.Lines.Add('SummaAR :'+IntToStr(Summ(MobsID))+' всего в бд');
stats.Lines.Add('rezu :'+IntToStr(delta(MyXpos, MyYpos, xpos, ypos))+' рез ближ');
stats.Lines.Add('MaxX :'+IntToStr(MaxX));
stats.Lines.Add('MaxID :'+IntToStr(MaxID));
stats.Lines.Add('MinX :'+IntToStr(MinX));
stats.Lines.Add('MinID :'+IntToStr(MinID));
stats.Lines.Add('povtor :'+VarToStr(povtor));
stats.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
stats.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
stats.Lines.Add('Hpotion: '+inttostr(Hpotion));
stats.Lines.Add('Apotion: '+inttostr(Apotion));
// if (MaxHP<>0) then begin
info.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
info.Lines.Add('HP:'+IntToStr(CurHP)+' из '+IntToStr(MaxHP)+' Цикл1='+IntToStr(attackk)+' Цикл2='+IntToStr(atck)+' Цикл бафа='+IntToStr(bfi));
if (Hpotion=0) then info.Lines.Add('Юзать HP бутылки?: НЕТ!');
if (Hpotion<>0) then info.Lines.Add('Юзать HP бутылки?: ДА!');
if (Apotion=0) then info.Lines.Add('Юзать AP бутылки?: НЕТ!');
if (Apotion<>0) then info.Lines.Add('Юзать AP бутылки?: ДА!');
if (sit=false) then info.Lines.Add('Бот стоит!');
if (sit=true) then info.Lines.Add('Бот сидит!');
for i:= 1 to last do begin
if (MobsID[i]<>0) then begin
if (attackIDMinID<>i) then info.Lines.Add('--'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
if (attackIDMinID=i) then info.Lines.Add('->'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
end;
end;
for i:= 1 to last do begin
if (MobsID[i]<>0) then begin
GameToMap(MobsX[i],MobsY[i]);
Shape[i].left:=xm; //координаты моба
Shape[i].top:=ym;
if Aggro[i]=true then Shape[i].Brush.Color:=clPurple;
end;
end;
// end;
if (MaxHP=0) then info.Lines.Add(' Для инициализации Бота используй аптечку!');
end;
//************************************************** *************
procedure Free;
begin
DelALL;
end;
//************************************************** *************
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
end;
end;
if (MaxHP<>0) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*PercentHP); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
end;
end;
//************************************************** *************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$01;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyXpos); //откуда
WriteD(MyYpos);
WriteD(MyZpos);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(Name);
msg.Lines.Add('MoveTo('+inttostr(targetx)+','+intt ostr(targety)+','+inttostr(targetz)+')');
end;
//************************************************** *************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:exte nded):boolean;
begin
if delta(targetx, targety, MyXpos, MyYpos)<=distanciya
then result:=true else result:=false;
end;
//************************************************** *************
function delta(xpos1, ypos1, xpos2, ypos2:extended):integer; //возвращает переменную rezu которая является растоянием между 2 точками
begin
result:= Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;
//************************************************** *************
procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsID[ele]:=0;
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
Aggro[ele]:=false;
Shape[ele].left:=-7; //координаты, чтобы небыло видно на карте
Shape[ele].top:=-7;
Shape[i].Brush.Color:=clGreen;
end;
//************************************************** *************
procedure DelALL; //обнуляем всю базу!
var
i: integer;
begin
for i:= 1 to max do begin
NPCid[i]:=0;
MobsID[i]:=0;
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
Aggro[i]:=false;
shape[i].free;
end;
shape[0].free;
timer1.Free;
timer2.Free;
timer3.Free;
info.Free;
msg.Free;
frm.Free;
map.Free;
end;
//************************************************** *************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
var
i: integer;
begin
MinX:=5000;
MinID:=0;
MaxX:=0;
MaxID:=0;
for i:= 1 to last do begin
if (arra[i]<=MinX) and (arra[i]<>0) then begin
MinX:=arra[i];
MinID:=i;
end;
if (arra[i]>=MaxX) then begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;
//************************************************** *************
function ETOpovtor(chislo: integer; arra:array of integer):boolean;
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
var
i: integer;
begin
Result:=false;
for i:= 1 to last do begin
if (arra[i]=chislo) then Result:=true;
end;
end;
//************************************************** *************
procedure attackt(mobus:integer);
begin
buf:=#$04; //action
WriteD(MobsID[mobus]);
WriteD(MyXpos);
WriteD(MyYpos);
WriteD(MyZpos);
WriteC(0);
SendToServerEx(Name);
end;
//************************************************** *************
function Summ(sum:array of integer):integer;
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
i: integer;
begin
Result:=0;
for i:= 1 to max do begin
if (sum[i]<>0) then inc(Result);
end;
end;
//************************************************** *************
procedure OnTimer1(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!!!!!!!!!!!!!
begin
//не всегда атакует по двойному клику, поэтому клики с задержкой в 1 сек.
//повторяем через 6 сек. двойной клик
if (MinID>0) then begin
if (sit=false) then begin
case attackk of
0: begin
msg.Lines.Add('Атакую! '+IntToStr(ID));
attackID:=MobsID[MinID];
attackIDMinID:=MinID;
attackt(attackIDMinID); //target
end;
//делаем паузу
1: begin
attackt(attackIDMinID); //attack
end;
6: begin
attackt(attackIDMinID); //target
end;
//делаем паузу
7: begin
attackt(attackIDMinID); //attack
attackk:=-1;
inc(atck);
end;
end;
//если стоим 35 сек ((attackk=7)*5), убираем текущий таргет и пробуем другой, вдруг поможет =)
case atck of
5: begin
MobsRAS[attackIDMinID]:=5000;
// GetMinMaxX(MobsRAS);
attackk:=-1;
atck:=0;
end;
end;
inc(attackk);
end;
end;
end;
//************************************************** *************
procedure OnTimer2(Sender: TObject); //
begin
//контролируем бафы, если время бафов, то пытаемся бафаться каждую секунду
dec(bfi);
if bfi<0 then begin
timer3.interval:=1000; //каждые 1 сек
bfi:=1200; //20 мин
end;
//выводим в форму
ViewInfo;
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
//идем в центр если нет мобов. Это можно включить при желании,
//только будет мешать при управлении мобом
{
if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
end;
}
//лечимся в промежутках между битвами
if (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Баффаюсь elemental heal!');
MagicSkillUse(elementalheal);
end;
//лечимся бутылками все время
if (CurHP<but) and (Hpotion<>0) then begin
if hpi=5 then begin
UseItem(Hpotion);
hpi:=0;
end else inc(hpi);
end;
//сидим если надо
if (CurHP<sud) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add(' все блин я отдыхаю!');
buf:=heal;
SendToServerEx(Name);
sit:=true;
end;
//встаем
if (CurHP>bst) and (sit=true) then begin
msg.Lines.Add(' пора за работу!');
buf:=heal;
SendToServerEx(Name);
attackk:=0;
atck:=0;
sit:=false;
end;
end;
//************************************************** *************
procedure OnTimer3(Sender: TObject); //баффы
begin
//если никого не бъем, то надо бафаться
if (Summ(Aggro)=0) and (sit=false) then begin
case ii of
1: begin
timer1.enabled:=false; //откл. атаку
msg.Lines.Add('Баффаюсь Defense aura!');
//бафф
MagicSkillUse(buff1);
inc(ii);
timer3.interval:=6000; //каждые 6 сек
end;
2: begin
msg.Lines.Add('Баффаюсь Attack aura!');
MagicSkillUse(buff2);
inc(ii);
end;
3: begin
msg.Lines.Add('Баффаюсь Deflect arrow!');
MagicSkillUse(buff3);
inc(ii);
end;
4: begin
msg.Lines.Add('Баффаюсь Sprint!');
MagicSkillUse(buff4);
inc(ii);
end;
5: begin
msg.Lines.Add('Баффаюсь Spirit barrier!');
MagicSkillUse(buff5);
inc(ii);
timer3.interval:=10000; //каждые 10 сек
end;
6: begin
msg.Lines.Add('Баффаюсь Storm cubic!');
MagicSkillUse(cubicstorm);
inc(ii);
end;
7: begin
msg.Lines.Add('Баффаюсь Life cubic!');
MagicSkillUse(cubiclife);
inc(ii);
end;
8: begin
if Hpotion<>0 then begin
msg.Lines.Add('Potion of Alacrity!');
UseItem(Apotion);
end;
inc(ii);
end;
9: begin
ii:=1;
timer3.interval:=1150000; //каждые 20 мин
bfi:=1150;
timer1.enabled:=true; //вкл. атаку
end;
end;
end;
end;
//************************************************** *************
procedure AddBD(id, posx, posy, posz:integer;); //добавляем моба в базу данных
var
i: integer;
begin
for i:=1 to last do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(id, MobsID)=false) then begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=delta(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
GameToMap(posx,posy);
shape[i].left:=xm; //координаты моба
shape[i].top:=ym;
break;
end;
end;
end;
//если нет свободного места ищем дальше
for i:=last+1 to max do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(id, MobsID)=false) then begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=delta(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
last:=i;
GameToMap(posx,posy);
shape[i].left:=xm; //координаты моба
shape[i].top:=ym;
break;
end;
end;
end;
end;
//************************************************** *************
function ISnpc(id: integer;): boolean;
var
i: integer;
begin
result:=false;
for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;
//************************************************** *************
procedure UseItem(ObjID:integer);
begin
buf:=#$14;
WriteD(ObjID);
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(S hiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
buf:=#$2F;
WriteD(MagicID);
WriteD(00);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
if (ConnectName=Name) and FromServer then begin
case pck[1] of
#$76: begin
msg.Lines.Add('S>C $76');
if (ReadD(2)=MyID) then begin //я юзнул какой то скилл
msg.Lines.Add(' юзнул скилл!');
skill:=1;
end;
end;
#$0E: begin
msg.Lines.Add('S>C $0E StatsUpdate');
if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
end;
//MagicSkillUse 48, Attack 05
#$05: begin
msg.Lines.Add('S>C $05 Attack');
if (ReadD(6)=MyID) then begin
//меня ударили
sit:=false;
if (ETOpovtor(ReadD(2),MobsID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
for i:=1 to last do begin
if (MobsID[i]=ReadD(2)) then begin //если моб записан в базе данных
msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(attackIDMinID));
MobsRAS[i]:=1;
Aggro[i]:=true; // стал агрессор
if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
attackIDMinID:=i;
timer1.enabled:=true;
end;
if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
break;
end;
end;
end;
end;
#$0C: begin
msg.Lines.Add('S>C $0C DropItem');
if (MyXpos<>0) then begin
if (delta(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
msg.Lines.Add('Выпала вещь!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
WriteC(0);
SendToServerEx(Name);
msg.Lines.Add(' Пробую поднять!!!');
delay(1000);
timer1.enabled:=true;
end;
end;
end;
#$04: begin
msg.Lines.Add('S>C $04 CharInfo');
//пакет с инфой о моём чаре
i:=2;
MyXpos:=ReadD(i); //получаю координату х моего чара
MyYpos:=ReadD(i); //получаю координату у моего чара
MyZpos:=ReadD(i); //получаю координату z моего чара
GameToMap(MyXpos,MyYpos);
shape[0].left:=xm; //координаты моего чара
shape[0].top:=ym;
//Запоминаем ИД
i:=18;
MyID:=ReadD(i); //получаю ид моего чара
//смещение переменное, зависит от имени (LenName*2+2)
i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
if (gdo=false) then begin //задаем центр окружности кача
cvaX:=MyXpos;
cvaY:=MyYpos;
gdo:=true;
end;
end;
#$01: begin
msg.Lines.Add('S>C $01 Move');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
i:=2;
ID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
xpos:=ReadD(i);
ypos:=ReadD(i);
zpos:=ReadD(i);
if not ISnpc(ID) and (delta(cvaX,cvaY,xpos,ypos)<=Radius) then AddBD(ID,xpos,ypos,zpos);
end;
end;
//принят пакет Die
#$06: begin
msg.Lines.Add('S>C $06 Die');
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
for i:=1 to last do begin
if (MobsID[i]=ReadD(2)) then begin
DelElArr(i);
attackk:=0;
atck:=0;
msg.Lines.Add('БОБИК СДОХ!! :'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
//принят пакет DeleteObject
#$12: begin
msg.Lines.Add('S>C $12 DeleteObject');
//выкидываем из базы
for i:=1 to last do begin
if (MobsID[i]=ReadD(2)) then begin
DelElArr(i);
msg.Lines.Add('Удаляю из базы!! :'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
#$03: begin
msg.Lines.Add('S>C $03 Char');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(18),NPCid)=false) then begin
NPCid[i]:=ReadD(18);
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
#$16: begin
msg.Lines.Add('S>C $16 NPC');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
msg.Lines.Add('Вижу NPC!');
if (ReadD(10)=0) then begin //если нельзя атаковать
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(2), NPCid)=false) then begin
NPCid[i]:=ReadD(2);
msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
break;
end;
end;
end;
end;
if (ReadD(10)=1) and (pck[120]=#$00) then begin //если можно атаковать
if (delta(cvaX, cvaY, ReadD(14), ReadD(18))<=RADIUS) then begin
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
end
else msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' вне радиуса действия!');
end;
end;
end;
//InventoryUpdate
#$27: begin
msg.Lines.Add('S>C $27 InventoryUpdate');
if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
Hpotion:=ReadD(8);
msg.Lines.Add('ID бутылок Hpotion:'+inttostr(Hpotion));
end;
if ReadD(12)=735 then begin //Potion of Alacrity
Apotion:=ReadD(8);
msg.Lines.Add('ID бутылок Apotion:'+inttostr(Apotion));
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=Name) and FromClient then begin
case pck[1] of
#$1B: begin
msg.Lines.Add('C>S $1B ');
case ReadD(2) of
//социальное действие Yes для начала
$06: begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
attackk:=0;
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты ОБНОВЛЕНЫ!!');
// GetMinMaxX(MobsRAS);
timer1.enabled:=true;
timer3.enabled:=true;
end;
//социальное действие No для окончания
$05: begin
timer1.enabled:=false;
timer3.enabled:=false;
msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
end;
{ //социальное действие Applaud
$0B: begin
if timer2.enabled=false
then timer2.enabled:=true
else timer2.enabled:=false;
attackk:=0;
atck:=0;
msg.Lines.Add('! ВКЛ/ВЫКЛ!!!');
end;
} //социальное действие Sorrow - удаляем текущую запись в базе
$0D: begin
ID:=MobsID[attackIDMinID];
DelElArr(attackIDMinID);
attackk:=0;
atck:=0;
msg.Lines.Add('Удаляем текущую запись в базе!!!');
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=ID;
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
//ValidatePosition пакет от клиента с моими кординатами
#$48: begin
msg.Lines.Add('C>S $48 ValidatePosition');
//обновляем ВСЕ растояния в BD если мы сошли с места
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
GameToMap(MyXpos,MyYpos);
shape[0].left:=xm; //координаты моего чара
shape[0].top:=ym;
for i:=1 to last do begin
if (MobsID[i]<>0) then begin
if (true<>Aggro[i]) then begin
MobsRAS[i]:=delta(MyXpos,MyYpos,MobsX[i],MobsY[i]);
end;
end;
end;
end;
end;
end;
end.
Отличный скрипт, спасибо.
Но при каче в катах бот может взять в таргет цель, которая на поверхности. Можно ли сделать ограничение по Z в скрипте? Еще не понял вот этот момент: atck:=0; //кол-во неуспешных атак после которых пробуем сместиться. Какое значение лучше оставить и на что влияет? Бот возьмет другой таргет при неудачной атаке (если поставить значение "1") или вернется в центр зоны?
Немного модернизированная версия Бота
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
{Бот для кача ТК 64+ лвл
Достоинства:
- миникарта;
- панель с инфой;
- бафает себя:
- юзает кубики;
- юзает пошин алакрити;
- лечит себя хил пошинами и элементал хилом;
- при желании можно отключить клиент
Скрипт распространяется как есть, и я не несу ответственности
за то, что ВЫ натворили у себя, его используя.}
//************************************************** *************
const
name='NLObP'; //имя чара для которого включен скрипт
//установить константу в зависимости от типа игры (С4 или Интерлюд)
IL=false; //true - IL, false - C4
max=100; //максимальное значение массива
buff1=91; //бафф defense aura
buff2=77; //бафф attack aura
buff3=112; //бафф deflect arrow
buff4=230; //бафф sprint
buff5=123; //бафф spirit barrier
cubicstorm=10;
cubiclife=67;
elementalheal=58;
//************************************************** *************
var
frm : TForm; //панель информации
info, msg, stats : TMemo;
splitter1, splitter2 : Tsplitter;
map : Tform; //виртуальная карта
xm, ym : integer; //координаты на карте
offs1 : integer; //смещение для типа игры Ил или С4
StartTime: TDateTime; //ведем подсчет времени
EndTime: TDateTime;
death1, mob1 : integer; //подсчитываем смерти
underAttack : boolean; //нас атакуют
heal, kill : string;
MaxHP, MyZpos, cvaZ, CurHP, ObjID, ID, xpos, ypos, skill, MyID, PercentHP, MEsit: integer;
MEup, but, sud, bst, Radius, cvaX, attackIDMinID, attackID, cvaY, zpos: integer;
Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc : Boolean;
attackk, bfi, atck, hpi, i, ii: integer; //индексы различных циклов
last : integer; //последняя запись в массиве, для ускорения скрипта
//массив мобов
MobsObjID: array[1..max] of integer;
MobsID: array[1..max] of integer;
MobsName: array[1..max] of string;
MobsRAS: array[1..max] of integer;
MobsX: array[1..max] of integer;
MobsY: array[1..max] of integer;
MobsZ: array[1..max] of integer;
NPCid: array[1..max] of integer;
Aggro: array[1..max] of Boolean;
TTShape: array [0..max] of Tshape; //объекты на карте
TTLabel: array [0..max] of Tlabel; //подписи к объектам
timer1: TTimer;
timer2: TTimer;
timer3: TTimer;
//************************************************** *************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
var
i: integer;
begin
if il then begin
//CharInfo
offs1:=48; //44 для С4, 48 для IL
end else begin
offs1:=44;
end;
StartTime:=time;
underattack:=false; //атакован?
atck:=0; //кол-во неуспешных атак после которых пробуем сменить таргет, здесь инициализация =0
hpi:=0;
bfi:=60; //60 сек
ii:=1;
last:=1; //начальное значение
Radius:=1500; // радиус круга кача!
PercentHP:=70; // при каком количестве хп в % юзать бутылку лечения
MEsit:=55; // при каком количестве хп в % надо сесть и подкопить хп
MEup:=90; // при каком количестве хп в % надо встать после отдыха
frm := TForm.Create(nil);
frm.Caption := 'BOT '+name;
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=520;
frm.Height:=700;
info:=TMemo.Create(frm);
info.parent:=frm;
info.align:=alLeft;
info.ReadOnly:=true;
info.ScrollBars:=0;
info.Width:=370;
info.Height:=370;
// info.Lines.Add('БОТ НЕ ПОДКЛЮЧЁН К СЕРВЕРУ!');
stats:=TMemo.Create(frm);
stats.parent:=frm;
stats.align:=alClient;
stats.ReadOnly:=true;
stats.ScrollBars:=0;
stats.Width:=240;
stats.Height:=100;
msg:=TMemo.Create(frm);
msg.parent:=frm;
msg.align:=alBottom;
msg.ReadOnly:=true;
msg.ScrollBars:=2;
msg.Width:=520;
msg.Height:=100;
msg.Lines.Add('...');
splitter1:=Tsplitter.Create(frm);
splitter1.parent:=frm;
splitter1.Top:=0;
splitter1.Width:=3;
splitter1.Left:=470;
splitter1.align:=alLeft;
splitter2:=Tsplitter.Create(frm);
splitter2.parent:=frm;
splitter2.Left:=0;
splitter2.Height:=3;
splitter2.align:=alBottom;
frm.Show;
map := TForm.Create(nil);
map.Caption:='MiniMap: '+name;
map.BorderStyle:=bsDialog; //bsSizeable;
map.Position:=poScreencenter;
map.Width:=300;
map.Height:=300;
map.FormStyle:=FsStayOnTop;
map.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!
//атака и прочее
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1; //
timer1.enabled:=false; // таймер по умолчанию выключен
timer1.interval:=1000; // через каждые 1сек будем обновлять
//вывод в форму
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2; //
timer2.enabled:=true; // таймер по умолчанию включен
timer2.interval:=1000; // через каждые 1сек будем обновлять
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3; //
timer3.enabled:=true; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
for i:= 1 to max do begin
Aggro[i]:=false;
TTShape[i]:=Tshape.create(nil); //для мобов
TTShape[i].parent:=map;
TTShape[i].Brush.Color:=clBlue; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
TTShape[i].shape:=stCircle;
TTShape[i].left:=-70; //координаты
TTShape[i].top:=-70;
TTShape[i].width:=7; //размеры
TTShape[i].height:=7;
TTlabel[i]:=Tlabel.create(nil);
TTlabel[i].parent:=map;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
TTlabel[i].font.size:=7;
TTlabel[i].font.color:=clBlue;
end;
TTshape[0]:=Tshape.create(nil); //для моего чара
TTshape[0].parent:=map;
TTshape[0].shape:=stCircle;
TTshape[0].Brush.Color:=clBlack;
TTshape[0].left:=-70; //координаты
TTshape[0].top:=-70;
TTshape[0].width:=5; //размеры
TTshape[0].height:=5;
TTlabel[0]:=Tlabel.create(nil); //для моего чара
TTlabel[0].parent:=map;
TTlabel[0].left:=TTShape[0].left+4; //координаты
TTlabel[0].top:=TTShape[0].top+4;
TTlabel[0].caption:=name;
TTlabel[0].font.size:=7;
TTlabel[0].font.color:=clBlack;
end;
//************************************************** *************
procedure GameToMap(x, y : integer);
//преобразуем игровые координаты в координаты карты
var
masshtabx, masshtaby : extended;
begin
// masshtabx:=radius*2 div map.Width;
// masshtaby:=radius*2 div map.Height;
xm:=Round(((X-myXpos)*map.Width/6000)+(map.Width/2));
ym:=Round(((Y-myYpos)*map.Height/6000)+(map.Width/2)*0.9);
// xm:=Round(((X-cvaX)*map.Width/5000)+(map.Width/2));
// ym:=Round(((Y-cvaY)*map.Height/5000)+(map.Width/2));
end;
//************************************************** *************
//RequestRestartPoint
//6D 00 00 00 00
procedure RequestRestartPoint;
begin
buf:=#$6D;
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
procedure ViewInfo;
var
i: integer;
begin
info.Lines.Clear;
stats.Lines.Clear;
stats.Lines.Add('Имя чара :'+Name);
stats.Lines.Add('Время старта :'+TimeToStr(starttime));
stats.Lines.Add('Время работы :'+TimeToStr(time-starttime));
stats.Lines.Add('Убили МОБов: '+IntToStr(mob1)+' раз');
stats.Lines.Add('Погибли: '+IntToStr(death1)+' раз');
stats.Lines.Add('MaxHP :'+IntToStr(MaxHP));
stats.Lines.Add('CurHP :'+IntToStr(CurHP));
stats.Lines.Add('MyID :'+IntToStr(MyID));
stats.Lines.Add('MyXpos :'+IntToStr(MyXpos));
stats.Lines.Add('MyYpos :'+IntToStr(MyYpos));
stats.Lines.Add('MyZpos :'+IntToStr(MyZpos));
stats.Lines.Add('Radius :'+IntToStr(RADIUS));
stats.Lines.Add('cvaX :'+IntToStr(cvaX)+' центр к');
stats.Lines.Add('cvaY :'+IntToStr(cvaY)+' центр к');
stats.Lines.Add('cvaZ :'+IntToStr(cvaZ)+' центр к');
stats.Lines.Add('skill :'+IntToStr(skill)+' юзал скил');
stats.Lines.Add('but :'+IntToStr(but)+' бутылки');
stats.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
stats.Lines.Add('bst :'+IntToStr(bst)+' встать');
stats.Lines.Add('ObjID :'+IntToStr(ObjID)+' кто ходит');
stats.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
stats.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
stats.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
stats.Lines.Add('sit :'+VarToStr(sit));
stats.Lines.Add('PercentHP :'+IntToStr(PercentHP)+' %хп');
stats.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
stats.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
stats.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
stats.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
stats.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
stats.Lines.Add('atck :'+IntToStr(atck)+' цикл неудачных атак');
stats.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
stats.Lines.Add('SummaAR :'+IntToStr(Summ(MobsObjID))+' всего в бд');
stats.Lines.Add('rezu :'+IntToStr(delta(MyXpos, MyYpos, xpos, ypos))+' рез ближ');
stats.Lines.Add('MaxX :'+IntToStr(MaxX));
stats.Lines.Add('MaxID :'+IntToStr(MaxID));
stats.Lines.Add('MinX :'+IntToStr(MinX));
stats.Lines.Add('MinID :'+IntToStr(MinID));
stats.Lines.Add('povtor :'+VarToStr(povtor));
stats.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
stats.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
stats.Lines.Add('Hpotion: '+inttostr(Hpotion));
stats.Lines.Add('Apotion: '+inttostr(Apotion));
stats.Lines.Add('xm :'+IntToStr(xm));
stats.Lines.Add('ym :'+IntToStr(ym));
// if (MaxHP<>0) then begin
info.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
info.Lines.Add('HP:'+IntToStr(CurHP)+' из '+IntToStr(MaxHP)+' Цикл1='+IntToStr(attackk)+' Цикл2='+IntToStr(atck)+' Цикл бафа='+IntToStr(bfi));
if (Hpotion=0) then info.Lines.Add('Юзать HP бутылки?: НЕТ!');
if (Hpotion<>0) then info.Lines.Add('Юзать HP бутылки?: ДА!');
if (Apotion=0) then info.Lines.Add('Юзать AP бутылки?: НЕТ!');
if (Apotion<>0) then info.Lines.Add('Юзать AP бутылки?: ДА!');
if (sit=false) then info.Lines.Add('Бот стоит!');
if (sit=true) then info.Lines.Add('Бот сидит!');
for i:= 1 to last do begin
if (MobsObjID[i]<>0) then begin
if (attackIDMinID<>i) then info.Lines.Add('--'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
if (attackIDMinID=i) then info.Lines.Add('->'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
end;
end;
for i:= 1 to last do begin
if (MobsObjID[i]<>0) then begin
GameToMap(MobsX[i],MobsY[i]);
TTShape[i].left:=xm; //координаты моба
TTShape[i].top:=ym;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
if Aggro[i]=true then begin
TTShape[i].Brush.Color:=clPurple;
TTlabel[i].font.color:=clPurple;
end;
end;
end;
// end;
if (MaxHP=0) then info.Lines.Add('Для инициализации Бота используй аптечку!');
end;
//************************************************** *************
procedure Free;
begin
DelALL;
end;
//************************************************** *************
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
end;
end;
// if (MaxHP<>0) and (tame=false) then // вычисляем процентное соотношение хп
if (MaxHP<>0) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*PercentHP); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
// tame:=true;
end;
end;
//************************************************** *************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$01;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyXpos); //откуда
WriteD(MyYpos);
WriteD(MyZpos);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(Name);
msg.Lines.Add('MoveTo('+inttostr(targetx)+','+intt ostr(targety)+','+inttostr(targetz)+')');
end;
//************************************************** *************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:exte nded):boolean;
begin
if delta(targetx, targety, MyXpos, MyYpos)<=distanciya
then result:=true else result:=false;
end;
//************************************************** *************
function delta(xpos1, ypos1, xpos2, ypos2:extended):integer; //возвращает переменную rezu которая является растоянием между 2 точками
begin
result:= Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;
//************************************************** *************
procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsObjID[ele]:=0;
MobsID[ele]:=0;
MobsName[ele]:='';
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
Aggro[ele]:=false;
TTShape[ele].left:=-70; //координаты
TTShape[ele].top:=-70;
TTShape[ele].Brush.Color:=clBlue;
TTlabel[ele].left:=TTShape[ele].left+4; //координаты
TTlabel[ele].top:=TTShape[ele].top+4;
TTlabel[ele].caption:='';
TTlabel[ele].font.color:=clBlue;
end;
//************************************************** *************
procedure DelALL; //обнуляем всю базу!
var
i: integer;
begin
for i:= 1 to max do begin
NPCid[i]:=0;
MobsObjID[i]:=0;
MobsID[i]:=0;
MobsName[i]:='';
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
Aggro[i]:=false;
TTshape[i].free;
TTlabel[i].free;
end;
TTshape[0].free;
TTlabel[0].free;
timer1.Free;
timer2.Free;
timer3.Free;
info.Free;
msg.Free;
frm.Free;
map.Free;
end;
//************************************************** *************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
var
minras, i: integer;
begin
MinX:=5000;
MinID:=0;
MaxX:=0;
MaxID:=0;
for i:= 1 to last do begin
if (delta(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius) then begin
if (arra[i]<=MinX) and (arra[i]<>0) then begin
MinX:=arra[i];
MinID:=i;
end;
if (arra[i]>=MaxX) then begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;
end;
//************************************************** *************
function ETOpovtor(chislo: integer; arra:array of integer):boolean;
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
var
i: integer;
begin
Result:=false;
for i:= 1 to last do begin
if (arra[i]=chislo) then Result:=true;
end;
end;
//************************************************** *************
procedure attackt(mobus:integer);
begin
buf:=#$04; //action
WriteD(MobsObjID[mobus]);
WriteD(MyXpos);
WriteD(MyYpos);
WriteD(MyZpos);
WriteC(0);
SendToServerEx(Name);
end;
//************************************************** *************
function Summ(sum:array of integer):integer;
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
i: integer;
begin
Result:=0;
for i:= 1 to max do begin
if (sum[i]<>0) then inc(Result);
end;
end;
//************************************************** *************
procedure OnTimer1(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!!!!!!!!!!!!!
begin
if (MinID>0) then begin
if (sit=false) then begin
case attackk of
0: begin
attackID:=MobsObjID[MinID];
msg.Lines.Add('Атакую! '+IntToStr(attackID));
attackIDMinID:=MinID;
attackt(attackIDMinID); //target
end;
//делаем паузу
1: begin
attackt(attackIDMinID); //attack
end;
6: begin
attackt(attackIDMinID); //target
end;
//делаем паузу
7: begin
attackt(attackIDMinID); //attack
attackk:=1;
inc(atck);
end;
end;
//пробуем сместиться
case atck of
9: begin
MobsRAS[attackIDMinID]:=5000;
// GetMinMaxX(MobsRAS);
attackk:=-1;
atck:=0;
end;
end;
inc(attackk);
end;
end;
end;
//************************************************** *************
procedure OnTimer2(Sender: TObject); //
begin
//контролируем бафы
dec(bfi);
if bfi<0 then begin
timer3.interval:=1000; //каждые 1 сек
bfi:=1200; //20 мин
end;
//выводим в форму
ViewInfo;
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
//идем в центр если нет мобов
// if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
//if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
// end;
if (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Баффаюсь elemental heal!');
MagicSkillUse(elementalheal);
end;
if (CurHP<but) and (Hpotion<>0) then begin
if hpi=5 then begin
UseItem(Hpotion);
hpi:=0;
end else inc(hpi);
end;
if (CurHP<sud) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('все блин я отдыхаю!');
buf:=heal;
SendToServerEx(Name);
sit:=true;
end;
if (CurHP>bst) and (sit=true) then begin
msg.Lines.Add('пора за работу!');
buf:=heal;
SendToServerEx(Name);
attackk:=0;
atck:=0;
sit:=false;
end;
end;
//************************************************** *************
procedure OnTimer3(Sender: TObject); //баффы
begin
if (Summ(Aggro)=0) and (sit=false) then begin
case ii of
1: begin
timer1.enabled:=false; //откл. атаку
msg.Lines.Add('Баффаюсь Defense aura!');
//бафф
MagicSkillUse(buff1);
inc(ii);
timer3.interval:=6000; //каждые 6 сек
end;
2: begin
msg.Lines.Add('Баффаюсь Attack aura!');
MagicSkillUse(buff2);
inc(ii);
end;
3: begin
msg.Lines.Add('Баффаюсь Deflect arrow!');
MagicSkillUse(buff3);
inc(ii);
end;
4: begin
msg.Lines.Add('Баффаюсь Sprint!');
MagicSkillUse(buff4);
inc(ii);
end;
5: begin
msg.Lines.Add('Баффаюсь Spirit barrier!');
MagicSkillUse(buff5);
inc(ii);
timer3.interval:=10000; //каждые 10 сек
end;
6: begin
msg.Lines.Add('Баффаюсь Storm cubic!');
MagicSkillUse(cubicstorm);
inc(ii);
end;
7: begin
msg.Lines.Add('Баффаюсь Life cubic!');
MagicSkillUse(cubiclife);
inc(ii);
end;
8: begin
if Hpotion<>0 then begin
msg.Lines.Add('Potion of Alacrite!');
UseItem(Apotion);
end;
inc(ii);
end;
9: begin
ii:=1;
timer3.interval:=1150000; //каждые 20 мин
bfi:=1150;
timer1.enabled:=true; //вкл. атаку
end;
end;
end;
end;
//************************************************** *************
procedure AddBD(objid, posx, posy, posz:integer;); //добавляем моба в базу данных
var
i: integer;
begin
for i:=1 to last do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(objid, MobsObjID)=false) then begin
MobsObjID[i]:=objid; //ид моба
// if id<>0 then MobsID[i]:=id; //ид моба
MobsRAS[i]:=delta(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
GameToMap(posx,posy);
TTshape[i].left:=xm; //координаты моего чара
TTshape[i].top:=ym;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
break;
end;
end;
end;
//если нет свободного места ищем дальше
for i:=last+1 to max do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(objid, MobsObjID)=false) then begin
MobsObjID[i]:=objid; //ид моба
if id<>0 then MobsID[i]:=id; //ид моба
MobsRAS[i]:=delta(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
last:=i;
GameToMap(posx,posy);
TTshape[i].left:=xm; //координаты моего чара
TTshape[i].top:=ym;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
break;
end;
end;
end;
end;
//************************************************** *************
function ISnpc(id: integer;): boolean;
var
i: integer;
begin
result:=false;
for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;
//************************************************** *************
procedure UseItem(ItemObjID:integer);
begin
buf:=#$14;
WriteD(ItemObjID);
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(S hiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
buf:=#$2F;
WriteD(MagicID);
WriteD(00);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
if (ConnectName=Name) and FromServer then begin
case pck[1] of
{ #$76: begin
msg.Lines.Add('S>C $76');
if (ReadD(2)=MyID) then begin //я юзнул какой то скилл
msg.Lines.Add(' юзнул скилл!');
skill:=1;
end;
end;
} #$0E: begin
msg.Lines.Add('S>C $0E StatsUpdate');
if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
end;
//MagicSkillUse 48, Attack 05
#$05: begin
msg.Lines.Add('S>C $05 Attack');
if (ReadD(6)=MyID) then begin
//меня ударили
sit:=false;
if (ETOpovtor(ReadD(2),MobsObjID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin //если моб записан в базе данных
msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(MobsObjID[i]));
MobsRAS[i]:=1;
Aggro[i]:=true; // стал агрессор
if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
attackIDMinID:=i;
timer1.enabled:=true;
end;
if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
break;
end;
end;
end;
end;
#$0C: begin
msg.Lines.Add('S>C $0C DropItem');
if (MyXpos<>0) then begin
if (delta(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
msg.Lines.Add('Выпала вещь!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
WriteC(0);
SendToServerEx(Name);
msg.Lines.Add(' Пробую поднять!!!');
delay(1000);
timer1.enabled:=true;
end;
end;
end;
#$04: begin
msg.Lines.Add('S>C $04 CharInfo');
//пакет с инфой о моём чаре
i:=2;
MyXpos:=ReadD(i); //получаю координату х моего чара
MyYpos:=ReadD(i); //получаю координату у моего чара
MyZpos:=ReadD(i); //получаю координату z моего чара
//Запоминаем ИД
i:=18;
MyID:=ReadD(i); //получаю ид моего чара
//смещение переменное, зависит от имени (LenName*2+2)
i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
if (gdo=false) then begin //задаем центр окружности кача
cvaX:=MyXpos;
cvaY:=MyYpos;
gdo:=true;
end;
GameToMap(MyXpos,MyYpos);
TTshape[0].left:=xm; //координаты моего чара
TTshape[0].top:=ym;
TTlabel[0].left:=TTShape[0].left+4; //координаты
TTlabel[0].top:=TTShape[0].top+4;
end;
#$01: begin
msg.Lines.Add('S>C $01 Move');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
i:=2;
ObjID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
ID:=0; //кто-то рыпнулся с места надо это записать...
xpos:=ReadD(i);
ypos:=ReadD(i);
zpos:=ReadD(i);
if not ISnpc(ObjID) {and (delta(cvaX,cvaY,xpos,ypos)<=Radius)} then AddBD(ObjID,xpos,ypos,zpos);
end;
end;
//принят пакет Die
#$06: begin
msg.Lines.Add('S>C $06 Die');
//нас убили
if (myID=ReadD(2)) then begin
info.Lines.Add('Нас убили в '+TimeToStr(time));
inc(death1);
RequestRestartPoint; //оживаем после смерти
// mov:=1;
//TODO сделать проверки на место появления
// moveto1.enabled:=true;
info.Lines.Add('Бежим после смерти на берег...');
underattack:=false;
for i:= 1 to max do begin
Aggro[i]:=false;
TTShape[i].Brush.Color:=clBlue;
TTlabel[i].font.color:=clBlue;
end;
end;
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin
inc(mob1);
DelElArr(i);
attackk:=0;
atck:=0;
msg.Lines.Add('БОБИК СДОХ!! :'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
//принят пакет DeleteObject
#$12: begin
msg.Lines.Add('S>C $12 DeleteObject');
//выкидываем из базы
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin
DelElArr(i);
msg.Lines.Add('Удаляю из базы!! :'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
#$03: begin
msg.Lines.Add('S>C $03 Char');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(18),NPCid)=false) then begin
NPCid[i]:=ReadD(18);
msg.Lines.Add('ДОБАВЛЕН ИГРОК:'+ReadS(22)+'-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
#$16: begin
msg.Lines.Add('S>C $16 NPC');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
msg.Lines.Add('Вижу NPC!');
if (ReadD(10)=0) then begin //если нельзя атаковать
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(2), NPCid)=false) then begin
NPCid[i]:=ReadD(2);
msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
break;
end;
end;
end;
end;
if (ReadD(10)=1) and (pck[120]=#$00) then begin //если можно атаковать
// if (delta(cvaX, cvaY, ReadD(14), ReadD(18))<=Radius) then begin
id:=ReadD(6);
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
// end
// else msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' вне радиуса действия!');
end;
end;
end;
//InventoryUpdate
#$27: begin
msg.Lines.Add('S>C $27 InventoryUpdate');
if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
Hpotion:=ReadD(8);
msg.Lines.Add('ID бутылок Hpotion:'+inttostr(Hpotion));
end;
if ReadD(12)=735 then begin //Potion of Alacrity
Apotion:=ReadD(8);
msg.Lines.Add('ID бутылок Apotion:'+inttostr(Apotion));
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=Name) and FromClient then begin
case pck[1] of
#$1B: begin
msg.Lines.Add('C>S $1B ');
case ReadD(2) of
//социальное действие Yes для начала
$06: begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
GameToMap(MyXpos,MyYpos);
TTshape[0].left:=xm; //координаты моего чара
TTshape[0].top:=ym;
TTlabel[0].left:=TTShape[0].left+4; //координаты
TTlabel[0].top:=TTShape[0].top+4;
attackk:=0;
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты ОБНОВЛЕНЫ!!');
// GetMinMaxX(MobsRAS);
timer1.enabled:=true;
timer3.enabled:=true;
end;
//социальное действие No для окончания
$05: begin
timer1.enabled:=false;
timer3.enabled:=false;
msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
end;
{ //социальное действие Applaud
$0B: begin
if timer2.enabled=false
then timer2.enabled:=true
else timer2.enabled:=false;
attackk:=0;
atck:=0;
msg.Lines.Add('! ВКЛ/ВЫКЛ!!!');
end;
} //социальное действие Sorrow - удаляем текущую запись в базе
$0D: begin
ObjID:=MobsObjID[attackIDMinID];
DelElArr(attackIDMinID);
attackk:=0;
atck:=0;
msg.Lines.Add('Удаляем текущую запись в базе!!!');
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=ObjID;
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
//ValidatePosition пакет от клиента с моими кординатами
#$48: begin
msg.Lines.Add('C>S $48 ValidatePosition');
//обновляем ВСЕ растояния в BD если мы сошли с места
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
GameToMap(MyXpos,MyYpos);
TTshape[0].left:=xm; //координаты моего чара
TTshape[0].top:=ym;
TTlabel[0].left:=TTShape[0].left+4; //координаты
TTlabel[0].top:=TTShape[0].top+4;
for i:=1 to last do begin
if (MobsObjID[i]<>0) then begin
if (true<>Aggro[i]) then begin
MobsRAS[i]:=delta(MyXpos,MyYpos,MobsX[i],MobsY[i]);
end;
end;
end;
end;
end;
end;
end.
Добавлено спустя 21 минуту 31 секунду:
Отличный скрипт, спасибо.
Но при каче в катах бот может взять в таргет цель, которая на поверхности. Можно ли сделать ограничение по Z в скрипте? Еще не понял вот этот момент: atck:=0; //кол-во неуспешных атак после которых пробуем сместиться. Какое значение лучше оставить и на что влияет? Бот возьмет другой таргет при неудачной атаке (если поставить значение "1") или вернется в центр зоны?
Спасибо.
В катах можно попробовать сильно уменьшить RADIUS - радиус кача.
Ограничение по Z можно сделать, например типа такого
const DeltaZ=200;
...
//NPCInfo, запоминаем мобов
if FromServer and (ConnectName=Name) and (pck[1]=#$16) then begin
...
//проверям, не под землей ли моб(в катакомбах)
tempZ:=BotCoordZ-ReadD(22);
if abs(tempZ)<=DeltaZ then begin
for i:=1 to max do begin
...
Переменная atck и attackk используются в процедуре OnTimer1.
attackk - нужна для контроля атаки
atck - если вдруг застряли - пытаемся изменить цель (через время atck(5) * attackk(7) = 35 сек)
цель меняется даже если не застряли но вреемя вышло, можно подкорректировать время в нужную сторону
NLObP, в катах там вообще жесть если моб в соседней комнате встанет у стеночки то бот затупит у стенки
СУПЕР СКРИПТЯРИЩЩЩЕЕ!!!! Я фигею как ты его написал то, я его даже прокручивать устал=)))
А в катах ка4 в 1 перс - лажа=)))
Добавлено спустя 35 минут 43 секунды:
Люди! Вот такие пакеты бутылей и они не пьютца!
Может знаете как расшифровать, или как заюзать энто???
Заранее спасибо - это Эльмор.ру
хрень1 - 0 14 ee
хрень2 - 252
время- 23 03 35 609
ИД- 408B7B96
14 96 7B 8B 40 00 00 00 00 E6 58 A5 52 E8 CE 6F 56 48 6D 90 ED 0D C8 46 2D
14 96 7B 8B 40 00 00 00 00 F5 13 52 66 E6 4D F9 72 5E 6D 05 59 25 34 13 A2
14 96 7B 8B 40 00 00 00 00 BE 42 64 63 38 C3 C5 18 79 F6 80 B2 B6 D4 DF 7F
14 96 7B 8B 40 00 00 00 00 9F 0D D3 0E FD F1 26 F5 D0 D9 04 D1 5A 34 B7 ED
14 96 7B 8B 40 00 00 00 00 8A 38 27 0E A1 28 DA F2 CE 66 98 BC B8 FF EC 82
14 96 7B 8B 40 00 00 00 00 1B 64 EF 77 3C 67 33 0A E5 4A C5 5D 71 DB A2 E2
14 96 7B 8B 40 00 00 00 00 B8 7C 53 68 27 DD 47 0A 8F BB 1E 82 C5 7E 59 60
14 96 7B 8B 40 00 00 00 00 68 6F E1 1E 4E ED DB AA 64 29 D1 E2 99 F5 DE 38
14 96 7B 8B 40 00 00 00 00 72 3A 58 67 6D 52 70 C6 EE 82 35 19 1B CE 02 65
14 96 7B 8B 40 00 00 00 00 14 60 D5 7D 9A C7 93 E8 D8 77 B5 C8 C6 40 D9 C1
14 96 7B 8B 40 00 00 00 00 CD 33 37 73 72 A9 6F A9 3A BA 4D 24 7C 09 4C 5A
14 96 7B 8B 40 00 00 00 00 0D 7F 7D 5A BD 6C 8D DA 1A 14 15 AC 61 BC EB 96
14 96 7B 8B 40 00 00 00 00 44 20 5E 79 67 04 71 9B 24 07 B3 1D 55 5B 11 E0
14 96 7B 8B 40 00 00 00 00 B4 1F 94 65 48 A5 5D AC 6D 92 A3 20 E9 28 2A CF
14 96 7B 8B 40 00 00 00 00 66 4F 08 6E D3 77 AA 3A 5B E7 5B 3B C2 6A 13 A2
14 96 7B 8B 40 00 00 00 00 33 78 FD 0C FA C1 0D 81 E1 9A CD DC 02 7F 35 59
14 96 7B 8B 40 00 00 00 00 CB 63 A5 64 68 96 66 56 CC 42 DC 70 40 FC F7 C2
14 96 7B 8B 40 00 00 00 00 10 54 0F 2F C2 CA C0 10 28 10 2A 27 40 29 39 A0
14 96 7B 8B 40 00 00 00 00 4C 3A F0 09 EF 2C A2 AE 10 58 62 D1 74 73 B4 84
14 96 7B 8B 40 00 00 00 00 03 55 42 08 4A A1 10 17 97 6E 77 3C B2 F9 A4 75
14 96 7B 8B 40 00 00 00 00 73 51 E2 6E DB F0 48 89 4C 0A 83 BD 96 CE 7A DB
14 96 7B 8B 40 00 00 00 00 05 36 48 35 54 38 02 B1 D5 2A D3 84 EF 7F AF 88
14 96 7B 8B 40 00 00 00 00 31 45 1A 05 35 A4 E9 34 83 BF F7 E1 E6 11 5F E0
14 96 7B 8B 40 00 00 00 00 AA 44 A0 37 E7 3D 13 B5 31 D5 C2 57 91 F1 6E AB
14 96 7B 8B 40 00 00 00 00 CF 32 03 5D 89 08 78 B3 AF B3 0F 4D E0 82 22 B7
14 96 7B 8B 40 00 00 00 00 B0 04 7B 51 0B 1E E4 00 6E 51 49 F9 E9 F3 FF 3B
14 96 7B 8B 40 00 00 00 00 27 19 64 18 B4 F2 1E 20 6E A3 32 81 3A 01 23 CD
14 96 7B 8B 40 00 00 00 00 D8 31 51 75 A9 09 E8 B0 CF 8D A6 9C C1 CA C2 4C
14 96 7B 8B 40 00 00 00 00 14 09 33 36 03 B0 9E D1 5F FA 8F C3 9F AE 8B 56
14 96 7B 8B 40 00 00 00 00 F4 13 E3 64 25 65 CE 2A AE 0F 35 46 90 09 9A 2A
14 96 7B 8B 40 00 00 00 00 27 3A D7 2F B0 0F AD 0B C5 B0 FE 74 14 63 D7 36
14 96 7B 8B 40 00 00 00 00 42 59 F7 30 CC 88 54 C5 95 F8 65 1B 47 A2 BD 33
14 96 7B 8B 40 00 00 00 00 9C 57 D2 45 10 5F BF 9B F1 9E 74 CA F3 92 3B 83
14 96 7B 8B 40 00 00 00 00 F8 6A 6F 4F C7 5E 7A 82 3C E8 18 A8 30 46 8B A9
14 96 7B 8B 40 00 00 00 00 8C 19 63 36 B2 00 A2 31 20 0C 68 2E 5B EA D8 F4
14 96 7B 8B 40 00 00 00 00 20 70 29 04 94 87 E9 F9 CE F8 1F 87 27 AA 60 E4
14 96 7B 8B 40 00 00 00 00 64 7E 8D 4F 50 31 37 69 0A 01 46 C0 A1 BE C2 CF
А в катах ка4 в 1 перс - лажа=)))
ну смотря какой перс и как играть :) тёмным сумонером ПП нужен 74 лвл, если котоводом то ПП и ШЕ в пати и комнаты где 8 мобов ну понятно без резистов к физике умирают если БД воткнуть до 60лвла даже то кошка и тень простаивают долго, тенью и кошкой это по раздельности.
Гринч ты не внимательно прочитал там же написано в одного перса т.е. без ШЕ ПП БД БИШОПА и прочих :)
Всем привет. Вот наконец доделал и протестил АвтоСвип.
Зацените мой первый скриптец. Если какие ошибки найдете, пишите.
//Автоматизация sweep'а by APXAHGEJI
//Свип производится тока при условии что моб был ,хоть один раз, ударен ВАМИ и
//находится в списке нужных мобов.
//Возможность работы нескольких одновременных скриптов
//Социальное действие YES - запусстить/приостановить запись/АвтоСвип мобов
//Социальное действие NO остановиться - завершить запись мобов и перейтии к АвтоСвип
//После того как скрипт запущен нажимаете Yes и атакуете по одному мобу каждого
//вида которых собираетесь спойлить. Атакуете до тех пор пока не появилась запись
//что моб записан. Для удобства процесс записи можно приостановить нажатие той же
//клавиши Yes. После того как все нужные мобы записаны жмакаете NO, запись мобов
//завершается, АвтоСвип запускается, можете приступать к спойлу. АвтоСвип можно
//приостановить нажав всю туже клавишу соцдействия Yes, но запись мобов под АвтоСвип
//не остановится, и снова активировав, все нужные мобы просвипятся.
Const
Name='Yes';
Sweep='2F 2A 00 00 00 00 00 00 00 00';
Var
Timer: TTimer;
N,M,i,NpcNum: Byte;
X,Y,Z,CharID: Integer;
NpcTypeID,TargetID: array of Integer;
NeedSweep,Dead: array of Boolean;
Switch,SaveID,HaveNpc,OffSweeper: Boolean;
//************************************************** ****************************
// Вызывается при включении скрипта
//************************************************** ****************************
Procedure Init;
begin
N:= 1;
M:= 0;
Switch:= False;
SaveID:= True;
SetLength( NpcTypeID, N );
SetLength( TargetID, N );
Timer:=TTimer.Create(nil);
Timer.OnTimer:=@Sweeper;
Timer.Enabled:= False;
Timer.Interval:= 500;//время задержки свипа
Say('Введите 1 в чат, чтобы начать/приостановить');
Say('запись мобов или АвтоСвип.');
Say('Введите 2 в чат, чтобы завершить запись мобов');
Say('и приступить к сполйу.');
end;
//************************************************** ****************************
//************************************************** ****************************
// Вызывается при выключении скрипта
//************************************************** ****************************
Procedure Free;
begin
Timer.Free;
end;
//************************************************** ****************************
//************************************************** ****************************
// Посылаем сообщение, которое видно только в окне бота
//************************************************** ****************************
Procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(Name);
WriteS(msg);
SendToClientEx(Name);
end;
//************************************************** ****************************
//************************************************** ****************************
// Проверка наличия ИД моба в массиве
//************************************************** ****************************
Procedure FindMob(ObjectID: Integer);
begin
HaveNpc:= False;
NpcNum:= M;
For i:=0 to (M-1) do
If (ObjectID=TargetID[i]) then begin
NpcNum:= i;
HaveNpc:= True;
break;
end Else
If (TargetID[i]= 0) and (NpcNum = M) then NpcNum:= i;
end;
//************************************************** ****************************
//************************************************** ****************************
// Запуск свипа каждые n секунд (n= Timer.Interval)
//************************************************** ****************************
Procedure Sweeper(Sender: TObject);
begin
OffSweeper:= True;
For i:=0 to (M-1) do begin
If NeedSweep[i] and Dead[i] then begin
If Switch then begin
buf:= #$04;
WriteD(TargetID[i]);
WriteD(X);
WriteD(Y);
WriteD(Z);
WriteC(00);
SendToServerEx(Name);
buf:=HStr(Sweep);
SendToServerEx(Name);
end;
exit;
end;
If (TargetID[i]<>0) then OffSweeper:= False;
end;
If OffSweeper then begin
M:= 0;
SetLength(TargetID, M);
SetLength(NeedSweep, M);
SetLength(Dead, M);
Timer.Enabled:= False;
exit;
end;
end;
//************************************************** ****************************
//************************************************** ****************************
// Вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
Begin
//************************************************** **************************
//Не обрабатываем пустые пакеты
If pck='' then exit;
//************************************************** **************************
//************************************************** **************************
//Если от сервака принят пакет UserInfo. Запоминаем собственный ИД.
If FromServer and (ConnectName=Name) and (pck[1]=#$04) then CharID:= ReadD(18);
//************************************************** **************************
//************************************************** **************************
//Переключение между записью ИД и АвтоСвипом
If SaveID then begin
//************************************************** ************************
//Делаем выборку нужных для свипа видов мобов
//************************************************** ************************
if Switch then
if FromServer and (ConnectName=Name) then
if (pck[1]=#$05) and (ReadD(2)=CharID) then
if (ReadD(6)<>TargetID[N-1]) then TargetID[N-1]:= ReadD(6);
if (pck[1]=#$16) and (ReadD(2)=TargetID[N-1]) then
if (ReadD(6)<> NpcTypeID[N-1]) then begin
NpcTypeID[N-1]:= ReadD(6);
Inc(N);
SetLength( NpcTypeID, N );
SetLength( TargetID, N );
TargetID[N-1]:= TargetID[N-2];
NpcTypeID[N-1]:= NpcTypeID[N-2];
Say('Моб записан');
end;
//************************************************** ************************
//Управление записью мобов
//************************************************** ************************
If FromClient and (ConnectName=Name) and (pck[1]=#$1B) then begin
If (ReadD(2)=6) then
if Switch then begin
pck:='';
Switch:= False;
Say('Запись мобов приостановлена');
end
else begin
pck:='';
Switch:= True;
Say('Начата запись мобов, атакуйте нужных мобов');
end;
If (ReadD(2)=5) then begin
pck:='';
Dec(N);
SetLength(NpcTypeID, N);
SetLength(TargetID, M);
SetLength(NeedSweep, M);
SetLength(Dead, M);
SaveID:= False;
Switch:= True;
Say('Запись мобов завершена, АвтоСвип активирован');
Say('Удачного спойла');
end;
end;
//************************************************** ************************
end
//************************************************** **************************
//************************************************** **************************
//Переходим от записи нужных мобов к АвтоСвипу
Else begin
//************************************************** **************************
//************************************************** ************************
//Записываем текущие координаты
if FromClient and (ConnectName=Name) and (pck[1]=#$48) then begin
X:= ReadD(2);
Y:= ReadD(6);
Z:= ReadD(10);
end;
//************************************************** ************************
//************************************************** ************************
//Анализ мобов :=))
If FromServer and (ConnectName=Name) then begin
//************************************************** **********************
//Записываем всех атакованых нами мобов (пакет Attack, причем Attacker=CharID)
If ((pck[1]= #$05) and (ReadD(2)= CharID)) then begin
FindMob(ReadD(6));
If not HaveNpc then
If (NpcNum <> M) then begin
TargetID[NpcNum]:= ReadD(6);
NeedSweep[NpcNum]:= False;
Dead[NpcNum]:= False
end Else begin
Inc(M);
SetLength(TargetID, M);
SetLength(NeedSweep, M);
SetLength(Dead, M);
TargetID[M-1]:= ReadD(6);
NeedSweep[M-1]:= False;
Dead[M-1]:= False;
Timer.enabled:= True;
end;
end;
//************************************************** **********************
//Проверяем есть ли в списке мобы
if (M <> 0) then begin
//************************************************** ********************
//Проверяем тот ли вид моба атакован (пакет NpcInfo)
If (pck[1]= #$16) then begin
FindMob(ReadD(2));
If HaveNpc and (not NeedSweep[NpcNum]) then begin
For i:=0 to (N-1) do
If (ReadD(6)= NpcTypeID[i]) then begin
HaveNpc:= False;
Break;
end;
If not HaveNpc then NeedSweep[NpcNum]:= True;
end;
end;
//************************************************** ********************
//Записываем что атакованый моб умер (пакет Die, причем Sweepable=1)
If (pck[1]= #$06) and (pck[22]= #$01) then begin
FindMob(ReadD(2));
If HaveNpc then Dead[NpcNum]:= True;
end;
//************************************************** ********************
//Удаляем записи об атакованом мобе (пакет DeleteObject)
If (pck[1]= #$12) then begin
FindMob(ReadD(2));
If HaveNpc then begin
TargetID[NpcNum]:= 0;
NeedSweep[NpcNum]:= False;
Dead[NpcNum]:= False;
end;
end;
//************************************************** ********************
end;
//************************************************** **********************
end;
//************************************************** ************************
//************************************************** ************************
//Запускаем/приостанавливаем АвтоСвип
//************************************************** ************************
If FromClient and (ConnectName=Name) and (pck[1]=#$1B) and (ReadD(2)=6) then
if Switch then begin
pck:='';
Switch:= False;
Say('АвтоСвип приостановлен');
end
else begin
pck:='';
Switch:= True;
Say('АвтоСвип запущен');
end;
//************************************************** ************************
end;
//************************************************** **************************
End.
//************************************************** ****************************
Я оценил! ошибок вроде нет, все автоматизировано. Кстати я ничего не смыслю в програмировании=))) но скрипт правда качаственный :)
Новая версия бота. Проверяет координату Z. Подрихтовал миникарту.
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
{Бот для кача ТК 64+ лвл
Скрипт распространяется как есть, и я не несу ответственности
за то, что ВЫ натворили у себя, его используя.
Возможности скрипта:
- работает на С4 и Интерлюде;
- миникарта, усл. обозн.:
- зеленые в зоне Radius кача;
- белые вне DeltaZ;
- синие вне зоны Radius кача;
- розовые нас атакуют;
- красный мы атакуем;
- панель с инфой;
- сам бафается;
- сам юзает кубики;
- сам юзает алакрити;
- сам лечит себя хил пошинами и элементал хилом;
- проверка координаты Z для кача в катакомбах;}
//************************************************** *************
const
name='NLObP'; //имя чара для которого включен скрипт
//установить константу в зависимости от типа игры (С4 или Интерлюд)
IL=false; //true - IL, false - C4
max=100; //максимальное значение массива
Radius=1500; //радиус участка для поиска мобов
DZ=200; //глубина/высота до мобов
PercentHP=70; //при каком количестве хп в % юзать бутылку лечения
MEsit=55; //при каком количестве хп в % надо сесть и подкопить хп
MEup=90; //при каком количестве хп в % надо встать после отдыха
buff1=91; //бафф defense aura
buff2=77; //бафф attack aura
buff3=112; //бафф deflect arrow
buff4=230; //бафф sprint
buff5=123; //бафф spirit barrier
cubicstorm=10;
cubiclife=67;
elementalheal=58;
//************************************************** *************
var
frm : TForm; //панель информации
info, msg, stats : TMemo;
splitter1, splitter2 : Tsplitter;
map : Tform; //виртуальная карта
xm, ym : integer; //координаты на карте
offs1 : integer; //смещение для типа игры Ил или С4
StartTime: TDateTime; //ведем подсчет времени
EndTime: TDateTime;
death1, mob1 : integer; //подсчитываем смерти
underAttack : boolean; //нас атакуют
heal, kill : string;
MaxHP, MyZpos, CurHP, ObjID, ID, xpos, ypos, skill, MyID : integer;
but, sud, bst, attackIDMinID, attackID, zpos: integer;
cvaX, cvaY, cvaZ: integer; //координата центра кача
Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc, stop: Boolean;
attackk, bfi, atck, hpi, i, ii: integer; //индексы различных циклов
last : integer; //последняя запись в массиве, для ускорения скрипта
//массив мобов
MobsObjID: array[1..max] of integer;
MobsID: array[1..max] of integer;
MobsName: array[1..max] of string;
MobsRAS: array[1..max] of integer;
MobsX: array[1..max] of integer;
MobsY: array[1..max] of integer;
MobsZ: array[1..max] of integer;
NPCid: array[1..max] of integer;
Aggro: array[1..max] of Boolean;
TTShpC : Tshape; //центр кача на карте
TTShape: array [0..max] of Tshape; //объекты на карте
TTLabel: array [0..max] of Tlabel; //подписи к объектам
timer1: TTimer;
timer2: TTimer;
timer3: TTimer;
timer4: TTimer;
//************************************************** *************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
var
i: integer;
begin
if il then begin
//CharInfo
offs1:=48; //44 для С4, 48 для IL
end else begin
offs1:=44;
end;
StartTime:=time;
underattack:=false; //атакован?
stop:=true; //откл. атака
atck:=0; //кол-во неуспешных атак после которых пробуем сменить таргет, здесь инициализация =0
hpi:=0;
bfi:=60; //60 сек
ii:=1;
last:=1; //начальное значение
//ПАНЕЛЬКА
frm := TForm.Create(nil);
frm.Caption := 'BOT '+name;
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=600;
frm.Height:=800;
//информация
info:=TMemo.Create(frm);
info.parent:=frm;
info.align:=alLeft;
info.ReadOnly:=true;
info.ScrollBars:=0;
info.Width:=450;
info.Height:=370;
//статистика
stats:=TMemo.Create(frm);
stats.parent:=frm;
stats.align:=alClient;
stats.ReadOnly:=true;
stats.ScrollBars:=0;
stats.Width:=150;
stats.Height:=100;
//сообщения
msg:=TMemo.Create(frm);
msg.parent:=frm;
msg.align:=alBottom;
msg.ReadOnly:=true;
msg.ScrollBars:=2;
msg.Width:=600;
msg.Height:=100;
msg.Lines.Add('...');
//разделители
splitter1:=Tsplitter.Create(frm);
splitter1.parent:=frm;
splitter1.Top:=0;
splitter1.Width:=3;
splitter1.Left:=470;
splitter1.align:=alLeft;
//разделители
splitter2:=Tsplitter.Create(frm);
splitter2.parent:=frm;
splitter2.Left:=0;
splitter2.Height:=3;
splitter2.align:=alBottom;
frm.Show;
//карта
map := TForm.Create(nil);
map.Caption:='MiniMap: '+name;
map.BorderStyle:=bsSizeable;
map.Position:=poScreencenter;
map.Width:=300;
map.Height:=300;
map.FormStyle:=FsStayOnTop;
map.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!
//атака и прочее
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnAttack;
timer1.enabled:=false; //таймер по умолчанию выключен
timer1.interval:=1000; //через каждые 1сек будем обновлять
//вывод в форму
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnView;
timer2.enabled:=true; //таймер по умолчанию включен
timer2.interval:=1000; //через каждые 1сек будем обновлять
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnBuff; //
timer3.enabled:=false; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
//рисуем карту
timer4:=TTimer.Create(nil);
timer4.OnTimer:=@OnMap;
timer4.enabled:=true; //таймер по умолчанию включен
timer4.interval:=1000; //через каждые 1сек будем обновлять
for i:= 1 to max do begin
Aggro[i]:=false;
//готовим точки МОБов
TTShape[i]:=Tshape.create(nil); //для мобов
TTShape[i].parent:=map;
TTShape[i].Brush.Color:=clBlue; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
TTShape[i].shape:=stCircle;
TTShape[i].left:=-70; //координаты
TTShape[i].top:=-70;
TTShape[i].width:=7; //размеры
TTShape[i].height:=7;
//Готовим названия
TTlabel[i]:=Tlabel.create(nil);
TTlabel[i].parent:=map;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
TTlabel[i].font.size:=7;
TTlabel[i].font.color:=clBlue;
end;
//Готовим точку для центра кача
TTShpC:=Tshape.create(nil); //для моего чара
TTShpC.parent:=map;
TTShpC.shape:=stCircle;
TTShpC.Brush.Color:=clYellow;
TTShpC.left:=-70; //координаты
TTShpC.top:=-70;
TTShpC.width:=3; //размеры
TTShpC.height:=3;
//Готовим точку для ГГ
TTshape[0]:=Tshape.create(nil); //для моего чара
TTshape[0].parent:=map;
TTshape[0].shape:=stCircle;
TTshape[0].Brush.Color:=clBlack;
TTshape[0].left:=-70; //координаты
TTshape[0].top:=-70;
TTshape[0].width:=5; //размеры
TTshape[0].height:=5;
//готовим имя ГГ
TTlabel[0]:=Tlabel.create(nil); //для моего чара
TTlabel[0].parent:=map;
TTlabel[0].left:=TTShape[0].left+4; //координаты
TTlabel[0].top:=TTShape[0].top+4;
TTlabel[0].caption:=name;
TTlabel[0].font.size:=7;
TTlabel[0].font.color:=clBlack;
end;
//************************************************** *************
procedure GameToMap(x, y : integer);
//Пока ничего умнее не придумал =(
//преобразуем игровые координаты в координаты карты
var
masshtabx, masshtaby:integer;
begin
masshtabx:=radius*map.Width div 200;
masshtaby:=radius*map.Height div 200;
xm:=Round(((X-myXpos)*map.Width/masshtabx)+(map.Width/2));
//коэфф. 0.9 для попадания точки X,Y=0 в центр карты
ym:=Round(((Y-myYpos)*map.Height/masshtaby)+(map.Width/2)*0.9);
end;
//************************************************** *************
//RequestRestartPoint
procedure RequestRestartPoint;
begin
buf:=#$6D;
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
procedure ViewInfo;
var
i: integer;
begin
info.Lines.Clear;
stats.Lines.Clear;
stats.Lines.Add('Имя чара :'+Name);
stats.Lines.Add('Время старта :'+TimeToStr(starttime));
stats.Lines.Add('Время работы :'+TimeToStr(time-starttime));
stats.Lines.Add('Убили МОБов: '+IntToStr(mob1)+' шт.');
stats.Lines.Add('Погибли: '+IntToStr(death1)+' раз');
stats.Lines.Add('MaxHP :'+IntToStr(MaxHP));
stats.Lines.Add('CurHP :'+IntToStr(CurHP));
stats.Lines.Add('MyID :'+IntToStr(MyID));
stats.Lines.Add('MyXpos :'+IntToStr(MyXpos));
stats.Lines.Add('MyYpos :'+IntToStr(MyYpos));
stats.Lines.Add('MyZpos :'+IntToStr(MyZpos));
stats.Lines.Add('PercentHP :'+IntToStr(PercentHP)+' %хп');
stats.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
stats.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
stats.Lines.Add('Radius :'+IntToStr(RADIUS));
stats.Lines.Add('DeltaZ :'+IntToStr(DZ));
stats.Lines.Add('cvaX :'+IntToStr(cvaX));
stats.Lines.Add('cvaY :'+IntToStr(cvaY));
stats.Lines.Add('cvaZ :'+IntToStr(cvaZ));
stats.Lines.Add('but :'+IntToStr(but)+' бутылки');
stats.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
stats.Lines.Add('bst :'+IntToStr(bst)+' встать');
stats.Lines.Add('ObjID :'+IntToStr(ObjID)+' кто ходит');
stats.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
stats.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
stats.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
stats.Lines.Add('sit :'+VarToStr(sit));
stats.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
stats.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
stats.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
stats.Lines.Add('atck :'+IntToStr(atck)+' цикл выбора другой цели');
stats.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
stats.Lines.Add('SummaAR :'+IntToStr(Summ(MobsObjID))+' всего в бд');
stats.Lines.Add('rezu :'+IntToStr(DeltaXY(MyXpos, MyYpos, xpos, ypos))+' рез ближ');
stats.Lines.Add('MaxX :'+IntToStr(MaxX));
stats.Lines.Add('MaxID :'+IntToStr(MaxID));
stats.Lines.Add('MinX :'+IntToStr(MinX));
stats.Lines.Add('MinID :'+IntToStr(MinID));
stats.Lines.Add('povtor :'+VarToStr(povtor));
stats.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
stats.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
stats.Lines.Add('Hpotion: '+inttostr(Hpotion));
stats.Lines.Add('Apotion: '+inttostr(Apotion));
stats.Lines.Add('xm :'+IntToStr(xm));
stats.Lines.Add('ym :'+IntToStr(ym));
if (MyID<>0) then begin
info.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
info.Lines.Add('HP:'+IntToStr(CurHP)+' из '+IntToStr(MaxHP)+' Цикл1='+IntToStr(attackk)+' Цикл2='+IntToStr(atck)+' Цикл бафа='+IntToStr(bfi));
if (Hpotion=0) then info.Lines.Add('Юзать HP бутылки?: НЕТ!');
if (Hpotion<>0) then info.Lines.Add('Юзать HP бутылки?: ДА!');
if (Apotion=0) then info.Lines.Add('Юзать AP бутылки?: НЕТ!');
if (Apotion<>0) then info.Lines.Add('Юзать AP бутылки?: ДА!');
if (sit=false) then info.Lines.Add('Бот стоит!');
if (sit=true) then info.Lines.Add('Бот сидит!');
for i:= 1 to last do begin
if (MobsObjID[i]<>0) then begin
if (attackIDMinID<>i) then info.Lines.Add('--'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
if (attackIDMinID=i) then begin
info.Lines.Add('->'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
TTShape[i].Brush.Color:=clRed;
end;
end;
end;
end else info.Lines.Add('Для инициализации Бота используй или брось и подбери аптечку!');
end;
//************************************************** *************
procedure Free;
begin
DelALL;
end;
//************************************************** *************
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
end;
end;
if (MaxHP<>0) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*PercentHP); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
end;
end;
//************************************************** *************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$01;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyXpos); //откуда
WriteD(MyYpos);
WriteD(MyZpos);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(Name);
msg.Lines.Add('MoveTo('+inttostr(targetx)+','+intt ostr(targety)+','+inttostr(targetz)+')');
end;
//************************************************** *************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:exte nded):boolean;
begin
if DeltaXY(targetx, targety, MyXpos, MyYpos)<=distanciya
then result:=true else result:=false;
end;
//************************************************** *************
//возвращает растоянием между двумя точками
function DeltaXY(xpos1, ypos1, xpos2, ypos2:extended):integer;
begin
result:=Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;
//************************************************** *************
//возвращает растоянием между двумя координатами Z
function DeltaZ(Zpos1, Zpos2 : extended) : integer;
begin
result:=Round(abs(Zpos1-Zpos2));
end;
//************************************************** *************
procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsObjID[ele]:=0;
MobsID[ele]:=0;
MobsName[ele]:='';
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
Aggro[ele]:=false;
TTShape[ele].left:=-70; //координаты
TTShape[ele].top:=-70;
TTShape[ele].Brush.Color:=clBlue;
TTlabel[ele].left:=TTShape[ele].left+4; //координаты
TTlabel[ele].top:=TTShape[ele].top+4;
TTlabel[ele].caption:='';
TTlabel[ele].font.color:=clBlue;
end;
//************************************************** *************
procedure DelALL; //обнуляем всю базу!
var
i: integer;
begin
for i:= 1 to max do begin
NPCid[i]:=0;
MobsObjID[i]:=0;
MobsID[i]:=0;
MobsName[i]:='';
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
Aggro[i]:=false;
TTshape[i].free;
TTlabel[i].free;
end;
TTShpC.free;
TTShape[0].free;
TTLabel[0].free;
timer1.Free;
timer2.Free;
timer3.Free;
timer4.Free;
splitter1.free;
splitter2.free;
info.Free;
msg.Free;
frm.Free;
map.Free;
end;
//************************************************** *************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
var
minras, i: integer;
begin
MinX:=5000;
MinID:=0;
MaxX:=0;
MaxID:=0;
for i:= 1 to last do begin
//проверяем что расстояние до моба в радиусе кача и по высоте не глубоко
if (DeltaXY(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius) and (DeltaZ(Mobsz[i],cvaz)<=DZ) then begin
if (arra[i]<=MinX) and (arra[i]<>0) then begin
MinX:=arra[i];
MinID:=i;
end;
if (arra[i]>=MaxX) then begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;
end;
//************************************************** *************
function ETOpovtor(chislo: integer; arra:array of integer):boolean;
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
var
i: integer;
begin
Result:=false;
for i:= 1 to last do begin
if (arra[i]=chislo) then Result:=true;
end;
end;
//************************************************** *************
procedure attackt(mobus:integer);
begin
buf:=#$04; //action
WriteD(MobsObjID[mobus]);
WriteD(MyXpos);
WriteD(MyYpos);
WriteD(MyZpos);
WriteC(0);
SendToServerEx(Name);
end;
//************************************************** *************
function Summ(sum:array of integer):integer;
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
i: integer;
begin
Result:=0;
for i:= 1 to max do begin
if (sum[i]<>0) then inc(Result);
end;
end;
//************************************************** *************
procedure OnMap(Sender: TObject); //рисуем карту
begin
if (myxpos=0) and (myypos=0) then exit;
for i:= 1 to last do begin
if (MobsObjID[i]<>0) then begin
//красим мобов на карте
if stop=true then
if (DeltaXY(Mobsx[i],Mobsy[i],MyXpos,MyYpos)<=Radius)
then
if (DeltaZ(Mobsz[i],MyZPos)<=DZ)
then
TTShape[i].Brush.Color:=clGreen
else
TTShape[i].Brush.Color:=clWhite
else
if (DeltaZ(Mobsz[i],cvaz)<=DZ)
then
TTShape[i].Brush.Color:=clBlue
else
TTShape[i].Brush.Color:=clWhite;
if stop=false then
if (DeltaXY(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius)
then
if (DeltaZ(Mobsz[i],cvaz)<=DZ)
then
TTShape[i].Brush.Color:=clGreen
else
TTShape[i].Brush.Color:=clWhite
else
if (DeltaZ(Mobsz[i],cvaz)<=DZ)
then
TTShape[i].Brush.Color:=clBlue
else
TTShape[i].Brush.Color:=clWhite;
if Aggro[i]=true then begin
TTShape[i].Brush.Color:=clPurple;
TTlabel[i].font.color:=clPurple;
end;
//ставим точку МОБа
GameToMap(MobsX[i],MobsY[i]);
TTShape[i].left:=xm; //координаты моба
TTShape[i].top:=ym;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
end;
end;
//ставим точку ГГ
GameToMap(MyXpos,MyYpos);
TTShape[0].left:=xm; //координаты чара
TTShape[0].top:=ym;
TTlabel[0].left:=TTShape[0].left+4; //координаты надписи
TTlabel[0].top:=TTShape[0].top+4;
TTlabel[0].caption:=name;
//ставим точку центра кача
GameToMap(cvaX,cvaY);
TTShpC.left:=xm; //координаты ГГ
TTShpC.top:=ym;
end;
//************************************************** *************
procedure OnAttack(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!
begin
if (MinID>0) then begin
if (sit=false) then begin
case attackk of
0: begin
attackID:=MobsObjID[MinID];
msg.Lines.Add('Атакую! '+IntToStr(attackID));
attackIDMinID:=MinID;
attackt(attackIDMinID); //target
end;
//делаем паузу
1: begin
attackt(attackIDMinID); //attack
end;
6: begin
attackt(attackIDMinID); //target
end;
//делаем паузу
7: begin
attackt(attackIDMinID); //attack
attackk:=1;
inc(atck);
end;
end;
//пробуем сместиться
case atck of
9: begin
MobsRAS[attackIDMinID]:=5000;
attackk:=-1;
atck:=0;
end;
end;
inc(attackk);
end;
end;
end;
//************************************************** *************
procedure OnView(Sender: TObject); //вывод данных в форму
begin
//контролируем бафы
dec(bfi);
if bfi<0 then begin
timer3.interval:=1000; //пытаемся начать бафы каждые 1 сек
bfi:=1200; //20 мин
end;
//выводим в форму
ViewInfo;
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('Мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
//идем в центр если нет мобов
// if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
//if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
// end;
if (MyID<>0) and (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Использую Elemental Heal!');
MagicSkillUse(elementalheal);
end;
if (CurHP<but) and (Hpotion<>0) then begin
if hpi=5 then begin
UseItem(Hpotion);
hpi:=0;
end else inc(hpi);
end;
if (CurHP<sud) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Всё, я отдыхаю!'+TimeToStr(time));
buf:=heal;
SendToServerEx(Name);
sit:=true;
end;
if (CurHP>bst) and (sit=true) then begin
msg.Lines.Add('Пора за работу!'+TimeToStr(time));
buf:=heal;
SendToServerEx(Name);
attackk:=0;
atck:=0;
sit:=false;
end;
end;
//************************************************** *************
procedure OnBuff(Sender: TObject); //баффы
begin
if (MyID<>0) and (Summ(Aggro)=0) and (sit=false) then begin
case ii of
1: begin
timer1.enabled:=false; //откл. атаку
msg.Lines.Add('Бафаюсь Defense aura!');
//бафф
MagicSkillUse(buff1);
inc(ii);
timer3.interval:=6000; //каждые 6 сек
end;
2: begin
msg.Lines.Add('Бафаюсь Attack aura!');
MagicSkillUse(buff2);
inc(ii);
end;
3: begin
msg.Lines.Add('Бафаюсь Deflect arrow!');
MagicSkillUse(buff3);
inc(ii);
end;
4: begin
msg.Lines.Add('Бафаюсь Sprint!');
MagicSkillUse(buff4);
inc(ii);
end;
5: begin
msg.Lines.Add('Бафаюсь Spirit barrier!');
MagicSkillUse(buff5);
inc(ii);
timer3.interval:=10000; //каждые 10 сек
end;
6: begin
msg.Lines.Add('Бафаюсь Storm cubic!');
MagicSkillUse(cubicstorm);
inc(ii);
end;
7: begin
msg.Lines.Add('Бафаюсь Life cubic!');
MagicSkillUse(cubiclife);
inc(ii);
end;
8: begin
if Apotion<>0 then begin
msg.Lines.Add('Пью Potion of Alacrite!');
UseItem(Apotion);
end;
inc(ii);
end;
9: begin
ii:=1;
timer3.interval:=1150000; //каждые 20 мин
bfi:=1150;
timer1.enabled:=true; //вкл. атаку
end;
end;
end;
end;
//************************************************** *************
procedure AddBD(objid, posx, posy, posz:integer;); //добавляем моба в базу данных
var
i: integer;
begin
for i:=1 to last do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(objid, MobsObjID)=false) then begin
MobsObjID[i]:=objid; //ид моба
if id<>0 then MobsID[i]:=id; //ид моба
MobsRAS[i]:=DeltaXY(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
break;
end;
end;
end;
//если нет свободного места ищем дальше
for i:=last+1 to max do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(objid, MobsObjID)=false) then begin
MobsObjID[i]:=objid; //ид моба
if id<>0 then MobsID[i]:=id; //ид моба
MobsRAS[i]:=DeltaXY(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
last:=i;
break;
end;
end;
end;
end;
//************************************************** *************
function ISnpc(id: integer;): boolean;
var
i: integer;
begin
result:=false;
for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;
//************************************************** *************
procedure UseItem(ItemObjID:integer);
begin
buf:=#$14;
WriteD(ItemObjID);
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(S hiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
buf:=#$2F;
WriteD(MagicID);
WriteD(00);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
if (ConnectName=Name) and FromServer then begin
case pck[1] of
#$01: begin
msg.Lines.Add('S>C $01 Move');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
i:=2;
ObjID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
ID:=0; //кто-то рыпнулся с места надо это записать...
xpos:=ReadD(i);
ypos:=ReadD(i);
zpos:=ReadD(i);
if not ISnpc(ObjID) {and (DeltaXY(cvaX,cvaY,xpos,ypos)<=Radius)} then AddBD(ObjID,xpos,ypos,zpos);
end;
end;
#$03: begin
msg.Lines.Add('S>C $03 Char');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(18),NPCid)=false) then begin
NPCid[i]:=ReadD(18);
msg.Lines.Add('ДОБАВЛЕН ИГРОК:'+ReadS(22)+'-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
#$04: begin
msg.Lines.Add('S>C $04 CharInfo');
//пакет с инфой о моём чаре
i:=2;
MyXpos:=ReadD(i); //получаю координату х моего чара
MyYpos:=ReadD(i); //получаю координату у моего чара
MyZpos:=ReadD(i); //получаю координату z моего чара
//Запоминаем ИД
i:=18;
MyID:=ReadD(i); //получаю ид моего чара
//смещение переменное, зависит от имени (LenName*2+2)
i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
//лупить всех без разбора, в пределах радиуса
{if (gdo=false) then begin //задаем центр окружности кача
cvaX:=MyXpos;
cvaY:=MyYpos;
gdo:=true;
end;}
for i:=1 to last do begin //перебираем базу и ищем себя
if (ETOpovtor(MyID, MobsObjID)=true) then begin
DelElArr(i);
msg.Lines.Add('Удаляем себя из базы МОБов!!!');
if isnpc(myID)=false then begin
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=MyID;
break;
end;
end;
end;
end;
end;
end;
//MagicSkillUse 48, Attack 05
#$05: begin
msg.Lines.Add('S>C $05 Attack');
if (ReadD(6)=MyID) then begin
//меня ударили
sit:=false;
{if myxpos<>0 then begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
end;}
if (ETOpovtor(ReadD(2),MobsObjID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin //если моб записан в базе данных
msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(MobsObjID[i]));
Aggro[i]:=true; // стал агрессор
if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
attackIDMinID:=i;
//вкл. атаку
timer1.enabled:=true;
stop:=false; //вкл. атака
end;
if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
break;
end;
end;
end;
end;
//принят пакет Die
#$06: begin
msg.Lines.Add('S>C $06 Die');
//нас убили
if (myID=ReadD(2)) then begin
//остановить атаку
timer1.enabled:=false;
msg.Lines.Add('Нас убили в '+TimeToStr(time));
inc(death1);
RequestRestartPoint; //оживаем после смерти
//мы в городе, снимаем атрибут атаки на нас
for i:= 1 to max do begin
Aggro[i]:=false;
TTShape[i].Brush.Color:=clBlue;
TTlabel[i].font.color:=clBlue;
end;
end else begin
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin
msg.Lines.Add('Убили очередного МОБа в '+TimeToStr(time));
inc(mob1);
DelElArr(i);
attackk:=0;
atck:=0;
if (i=last) and (last<>1) then dec(last);
//timer1.enabled:=true;
break;
end;
end;
end;
end;
#$0C: begin
msg.Lines.Add('S>C $0C DropItem');
if (MyXpos<>0) then begin
if (DeltaXY(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
msg.Lines.Add('Выпала вещь!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
WriteC(0);
SendToServerEx(Name);
msg.Lines.Add(' Пробую поднять!!!');
delay(1000);
timer1.enabled:=true;
end;
end;
end;
#$0E: begin
msg.Lines.Add('S>C $0E StatsUpdate');
if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
end;
//принят пакет DeleteObject
#$12: begin
msg.Lines.Add('S>C $12 DeleteObject');
//выкидываем из базы
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin
DelElArr(i);
msg.Lines.Add('Удаляю из базы:'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
#$16: begin
msg.Lines.Add('S>C $16 NPC');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
msg.Lines.Add('Вижу NPC!');
if (ReadD(10)=0) then begin //если нельзя атаковать
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(2), NPCid)=false) then begin
NPCid[i]:=ReadD(2);
msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
break;
end;
end;
end;
end;
if (ReadD(10)=1) and (pck[120]=#$00) then begin //если можно атаковать
id:=ReadD(6);
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
end;
end;
end;
//InventoryUpdate
#$27: begin
msg.Lines.Add('S>C $27 InventoryUpdate');
if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
Hpotion:=ReadD(8);
msg.Lines.Add('ID бутылок H.Potion:'+inttostr(Hpotion));
end;
if ReadD(12)=735 then begin //Potion of Alacrity
Apotion:=ReadD(8);
msg.Lines.Add('ID бутылок A.Potion:'+inttostr(Apotion));
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=Name) and FromClient then begin
case pck[1] of
#$1B: begin
msg.Lines.Add('C>S $1B Yes');
case ReadD(2) of
//социальное действие Yes для начала
$06: begin
//не передаем серверу
pck:='';
msg.Lines.Add('C>S $1B Yes');
//устанавливаем центр кача
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
//переменные циклов сбрасываем
attackk:=0;
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты центра ОБНОВЛЕНЫ!!');
//вкл. атаку
timer1.enabled:=true;
//вкл. бафы
timer3.enabled:=true;
stop:=false; //вкл. атака
end;
//социальное действие No для окончания
$05: begin
//не передаем серверу
pck:='';
msg.Lines.Add('C>S $1B No');
//откл. атаку
timer1.enabled:=false;
//откл. бафы
timer3.enabled:=false;
stop:=true; //откл. атака
msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
end;
//социальное действие Sorrow - удаляем текущую запись в базе
$0D: begin
//не передаем серверу
pck:='';
msg.Lines.Add('C>S $1B Sorrow');
ObjID:=MobsObjID[attackIDMinID];
DelElArr(attackIDMinID);
attackk:=0;
atck:=0;
msg.Lines.Add('Удаляем текущую запись в базе!!!');
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=ObjID;
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
//ValidatePosition пакет от клиента с моими кординатами
#$48: begin
msg.Lines.Add('C>S $48 ValidatePosition');
//обновляем ВСЕ растояния в BD если мы сошли с места
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
//пересчитываем расстояние до мобов
for i:=1 to last do begin
if MobsObjID[i]<>0 then begin
//до атакующих нас мобов всегда расстояние 1
MobsRAS[i]:=DeltaXY(MyXpos,MyYpos,MobsX[i],MobsY[i]);
end;
end;
end;
end;
end;
end.
nezabudkin
13.03.2008, 18:43
Ну все, Господа... Выкладываю свой собственный ботоскрипт- локомотив :D
Прошу высказывать свои замечания и предложения.
{################################################# ############################
Бот от Alexus
версия : 0.1 (бета)
дата: 12.03.08
Скрипт основан на всем том что я вычитал на этом форуме и моем опыте программирования.
Некоторые интересные идеи взяты из волкера.
Скрипт распространяется как есть. Используем его на свой страх и риск.
Любые изменения и дополнения только приветствуются!!!
Бот для кача в принципе любого война, но тестился на гноме.
Бот оптимизирован для кача в катах, лучше в квадратных комнатах (равносторонний четырехугольник).
Охотиться только на заданных мобов, а то излишняя самостоятельность бота немного пугает.
Пока что бот умеет следующее:
- запоминать центр и радиус кача
- запоминать список мобов на которых надо охотиться!
- управляется из окна чата в самом клиенте
- имеет окно для вывода всех параметров и статистики
- работает пока только под С4
Инструкция:
1. Запускаем игру, запускаем скрипт, добираемся до места кача
2. Пьем HP пробирку (надежный способ добывания своего ID-номера).
3. Выбираем в таргет моба на которого хотим охотится и пишем в общий чат-> 1
4. Валим моба. Если все правильно сделали будет выдано сообщение в чате что моб добавлен.
5. Выбираем следующего моба пишем цифру 2, валим его и т.д. можно выбрать до 10 разных тварей.
6. Становимся в центр комнаты и пишем в чат-> pos , если все правильно то в чате будет выдано сообщение.
7. Бежим к выходу из комнаты, и пишем-> dist, в чате вылезет сообщение от системы
8. Валим всех мобов в комнате, становимся примерно в центр и пишем-> start , если все сделано верно,
то будет выдано соответствующее сообщение.
9. если бот поймал моба в таргет и побежал его атаковать, то можно свернуть окно игры
и смотреть на информационное окно скрипта.
################################################## ###########################}
const
NickName = 'abc'; // Твой ник в игре
maximumItems = 100; // Размер базы мобов
MobsListRazmer = 10; // Размер списка мобов (не трогать!)
Vertical = 1000; // Вертикальный радиус кача
// HPMedium = 70; // Пока не используется
OX = 1; OY = 2; OZ= 3; // Служебные константы
var
InitMode : boolean;
//-------------------------------------- БД мобов ------
MobsID : array [1..maximumItems] of integer;
MobsDist : array [1..maximumItems] of integer; // Расстояние от центра кача
MobsXYZ : array [1..maximumItems, 1..3] of integer; // Координаты
MobsAgression : array [1..maximumItems] of boolean; // Моб атакует меня или стоит в сторонке...
LastItem: integer; // индекс последнего элемента базы
MobsList : array [1..MobsListRazmer] of integer; // Список мобов (коды мобов)
MobsListCount : integer; // Текущий размер списка
TargetID: integer; // Текущая цель
Povtor: integer;
CenterX, CenterY, CenterZ : integer; // Центр кача
Radius: integer; // Радиус кача
//--------------------------------------------------------
MyX, MyY, MyZ : integer; // Мои статы
MyID, MyHP, MyMaxHP: integer;
MyMP, MyMaxMP, MyCP, MyMaxCP: integer;
//--------------------------------------------------------
frm: TForm; // переменные описания формы
log, mainscreen: TMemo;
panel: TPanel;
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, textLastItem: TEdit;
//----------------------------------------------------------
TimerForm, TimerCombat: TTimer;
AttackCycle: integer; // Цикл атаки
procedure ClearDB; // Очистка БД
var // Надо все занулять, иначе там хрень всякая вылезает или старые данные
i: word;
begin
LastItem:= 0; // Очищаем переменные
TargetID:= 0;
Povtor:= 0;
CenterX:= 0;
CenterY:= 0;
CenterZ:= 0;
Radius:= 0;
AttackCycle:= 0;
for i:=1 to MobsListRazmer do MobsList[i]:= 0;
MobsListCount:= 0;
for i:=1 to maximumItems do // Очищаем базу
begin
MobsID[i]:= 0;
MobsDist[i]:= 0;
MobsXYZ[i, OX]:= 0;
MobsXYZ[i, OY]:= 0;
MobsXYZ[i, OZ]:= 0;
MobsAgression[i]:= false;
end;
end;
function SearchFreeItemDB : integer; // Функция ищет первый свободный елемент в БД
var
i:integer;
begin
result:=0;
for i:=1 to maximumItems do if MobsID[i] = 0 then
begin
result:=i;
break;
end;
if result = 0 then result:=maximumItems; // Если БД переполнена, то возвращаем индекс последнего элемента
if result > LastItem then LastItem := result; // если надо, увеличиваем текущий размер БД
end;
function rastoyanie(NpcX, NpcY, NpcZ : integer) : integer; // вычисление растояния между 2 точками
var
dx,dy,dz, summa : integer;
begin
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 + 5000; // добавляем коррекцию по вертикали
end;
procedure AddtoDB (id, x,y,z : integer; agression : boolean); // Процедура добавляет в БД нового моба
var
i:integer;
dist: integer;
begin
dist:= rastoyanie (x,y,z); // вычиляем расстояние от центра кача до моба
if dist > (Radius + 1000) then exit; // если моб слишко далеко то ничего не делаем
i:= SearchFreeItemDB; // ищем свободный эл. БД
log.Lines.Add('Моб добавлен, индекс в БД: '+ inttostr(i));
if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsID[i]:= id; // Записываем моба
MobsDist[i]:= dist;
MobsXYZ[i, OX]:= x;
MobsXYZ[i, OY]:= y;
MobsXYZ[i, OZ]:= z;
MobsAgression[i]:= agression;
end;
procedure UpdateDB (i:integer; id, x,y,z : integer; agression : boolean); // Процедура обновляет данные в БД по мобу
var
dist: integer;
begin
if (MOBSXYZ[i, OX] = x) and (MOBSXYZ[i, OY] = y) and (MobsAgression[i] = agression) then exit; // проверяем, а надо ли чего нить менят
dist:= rastoyanie (x,y,z);
if dist > (Radius + 1000) 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;
MobsAgression[i]:= agression;
end;
end;
procedure DelDBItem (i: integer); // процедура удалаяет моба из БД
begin
log.Lines.Add('Моб удален, индекс в БД: '+ inttostr(i));
MobsID[i]:= 0;
MobsDist[i]:= 0;
MobsXYZ[i, OX]:= 0;
MobsXYZ[i, OY]:= 0;
MobsXYZ[i, OZ]:= 0;
MobsAgression[i]:= false;
if i = LastItem then LastItem := LastItem -1; // если надо, уменьшаем размер БД
end;
function TestPovtor (id: integer) : integer; // функция проверяет наличие заданного моба в БД
var
i: integer;
begin
result:=0;
for i:=1 to LastItem do if MobsID[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 MobsListCount do if MobsList[i] = NpcTypeID then result:= true; // проверяем по списку
end;
procedure SendMsg(msg:string); // отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(NickName);
end;
function ValidateData : boolean; // функция проверки правильности задания всех параметров для начала кача
procedure ValidateMobsList; // подпроцедурка, перепроверяющая список мобов, и подсчитывающая количество записей в нем
var // этот алгоритм мне не нравится, буду переделывать
i: integer;
begin
for i:=1 to MobsListRazmer do if MobsList[i] = 0 then break;
i:= i - 1;
MobsListCount := i;
log.Lines.Add('MobsListCount = '+ inttostr(MobsListCount));
end;
begin
ValidateMobsList;
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 (MobsListCount > 0) then
begin
SendMsg('Все начальные параметры заданы и проверены!');
log.Lines.Add('Все начальные параметры заданы и проверены!');
result:= true;
end
else
begin
SendMsg('Ошибка задания начальных параметров!');
log.Lines.Add('Ошибка задания начальных параметров!');
result:= false;
end;
end;
procedure UserCommandsInitMode; // комманды пользователя для режима настройки бота
begin // если комманда обработана удачно, то в чат сообщение не попадет, а будет выдано системное сообщение прямо в клиент
case (ReadS(2)) of
'pos' : if MyX <> 0 then // центр кача
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
SendMsg('Центр кача задан успешно!');
log.Lines.Add('Центр кача задан успешно!');
pck:='';
end;
'dist' : if (CenterX <> 0) and (MyX <> 0) then // радиус кача
begin
Radius:= rastoyanie (MyX,MyY,MyZ);
SendMsg('Радиус кача задан успешно');
SendMsg('R= '+ inttostr(Radius));
log.Lines.Add('Радиус кача задан успешно, R = '+ inttostr(Radius));
pck:='';
end;
'reset': begin // сброс параметров
ClearDB;
SendMsg('БД очищена, введите заново все параметры');
log.Lines.Add('БД очищена!');
pck:='';
end;
'1', '2', '3', '4', '5', '6', '7', '8', '9', '10' : // задаем мобов
begin
MobsListCount:= strtoint(ReadS(2));
SendMsg('Добавляем моба № '+ ReadS(2));
pck:='';
end;
'start': begin // собственно запуск бота
if ValidateData and InitMode then
begin
SendMsg('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
log.Lines.Add('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
TargetID:=0;
InitMode:= false;
TimerCombat.enabled:=true; // запускаем таймер
end
else
begin
SendMsg('Еще не все параметры заданы. Проверьте параметры...');
log.Lines.Add('Еще не все параметры заданы. Проверьте параметры...');
end;
pck:='';
end;
end;
end;
procedure UserCommandsCombatMode; // комманды пользователя для боевого режима
begin // команды говорят сами за себя)
case (ReadS(2)) of
'pause' : begin
TimerCombat.enabled:= not(TimerCombat.enabled);
pck:='';
if TimerCombat.enabled then
begin
SendMsg('Искуственный интелект запущен!');
log.Lines.Add('Искуственный интелект запущен!');
end
else
begin
SendMsg('Искуственный интелект приостановлен.');
log.Lines.Add('Искуственный интелект приостановлен.');
end
end;
'stop' : begin
pck:='';
TimerCombat.enabled:= false;
InitMode:= true;
SendMsg('Искуственный интелект остановлен.');
log.Lines.Add('Искуственный интелект остановлен.');
end;
end;
end;
function GetMinDistID : integer; // функция поиска ближайшего моба в БД
var
i, dist : integer;
begin
dist:=10000; // задаем заранее нереальную дистанцию
for i:=1 to LastItem do if (MobsID[i] <> 0) and (MobsDist[i] < dist) then
begin // фишка в том, что в базе хранятся расстояния не до меня, а до центра кача
dist:= MobsDist[i]; // но в катах то расстояния небольшие
result:= i; // если нашли хоть одного моба или несколько возращаем его индекс ближайшего к центру кача
end;
if dist = 10000 then result:= dist; // иначе возвращаем 10000
end;
function AgroTest : integer; // функция проверяет, атакует ли меня кто-нибудь или нет
var
i: integer;
begin
result:=0;
for i:=1 to LastItem do if MobsAgression[i] then // ищем первого попавшегося моба, который нас атакует
begin
result:= i; // возвращаем его индекс по БД
break;
end;
end;
procedure PhisicalAttack; // команда атаки
begin
buf:=#$04; //action
WriteD(TargetID);
WriteD(MyX);
WriteD(MyY);
WriteD(MyZ);
WriteC(0);
SendToServerEx(NickName);
end;
procedure OnTimerCombat (Sender: TObject); // боевой таймер, вся логика поведения бота находится именно здесь!!!
var
Agro, MinDistID: integer;
begin
if LastItem > 0 then // если есть мобы в базе то:
begin
if TargetID = 0 then // если нет текущей цели, то
begin
Agro:= AgroTest; // запускаем алгоритм выбора цели
MinDistID:= GetMinDistID;
if Agro > 0 then // если нас кто-то атакует, то его и выбираем
begin
TargetID:= MobsID[Agro];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0;
end
else if MinDistID <= Radius then // иначе ищем ближайшего
begin
TargetID:= MobsID[MinDistID];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0;
end;
end;
if TargetID > 0 then
begin
case AttackCycle of // валим вражину
1, 5, 6 : PhisicalAttack;
10 : ;
end;
inc(AttackCycle)
end;
end;
if LastItem = 0 then ; // если нет мобов в базе, то по идее надо вернуться в центр кача, пока не разобрался с алгоритмом
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);
textLastItem.text:= inttostr(LastItem);
mainscreen.lines.Clear;
for i:=1 to LastItem do if MobsID[i] > 0 then // выводим БД мобов
begin // алгоритм пока не доделан
mainscreen.lines.add ('-- '+inttostr(i)+' МобID: '+inttostr(MobsID[i])+' дистанция '+inttostr(MobsDist[i]));
end;
end;
procedure CreateLabel (text: string); // процедура автоматизирует создание текстовых меток в форме
var
l: TLabel;
begin
l:= TLabel.Create(panel);
l.caption:=text;
l.parent:=panel;
l.left:=5;
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:=60;
e.top:=10+20*frmParamIndex;
result:= e;
end;
procedure Init; //Вызывается при включении скрипта
begin
ClearDB;
MyID:= 0; // обнуляем ВСЕ данные
MyX:= 0;
MyY:= 0;
MyZ:= 0;
MyID:= 0;
MyHP:= 0;
MyMaxHP:= 0;
MyMP:= 0;
MyMaxMP:= 0;
MyCP:= 0;
MyMaxCP:= 0;
InitMode:= true;
TimerCombat:=TTimer.Create(nil); // создаем таймеры
TimerCombat.OnTimer:=@OnTimerCombat;
TimerCombat.enabled:=false;
TimerCombat.interval:=1000;
TimerForm:=TTimer.Create(nil);
TimerForm.OnTimer:=@OnTimerForm;
TimerForm.enabled:=true;
TimerForm.interval:=1000;
frmParamIndex:=0; // создаем контролы в форме
frm:= TForm.Create(nil);
frm.Caption:= 'BOT info';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=650;
frm.Height:=700;
mainscreen:=TMemo.Create(frm);
mainscreen.parent:=frm;
mainscreen.align:=alLeft;
mainscreen.ReadOnly:=true;
mainscreen.ScrollBars:=2;
mainscreen.Width:=470;
mainscreen.Height:=370;
mainscreen.Lines.Add('Инициализация');
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:=0;
log.Width:=570;
log.Height:=100;
log.Lines.Add('...');
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('Цикл атаки:');
textLastItem:= CreateTextBox('LastItem');
CreateLabel('Элем. БД:');
frm.Show; // выводим форму на экран
end;
procedure Free; //Вызывается при выключении скрипта
begin
mainscreen.free;
log.free;
frm.free;
ClearDB;
TimerForm.free;
TimerCombat.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+44;
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;
end;
begin
if pck = '' then exit;
if (ConnectName = NickName) and FromServer and (not InitMode) then // разбор пакетов от сервера в Боевом режиме
case pck[1] of
#$01: begin // MoveToLocation:h(ObjectID)d(CurX)d(CurY)d(CurZ)d(D estX)d(DestY)d(DestZ)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
updateDB(Povtor, ReadD(2), ReadD(18), ReadD(22), ReadD(26), false);
end;
end;
#$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(Wal kSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed )d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(Move mentSpeedMultiplier)f(AttackSpeedMultiplier)f(Coll isionRadius)f(CollisionHeight)d(HairStyle)d(HairCo lor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCr estId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sittin g)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(M ountType)b(PrivateStoreType)
#$04: if ReadS(22) = NickName then UserInfo; // 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(F eet)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(Ha ir)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accurac y)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef) d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRun Speed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d (FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultipl ier)f(AttackSpeedMultiplier)f(CollisionRadius)f(Co llisionHeight)d(HairStyle)d(HairColor)d(Face)d(Acc essLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d (AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateS toreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cub ics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b ()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLef t)b()b(RecomHave)b()
#$05{, #$48}: begin // 05= Attack:d(AttackerID)d(TargetID)d(Damage)b(Flags)d( X)d(Y)d(Z)h(Hits)
if ReadD(6) = MyID then
begin
Povtor:= TestPovtor(ReadD(2));// 48= MagicSkillUse
if Povtor = 0 then AddtoDB (ReadD(2), ReadD(15), ReadD(19), ReadD(23), true)
else UpdateDB(Povtor, ReadD(2), ReadD(15), ReadD(19), ReadD(23), true);
end;
end;
#$06: begin // Die:d(ChaID)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
if MobsID[povtor] = TargetID then
begin
TargetID:= 0;
// статистика тут должна считаться
// и споил надо делать
end;
DelDBItem(povtor);
end;
end;
#$0C: ; // DropItem:h(PlayerID)h(ObjectID)i(ItemID)d(X)d(Y)d( Z)d(Stackable)d(Count)
#$0E: if MyID=ReadD(2) then StatusUpdate; // StatusUpdate:h(ObjectID)d(Attributes)
{ #$12: begin // DeleteObject:h(ObjectID)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
DelDBItem(povtor);
end;
end;}
#$16: begin // 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(FlRu nSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(Proper Multiplier)f(PAtkSpd)f(CollisionRadius)f(Collision Height)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRun ning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Nam e)s(Title)
if InMobsList(ReadD(6)) and (ReadD(10)=1) and (pck[121]=#$00) then
begin
Povtor:= TestPovtor(ReadD(2));
if Povtor = 0 then AddtoDB (ReadD(2), ReadD(14), ReadD(18), ReadD(22), false)
else UpdateDB(Povtor, ReadD(2), ReadD(14), ReadD(18), ReadD(22), false);
end;
end;
end;
if (ConnectName = NickName) and FromClient and (not InitMode) then // разбор пакетов от клиента в боевом режиме
case pck[1] of
#$04: {TargetID:= ReadD(2)}; // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b( ActionID)
#$38: UserCommandsCombatMode; // Say2:s(Text)d(Type)s(Target)
#$48: begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD(2);
MyY:= ReadD(6);
MyZ:= ReadD(10);
end;
end;
if (ConnectName = NickName) and FromServer and InitMode then // разбор клиентов от сервера в режиме настройки бота
case pck[1] of
#$04: if ReadS(22) = NickName then UserInfo; // 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(F eet)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(Ha ir)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accurac y)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef) d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRun Speed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d (FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultipl ier)f(AttackSpeedMultiplier)f(CollisionRadius)f(Co llisionHeight)d(HairStyle)d(HairColor)d(Face)d(Acc essLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d (AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateS toreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cub ics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b ()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLef t)b()b(RecomHave)b()
#$06: if (ReadD(2) = TargetID) and (MobsListCount <> 0) then // Die:d(ChaID)
if (MobsList[MobsListCount] <> 0) then
begin
SendMsg('Моб №' + inttostr(MobsListCount) + ' добавлен в базу');
log.Lines.Add('Моб №' + inttostr(MobsListCount) + ' добавлен в базу');
MobsListCount:= 0;
TargetID:= 0;
end;
#$16: if (ReadD(2) = TargetID) and (MobsListCount <> 0) then MobsList[MobsListCount]:= ReadD(6);//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(FlRu nSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(Proper Multiplier)f(PAtkSpd)f(CollisionRadius)f(Collision Height)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRun ning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Nam e)s(Title)
end;
if (ConnectName = NickName) and FromClient and InitMode then // разбор пакетов от клиента в режиме настройки бота
case pck[1] of
#$04: TargetID:= ReadD(2); // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b( ActionID)
#$38: UserCommandsInitMode; // Say2:s(Text)d(Type)s(Target)
#$48: begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD(2);
MyY:= ReadD(6);
MyZ:= ReadD(10);
end;
end;
end.
Ну все, Господа... Выкладываю свой собственный ботоскрипт- локомотив :D
Прошу высказывать свои замечания и предложения.
Надо посмотреть, попробовать. :)
Константы для ИЛ и С4
установить константы в зависимости от типа игры (С4 или Интерлюд)
//CreateItemBase
offs1=24; //16 для С4, 24 для IL
//InventoryUpdate
offs2=22; //14 для С4, 22 для IL
//UserInfo, основной цикл
offs3=48; //44 для С4, 48 для IL
//InventoryUpdate, основной цикл
offs4=41; //32 для С4, 41 для IL
//StatsUpdate
offs5=14; //одинаково для C4 и IL
Например в твоем случае
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; //<----------- 44 для С4, 48 для IL
MyMaxHP:=ReadD(i);
MyHP:=ReadD(i);
MyMaxMP:=ReadD(i);
MyMP:=ReadD(i);
i:=515 //<-------i+363;
MyMaxCP:=ReadD(i);
MyCP:=ReadD(i);
end;
Так и не смог моба в базу добавить (на интерлюде).
НАрод а можно ли сымитировать нажатие клавиш в л2пкх?
Например каждые 30 сек F2?
%)
nezabudkin
14.03.2008, 01:12
НАрод а можно ли сымитировать нажатие клавиш в л2пкх?
Например каждые 30 сек F2?
%)
По моему никак нельзя! F2 ты жмешь в клиенте, а он уже подставляет заданную команду для F2 и отправляет на сервер... Но можно посмотреть какой пакетик уходит на сервер когда жмешь эту кнопку. И вот этот пакетик уже можно каждые 30 секунд отправлять серверу через пакетхак! Скриптик получается примитивнейший.
Залил рабочий скрипт бота. Пробуйте.
- поправил питьё Алакрити пошн
- показывает центр кача
Добавлено спустя 5 минут:
Re:
НАрод а можно ли сымитировать нажатие клавиш в л2пкх?
Например каждые 30 сек F2?
%)
Вот посмотри, скрипт про клавиши. Сам не пробовал.
//// для активации скрипта советую создать макрос +panel
{
Заготовка Cкрипта Управления
DeVolf Вчера, 18:42
Вот давно мучался ... Собрал все что надо ... И седня сделал то что действительно хотел )
Поделюсь и с вами )
Это тот самы самый скрипт который я хотел тут viewtopic.php?f=9&t=30&st=0&sk=t&sd=a
Скрипт заготовочный тоесть не надо вырезать куски а только поставить свои условия и переименовать функции )
Коментарии и Спасибо высказаны в скрипте так что "Грайтесь малята"
Сори в скрипте могут быть грамматические ошибки , так что простите , голова уже давно болит
Для тех кто не знает как ставить условие тогда читайте внимательно
1 Запускаем скрипт
2 Используем ту клавишу к которой хотим привязать действие
3 Отлавливаем пакет от клиента он будет типа Бай Пас
4 добавляем в скрипте перед end. такие строчки
Код: Выделить всё
if fromclient and (pck=HStr('в етих скобках пишем пакет который поймали')) then begin
buf:=#$0F;
WriteD(5);
WriteS(HTML2);
SendToClient;
buf:=hstr('а тут пишем пакет действия , которое присвоим клавише');
pck:='';
sendtoserver;
end;
}
const
HTML2='<html>'+
'<body>'+
'<font color="FF9900">Изменено :</font>
'+
'1. Ничего
'+
'2. Ничего
'+
'3. Ничего
'+
'<font color="FF9900">Добавлено :</font>
'+
'1. Ничего
'+
'2. Ничего
'+
'3. Ничего
'+
'
<a action="bypass -h Beck"> Назад</a>'+
'</body>'+
'</html>';
HTML1='<html>'+
'<body> '+
'<font color="FF9900">Большое спасибо: NLObP"у , QaK"е , xkor"у , VORON"у , mks"y и всему форуму xkorem.net ;) .
'+
'Да и очень прошу не изменять ету константу, так как ето все сделать было не легко.
'+
'Пользуйтесь на здорове ;) .
'+
'
Powered by : DeVolf </font> '+
'
<a action="bypass -h Beck"> Назад</a>'+
'</body> '+
'</html>';
HTML=' <html> '+
'<body> '+
'<center> '+
'<font color="FF9900">Универсальный скрипт управления</font>
'+
'<font color="FF0000">Ну чо будем делать?</font> '+
'</center> '+
'</td> '+
'<td width=40> '+
'</tr> '+
'
'+
'<center> '+
'<table width=230> '+
'<tr><td><font color="LEVEL">Управление</font></td><td><font color="LEVEL">Другое</font></td><td><font color="LEVEL">Вапще левое:</font></td></tr> '+
'<tr><td><a action="bypass -h 1"><font color="FF9900">Функция №1</font></a></td><td><a action="bypass -h 13"><font color="FF9900">Функция №1</font></a></td><td><a action="bypass -h 25"><font color="FF9900">Функция №1</font></a></td></tr> '+
'<tr><td><a action="bypass -h 2"><font color="FF9900">Функция №2</font></a></td><td><a action="bypass -h 14"><font color="FF9900">Функция №2</font></a></td><td><a action="bypass -h 26"><font color="FF9900">Функция №2</font></a></td></tr> '+
'<tr><td><a action="bypass -h 3"><font color="FF9900">Функция №3</font></a></td><td><a action="bypass -h 15"><font color="FF9900">Функция №3</font></a></td><td><a action="bypass -h 27"><font color="FF9900">Функция №3</font></a></td></tr> '+
'<tr><td><a action="bypass -h 4"><font color="FF9900">Функция №4</font></a></td><td><a action="bypass -h 16"><font color="FF9900">Функция №4</font></a></td><td><a action="bypass -h 28"><font color="FF9900">Функция №4</font></a></td></tr> '+
'<tr><td><a action="bypass -h 5"><font color="FF9900">Функция №5</font></a></td><td><a action="bypass -h 17"><font color="FF9900">Функция №5</font></a></td><td><a action="bypass -h 29"><font color="FF9900">Функция №5</font></a></td></tr> '+
'<tr><td><a action="bypass -h 6"><font color="FF9900">Функция №6</font></a></td><td><a action="bypass -h 18"><font color="FF9900">Функция №6</font></a></td><td><a action="bypass -h 30"><font color="FF9900">Функция №6</font></a></td></tr> '+
'<tr><td><a action="bypass -h 7"><font color="FF9900">Функция №7</font></a></td><td><a action="bypass -h 19"><font color="FF9900">Функция №7</font></a></td><td><td><a action="bypass -h 31"><font color="FF9900">Функция №7</font></a></td></tr> '+
'<tr><td><a action="bypass -h 8"><font color="FF9900">Функция №8</font></a></td><td><a action="bypass -h 20"><font color="FF9900">Функция №8</font></a></td><td><a action="bypass -h 32"><font color="FF9900">Функция №8</font></a></td></tr> '+
'<tr><td><a action="bypass -h 9"><font color="FF9900">Функция №9</font></a></td><td><a action="bypass -h 21"><font color="FF9900">Функция №9</font></a></td><td><a action="bypass -h 33"><font color="FF9900">Функция №9</font></a></td></tr> '+
'<tr><td><a action="bypass -h 10"><font color="FF9900">Функция №10</font></a></td><td><a action="bypass -h 22"><font color="FF9900">Функция №10</font></a></td><td><a action="bypass -h 34"><font color="FF9900">Функция №10</font></a></td></tr> '+
'<tr><td><a action="bypass -h 11"><font color="FF9900">Функция №11</font></a></td><td><a action="bypass -h 23"><font color="FF9900">Функция №11</font></a></td><td><a action="bypass -h 35"><font color="FF9900">Функция №11</font></a></td></tr> '+
'<tr><td><a action="bypass -h 12"><font color="FF9900">Функция №12</font></a></td><td><a action="bypass -h 24"><font color="FF9900">Функция №12</font></a></td><td><a action="bypass -h 36"><font color="FF9900">Функция №12</font></a></td></tr> '+
'<tr><td></td><td></td><td></td></tr> '+
'</table> '+
'<table width=230> '+
'<tr><td></td><td><a action="bypass -h Exit"><font color="LEVEL">Выход</font></a></td></tr> '+
'</table> '+
'</center> '+
'
<a action="bypass -h Addons">Что нового?</a>
'+
'<a action="bypass -h Creators">Коментарии и Спасибки ;-)</a>
'+
'<font color="FF9900">Powered by : DeVolf Версия реализа:1.1</font> '+
'</body>'+
'</html>';
begin
if fromclient and (pck=HStr('38 70 00 61 00 6E 00 65 00 6C 00 00 00 08 00 00 00')) or (pck=HStr('21 42 00 65 00 63 00 6B 00 00 00')) then begin
buf:=#$0F;
WriteD(5);
WriteS(HTML);
SendToClient;
pck:='';
end;
if fromclient and (pck=HStr('21 43 00 72 00 65 00 61 00 74 00 6F 00 72 00 73 00 00 00')) then begin
buf:=#$0F;
WriteD(5);
WriteS(HTML1);
SendToClient;
pck:='';
end;
if fromclient and (pck=HStr('21 41 00 64 00 64 00 6F 00 6E 00 73 00 00 00')) then begin
buf:=#$0F;
WriteD(5);
WriteS(HTML2);
SendToClient;
pck:='';
end;
end.
nezabudkin
14.03.2008, 13:36
Константы для ИЛ и С4
установить константы в зависимости от типа игры (С4 или Интерлюд)
//CreateItemBase
offs1=24; //16 для С4, 24 для IL
//InventoryUpdate
offs2=22; //14 для С4, 22 для IL
//UserInfo, основной цикл
offs3=48; //44 для С4, 48 для IL
//InventoryUpdate, основной цикл
offs4=41; //32 для С4, 41 для IL
//StatsUpdate
offs5=14; //одинаково для C4 и IL
Так и не смог моба в базу добавить (на интерлюде).
А в форму правильно отображались данные ID, здоровье, коорды, ID цели ?
Там алгоритм простой. Берем в таргет моба, пишем в чат "1" (без кавычек), там вылезет сообщение что "Добавляем моба 1", валим его, вылезает сообщение, что "Моб добавлен".
На следующей неделе начну тестировать на интерлюде!
А в форму правильно отображались данные ID, здоровье, коорды, ID цели ?
Там алгоритм простой. Берем в таргет моба, пишем в чат "1" (без кавычек), там вылезет сообщение что "Добавляем моба 1", валим его, вылезает сообщение, что "Моб добавлен".
На следующей неделе начну тестировать на интерлюде!
Данные чара показывались верно. У моба ID показывался. Сообщение, что моб добавлен не появляется. Наверно еще где-то смещения править надо.
Что ты у этого моба запоминаешь? Ведь кроме objid и координат по таргету ничего не возвращает и objid каждый раз новое. Какой пакет используешь для сохранения мобов в базе?
2 NLobP
Sps большошое =))) будем пробовать...
Кстати я вроде первый раз завалил сервак, посылал 10 мс пакет на трейд, пытался дюп сделать в 2 окна...
я еще проверю разок, ляжет он или нет :good:
Добавлено спустя 1 минуту:
Жалко тока шотел поигратцо...как все повисло :sorry:
Добавлено спустя 11 часов 34 минуты 18 секунд:
Попробовал )))
Да не то не много..там клвиши к пакетам привязываются, хорошо было бы, чтоб при нажатии клавиши Л2пх както чтоли к кленту обращалась и нажимала на нужные кнопки, как макрос..
ЗЫ.
Тока вот обычные макросы оч сильно затормаживают систему
Попробовал )))
Да не то не много..там клвиши к пакетам привязываются, хорошо было бы, чтоб при нажатии клавиши Л2пх както чтоли к кленту обращалась и нажимала на нужные кнопки, как макрос..
ЗЫ.
Тока вот обычные макросы оч сильно затормаживают систему
Попробуй ACTools. Тоже нужно писать скрипты.
What is AC Tool?
AC Tool is a utility that allows you to list a series of keystrokes and mouse clicks in advance and send them to Asheron's Call at a later time. The list of keystrokes and mouse clicks is called a macro or a script.
AC Tool does not intercept data returned by Asheron's Call. That means a macro cannot tell when you are attacked, if you have run out of something needed by the macro, etc, however there is a Decal Companion for AC Tool can be used to intercept data and perform other useful functions. See the CHANGE THIS section on AC Tool Companion.
ДРУЗЬЯ, частично перечитал топ.. и с ужасом обнаружил что нет нормальной реализации глотания банок ХП, ГХП, ГЦП... тот вариант что предложил МКС предполагает предварительную подготовку скрипта.. т.е. после запуска скрипта следуют самому ручками глотнуть банки в нужной последовательности..
спешу исправить етот пробел в наших знаниях.. хотя тут дело не в знаниях а просто лень было делать многим.. но!.. спешу представиить вышеупомянутый скрипт в более продвинутой модификации.. теперь если у вас даже и нет вовсе ПП ШЕ ЕЕ или БИША то и вы совсем один то всё равно скрипт вам будет полезен ибо он нетребует никаких настроек и будет пить банки ХП ГЦП ГХП при условии что они есть в инвенторе у вас.. скрипт также настроен на то что ети зелья будут пить ваши баферы- (если они у них есть..).. плиз неспрашивайте меня почему не работают елексиры- я пока не разбирался.. в сыром виде их реализовал но они не пашут.. незнаю почему но они никак не влеяют на работоспособность скрипта.. для подготовки скрипта к работе требуется лиш имена поменять на реальные.. в 4-х строчках (188-192), после етого скрипт щитается полностью рабочим и готовым к использованию.. но если вам хочется изменить уровни ХП и МП при которых срабатывает ХИЛ и ЗАЛИВКА МП и ХП то там просто значения исправте.. ну я думаю понятно что в конце скрипта написан код- какие бафы на ково класть там весде вбито АСИСТ ТАРГЕТ. т.е. если вас кто то просит: "БАФНИ ПЛЗ" то просто береш его в таргет и жмеш NO или UNWARE от кнопки будет зависеть буф мага или физика.. нужные бафы перечисляются в конце скрипта кому и что бафать.. вопщем.. отличие етого скрипта от того что я раньше дал в том что командир и баферы глотают банки ГЦП,ХП,ГХП сами- автоматом.. при етом ненужно никаких подготовок скрипта.. ето реализуется очень просто.. 1 умный человек в етом топе сказал что пакет ЮЗЕР ИНФО можно вызвать если отправиить запрос на открытие инвенторя.. я проверил- ето правда.. когда скрипт начинает свою работу на все аки отсылается запрос на открытие инвенторя (автоматически).. из попутного пакета ЮЗЕР ИНФО скрипт сам узнает ИДешники всех.. а из инвенторя скрипт сам ищет БАНКИ с ХП,ГХП и ГЦП.. запоминает их OID и потом когда надо использует..
var
Bot1X,Bot1Y,Bot1Z,Bot2X,Bot2Y,Bot2Z,Bot3X,Bot3Y,Bo t3Z,Bot4X,Bot4Y,Bot4Z:string; //координаты баферов
IDAssistTarget:string; //таргет командира
rnd:integer; // вспомогательная для случайного события
bafSE: array [1..100] of string; //список бафов ШЕ
bafPP: array [1..100] of string; //список бафов ПП
bafEE: array [1..100] of string; //список бафов ЕЕ
BafSEApplyChar: array [1..100] of string; //указывает ИД чара на которого нужно наложить баф с помощью ШЕ
BafSEApplyBaf: array [1..100] of string; //указывает какой баф наложить на чара с помощью ШЕ
BafPPApplyChar: array [1..100] of string; //указывает ИД чара на которого нужно наложить баф с помощью ПП
BafPPApplyBaf: array [1..100] of string; //указывает какой баф наложить на чара с помощью ПП
BafEEApplyChar: array [1..100] of string; //указывает ИД чара на которого нужно наложить баф с помощью ЕЕ
BafEEApplyBaf: array [1..100] of string; //указывает какой баф наложить на чара с помощью ЕЕ
NameKom,NameBot1,NameBot2,NameBot3,NameBot4:string ; //имена чаров учавствующих в процессе
MaxHPKom,MaxHPBot1,MaxHPBot2,MaxHPBot3,MaxHPBot4:i nteger; //максимальные уровни ХП (лимиты)
MaxMPKom,MaxMPBot1,MaxMPBot2,MaxMPBot3,MaxMPBot4:i nteger; //максимальные уровни МП (лимиты)
MaxCPKom,MaxCPBot1,MaxCPBot2,MaxCPBot3,MaxCPBot4:i nteger; //максимальные уровни ЦП (лимиты)
CurHPKom,CurHPBot1,CurHPBot2,CurHPBot3,CurHPBot4:i nteger; //текущие значения ХП
CurMPKom,CurMPBot1,CurMPBot2,CurMPBot3,CurMPBot4:i nteger; //текущие значения МП
CurCPKom,CurCPBot1,CurCPBot2,CurCPBot3,CurCPBot4:i nteger; //текущие значения ЦП
IDKomandos,IDbot1,IDbot2,IDbot3,IDbot4:string; // идешники всех
timer3: TTimer; //для создания пати
timer4: TTimer; //мульти-баф, общий как для физика так и для мага.. нужные бафы указываются заранее в конце скрипта
BufEndSE,BufEndPP,BufEndEE:boolean;// используется в таймере (мультибаф) для указания на то что 1 из баферов закончил бафать
tick3,tick4:integer; // используется в таймере бафа для тиков.. каждый тик- новый баф..
OidHPPotion0,OidGCPPotion0,OidGHPPotion0,OidHPLexi r0,OidCPLexir0:string; //обжэкт ИД зелий разных у командира
OidHPPotion1,OidGCPPotion1,OidGHPPotion1,OidHPLexi r1,OidCPLexir1:string; //обжэкт ИД зелий разных у первого бота
OidHPPotion2,OidGCPPotion2,OidGHPPotion2,OidHPLexi r2,OidCPLexir2:string; //обжэкт ИД зелий разных у второго
OidHPPotion3,OidGCPPotion3,OidGHPPotion3,OidHPLexi r3,OidCPLexir3:string; //обжэкт ИД зелий разных
OidHPPotion4,OidGCPPotion4,OidGHPPotion4,OidHPLexi r4,OidCPLexir4:string; //обжэкт ИД зелий разных
i,x:integer;
tempD:integer;
tempS:String;
//**********************МУЛЬТИБАФ******************* ****************************************
procedure OnTimer4(Sender: TObject);
begin
//если очередной баф в списке бафов для бафера = '' (окончание процесса бафа) то значит бафер уже отбафал всё что нужно, хватит бафать..
if (BafPPApplyChar[tick4]='') then BufEndPP:=True;
if (BafSEApplyChar[tick4]='') then BufEndSE:=True;
if (BafEEApplyChar[tick4]='') then BufEndEE:=True;
//если все баферы закончили бафать то выключаем таймер мультибафа
//ну и счетчик тиков ставим в исходное положение
if (BufEndPP=True) and (BufEndSE=True) and (BufEndEE=True) then
begin
tick4:=1;
timer4.enabled:=false;
BufEndSE:=False;
BufEndPP:=False;
BufEndEE:=False;
//раз закончили бафать то не допускаем выполнение нижеследущего кода
exit;
end;
//бафаем чара.. используется переменные BafPPApplyChar[tick4],BafPPApplyBaf[tick4] для ПП и аналогичные для ШЕ и ЕЕ указывающие на то какому баферу ково бафать и каким бафом в текущий ТИК.
//ТИК- (tick4) - ето счетчик, который изменяется на 1 с каждым новым бафом.. т.е. каждые 4 секунды (интервал таймера) тик увеличивается на 1
//ТИКИ нужны чтоб каждый раз новый баф кастовать..
buf:=hstr('04') + BafPPApplyChar[tick4] + Bot2X + Bot2Y + Bot2Z + hstr('00');
if (BufEndPP=False) and (IDbot2<>'') then SendToServerEX(NameBot2);
buf:=BafPPApplyBaf[tick4];
if (BufEndPP=False) and (IDbot2<>'') then SendToServerEX(NameBot2);
buf:=hstr('04') + BafSEApplyChar[tick4] + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (BufEndSE=False) and (IDbot3<>'') then SendToServerEX(NameBot3);
buf:=BafSEApplyBaf[tick4];
if (BufEndSE=False) and (IDbot3<>'') then SendToServerEX(NameBot3);
buf:=hstr('04') + BafEEApplyChar[tick4] + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (BufEndEE=False) and (IDbot4<>'') then SendToServerEX(NameBot4);
buf:=BafEEApplyBaf[tick4];
if (BufEndEE=False) and (IDbot4<>'') then SendToServerEX(NameBot4);
tick4:=tick4+1;
end;
//****************************РАЗДАЧА ПРИГЛАШЕНИЙ НА ВСТУПЛЕНИЕ В ПАТИ*******************
procedure OnTimer3(Sender: TObject);
begin
if tick3 = 1 then
begin
buf:=hstr('2B');
//этот код закоментирован , для того чтобы не разрывать пати.. впринципе хз каму как.. если надо четко стабиильно пати создать быстро из своих ботов-баферов то раскоментить
//а если ты с баферами + другие чары с тобой бегают- то ненадо раскоменчивать.. хотя можно тока баферов раскоментить тогда они свою пати порвут и снова вступят к командиру (если он лидер пати)
// if IDKomandos<>'' then SendToServerEX(NameKom);
// if IDBot1<>'' then SendToServerEX(NameBot1);
// if IDBot2<>'' then SendToServerEX(NameBot2);
// if IDBot3<>'' then SendToServerEX(NameBot3);
// if IDBot4<>'' then SendToServerEX(NameBot4);
end;
if tick3 = 2 then
begin
buf:=hstr('29');
writeS(namebot1);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
if tick3 = 3 then
begin
buf:=hstr('29');
writeS(namebot2);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
if tick3 = 4 then
begin
buf:=hstr('29');
writeS(namebot3);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
if tick3 = 5 then
begin
buf:=hstr('29');
writeS(namebot4);
buf:=buf + hstr('00 00 00 00');
SendToServerEX(NameKom);
end;
tick3:=tick3+1;
//ну когда всем баферам приглашение отправили то вырубаем таймер
if tick3=6 then
begin
tick3:=1;
timer3.enabled:=false;
end;
end;
//*************************БЕЖИМ ЗА ЛИДЕРОМ*******************************************
//процедура заставляет бежать ботов за лидером
procedure BotBeg;
begin
//проверяем условие чтоб координаты ботов небыли равными '' и ИД был перехвачен
if IDKomandos <> '' then
begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot2X + Bot2Y + Bot2Z + hstr('00');
if IDBot2<>'' then SendToServerEX(NameBot2);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot2X + Bot2Y + Bot2Z + hstr('00');
if IDBot2<>'' then SendToServerEX(NameBot2);
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if IDBot3<>'' then SendToServerEX(NameBot3);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if IDBot3<>'' then SendToServerEX(NameBot3);
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if IDBot4<>'' then SendToServerEX(NameBot4);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if IDBot4<>'' then SendToServerEX(NameBot4);
end;
end;
procedure Init; //Вызывается при включении скрипта
begin
NameKom:='ИМЯ КОМАНДИРА';
NameBot1:='ИМЯ БИША'; //биш
NameBot2:='ИМЯ ПП'; //пп
NameBot3:='ИМЯ ШЕ'; //ше
NameBot4:='ИМЯ ЕЕ'; //ее
//список бафов:
//само собой вы его можете расширить новыми бафами которых тут нет..
//это те бафы кторые я использую от ПП
bafPP[1]:=hstr('2F 0B 04 00 00 00 00 00 00 00'); // ментал
bafPP[2]:=hstr('2F 10 04 00 00 00 00 00 00 00'); // пд
bafPP[3]:=hstr('2F 2C 04 00 00 00 00 00 00 00'); // па
bafPP[4]:=hstr('2F 35 04 00 00 00 00 00 00 00'); // фокус
bafPP[5]:=hstr('2F 36 04 00 00 00 00 00 00 00'); // кон
bafPP[6]:=hstr('2F 3D 04 00 00 00 00 00 00 00'); // акумен
bafPP[7]:=hstr('2F A7 04 00 00 00 00 00 00 00'); // резист к огню
bafPP[8]:=hstr('2F B4 04 00 00 00 00 00 00 00'); // вв
bafPP[9]:=hstr('2F 26 04 00 00 00 00 00 00 00'); // берс
bafPP[10]:=hstr('2F 14 04 00 00 00 00 00 00 00'); // ХП реген
bafPP[12]:=hstr('2F 3E 04 00 00 00 00 00 00 00'); // хаст
bafPP[13]:=hstr('2F 15 04 00 00 00 00 00 00 00'); // блесс ХП
bafPP[14]:=hstr('2F 0C 04 00 00 00 00 00 00 00'); // маджик барьер
bafPP[15]:=hstr('2F 6C 05 00 00 00 00 00 00 00'); // гритер ПА
bafPP[16]:=hstr('2F 6D 05 00 00 00 00 00 00 00'); // гритер ПД
bafPP[17]:=hstr('2F 70 05 00 00 00 00 00 00 00'); // скаред атак резист
bafPP[18]:=hstr('2F 71 05 00 00 00 00 00 00 00'); // дарк атак резист
bafPP[19]:=hstr('2F A5 04 00 00 00 00 00 00 00'); // резист к ветру
bafPP[20]:=hstr('2F 9E 04 00 00 00 00 00 00 00'); // резист к воде
bafPP[21]:=hstr('2F DA 04 00 00 00 00 00 00 00'); // деф виспер
bafPP[22]:=hstr('2F D8 04 00 00 00 00 00 00 00'); // гвиданс
bafPP[23]:=hstr('2F 18 04 00 00 00 00 00 00 00'); // блесс МП
bafPP[24]:=hstr('2F DB 04 00 00 00 00 00 00 00'); // ЩИТ РЕЙТ
//это от ШЕ бафы
bafSE[1]:=hstr('2F 0B 04 00 00 00 00 00 00 00'); // ментал
bafSE[2]:=hstr('2F 10 04 00 00 00 00 00 00 00'); // ПД
bafSE[3]:=hstr('2F 2C 04 00 00 00 00 00 00 00'); // ПА
bafSE[4]:=hstr('2F F4 04 00 00 00 00 00 00 00'); // ВАМП
bafSE[5]:=hstr('2F 23 04 00 00 00 00 00 00 00'); // ЕМП
bafSE[6]:=hstr('2F 17 05 00 00 00 00 00 00 00'); // М.КРИТ
bafSE[7]:=hstr('2F 35 04 00 00 00 00 00 00 00'); // ФОКУС
bafSE[8]:=hstr('2F DA 04 00 00 00 00 00 00 00'); // ДЕФ ВИСПЕР
bafSE[9]:=hstr('2F D8 04 00 00 00 00 00 00 00'); // гвиданс
bafSE[10]:=hstr('2F B4 04 00 00 00 00 00 00 00'); // ВВ
//это от ЕЕ
//список дополнять аналогично етому коду.. просто строки с новыми бафами добавляйте..
bafEE[1]:=hstr('2F EB 04 00 00 00 00 00 00 00'); // резист ШОК
bafEE[2]:=hstr('2F 3F 04 00 00 00 00 00 00 00'); // ЭВЕЙШН
bafEE[3]:=hstr('2F 75 05 00 00 00 00 00 00 00'); // РАСХОД МАНЫ
//при старте скрипта значения переменных =0
//поетому скрипт подумает что у всех 0 ХП и начнется хаос.. все начнут друг друга хилить без остановки
//чтоб избежать етого выставим начальные значения.. то что ХП у нас- дожопы.. много.. 15к.. т.е. хилить ненадо.
//а потом скрипт сам захватит текущее знасение.. и всё коректно будет...
CurHPKom:=15000;
CurHPBot1:=15000;
CurHPBot2:=15000;
CurHPBot3:=15000;
CurHPBot4:=15000;
//для маны аналогичная ситуация
CurMPKom:=15000;
CurMPBot1:=15000;
CurMPBot2:=15000;
CurMPBot3:=15000;
CurMPBot4:=15000;
//дело в том что скрипт расчитывает хилить или нет в зависимости от % от шкалы.. если вся шкала =0 (по дефолту)
//то ето както некоректно там будет хотя вроде пофиг..
//но для коректности понимания процесса мы пишем что максимальная шкала ХП у нас оч маленькая а текущие значения- оч большие..
//поетому никакие хилы небудут происходить при старте скрипта..
MaxHPKom:=10;
MaxHPBot1:=10;
MaxHPBot2:=10;
MaxHPBot3:=10;
MaxHPBot4:=10;
//тики для таймеров
tick3:=1;
tick4:=1;
BufEndSE:=False;
BufEndPP:=False;
BufEndEE:=False;
//новый баф кастовать через 4 секунды
timer4:=TTimer.Create(nil);
timer4.OnTimer:=@OnTimer4; //
timer4.enabled:=false; //
timer4.interval:=4000;
//в пати баферов пинимать с интервалом 1 сек
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3; //
timer3.enabled:=false; //
timer3.interval:=1000;
// ЗАПРОС НА ОТКРЫТИЕ ИНВЕНТОРЯ!!!! ДЛЯ ЗАХВАТА ИДЕШНИКА!
// чтобы принудительно вызвать от сервера пакет ЮЗЕР ИНФО в котором ИД указан
//а также для того чтобы захвватить ИД банок для питья
buf:=hstr('0F');
SendToServerEX(NameKom);
SendToServerEX(NameBot1);
SendToServerEX(NameBot2);
SendToServerEX(NameBot3);
SendToServerEX(NameBot4);
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer3.Free; // освобождаем память связанную с созданными нами объектами
timer4.Free;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//для тго чтоб 2-3 скрипта коректно работали одновременно..
if pck='' then exit; // нех пустые пакеты обрабатывать типа
//******************************АВТОСОГЛАШЕНИЕ НА ВСТУПЛЕНИЕ В ПАТИ************************
//******************************ПРИ УСЛОВИИ ЧТО ПАТИ ДАЕТ- КОМАНДИР************************
//ну тут тупо считываем имя кто нам шлет пати из пакета на предложение в него вступить
//ну и если имя- командир то вступаем в ету пати автоматом..
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot1);
end;
if FromServer then
if ConnectName=NameBot2 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot2);
end;
if FromServer then
if ConnectName=NameBot3 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot3);
end;
if FromServer then
if ConnectName=NameBot4 then
if pck[1]=#$39 then
if ReadS(2)=NameKom then
begin
buf:=hstr('2A 01 00 00 00');
sendtoserverex(NameBot4);
end;
//*******************ЗАХВАТ КООРДИНАТ***************************************** **********
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot1 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot1X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot1Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot1Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot2 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot2X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot2Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot2Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot3 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot3X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot3Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot3Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot4 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot4X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot4Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot4Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//********************ЗАХВАТ OID ЗЕЛИЙ********************************************* ***************
//при старте скрипта отправляется запрос на открытие инвенторя автоматически
//в ответе сервера содержится всё содердимое инвенторя.. ищем доступные для использования зелья там
//и запоминаем их OID для дальнейшего использования.. если какието банки кончились и вы их докупили
//то следует перезапустить скрипт.. чтоб заного ИД захватить..
//тут вот в скобачках 2 байта ето ИТЕМ ИД.. он константа.. с помощью итем ИД клинт знает какую текстуру подстовлять для визуализации и т.д.
//но для использования предмета- есть ОБЖЕКТ ИД.. например у вас 3 пушки одинаковых в инвенторе.. при етом ИТЕМ ИД у всех будет одинаковый..
//вы наденете то одну то другую.. ето еще лучше на примере бижи объяснять.. 3 кольца у вас одинаковых..
//2 надето а 1 в инвенторе лежит.. вы тыкаете по нему.. (по инвентарю- кольцу) и вродебы ничего для вас не происходит..
// но сервер у себя в мозгах меняет одно на другое кольцо..просто они одинаковые на вид и вы етого не видите..
//но на самом деле ИД у всех 3-х колец разный.. вопщем ОБЖЕКТ ИД- ето предмет который можно юзать каким либо способом в игре..
//самостоятельяная единица.. а ИТЕМ ИД- чисто сопостовление что такойто ОБЖЭКТ- визуализировать- такто..
// с помощью манипуляций с етими числами мы можем увидеть что в место НГ пухи у вас будет нарисован- зарич..
//или вместо моба 12 лвл нарисован АНТАРАС.. и вы его геройски убиваете..
//так вот (заболтался) наша задача соспоставить ИТЕМ ИД к ОБЖЭКТ ИД.. (в скобочках там ИТЕМ ИД)
//для етого мы перебираем пакет с инвентарем и ишем там среди кучи предметов тока те которые нас интерисуют и запоминаем их ОБЖЭКТ ИД..
//у командира:
if FromServer then
if ConnectName=NameKom then
if pck[1]=#$1B then
begin
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8]; // 2504 - это итем ИД банки с ХП обычной с магазина
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('03 06')) then OidGHPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('B2 21')) then OidHPLexir0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('BE 21')) then OidHPLexir0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('D8 15')) then OidGCPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
end
end;
//у БОТА1:
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$1B then
begin
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion1:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8]; // 2504 - это итем ИД банки с ХП обычной с магазина
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('03 06')) then OidGHPPotion1:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('B2 21')) then OidHPLexir1:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('BE 21')) then OidHPLexir1:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('D8 15')) then OidGCPPotion1:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
end
end;
//у БОТА2:
if FromServer then
if ConnectName=NameBot2 then
if pck[1]=#$1B then
begin
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion2:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8]; // 2504 - это итем ИД банки с ХП обычной с магазина
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('03 06')) then OidGHPPotion2:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('B2 21')) then OidHPLexir2:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('BE 21')) then OidHPLexir2:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('D8 15')) then OidGCPPotion2:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
end
end;
//у БОТА3:
if FromServer then
if ConnectName=NameBot3 then
if pck[1]=#$1B then
begin
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion3:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8]; // 2504 - это итем ИД банки с ХП обычной с магазина
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('03 06')) then OidGHPPotion3:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('B2 21')) then OidHPLexir3:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('BE 21')) then OidHPLexir3:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('D8 15')) then OidGCPPotion3:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
end
end;
//у БОТА4:
if FromServer then
if ConnectName=NameBot4 then
if pck[1]=#$1B then
begin
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion4:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8]; // 2504 - это итем ИД банки с ХП обычной с магазина
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('03 06')) then OidGHPPotion4:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('B2 21')) then OidHPLexir4:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('BE 21')) then OidHPLexir4:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('D8 15')) then OidGCPPotion4:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
end
end;
//********************ОСТСЛЕЖИВАЕМ ТРУПАКИ******************************************* *************
//если кто то умер то приходит пакет DIE.. то хилить его ненадо...
//нефиг трупы хилить...
//для того чтоб трупяков боты не хилили ставим кодом то что ХП (текущее) у них до жопы... т.е. 15к
if FromServer then
if ConnectName=NameKom then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDKomandos then
CurHPKom:=15000;
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot1 then
CurHPBot1:=15000;
if FromServer then
if ConnectName=NameBot2 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot2 then
CurHPBot2:=15000;
if FromServer then
if ConnectName=NameBot3 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot3 then
CurHPBot3:=15000;
if FromServer then
if ConnectName=NameBot4 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot3 then
CurHPBot4:=15000;
//*************************УЗНАЕМ ЛИМИТЫ ХП и МП и ИД***********************************************
//из пакета UserInfo который приходит во время бафа и не только
//как тока скрипт начинает свою работу то он на все аки отправляет запрос на открытие ИНВЕНТОРЯ
//вместе с ответом сервера всегда приходит пакет ЮЗЕР ИНФО.. из етого замечательного пакета мы считываем максимальные значения ХП и МП
//а так жэ ИД чара (бота- бафера)
//КОМАНДИР
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$04 then
begin
IDKomandos:=pck[18]+pck[19]+pck[20]+pck[21]; //тут выдергиваем ИД чара
i:=22;
tempS:=readS(i); // ето используем для удобства.. имя типа пропускаем.. потому как каждый раз оно из разного кол-ва букв состоит.. в скобках переменная автоматом увеличивается на кол-во букв (ну там по формуле.. в юникоде 1 буква=2 байта, и символ окончания строки еще 00 00)
i:=i+48; // через 48 байтофъ после имени указывается лимиты и текущие значения для ХП и МП
//запоминаем их.. тут нам не особо важны текущие значения.. хотя лишний раз не помешают
//но важно- максимальное значение- ЛИМИТЫ
MaxHPKom:=readD(i);
CurHPKOM:=readD(i);
MaxMPKom:=readD(i);
CurMPKOM:=readD(i);
MaxCPKom:=round(MaxHPKom/2);
end;
//1-й бот
if FromServer then
if ConnectName = NameBot1 then
if pck[1]=#$04 then
begin
IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot1:=readD(i);
CurHPBot1:=readD(i);
MaxMPBot1:=readD(i);
CurMPBot1:=readD(i);
MaxCPBot1:=round(MaxHPBot1/2);
end;
//2-й бот
if FromServer then
if ConnectName = NameBot2 then
if pck[1]=#$04 then
begin
IDBot2:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot2:=readD(i);
CurHPBot2:=readD(i);
MaxMPBot2:=readD(i);
CurMPBot2:=readD(i);
MaxCPBot2:=round(MaxHPBot2/2);
end;
//3-й бот
if FromServer then
if ConnectName = NameBot3 then
if pck[1]=#$04 then
begin
IDBot3:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot3:=readD(i);
CurHPBot3:=readD(i);
MaxMPBot3:=readD(i);
CurMPBot3:=readD(i);
MaxCPBot3:=round(MaxHPBot3/2);
end;
//4-й бот
if FromServer then
if ConnectName = NameBot4 then
if pck[1]=#$04 then
begin
IDBot4:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot4:=readD(i);
CurHPBot4:=readD(i);
MaxMPBot4:=readD(i);
CurMPBot4:=readD(i);
MaxCPBot4:=round(MaxHPBot4/2);
end;
//*************************СЛЕДИМ ЗА ХП и МП******************************************
//а ету часть кода требуется под ваши жэлания настроить..
//тут указываются значения при которых ПП ШШ ЕЕ БИШ будут вам ману лить и ХП заливать и каким именно скилом
//следим за ХП КОМАНДИРА
//отлавливаем СТАТУС АПДЕЙТ!!!!!
//как выяснилось статус апдейта бывает 2 разных..
//1 для ХП, 2 для МП
//етот пакет приходит при любом изменении ХП и МП у чара..
//чтоб их отличить сервак использует индекс.. в 6-м байте присылает либо 4 либо 2..
//если в 6-м байте СТАТУС АПДЕЙТ цифра #$04 то значит реч в етом пакете про ХП
//а если #$02 то реч в етом пакете про МП..
//ДЛЯ ЦП используется дурацкая формула: базовое ХП/2 .. в пакете нигде не указывается максимальное кол-во ЦП поетому мы его вот так вот высчитываем.. спросите почиму дурацкая?.. потомучто бафните от ПП блесс ХП и пипец..
//я долго не мог понять почеу у меня скрипт сам бухал ЦП банки под бафом без надобности.. пока не понял что ЦП от базового ХП расщитывается без учета бафа..
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$0e then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$04) then
begin
//считываем текущее состояние ХП!!-)
CurHPKom:=ReadD(14);
//считываем текущее состояние ЦП!!-)
CurCPKom:=ReadD(30);
//ну собственно ето уже можно править под желания каждого:
//если жизни текущие меньше 0,7 от шкалы (70%) то..
//то биш использует свой любимый скил МАЖОР ХИЛ за спирит оре (в интерлюде) (для ц4 такого скила нету)
if (CurHPKom < round(MaxHPKom*0.7)) then
begin
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00'); // МАЖОР ХИЛ БИШ
if (IDBot1 <> '') then SendToServerEX(NameBot1);
end;
if (CurHPKom < round(MaxHPKom*0.4)) then
begin
buf:=hstr('04') + IDKomandos + Bot2X + Bot2Y + Bot2Z + hstr('00');
if (IDBot2 <> '') then SendToServerEX(NameBot2);
buf:=hstr('2F F7 03 00 00 00 00 00 00 00'); //ПП ХИЛИТ
if (IDBot2 <> '') then SendToServerEX(NameBot2);
end;
if (CurHPKom < round(MaxHPKom*0.75)) then
begin
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00'); //ЕЕ ХИЛИТ
if (IDBot4 <> '') then SendToServerEX(NameBot4);
end;
if (CurHPKom < round(MaxHPKom*0.6)) then
begin
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F C1 04 00 00 00 00 00 00 00 '); //ШЕ ХИЛИТ
if (IDBot3 <> '') then SendToServerEX(NameBot3);
end;
//КОМАНДИР БУХАЕТ ЗЕЛЬЯ
if (CurHPKom < round(MaxHPKom*0.90)) and (CurCPKom < round(MaxCPKom*0.6)) then
begin
buf:= hstr('14') + OidGHPPotion0 + hstr('00 00 00 00'); // гритер хилку
if (OidGHPPotion0 <> '') then SendToServerEX(NameKom);
end;
if (CurHPKom < round(MaxHPKom*0.8)) then
begin
buf:= hstr('14') + OidHPPotion0 + hstr('00 00 00 00'); // обычную хилку
if (OidHPPotion0 <> '') then SendToServerEX(NameKom);
end;
if (CurHPKom < round(MaxHPKom*0.3)) then
begin
buf:= hstr('14') + OidHPLexir0 + hstr('00 00 00 00'); // лексир ХП
if (OidHPPotion0 <> '') then SendToServerEX(NameKom);
end;
///ТУТ МЕНЯЙТЕ ЗНАЧЕНИЕ ОЧ АКУРАТНО.. 1,0 ето не 100% шкалы изза бафа на блесс ХП..
// поетому ставьте немного меньше с учетом возможного бафа на блес ХП..
if (CurCPKom < round(MaxCPKom*0.6)) then
begin
buf:= hstr('14') + OidGCPPotion0 + hstr('00 00 00 00'); // ГЦП БАНКУ
if (OidGCPPotion0 <> '') then SendToServerEX(NameKom);
end;
if (CurCPKom < round(MaxCPKom*0.1)) then
begin
buf:= hstr('14') + OidCPLexir0 + hstr('00 00 00 00'); // лексир ЦП
if (OidGCPPotion0 <> '') then SendToServerEX(NameKom);
end;
end;
//следим за ХП у БОТ1
//если злой хренко решит наших баферов бить, а потом нас- то мы просто так не сдадимся..
//баферам ХИЛ дадим.. чтоб хренко били били и не убили...
//я сделал тупо- чтоб тока сам себя хилял бафер.. добавьте аналогичные строки сюда и будет так что все баферы будут хилить баф-бота
//ето надо полюбасу- но пока руки не дошли.. и вам немного задачи- доделать скрипт..
//но я етого не сделал еще по одной причине.. в реальных условиях мой командир бегает оч шустро..
//баферы отстают.. если 1 бафер на пвп отстанет- да и хер с ним.. а если етого отстающего бьют..
//и все мои баферы кинутся его хилить (если его бьют) то я через 15 сек буду оч далеко и меня уже баферы не догонят
//и я буду- (командир пати) без хила.. поетому если бафера атакуют то я сделал чтоб он сам себя лечил..
// но чтоб другие не лечили, чтоб другие за мной бежали..
if FromServer then
if ConnectName = NameBot1 then
if pck[1]=#$0e then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot1 + #$04) then
begin
CurHPbot1:=ReadD(14);
CurCPbot1:=ReadD(30);
//на 70% шкалы хилит бафер сам себя (бишоп) скилом мажор хил
if (CurHPbot1 < round(MaxHPBot1*0.7)) then
begin
buf:=hstr('04') + IDbot1 + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00'); //скил бишопа: можор хил
if (IDBot1 <> '') then SendToServerEX(NameBot1);
end;
//БОТ1 БУХАЕТ ЗЕЛЬЯ
if (CurHPBot1 < round(MaxHPBot1*0.90)) and (CurCPBot1 < round(MaxCPBot1*0.6)) then
begin
buf:= hstr('14') + OidGHPPotion1 + hstr('00 00 00 00'); // гритер хилку
if (OidGHPPotion1 <> '') then SendToServerEX(NameBot1);
end;
if (CurHPBot1 < round(MaxHPBot1*0.8)) then
begin
buf:= hstr('14') + OidHPPotion1 + hstr('00 00 00 00'); // обычную хилку
if (OidHPPotion1 <> '') then SendToServerEX(NameBot1);
end;
if (CurHPBot1 < round(MaxHPBot1*0.3)) then
begin
buf:= hstr('14') + OidHPLexir1 + hstr('00 00 00 00'); // лексир ХП
if (OidHPLexir1 <> '') then SendToServerEX(NameBot1);
end;
if (CurCPBot1 < round(MaxCPBot1*0.6)) then
begin
buf:= hstr('14') + OidGCPPotion1 + hstr('00 00 00 00'); // ГЦП БАНКУ
if (OidGCPPotion1 <> '') then SendToServerEX(NameBot1);
end;
if (CurCPBot1 < round(MaxCPBot1*0.1)) then
begin
buf:= hstr('14') + OidCPLexir1 + hstr('00 00 00 00'); // лексир ЦП
if (OidCPLexir1 <> '') then SendToServerEX(NameBot1);
end;
end;
//следим за ХП у БОТ2
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot2 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot2 + #$04) then
begin
CurHPbot2:=ReadD(14);
CurCPbot2:=ReadD(30);
if (CurHPbot2 < round(MaxHPBot2*0.7)) then
begin
buf:=hstr('04') + IDbot2 + Bot1X + Bot1Y + Bot1Z + hstr('00');
if (IDBot1 <> '') and (IDBot2 <> '') then SendToServerEX(NameBot1);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00');
if (IDBot1 <> '') and (IDBot2 <> '') then SendToServerEX(NameBot1);
end;
//БОТ2 БУХАЕТ ЗЕЛЬЯ
if (CurHPBot2 < round(MaxHPBot2*0.90)) and (CurCPBot2 < round(MaxCPBot2*0.6)) then
begin
buf:= hstr('14') + OidGHPPotion2 + hstr('00 00 00 00'); // гритер хилку
if (OidGHPPotion2 <> '') then SendToServerEX(NameBot2);
end;
if (CurHPBot2 < round(MaxHPBot2*0.8)) then
begin
buf:= hstr('14') + OidHPPotion2 + hstr('00 00 00 00'); // обычную хилку
if (OidHPPotion2 <> '') then SendToServerEX(NameBot2);
end;
if (CurHPBot2 < round(MaxHPBot2*0.3)) then
begin
buf:= hstr('14') + OidHPLexir2 + hstr('00 00 00 00'); // лексир ХП
if (OidHPLexir2 <> '') then SendToServerEX(NameBot2);
end;
if (CurCPBot2 < round(MaxCPBot2*0.6)) then
begin
buf:= hstr('14') + OidGCPPotion2 + hstr('00 00 00 00'); // ГЦП БАНКУ
if (OidGCPPotion2 <> '') then SendToServerEX(NameBot2);
end;
if (CurCPBot2 < round(MaxCPBot2*0.1)) then
begin
buf:= hstr('14') + OidCPLexir2 + hstr('00 00 00 00'); // лексир ЦП
if (OidCPLexir2 <> '') then SendToServerEX(NameBot2);
end;
end;
//следим за ХП у БОТ3
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot3 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot3 + #$04) then
begin
CurHPbot3:=ReadD(14);
CurCPbot3:=ReadD(30);
if (CurHPbot3 < round(MaxHPBot3*0.7)) then
begin
buf:=hstr('04') + IDbot3 + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F C1 04 00 00 00 00 00 00 00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
end;
//БОТ3 БУХАЕТ ЗЕЛЬЯ
if (CurHPBot3 < round(MaxHPBot3*0.90)) and (CurCPBot3 < round(MaxCPBot3*0.6)) then
begin
buf:= hstr('14') + OidGHPPotion3 + hstr('00 00 00 00'); // гритер хилку
if (OidGHPPotion3 <> '') then SendToServerEX(NameBot3);
end;
if (CurHPBot3 < round(MaxHPBot3*0.8)) then
begin
buf:= hstr('14') + OidHPPotion3 + hstr('00 00 00 00'); // обычную хилку
if (OidHPPotion3 <> '') then SendToServerEX(NameBot3);
end;
if (CurHPBot3 < round(MaxHPBot3*0.3)) then
begin
buf:= hstr('14') + OidHPLexir3 + hstr('00 00 00 00'); // лексир ХП
if (OidHPLexir3 <> '') then SendToServerEX(NameBot3);
end;
if (CurCPBot3 < round(MaxCPBot3*0.6)) then
begin
buf:= hstr('14') + OidGCPPotion3 + hstr('00 00 00 00'); // ГЦП БАНКУ
if (OidGCPPotion3 <> '') then SendToServerEX(NameBot3);
end;
if (CurCPBot3 < round(MaxCPBot3*0.1)) then
begin
buf:= hstr('14') + OidCPLexir3 + hstr('00 00 00 00'); // лексир ЦП
if (OidCPLexir3 <> '') then SendToServerEX(NameBot3);
end;
end;
//следим за ХП у БОТ4
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot4 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot4 + #$04) then
begin
CurHPbot4:=ReadD(14);
CurCPbot4:=ReadD(30);
if (CurHPbot4 < round(MaxHPBot4*0.7)) then
begin
buf:=hstr('04') + IDbot4 + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (IDBot4 <> '') and (IDBot4 <> '') then SendToServerEX(NameBot4);
buf:=hstr('2F 79 05 00 00 00 00 00 00 00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
end;
//БОТ4 БУХАЕТ ЗЕЛЬЯ
if (CurHPBot4 < round(MaxHPBot4*0.90)) and (CurCPBot4 < round(MaxCPBot4*0.6)) then
begin
buf:= hstr('14') + OidGHPPotion4 + hstr('00 00 00 00'); // гритер хилку
if (OidGHPPotion4 <> '') then SendToServerEX(NameBot4);
end;
if (CurHPBot4 < round(MaxHPBot4*0.8)) then
begin
buf:= hstr('14') + OidHPPotion4 + hstr('00 00 00 00'); // обычную хилку
if (OidHPPotion4 <> '') then SendToServerEX(NameBot4);
end;
if (CurHPBot4 < round(MaxHPBot4*0.3)) then
begin
buf:= hstr('14') + OidHPLexir4 + hstr('00 00 00 00'); // лексир ХП
if (OidHPLexir4 <> '') then SendToServerEX(NameBot4);
end;
if (CurCPBot4 < round(MaxCPBot4*0.6)) then
begin
buf:= hstr('14') + OidGCPPotion4 + hstr('00 00 00 00'); // ГЦП БАНКУ
if (OidGCPPotion4 <> '') then SendToServerEX(NameBot4);
end;
if (CurCPBot4 < round(MaxCPBot4*0.1)) then
begin
buf:= hstr('14') + OidCPLexir4 + hstr('00 00 00 00'); // лексир ЦП
if (OidCPLexir4 <> '') then SendToServerEX(NameBot4);
end;
end;
//следим за МП у КОМАНДИРА (ШЕ следит)
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameKom then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$02) then
begin
CurMPkom:=ReadD(14);
rnd:=round(random*100);
if (CurMPkom < round(MaxMPkom*0.5)) and (rnd<15) then
begin
buf:=hstr('04') + IDKomandos + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F F5 03 00 00 00 00 00 00 00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
end;
end;
//следим за МП у КОМАНДИРА (ЕЕ следит)
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameKom then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$02) then
begin
CurMPkom:=ReadD(14);
rnd:=round(random*100);
if (CurMPkom < round(MaxMPkom*0.5)) and (rnd<15) then
begin
buf:=hstr('04') + IDKomandos + Bot4X + Bot4Y + Bot4Z + hstr('00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
buf:=hstr('2F F5 03 00 00 00 00 00 00 00');
if (IDBot4 <> '') then SendToServerEX(NameBot4);
end;
end;
//следим за МП у БИША
//этот кусок кода вполне альтернативный..
if FromServer then
if pck[1]=#$0e then
if ConnectName = NameBot1 then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDbot1 + #$02) then
begin
CurMPBot1:=ReadD(14);
if (CurMPBot1 < round(MaxMPBot1*0.9)) then
begin
buf:=hstr('04') + IDBot1 + Bot3X + Bot3Y + Bot3Z + hstr('00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
buf:=hstr('2F F5 03 00 00 00 00 00 00 00');
if (IDBot3 <> '') then SendToServerEX(NameBot3);
end;
end;
//**********************СЛЕДИМ ЗА ТАРГЕТАМИ****************************************
//КОМАНДИР
//если принят пакет со сменой таргета у командира то
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$A6 then
begin
//запоминаем ИД таргета командира для ассиста
IDAssistTarget:= pck[2]+pck[3]+pck[4]+pck[5];
end;
//**********************САЖАЕМ ВСЮ ПАТИ ЧЕРЕЗ КОНТРОЛ****************************************
//если принят пакет на сажание с контролом то сажаем всю пати
if FromClient then
if (ConnectName = NameKom) then
if (pck[1]+pck[2]+pck[6]=hstr('45 00 01')) then
begin
buf:=hstr('45 00 00 00 00 01 00 00 00 00');
if IDBot1<>'' then SendToServerEX(NameBot1);
if IDBot2<>'' then SendToServerEX(NameBot2);
if IDBot3<>'' then SendToServerEX(NameBot3);
if IDBot4<>'' then SendToServerEX(NameBot4);
end;
//*******************БЕЖИМ ЗА КОМАНДИРОМ ПОСЛЕ ИСПОЛЬЗОВАНИЯ СКИЛА***************************
//ловим пакет МАДЖИКСКИЛЮЗ
if FromServer then
if pck[1] = #$48 then
if (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT1) or (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT2) or (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT3) or (pck[2]+pck[3]+pck[4]+pck[5]=IDBOT4) then
begin
BotBeg;
end;
//**************************УПРАВЛЕНИЕ************** **********************************
//"Bow" (ПОКЛОН)- БЕЖАТЬ за КОМАНДИРОМ
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 07') then
begin
pck:='';
BotBeg;
exit;
end;
//ADVANCE- В АТАКУ - пати быстрое создание (3-я кнопка)
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 04') then
begin
pck:='';
//сразу рвем пати у всех чаров и командир раздает пати поновому
//чары автоматически принимают пати
//используется таймер т.к. одновременно 2-м чарам пати кинуть нельзя
timer3.enabled:=true;
exit;
end;
//YES- РУТ ПО АССИСТУ (4-я кнопка) либо переделать в какойто дебаф от каждого бафера он свой.. по ассисту все баферы какуюто куйню кинут на цель по ассисту..
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 06') then
begin
pck:='';
buf:= hstr('14') + OidgcpPotion0 + hstr('00 00 00 00'); // обычную хилку
if (OidgcpPotion0 <> '') then SendToServerEX(NameKom);
{ buf:=hstr('04') + IDAssistTarget + Bot1X + Bot1Y + Bot1Z + hstr('00');
if NameBot1<>'' then SendToServerEX(NameBot1);
buf:=hstr('04') + IDAssistTarget + Bot2X + Bot2Y + Bot2Z + hstr('00');
if NameBot2<>'' then SendToServerEX(NameBot2);
buf:=hstr('04') + IDAssistTarget + Bot3X + Bot3Y + Bot3Z + hstr('00');
if NameBot3<>'' then SendToServerEX(NameBot3);
buf:=hstr('2F 72 05 00 00 01 00 00 00 00');
if NameBot1<>'' then SendToServerEX(NameBot1);
buf:=hstr('2F B1 04 00 00 01 00 00 00 00');
if NameBot2<>'' then SendToServerEX(NameBot2);
buf:=hstr('2F B1 04 00 00 00 00 00 00 00');
if NameBot3<>'' then SendToServerEX(NameBot3);}
exit;
end;
//NO буф МАГА по ассисту
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 05') then
begin
BafPPApplyChar[1]:=IDAssistTarget;
BafPPApplyBaf[1]:=bafPP[24];
BafPPApplyChar[2]:=IDAssistTarget;
BafPPApplyBaf[2]:=bafPP[5];
BafPPApplyChar[3]:=IDAssistTarget;
BafPPApplyBaf[3]:=bafPP[2];
BafPPApplyChar[4]:=IDAssistTarget;
BafPPApplyBaf[4]:=bafPP[6];
BafPPApplyChar[5]:=IDAssistTarget;
BafPPApplyBaf[5]:=bafPP[7];
BafPPApplyChar[6]:=IDAssistTarget;
BafPPApplyBaf[6]:=bafPP[8];
BafPPApplyChar[7]:=IDAssistTarget;
BafPPApplyBaf[7]:=bafPP[9];
BafPPApplyChar[8]:=IDAssistTarget;
BafPPApplyBaf[8]:=bafPP[1];
BafPPApplyChar[9]:=IDAssistTarget;
BafPPApplyBaf[9]:=bafPP[13];
BafPPApplyChar[10]:=IDAssistTarget;
BafPPApplyBaf[10]:=bafPP[14];
BafPPApplyChar[11]:=IDAssistTarget;
BafPPApplyBaf[11]:=bafPP[16];
BafPPApplyChar[12]:=IDAssistTarget;
BafPPApplyBaf[12]:=bafPP[18];
BafPPApplyChar[13]:=IDAssistTarget;
BafPPApplyBaf[13]:=bafPP[19];
BafPPApplyChar[14]:=IDAssistTarget;
BafPPApplyBaf[14]:=bafPP[20];
BafPPApplyChar[16]:='';
BafPPApplyBaf[16]:='';
BafSEApplyChar[1]:=IDAssistTarget;
BafSEApplyBaf[1]:=bafSE[2];
BafSEApplyChar[2]:=IDAssistTarget;
BafSEApplyBaf[2]:=bafSE[2];
BafSEApplyChar[3]:=IDAssistTarget;
BafSEApplyBaf[3]:=bafSE[5];
BafSEApplyChar[4]:=IDAssistTarget;
BafSEApplyBaf[4]:=bafSE[6];
BafSEApplyChar[5]:='';
BafSEApplyBaf[5]:='';
BafEEApplyChar[1]:=IDAssistTarget;
BafEEApplyBaf[1]:=bafEE[2];
BafEEApplyChar[2]:=IDAssistTarget;
BafEEApplyBaf[2]:=bafEE[2];
BafEEApplyChar[3]:=IDAssistTarget;
BafEEApplyBaf[3]:=bafEE[3];
BafEEApplyChar[4]:=IDAssistTarget;
BafEEApplyBaf[4]:=bafEE[1];
BafEEApplyChar[5]:='';
BafEEApplyBaf[5]:='';
timer4.enabled:=true;
pck:='';
exit;
end;
//UNAWARE буф ФИЗИКА по ассисту
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 08') then
begin
BafPPApplyChar[1]:=IDAssistTarget;
BafPPApplyBaf[1]:=bafPP[1];
BafPPApplyChar[2]:=IDAssistTarget;
BafPPApplyBaf[2]:=bafPP[2];
BafPPApplyChar[3]:=IDAssistTarget;
BafPPApplyBaf[3]:=bafPP[3];
BafPPApplyChar[4]:=IDAssistTarget;
BafPPApplyBaf[4]:=bafPP[4];
BafPPApplyChar[5]:=IDAssistTarget;
BafPPApplyBaf[5]:=bafPP[7];
BafPPApplyChar[6]:=IDAssistTarget;
BafPPApplyBaf[6]:=bafPP[8];
BafPPApplyChar[7]:=IDAssistTarget;
BafPPApplyBaf[7]:=bafPP[9];
BafPPApplyChar[8]:=IDAssistTarget;
BafPPApplyBaf[8]:=bafPP[22];
BafPPApplyChar[9]:=IDAssistTarget;
BafPPApplyBaf[9]:=bafPP[12];
BafPPApplyChar[10]:=IDAssistTarget;
BafPPApplyBaf[10]:=bafPP[13];
BafPPApplyChar[11]:=IDAssistTarget;
BafPPApplyBaf[11]:=bafPP[14];
BafPPApplyChar[12]:=IDAssistTarget;
BafPPApplyBaf[12]:=bafPP[15];
BafPPApplyChar[13]:=IDAssistTarget;
BafPPApplyBaf[13]:=bafPP[18];
BafPPApplyChar[14]:=IDAssistTarget;
BafPPApplyBaf[14]:=bafPP[19];
BafPPApplyChar[15]:=IDAssistTarget;
BafPPApplyBaf[15]:=bafPP[20];
BafPPApplyChar[16]:=IDAssistTarget;
BafPPApplyBaf[16]:=bafPP[21];
BafPPApplyChar[17]:='';
BafPPApplyBaf[17]:='';
BafSEApplyChar[1]:=IDAssistTarget;
BafSEApplyBaf[1]:=bafSE[4];
BafSEApplyChar[2]:='';
BafSEApplyBaf[2]:='';
BafEEApplyChar[1]:=IDAssistTarget;
BafEEApplyBaf[1]:=bafEE[2];
BafEEApplyChar[2]:=IDAssistTarget;
BafEEApplyBaf[2]:=bafEE[1];
BafEEApplyChar[3]:='';
BafEEApplyBaf[3]:='';
timer4.enabled:=true;
pck:='';
exit;
end;
end.
APXAHGEJI
16.03.2008, 10:12
Слегка поправил выложенный ранее АвтоСвип. Упростил запись мобов, свипает стабильнее.
//Автоматизация sweep'а by APXAHGEJI
//Свип производится тока при условии что моб был ,хоть один раз, ударен ВАМИ и
//находится в списке нужных мобов.
//Возможность работы нескольких одновременных скриптов
//Социальное действие YES - запусстить/приостановить запись/АвтоСвип мобов
//Социальное действие NO остановиться - завершить запись мобов и перейтии к АвтоСвип
//После того как скрипт запущен нажимаете Yes и атакуете мобов
//которых собираетесь спойлить. Атакуете до тех пор пока не появилась запись
//что моб записан. Для удобства процесс записи можно приостановить нажатие той же
//клавиши Yes. После того как все нужные мобы записаны жмакаете NO, запись мобов
//завершается, АвтоСвип запускается, можете приступать к спойлу. АвтоСвип можно
//приостановить нажав всю туже клавишу соцдействия Yes, но запись мобов под АвтоСвип
//не остановится, и снова активировав, все нужные мобы просвипятся.
Const
Name='Ник перса';
Sweep='2F 2A 00 00 00 00 00 00 00 00';
Var
TimerSweep,TimerDel: TTimer;
N,M,i,NpcNum: Byte;
X,Y,Z,CharID: Integer;
NpcTypeID,TargetID: array of Integer;
NeedSweep,Dead: array of Boolean;
Switch,SaveID,HaveNpc: Boolean;
//************************************************** ****************************
// Вызывается при включении скрипта
//************************************************** ****************************
Procedure Init;
begin
N:= 1;
M:= 1;
Switch:= False;
SaveID:= True;
SetLength( NpcTypeID, N );
SetLength( TargetID, N );
TimerSweep:=TTimer.Create(nil);
TimerSweep.OnTimer:=@Sweeper;
TimerSweep.Enabled:= False;
TimerSweep.Interval:= 1000;
TimerDel:=TTimer.Create(nil);
TimerDel.OnTimer:=@Del;
TimerDel.Enabled:= False;
TimerDel.Interval:= 5000;
Say('Нажмите Yes, чтобы начать/приостановить');
Say('запись мобов или АвтоСвип.');
Say('Нажмите No, чтобы завершить запись мобов');
Say('и приступить к сполйу.');
end;
//************************************************** ****************************
//************************************************** ****************************
// Вызывается при выключении скрипта
//************************************************** ****************************
Procedure Free;
begin
TimerSweep.Free;
TimerDel.Free;
end;
//************************************************** ****************************
//************************************************** ****************************
// Посылаем сообщение, которое видно только в окне бота
//************************************************** ****************************
Procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(Name);
WriteS(msg);
SendToClientEx(Name);
end;
//************************************************** ****************************
//************************************************** ****************************
// Проверка наличия ИД моба в массиве
//************************************************** ****************************
Procedure FindMob(ObjectID: Integer);
begin
HaveNpc:= False;
NpcNum:= M;
For i:=0 to (M-1) do
If (ObjectID=TargetID[i]) then begin
NpcNum:= i;
HaveNpc:= True;
break;
end Else
If (TargetID[i]= 0) and (NpcNum = M) then NpcNum:= i;
end;
//************************************************** ****************************
//************************************************** ****************************
// Запуск свипа каждые n секунд (n= Timer.Interval)
//************************************************** ****************************
Procedure Sweeper(Sender: TObject);
begin
For i:=0 to (M-1) do
If NeedSweep[i] and Dead[i] then begin
buf:= #$04;
WriteD(TargetID[i]);
WriteD(X);
WriteD(Y);
WriteD(Z);
WriteC(00);
SendToServerEx(Name);
buf:=HStr(Sweep);
SendToServerEx(Name);
NeedSweep[i]:= False;
exit;
end;
end;
//************************************************** ****************************
//************************************************** ****************************
//Удаление списка при отстуствии записей о мобах
//************************************************** ****************************
Procedure Del(Sender: TObject);
begin
For i:=0 to (M-1) do
If (TargetID[i]<>0) then exit;
M:= 0;
SetLength(TargetID, M);
SetLength(NeedSweep, M);
SetLength(Dead, M);
TimerDel.Enabled:= False;
TimerSweep.Enabled:= False;
end;
//************************************************** ****************************
//************************************************** ****************************
// Вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
Begin
//************************************************** **************************
//Не обрабатываем пустые пакеты
If pck='' then exit;
//************************************************** **************************
//************************************************** **************************
//Если от сервака принят пакет UserInfo. Запоминаем собственный ИД.
If FromServer and (ConnectName=Name) and (pck[1]=#$04) then CharID:= ReadD(18);
//************************************************** **************************
//************************************************** **************************
//Переключение между записью ИД и АвтоСвипом
If SaveID then begin
//************************************************** ************************
//Делаем выборку нужных для свипа видов мобов
//************************************************** ************************
if Switch then
if FromServer and (ConnectName=Name) then
if (pck[1]=#$05) and (ReadD(2)=CharID) then begin
FindMob(ReadD(6));
If not HaveNpc then begin
TargetID[N-1]:= ReadD(6);
Inc(M);
SetLength( TargetID, M );
end;
end;
If (pck[1]=#$16) then
For i:=0 to (M-1) do
if (ReadD(2) = TargetID[i]) then begin
For NpcNum:= 0 to (N-1) do
If (ReadD(6)= NpcTypeID[NpcNum]) then exit;
NpcTypeID[N-1]:= ReadD(6);
Say(IntToStr(N)+' вид мобов записан');
Inc(N);
SetLength( NpcTypeID, N );
exit;
end;
//************************************************** ************************
//Управление записью мобов
//************************************************** ************************
If FromClient and (ConnectName=Name) and (pck[1]=#$1B) then begin
If (ReadD(2)=6) then
if Switch then begin
pck:='';
Switch:= False;
Say('Запись мобов приостановлена');
end
else begin
pck:='';
Switch:= True;
Say('Начата запись мобов, атакуйте нужных мобов');
end;
If (ReadD(2)=5) then begin
pck:='';
Dec(N);
M:= 0;
SetLength(NpcTypeID, N);
SetLength(TargetID, M);
SetLength(NeedSweep, M);
SetLength(Dead, M);
SaveID:= False;
Switch:= True;
Say('Запись мобов завершена, АвтоСвип активирован');
Say('Удачного спойла');
end;
end;
//************************************************** ************************
end
//************************************************** **************************
//************************************************** **************************
//Переходим от записи нужных мобов к АвтоСвипу
Else begin
//************************************************** **************************
//************************************************** ************************
//Записываем текущие координаты
if FromClient and (ConnectName=Name) and (pck[1]=#$48) then begin
X:= ReadD(2);
Y:= ReadD(6);
Z:= ReadD(10);
end;
//************************************************** ************************
//************************************************** ************************
//Анализ мобов :=))
If FromServer and (ConnectName=Name) then begin
//************************************************** **********************
//Записываем всех атакованых нами мобов (пакет Attack, причем Attacker=CharID)
If ((pck[1]= #$05) and (ReadD(2)= CharID)) then begin
FindMob(ReadD(6));
If not HaveNpc then
If (NpcNum <> M) then begin
TargetID[NpcNum]:= ReadD(6);
NeedSweep[NpcNum]:= False;
Dead[NpcNum]:= False
end Else begin
Inc(M);
SetLength(TargetID, M);
SetLength(NeedSweep, M);
SetLength(Dead, M);
TargetID[M-1]:= ReadD(6);
NeedSweep[M-1]:= False;
Dead[M-1]:= False;
If Switch then TimerSweep.Enabled:= True;
TimerDel.Enabled:= True;
end;
end;
//************************************************** **********************
//Проверяем есть ли в списке мобы
if (M <> 0) then begin
//************************************************** ********************
//Проверяем тот ли вид моба атакован (пакет NpcInfo)
If (pck[1]= #$16) then begin
FindMob(ReadD(2));
If HaveNpc and (not NeedSweep[NpcNum]) then begin
For i:=0 to (N-1) do
If (ReadD(6)= NpcTypeID[i]) then begin
HaveNpc:= False;
Break;
end;
If not HaveNpc then NeedSweep[NpcNum]:= True;
end;
end;
//************************************************** ********************
//Записываем что атакованый моб умер (пакет Die, причем Sweepable=1)
If (pck[1]= #$06) and (pck[22]= #$01) then begin
FindMob(ReadD(2));
If HaveNpc then Dead[NpcNum]:= True;
end;
//************************************************** ********************
//Удаляем записи об атакованом мобе (пакет DeleteObject)
If (pck[1]= #$12) then begin
FindMob(ReadD(2));
If HaveNpc then begin
TargetID[NpcNum]:= 0;
NeedSweep[NpcNum]:= False;
Dead[NpcNum]:= False;
end;
end;
//************************************************** ********************
end;
//************************************************** **********************
end;
//************************************************** ************************
//************************************************** ************************
//Запускаем/приостанавливаем АвтоСвип
//************************************************** ************************
If FromClient and (ConnectName=Name) and (pck[1]=#$1B) and (ReadD(2)=6) then
if Switch then begin
pck:='';
TimerSweep.Enabled:= False;
Switch:= False;
Say('АвтоСвип приостановлен');
end
else begin
pck:='';
TimerSweep.Enabled:= True;
Switch:= True;
Say('АвтоСвип запущен');
end;
//************************************************** ************************
end;
//************************************************** **************************
End.
//************************************************** ****************************
Добавлено спустя 5 минут 19 секунд:
И кстати у меня еще вопросик назрел.
Мне крайне ненравятся все эти извращения с вводом чего либо в чат или использования соцдействия.
Нельзяли аткивировать некоторый код при нажатии ,например, клавиши W?
И кстати у меня еще вопросик назрел.
Мне крайне ненравятся все эти извращения с вводом чего либо в чат или использования соцдействия.
Нельзяли аткивировать некоторый код при нажатии ,например, клавиши W?
Выше по теме лежит скрипт DeVolf'a. Я сам не пробовал применять его, но вроде он про присвоение действий клавишам.
1 Запускаем скрипт
2 Используем ту клавишу к которой хотим привязать действие
3 Отлавливаем пакет от клиента он будет типа Бай Пас
4 добавляем в скрипте перед end. такие строчки
Код: Выделить всё
if fromclient and (pck=HStr('в етих скобках пишем пакет который поймали')) then begin
buf:=#$0F;
WriteD(5);
WriteS(HTML2);
SendToClient;
buf:=hstr('а тут пишем пакет действия , которое присвоим клавише');
pck:='';
sendtoserver;
end;
APXAHGEJI
16.03.2008, 18:09
Это не то что мне нужно. Аналогия команд в чат и соц действий.
Кароч тот же хрен тока в левой руке.
Допустим это еще покатит для взятой в пример клавишей W, так как к ней идет привязка покета передвижения.
А как задействовать клавищу которая на клиент не действеут и соответственно не отправляет никаких
пакетов.
Блин я читал что вроде есть в Л2ПНХ обработчик событий.
Нельзя ли перехватывать нажатие клавиши?
(Я нифига в этом деле не шарю. Пытался в инете на эту тему найти какую нить инфу, но безрезультатно, тока денег угрохал.)
Если такое есть, выложите код как это работает с описанием, ну или хотя бы ссылку дайте где мона найти инфу по этому
делу.
DashKAaa
18.03.2008, 15:25
Залил рабочий скрипт бота. Пробуйте.
- поправил питьё Алакрити пошн
- показывает центр кача
В твоем боте есть недочет так же как и в версии skay.
Если бот напал на 2-3 мобов бить начинает то одного то другого(в итоге он всех убивает но всеже) -это раз.
Если бот бьет моба и рядом с магии моб в него стреляет и тут же появляется еще 1 моб (рядом респнулся) то тут же не добив тех 2 мобов он кидается бить нового, убив нового он убивает первого но не того кто стрелят с магии(он его как будто не замечает хотя на карте отмечается что моб рядом стоит) -так часто дохнул бот! тупо стоял и получал магические удары от моба и не бив его, либо просто бегая в заданном радиусе на хвосте с мобом.
а так все вполне играбельно в сочетание с вороновским буфф скриптом, можно и уже парти запускать на кач )
спасибо за скрипты :good:
Залил рабочий скрипт бота. Пробуйте.
- поправил питьё Алакрити пошн
- показывает центр кача
В твоем боте есть недочет так же как и в версии skay.
Если бот напал на 2-3 мобов бить начинает то одного то другого(в итоге он всех убивает но всеже) -это раз.
Если бот бьет моба и рядом с магии моб в него стреляет и тут же появляется еще 1 моб (рядом респнулся) то тут же не добив тех 2 мобов он кидается бить нового, убив нового он убивает первого но не того кто стрелят с магии(он его как будто не замечает хотя на карте отмечается что моб рядом стоит) -так часто дохнул бот! тупо стоял и получал магические удары от моба и не бив его, либо просто бегая в заданном радиусе на хвосте с мобом.
а так все вполне играбельно в сочетание с вороновским буфф скриптом, можно и уже парти запускать на кач )
спасибо за скрипты :good:
Похожие недочеты из-за того, что я делал на основе его скрипта. :)
Нет защелки на одного моба, нужно добавить. Про магическую атаку я знаю. Нападение проверяется, только если нас бьют физической атакой.
DashKAaa
20.03.2008, 22:34
после двух дневного теста.. еще парочку недочетов выявил!
у нас 2 окна.
1 окно тот кто крошит мобов
2 окно хеллера(буффера работающего оффпарти) СЕ в нашем случае ( скрипт ворона )
воин бежит долбит мобов цеплят на себя рядом 2-3 мобов его хп начинают падать (се начинает лечить по скрипту ворона) лечит и агрит на себя 2 мобов. воин убивает 1 моба и бежит за другими мобами которые в радиусе (на этих которые возле него и долбят СЕ он 0 внимания)
т.е не всегда он ищет ближайшего к себе моба и атакует его.
Аналогично бывает при каче и одному т.е бьет 2-3 сразу мобов раздает им люлей не половину или почти что убивает мобов и сразуже выделяет другого не всегда скрпит что моб умер проверяется...судя по всему.. ну кидается он на других рядом мобов убивает их и иногда возвращается и добивает моба которого не добил.
ну и еще недочет один.. радиус запоминаем допустим 1500 он бегает долбит мобов в этом радиусе когда все убил он не всегда кидается на мобов которые появились в этом радиусе, видет только и атакует которые рядом с ним нарисовались.. пробовал активировать бежать в центр радиуса если мобов нет.. что-то не прокатило
Добавлено спустя 19 часов 6 минут 12 секунд:
Re: ДА БУДЕТ БОТ!
Новая версия бота. Проверяет координату Z. Подрихтовал миникарту.
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
{Бот для кача ТК 64+ лвл
Скрипт распространяется как есть, и я не несу ответственности
за то, что ВЫ натворили у себя, его используя.
Возможности скрипта:
- работает на С4 и Интерлюде;
- миникарта, усл. обозн.:
- зеленые в зоне Radius кача;
- белые вне DeltaZ;
- синие вне зоны Radius кача;
- розовые нас атакуют;
- красный мы атакуем;
- панель с инфой;
- сам бафается;
- сам юзает кубики;
- сам юзает алакрити;
- сам лечит себя хил пошинами и элементал хилом;
- проверка координаты Z для кача в катакомбах;}
//************************************************** *************
const
name='NLObP'; //имя чара для которого включен скрипт
//установить константу в зависимости от типа игры (С4 или Интерлюд)
IL=false; //true - IL, false - C4
max=100; //максимальное значение массива
Radius=1500; //радиус участка для поиска мобов
DZ=200; //глубина/высота до мобов
PercentHP=70; //при каком количестве хп в % юзать бутылку лечения
MEsit=55; //при каком количестве хп в % надо сесть и подкопить хп
MEup=90; //при каком количестве хп в % надо встать после отдыха
buff1=91; //бафф defense aura
buff2=77; //бафф attack aura
buff3=112; //бафф deflect arrow
buff4=230; //бафф sprint
buff5=123; //бафф spirit barrier
cubicstorm=10;
cubiclife=67;
elementalheal=58;
//************************************************** *************
var
frm : TForm; //панель информации
info, msg, stats : TMemo;
splitter1, splitter2 : Tsplitter;
map : Tform; //виртуальная карта
xm, ym : integer; //координаты на карте
offs1 : integer; //смещение для типа игры Ил или С4
StartTime: TDateTime; //ведем подсчет времени
EndTime: TDateTime;
death1, mob1 : integer; //подсчитываем смерти
underAttack : boolean; //нас атакуют
heal, kill : string;
MaxHP, MyZpos, CurHP, ObjID, ID, xpos, ypos, skill, MyID : integer;
but, sud, bst, attackIDMinID, attackID, zpos: integer;
cvaX, cvaY, cvaZ: integer; //координата центра кача
Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc, stop: Boolean;
attackk, bfi, atck, hpi, i, ii: integer; //индексы различных циклов
last : integer; //последняя запись в массиве, для ускорения скрипта
//массив мобов
MobsObjID: array[1..max] of integer;
MobsID: array[1..max] of integer;
MobsName: array[1..max] of string;
MobsRAS: array[1..max] of integer;
MobsX: array[1..max] of integer;
MobsY: array[1..max] of integer;
MobsZ: array[1..max] of integer;
NPCid: array[1..max] of integer;
Aggro: array[1..max] of Boolean;
TTShpC : Tshape; //центр кача на карте
TTShape: array [0..max] of Tshape; //объекты на карте
TTLabel: array [0..max] of Tlabel; //подписи к объектам
timer1: TTimer;
timer2: TTimer;
timer3: TTimer;
timer4: TTimer;
//************************************************** *************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
var
i: integer;
begin
if il then begin
//CharInfo
offs1:=48; //44 для С4, 48 для IL
end else begin
offs1:=44;
end;
StartTime:=time;
underattack:=false; //атакован?
stop:=true; //откл. атака
atck:=0; //кол-во неуспешных атак после которых пробуем сменить таргет, здесь инициализация =0
hpi:=0;
bfi:=60; //60 сек
ii:=1;
last:=1; //начальное значение
//ПАНЕЛЬКА
frm := TForm.Create(nil);
frm.Caption := 'BOT '+name;
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=600;
frm.Height:=800;
//информация
info:=TMemo.Create(frm);
info.parent:=frm;
info.align:=alLeft;
info.ReadOnly:=true;
info.ScrollBars:=0;
info.Width:=450;
info.Height:=370;
//статистика
stats:=TMemo.Create(frm);
stats.parent:=frm;
stats.align:=alClient;
stats.ReadOnly:=true;
stats.ScrollBars:=0;
stats.Width:=150;
stats.Height:=100;
//сообщения
msg:=TMemo.Create(frm);
msg.parent:=frm;
msg.align:=alBottom;
msg.ReadOnly:=true;
msg.ScrollBars:=2;
msg.Width:=600;
msg.Height:=100;
msg.Lines.Add('...');
//разделители
splitter1:=Tsplitter.Create(frm);
splitter1.parent:=frm;
splitter1.Top:=0;
splitter1.Width:=3;
splitter1.Left:=470;
splitter1.align:=alLeft;
//разделители
splitter2:=Tsplitter.Create(frm);
splitter2.parent:=frm;
splitter2.Left:=0;
splitter2.Height:=3;
splitter2.align:=alBottom;
frm.Show;
//карта
map := TForm.Create(nil);
map.Caption:='MiniMap: '+name;
map.BorderStyle:=bsSizeable;
map.Position:=poScreencenter;
map.Width:=300;
map.Height:=300;
map.FormStyle:=FsStayOnTop;
map.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!
//атака и прочее
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnAttack;
timer1.enabled:=false; //таймер по умолчанию выключен
timer1.interval:=1000; //через каждые 1сек будем обновлять
//вывод в форму
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnView;
timer2.enabled:=true; //таймер по умолчанию включен
timer2.interval:=1000; //через каждые 1сек будем обновлять
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnBuff; //
timer3.enabled:=false; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
//рисуем карту
timer4:=TTimer.Create(nil);
timer4.OnTimer:=@OnMap;
timer4.enabled:=true; //таймер по умолчанию включен
timer4.interval:=1000; //через каждые 1сек будем обновлять
for i:= 1 to max do begin
Aggro[i]:=false;
//готовим точки МОБов
TTShape[i]:=Tshape.create(nil); //для мобов
TTShape[i].parent:=map;
TTShape[i].Brush.Color:=clBlue; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
TTShape[i].shape:=stCircle;
TTShape[i].left:=-70; //координаты
TTShape[i].top:=-70;
TTShape[i].width:=7; //размеры
TTShape[i].height:=7;
//Готовим названия
TTlabel[i]:=Tlabel.create(nil);
TTlabel[i].parent:=map;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
TTlabel[i].font.size:=7;
TTlabel[i].font.color:=clBlue;
end;
//Готовим точку для центра кача
TTShpC:=Tshape.create(nil); //для моего чара
TTShpC.parent:=map;
TTShpC.shape:=stCircle;
TTShpC.Brush.Color:=clYellow;
TTShpC.left:=-70; //координаты
TTShpC.top:=-70;
TTShpC.width:=3; //размеры
TTShpC.height:=3;
//Готовим точку для ГГ
TTshape[0]:=Tshape.create(nil); //для моего чара
TTshape[0].parent:=map;
TTshape[0].shape:=stCircle;
TTshape[0].Brush.Color:=clBlack;
TTshape[0].left:=-70; //координаты
TTshape[0].top:=-70;
TTshape[0].width:=5; //размеры
TTshape[0].height:=5;
//готовим имя ГГ
TTlabel[0]:=Tlabel.create(nil); //для моего чара
TTlabel[0].parent:=map;
TTlabel[0].left:=TTShape[0].left+4; //координаты
TTlabel[0].top:=TTShape[0].top+4;
TTlabel[0].caption:=name;
TTlabel[0].font.size:=7;
TTlabel[0].font.color:=clBlack;
end;
//************************************************** *************
procedure GameToMap(x, y : integer);
//Пока ничего умнее не придумал =(
//преобразуем игровые координаты в координаты карты
var
masshtabx, masshtaby:integer;
begin
masshtabx:=radius*map.Width div 200;
masshtaby:=radius*map.Height div 200;
xm:=Round(((X-myXpos)*map.Width/masshtabx)+(map.Width/2));
//коэфф. 0.9 для попадания точки X,Y=0 в центр карты
ym:=Round(((Y-myYpos)*map.Height/masshtaby)+(map.Width/2)*0.9);
end;
//************************************************** *************
//RequestRestartPoint
procedure RequestRestartPoint;
begin
buf:=#$6D;
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
procedure ViewInfo;
var
i: integer;
begin
info.Lines.Clear;
stats.Lines.Clear;
stats.Lines.Add('Имя чара :'+Name);
stats.Lines.Add('Время старта :'+TimeToStr(starttime));
stats.Lines.Add('Время работы :'+TimeToStr(time-starttime));
stats.Lines.Add('Убили МОБов: '+IntToStr(mob1)+' шт.');
stats.Lines.Add('Погибли: '+IntToStr(death1)+' раз');
stats.Lines.Add('MaxHP :'+IntToStr(MaxHP));
stats.Lines.Add('CurHP :'+IntToStr(CurHP));
stats.Lines.Add('MyID :'+IntToStr(MyID));
stats.Lines.Add('MyXpos :'+IntToStr(MyXpos));
stats.Lines.Add('MyYpos :'+IntToStr(MyYpos));
stats.Lines.Add('MyZpos :'+IntToStr(MyZpos));
stats.Lines.Add('PercentHP :'+IntToStr(PercentHP)+' %хп');
stats.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
stats.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
stats.Lines.Add('Radius :'+IntToStr(RADIUS));
stats.Lines.Add('DeltaZ :'+IntToStr(DZ));
stats.Lines.Add('cvaX :'+IntToStr(cvaX));
stats.Lines.Add('cvaY :'+IntToStr(cvaY));
stats.Lines.Add('cvaZ :'+IntToStr(cvaZ));
stats.Lines.Add('but :'+IntToStr(but)+' бутылки');
stats.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
stats.Lines.Add('bst :'+IntToStr(bst)+' встать');
stats.Lines.Add('ObjID :'+IntToStr(ObjID)+' кто ходит');
stats.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
stats.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
stats.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
stats.Lines.Add('sit :'+VarToStr(sit));
stats.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
stats.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
stats.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
stats.Lines.Add('atck :'+IntToStr(atck)+' цикл выбора другой цели');
stats.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
stats.Lines.Add('SummaAR :'+IntToStr(Summ(MobsObjID))+' всего в бд');
stats.Lines.Add('rezu :'+IntToStr(DeltaXY(MyXpos, MyYpos, xpos, ypos))+' рез ближ');
stats.Lines.Add('MaxX :'+IntToStr(MaxX));
stats.Lines.Add('MaxID :'+IntToStr(MaxID));
stats.Lines.Add('MinX :'+IntToStr(MinX));
stats.Lines.Add('MinID :'+IntToStr(MinID));
stats.Lines.Add('povtor :'+VarToStr(povtor));
stats.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
stats.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
stats.Lines.Add('Hpotion: '+inttostr(Hpotion));
stats.Lines.Add('Apotion: '+inttostr(Apotion));
stats.Lines.Add('xm :'+IntToStr(xm));
stats.Lines.Add('ym :'+IntToStr(ym));
if (MyID<>0) then begin
info.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
info.Lines.Add('HP:'+IntToStr(CurHP)+' из '+IntToStr(MaxHP)+' Цикл1='+IntToStr(attackk)+' Цикл2='+IntToStr(atck)+' Цикл бафа='+IntToStr(bfi));
if (Hpotion=0) then info.Lines.Add('Юзать HP бутылки?: НЕТ!');
if (Hpotion<>0) then info.Lines.Add('Юзать HP бутылки?: ДА!');
if (Apotion=0) then info.Lines.Add('Юзать AP бутылки?: НЕТ!');
if (Apotion<>0) then info.Lines.Add('Юзать AP бутылки?: ДА!');
if (sit=false) then info.Lines.Add('Бот стоит!');
if (sit=true) then info.Lines.Add('Бот сидит!');
for i:= 1 to last do begin
if (MobsObjID[i]<>0) then begin
if (attackIDMinID<>i) then info.Lines.Add('--'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
if (attackIDMinID=i) then begin
info.Lines.Add('->'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
TTShape[i].Brush.Color:=clRed;
end;
end;
end;
end else info.Lines.Add('Для инициализации Бота используй или брось и подбери аптечку!');
end;
//************************************************** *************
procedure Free;
begin
DelALL;
end;
//************************************************** *************
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
end;
end;
if (MaxHP<>0) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*PercentHP); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
end;
end;
//************************************************** *************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$01;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyXpos); //откуда
WriteD(MyYpos);
WriteD(MyZpos);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(Name);
msg.Lines.Add('MoveTo('+inttostr(targetx)+','+intt ostr(targety)+','+inttostr(targetz)+')');
end;
//************************************************** *************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:exte nded):boolean;
begin
if DeltaXY(targetx, targety, MyXpos, MyYpos)<=distanciya
then result:=true else result:=false;
end;
//************************************************** *************
//возвращает растоянием между двумя точками
function DeltaXY(xpos1, ypos1, xpos2, ypos2:extended):integer;
begin
result:=Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;
//************************************************** *************
//возвращает растоянием между двумя координатами Z
function DeltaZ(Zpos1, Zpos2 : extended) : integer;
begin
result:=Round(abs(Zpos1-Zpos2));
end;
//************************************************** *************
procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsObjID[ele]:=0;
MobsID[ele]:=0;
MobsName[ele]:='';
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
Aggro[ele]:=false;
TTShape[ele].left:=-70; //координаты
TTShape[ele].top:=-70;
TTShape[ele].Brush.Color:=clBlue;
TTlabel[ele].left:=TTShape[ele].left+4; //координаты
TTlabel[ele].top:=TTShape[ele].top+4;
TTlabel[ele].caption:='';
TTlabel[ele].font.color:=clBlue;
end;
//************************************************** *************
procedure DelALL; //обнуляем всю базу!
var
i: integer;
begin
for i:= 1 to max do begin
NPCid[i]:=0;
MobsObjID[i]:=0;
MobsID[i]:=0;
MobsName[i]:='';
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
Aggro[i]:=false;
TTshape[i].free;
TTlabel[i].free;
end;
TTShpC.free;
TTShape[0].free;
TTLabel[0].free;
timer1.Free;
timer2.Free;
timer3.Free;
timer4.Free;
splitter1.free;
splitter2.free;
info.Free;
msg.Free;
frm.Free;
map.Free;
end;
//************************************************** *************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
var
minras, i: integer;
begin
MinX:=5000;
MinID:=0;
MaxX:=0;
MaxID:=0;
for i:= 1 to last do begin
//проверяем что расстояние до моба в радиусе кача и по высоте не глубоко
if (DeltaXY(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius) and (DeltaZ(Mobsz[i],cvaz)<=DZ) then begin
if (arra[i]<=MinX) and (arra[i]<>0) then begin
MinX:=arra[i];
MinID:=i;
end;
if (arra[i]>=MaxX) then begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;
end;
//************************************************** *************
function ETOpovtor(chislo: integer; arra:array of integer):boolean;
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
var
i: integer;
begin
Result:=false;
for i:= 1 to last do begin
if (arra[i]=chislo) then Result:=true;
end;
end;
//************************************************** *************
procedure attackt(mobus:integer);
begin
buf:=#$04; //action
WriteD(MobsObjID[mobus]);
WriteD(MyXpos);
WriteD(MyYpos);
WriteD(MyZpos);
WriteC(0);
SendToServerEx(Name);
end;
//************************************************** *************
function Summ(sum:array of integer):integer;
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
i: integer;
begin
Result:=0;
for i:= 1 to max do begin
if (sum[i]<>0) then inc(Result);
end;
end;
//************************************************** *************
procedure OnMap(Sender: TObject); //рисуем карту
begin
if (myxpos=0) and (myypos=0) then exit;
for i:= 1 to last do begin
if (MobsObjID[i]<>0) then begin
//красим мобов на карте
if stop=true then
if (DeltaXY(Mobsx[i],Mobsy[i],MyXpos,MyYpos)<=Radius)
then
if (DeltaZ(Mobsz[i],MyZPos)<=DZ)
then
TTShape[i].Brush.Color:=clGreen
else
TTShape[i].Brush.Color:=clWhite
else
if (DeltaZ(Mobsz[i],cvaz)<=DZ)
then
TTShape[i].Brush.Color:=clBlue
else
TTShape[i].Brush.Color:=clWhite;
if stop=false then
if (DeltaXY(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius)
then
if (DeltaZ(Mobsz[i],cvaz)<=DZ)
then
TTShape[i].Brush.Color:=clGreen
else
TTShape[i].Brush.Color:=clWhite
else
if (DeltaZ(Mobsz[i],cvaz)<=DZ)
then
TTShape[i].Brush.Color:=clBlue
else
TTShape[i].Brush.Color:=clWhite;
if Aggro[i]=true then begin
TTShape[i].Brush.Color:=clPurple;
TTlabel[i].font.color:=clPurple;
end;
//ставим точку МОБа
GameToMap(MobsX[i],MobsY[i]);
TTShape[i].left:=xm; //координаты моба
TTShape[i].top:=ym;
TTlabel[i].left:=TTShape[i].left+4; //координаты
TTlabel[i].top:=TTShape[i].top+4;
TTlabel[i].caption:=inttostr(i);
end;
end;
//ставим точку ГГ
GameToMap(MyXpos,MyYpos);
TTShape[0].left:=xm; //координаты чара
TTShape[0].top:=ym;
TTlabel[0].left:=TTShape[0].left+4; //координаты надписи
TTlabel[0].top:=TTShape[0].top+4;
TTlabel[0].caption:=name;
//ставим точку центра кача
GameToMap(cvaX,cvaY);
TTShpC.left:=xm; //координаты ГГ
TTShpC.top:=ym;
end;
//************************************************** *************
procedure OnAttack(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!
begin
if (MinID>0) then begin
if (sit=false) then begin
case attackk of
0: begin
attackID:=MobsObjID[MinID];
msg.Lines.Add('Атакую! '+IntToStr(attackID));
attackIDMinID:=MinID;
attackt(attackIDMinID); //target
end;
//делаем паузу
1: begin
attackt(attackIDMinID); //attack
end;
6: begin
attackt(attackIDMinID); //target
end;
//делаем паузу
7: begin
attackt(attackIDMinID); //attack
attackk:=1;
inc(atck);
end;
end;
//пробуем сместиться
case atck of
9: begin
MobsRAS[attackIDMinID]:=5000;
attackk:=-1;
atck:=0;
end;
end;
inc(attackk);
end;
end;
end;
//************************************************** *************
procedure OnView(Sender: TObject); //вывод данных в форму
begin
//контролируем бафы
dec(bfi);
if bfi<0 then begin
timer3.interval:=1000; //пытаемся начать бафы каждые 1 сек
bfi:=1200; //20 мин
end;
//выводим в форму
ViewInfo;
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('Мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
//идем в центр если нет мобов
// if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
//if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
// end;
if (MyID<>0) and (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Использую Elemental Heal!');
MagicSkillUse(elementalheal);
end;
if (CurHP<but) and (Hpotion<>0) then begin
if hpi=5 then begin
UseItem(Hpotion);
hpi:=0;
end else inc(hpi);
end;
if (CurHP<sud) and (Summ(Aggro)=0) and (sit=false) then begin
msg.Lines.Add('Всё, я отдыхаю!'+TimeToStr(time));
buf:=heal;
SendToServerEx(Name);
sit:=true;
end;
if (CurHP>bst) and (sit=true) then begin
msg.Lines.Add('Пора за работу!'+TimeToStr(time));
buf:=heal;
SendToServerEx(Name);
attackk:=0;
atck:=0;
sit:=false;
end;
end;
//************************************************** *************
procedure OnBuff(Sender: TObject); //баффы
begin
if (MyID<>0) and (Summ(Aggro)=0) and (sit=false) then begin
case ii of
1: begin
timer1.enabled:=false; //откл. атаку
msg.Lines.Add('Бафаюсь Defense aura!');
//бафф
MagicSkillUse(buff1);
inc(ii);
timer3.interval:=6000; //каждые 6 сек
end;
2: begin
msg.Lines.Add('Бафаюсь Attack aura!');
MagicSkillUse(buff2);
inc(ii);
end;
3: begin
msg.Lines.Add('Бафаюсь Deflect arrow!');
MagicSkillUse(buff3);
inc(ii);
end;
4: begin
msg.Lines.Add('Бафаюсь Sprint!');
MagicSkillUse(buff4);
inc(ii);
end;
5: begin
msg.Lines.Add('Бафаюсь Spirit barrier!');
MagicSkillUse(buff5);
inc(ii);
timer3.interval:=10000; //каждые 10 сек
end;
6: begin
msg.Lines.Add('Бафаюсь Storm cubic!');
MagicSkillUse(cubicstorm);
inc(ii);
end;
7: begin
msg.Lines.Add('Бафаюсь Life cubic!');
MagicSkillUse(cubiclife);
inc(ii);
end;
8: begin
if Apotion<>0 then begin
msg.Lines.Add('Пью Potion of Alacrite!');
UseItem(Apotion);
end;
inc(ii);
end;
9: begin
ii:=1;
timer3.interval:=1150000; //каждые 20 мин
bfi:=1150;
timer1.enabled:=true; //вкл. атаку
end;
end;
end;
end;
//************************************************** *************
procedure AddBD(objid, posx, posy, posz:integer;); //добавляем моба в базу данных
var
i: integer;
begin
for i:=1 to last do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(objid, MobsObjID)=false) then begin
MobsObjID[i]:=objid; //ид моба
if id<>0 then MobsID[i]:=id; //ид моба
MobsRAS[i]:=DeltaXY(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
break;
end;
end;
end;
//если нет свободного места ищем дальше
for i:=last+1 to max do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
if (ETOpovtor(objid, MobsObjID)=false) then begin
MobsObjID[i]:=objid; //ид моба
if id<>0 then MobsID[i]:=id; //ид моба
MobsRAS[i]:=DeltaXY(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
last:=i;
break;
end;
end;
end;
end;
//************************************************** *************
function ISnpc(id: integer;): boolean;
var
i: integer;
begin
result:=false;
for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;
//************************************************** *************
procedure UseItem(ItemObjID:integer);
begin
buf:=#$14;
WriteD(ItemObjID);
WriteD(00);
SendToServerEx(Name);
end;
//************************************************** *************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(S hiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
buf:=#$2F;
WriteD(MagicID);
WriteD(00);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
if (ConnectName=Name) and FromServer then begin
case pck[1] of
#$01: begin
msg.Lines.Add('S>C $01 Move');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
i:=2;
ObjID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
ID:=0; //кто-то рыпнулся с места надо это записать...
xpos:=ReadD(i);
ypos:=ReadD(i);
zpos:=ReadD(i);
if not ISnpc(ObjID) {and (DeltaXY(cvaX,cvaY,xpos,ypos)<=Radius)} then AddBD(ObjID,xpos,ypos,zpos);
end;
end;
#$03: begin
msg.Lines.Add('S>C $03 Char');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(18),NPCid)=false) then begin
NPCid[i]:=ReadD(18);
msg.Lines.Add('ДОБАВЛЕН ИГРОК:'+ReadS(22)+'-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
#$04: begin
msg.Lines.Add('S>C $04 CharInfo');
//пакет с инфой о моём чаре
i:=2;
MyXpos:=ReadD(i); //получаю координату х моего чара
MyYpos:=ReadD(i); //получаю координату у моего чара
MyZpos:=ReadD(i); //получаю координату z моего чара
//Запоминаем ИД
i:=18;
MyID:=ReadD(i); //получаю ид моего чара
//смещение переменное, зависит от имени (LenName*2+2)
i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
//лупить всех без разбора, в пределах радиуса
{if (gdo=false) then begin //задаем центр окружности кача
cvaX:=MyXpos;
cvaY:=MyYpos;
gdo:=true;
end;}
for i:=1 to last do begin //перебираем базу и ищем себя
if (ETOpovtor(MyID, MobsObjID)=true) then begin
DelElArr(i);
msg.Lines.Add('Удаляем себя из базы МОБов!!!');
if isnpc(myID)=false then begin
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=MyID;
break;
end;
end;
end;
end;
end;
end;
//MagicSkillUse 48, Attack 05
#$05: begin
msg.Lines.Add('S>C $05 Attack');
if (ReadD(6)=MyID) then begin
//меня ударили
sit:=false;
{if myxpos<>0 then begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
end;}
if (ETOpovtor(ReadD(2),MobsObjID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin //если моб записан в базе данных
msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(MobsObjID[i]));
Aggro[i]:=true; // стал агрессор
if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
attackIDMinID:=i;
//вкл. атаку
timer1.enabled:=true;
stop:=false; //вкл. атака
end;
if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
break;
end;
end;
end;
end;
//принят пакет Die
#$06: begin
msg.Lines.Add('S>C $06 Die');
//нас убили
if (myID=ReadD(2)) then begin
//остановить атаку
timer1.enabled:=false;
msg.Lines.Add('Нас убили в '+TimeToStr(time));
inc(death1);
RequestRestartPoint; //оживаем после смерти
//мы в городе, снимаем атрибут атаки на нас
for i:= 1 to max do begin
Aggro[i]:=false;
TTShape[i].Brush.Color:=clBlue;
TTlabel[i].font.color:=clBlue;
end;
end else begin
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin
msg.Lines.Add('Убили очередного МОБа в '+TimeToStr(time));
inc(mob1);
DelElArr(i);
attackk:=0;
atck:=0;
if (i=last) and (last<>1) then dec(last);
//timer1.enabled:=true;
break;
end;
end;
end;
end;
#$0C: begin
msg.Lines.Add('S>C $0C DropItem');
if (MyXpos<>0) then begin
if (DeltaXY(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
msg.Lines.Add('Выпала вещь!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
WriteC(0);
SendToServerEx(Name);
msg.Lines.Add(' Пробую поднять!!!');
delay(1000);
timer1.enabled:=true;
end;
end;
end;
#$0E: begin
msg.Lines.Add('S>C $0E StatsUpdate');
if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
end;
//принят пакет DeleteObject
#$12: begin
msg.Lines.Add('S>C $12 DeleteObject');
//выкидываем из базы
for i:=1 to last do begin
if (MobsObjID[i]=ReadD(2)) then begin
DelElArr(i);
msg.Lines.Add('Удаляю из базы:'+IntToStr(i));
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
#$16: begin
msg.Lines.Add('S>C $16 NPC');
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
msg.Lines.Add('Вижу NPC!');
if (ReadD(10)=0) then begin //если нельзя атаковать
for i:=last to max do begin
if (NPCid[i]=0) then begin
if (ETOpovtor(ReadD(2), NPCid)=false) then begin
NPCid[i]:=ReadD(2);
msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
break;
end;
end;
end;
end;
if (ReadD(10)=1) and (pck[120]=#$00) then begin //если можно атаковать
id:=ReadD(6);
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
end;
end;
end;
//InventoryUpdate
#$27: begin
msg.Lines.Add('S>C $27 InventoryUpdate');
if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
Hpotion:=ReadD(8);
msg.Lines.Add('ID бутылок H.Potion:'+inttostr(Hpotion));
end;
if ReadD(12)=735 then begin //Potion of Alacrity
Apotion:=ReadD(8);
msg.Lines.Add('ID бутылок A.Potion:'+inttostr(Apotion));
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=Name) and FromClient then begin
case pck[1] of
#$1B: begin
msg.Lines.Add('C>S $1B Yes');
case ReadD(2) of
//социальное действие Yes для начала
$06: begin
//не передаем серверу
pck:='';
msg.Lines.Add('C>S $1B Yes');
//устанавливаем центр кача
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
//переменные циклов сбрасываем
attackk:=0;
atck:=0;
msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты центра ОБНОВЛЕНЫ!!');
//вкл. атаку
timer1.enabled:=true;
//вкл. бафы
timer3.enabled:=true;
stop:=false; //вкл. атака
end;
//социальное действие No для окончания
$05: begin
//не передаем серверу
pck:='';
msg.Lines.Add('C>S $1B No');
//откл. атаку
timer1.enabled:=false;
//откл. бафы
timer3.enabled:=false;
stop:=true; //откл. атака
msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
end;
//социальное действие Sorrow - удаляем текущую запись в базе
$0D: begin
//не передаем серверу
pck:='';
msg.Lines.Add('C>S $1B Sorrow');
ObjID:=MobsObjID[attackIDMinID];
DelElArr(attackIDMinID);
attackk:=0;
atck:=0;
msg.Lines.Add('Удаляем текущую запись в базе!!!');
for i:= last to max do begin
if (NPCid[i]=0) then begin
NPCid[i]:=ObjID;
msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
//ValidatePosition пакет от клиента с моими кординатами
#$48: begin
msg.Lines.Add('C>S $48 ValidatePosition');
//обновляем ВСЕ растояния в BD если мы сошли с места
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
//пересчитываем расстояние до мобов
for i:=1 to last do begin
if MobsObjID[i]<>0 then begin
//до атакующих нас мобов всегда расстояние 1
MobsRAS[i]:=DeltaXY(MyXpos,MyYpos,MobsX[i],MobsY[i]);
end;
end;
end;
end;
end;
end.
еще 1 недочет...
если ID мобов доходит до 90+ то вылетает ошибка как я понял связанная с этим
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('Мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
при отключение этого.. доходит до 100 и начинает не видеть рядом стоящих мобов вплоть до тех которые его бьют, тестил в катакомбах!
Добавлено спустя 1 день 9 часов 1 минуту 39 секунд:
Re:
Ну все, Господа... Выкладываю свой собственный ботоскрипт- локомотив :D
Прошу высказывать свои замечания и предложения.
{################################################# ############################
Бот от Alexus
версия : 0.1 (бета)
дата: 12.03.08
Скрипт основан на всем том что я вычитал на этом форуме и моем опыте программирования.
Некоторые интересные идеи взяты из волкера.
Скрипт распространяется как есть. Используем его на свой страх и риск.
Любые изменения и дополнения только приветствуются!!!
Бот для кача в принципе любого война, но тестился на гноме.
Бот оптимизирован для кача в катах, лучше в квадратных комнатах (равносторонний четырехугольник).
Охотиться только на заданных мобов, а то излишняя самостоятельность бота немного пугает.
Пока что бот умеет следующее:
- запоминать центр и радиус кача
- запоминать список мобов на которых надо охотиться!
- управляется из окна чата в самом клиенте
- имеет окно для вывода всех параметров и статистики
- работает пока только под С4
Инструкция:
1. Запускаем игру, запускаем скрипт, добираемся до места кача
2. Пьем HP пробирку (надежный способ добывания своего ID-номера).
3. Выбираем в таргет моба на которого хотим охотится и пишем в общий чат-> 1
4. Валим моба. Если все правильно сделали будет выдано сообщение в чате что моб добавлен.
5. Выбираем следующего моба пишем цифру 2, валим его и т.д. можно выбрать до 10 разных тварей.
6. Становимся в центр комнаты и пишем в чат-> pos , если все правильно то в чате будет выдано сообщение.
7. Бежим к выходу из комнаты, и пишем-> dist, в чате вылезет сообщение от системы
8. Валим всех мобов в комнате, становимся примерно в центр и пишем-> start , если все сделано верно,
то будет выдано соответствующее сообщение.
9. если бот поймал моба в таргет и побежал его атаковать, то можно свернуть окно игры
и смотреть на информационное окно скрипта.
################################################## ###########################}
const
NickName = 'abc'; // Твой ник в игре
maximumItems = 100; // Размер базы мобов
MobsListRazmer = 10; // Размер списка мобов (не трогать!)
Vertical = 1000; // Вертикальный радиус кача
// HPMedium = 70; // Пока не используется
OX = 1; OY = 2; OZ= 3; // Служебные константы
var
InitMode : boolean;
//-------------------------------------- БД мобов ------
MobsID : array [1..maximumItems] of integer;
MobsDist : array [1..maximumItems] of integer; // Расстояние от центра кача
MobsXYZ : array [1..maximumItems, 1..3] of integer; // Координаты
MobsAgression : array [1..maximumItems] of boolean; // Моб атакует меня или стоит в сторонке...
LastItem: integer; // индекс последнего элемента базы
MobsList : array [1..MobsListRazmer] of integer; // Список мобов (коды мобов)
MobsListCount : integer; // Текущий размер списка
TargetID: integer; // Текущая цель
Povtor: integer;
CenterX, CenterY, CenterZ : integer; // Центр кача
Radius: integer; // Радиус кача
//--------------------------------------------------------
MyX, MyY, MyZ : integer; // Мои статы
MyID, MyHP, MyMaxHP: integer;
MyMP, MyMaxMP, MyCP, MyMaxCP: integer;
//--------------------------------------------------------
frm: TForm; // переменные описания формы
log, mainscreen: TMemo;
panel: TPanel;
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, textLastItem: TEdit;
//----------------------------------------------------------
TimerForm, TimerCombat: TTimer;
AttackCycle: integer; // Цикл атаки
procedure ClearDB; // Очистка БД
var // Надо все занулять, иначе там хрень всякая вылезает или старые данные
i: word;
begin
LastItem:= 0; // Очищаем переменные
TargetID:= 0;
Povtor:= 0;
CenterX:= 0;
CenterY:= 0;
CenterZ:= 0;
Radius:= 0;
AttackCycle:= 0;
for i:=1 to MobsListRazmer do MobsList[i]:= 0;
MobsListCount:= 0;
for i:=1 to maximumItems do // Очищаем базу
begin
MobsID[i]:= 0;
MobsDist[i]:= 0;
MobsXYZ[i, OX]:= 0;
MobsXYZ[i, OY]:= 0;
MobsXYZ[i, OZ]:= 0;
MobsAgression[i]:= false;
end;
end;
function SearchFreeItemDB : integer; // Функция ищет первый свободный елемент в БД
var
i:integer;
begin
result:=0;
for i:=1 to maximumItems do if MobsID[i] = 0 then
begin
result:=i;
break;
end;
if result = 0 then result:=maximumItems; // Если БД переполнена, то возвращаем индекс последнего элемента
if result > LastItem then LastItem := result; // если надо, увеличиваем текущий размер БД
end;
function rastoyanie(NpcX, NpcY, NpcZ : integer) : integer; // вычисление растояния между 2 точками
var
dx,dy,dz, summa : integer;
begin
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 + 5000; // добавляем коррекцию по вертикали
end;
procedure AddtoDB (id, x,y,z : integer; agression : boolean); // Процедура добавляет в БД нового моба
var
i:integer;
dist: integer;
begin
dist:= rastoyanie (x,y,z); // вычиляем расстояние от центра кача до моба
if dist > (Radius + 1000) then exit; // если моб слишко далеко то ничего не делаем
i:= SearchFreeItemDB; // ищем свободный эл. БД
log.Lines.Add('Моб добавлен, индекс в БД: '+ inttostr(i));
if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsID[i]:= id; // Записываем моба
MobsDist[i]:= dist;
MobsXYZ[i, OX]:= x;
MobsXYZ[i, OY]:= y;
MobsXYZ[i, OZ]:= z;
MobsAgression[i]:= agression;
end;
procedure UpdateDB (i:integer; id, x,y,z : integer; agression : boolean); // Процедура обновляет данные в БД по мобу
var
dist: integer;
begin
if (MOBSXYZ[i, OX] = x) and (MOBSXYZ[i, OY] = y) and (MobsAgression[i] = agression) then exit; // проверяем, а надо ли чего нить менят
dist:= rastoyanie (x,y,z);
if dist > (Radius + 1000) 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;
MobsAgression[i]:= agression;
end;
end;
procedure DelDBItem (i: integer); // процедура удалаяет моба из БД
begin
log.Lines.Add('Моб удален, индекс в БД: '+ inttostr(i));
MobsID[i]:= 0;
MobsDist[i]:= 0;
MobsXYZ[i, OX]:= 0;
MobsXYZ[i, OY]:= 0;
MobsXYZ[i, OZ]:= 0;
MobsAgression[i]:= false;
if i = LastItem then LastItem := LastItem -1; // если надо, уменьшаем размер БД
end;
function TestPovtor (id: integer) : integer; // функция проверяет наличие заданного моба в БД
var
i: integer;
begin
result:=0;
for i:=1 to LastItem do if MobsID[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 MobsListCount do if MobsList[i] = NpcTypeID then result:= true; // проверяем по списку
end;
procedure SendMsg(msg:string); // отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(NickName);
end;
function ValidateData : boolean; // функция проверки правильности задания всех параметров для начала кача
procedure ValidateMobsList; // подпроцедурка, перепроверяющая список мобов, и подсчитывающая количество записей в нем
var // этот алгоритм мне не нравится, буду переделывать
i: integer;
begin
for i:=1 to MobsListRazmer do if MobsList[i] = 0 then break;
i:= i - 1;
MobsListCount := i;
log.Lines.Add('MobsListCount = '+ inttostr(MobsListCount));
end;
begin
ValidateMobsList;
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 (MobsListCount > 0) then
begin
SendMsg('Все начальные параметры заданы и проверены!');
log.Lines.Add('Все начальные параметры заданы и проверены!');
result:= true;
end
else
begin
SendMsg('Ошибка задания начальных параметров!');
log.Lines.Add('Ошибка задания начальных параметров!');
result:= false;
end;
end;
procedure UserCommandsInitMode; // комманды пользователя для режима настройки бота
begin // если комманда обработана удачно, то в чат сообщение не попадет, а будет выдано системное сообщение прямо в клиент
case (ReadS(2)) of
'pos' : if MyX <> 0 then // центр кача
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
SendMsg('Центр кача задан успешно!');
log.Lines.Add('Центр кача задан успешно!');
pck:='';
end;
'dist' : if (CenterX <> 0) and (MyX <> 0) then // радиус кача
begin
Radius:= rastoyanie (MyX,MyY,MyZ);
SendMsg('Радиус кача задан успешно');
SendMsg('R= '+ inttostr(Radius));
log.Lines.Add('Радиус кача задан успешно, R = '+ inttostr(Radius));
pck:='';
end;
'reset': begin // сброс параметров
ClearDB;
SendMsg('БД очищена, введите заново все параметры');
log.Lines.Add('БД очищена!');
pck:='';
end;
'1', '2', '3', '4', '5', '6', '7', '8', '9', '10' : // задаем мобов
begin
MobsListCount:= strtoint(ReadS(2));
SendMsg('Добавляем моба № '+ ReadS(2));
pck:='';
end;
'start': begin // собственно запуск бота
if ValidateData and InitMode then
begin
SendMsg('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
log.Lines.Add('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
TargetID:=0;
InitMode:= false;
TimerCombat.enabled:=true; // запускаем таймер
end
else
begin
SendMsg('Еще не все параметры заданы. Проверьте параметры...');
log.Lines.Add('Еще не все параметры заданы. Проверьте параметры...');
end;
pck:='';
end;
end;
end;
procedure UserCommandsCombatMode; // комманды пользователя для боевого режима
begin // команды говорят сами за себя)
case (ReadS(2)) of
'pause' : begin
TimerCombat.enabled:= not(TimerCombat.enabled);
pck:='';
if TimerCombat.enabled then
begin
SendMsg('Искуственный интелект запущен!');
log.Lines.Add('Искуственный интелект запущен!');
end
else
begin
SendMsg('Искуственный интелект приостановлен.');
log.Lines.Add('Искуственный интелект приостановлен.');
end
end;
'stop' : begin
pck:='';
TimerCombat.enabled:= false;
InitMode:= true;
SendMsg('Искуственный интелект остановлен.');
log.Lines.Add('Искуственный интелект остановлен.');
end;
end;
end;
function GetMinDistID : integer; // функция поиска ближайшего моба в БД
var
i, dist : integer;
begin
dist:=10000; // задаем заранее нереальную дистанцию
for i:=1 to LastItem do if (MobsID[i] <> 0) and (MobsDist[i] < dist) then
begin // фишка в том, что в базе хранятся расстояния не до меня, а до центра кача
dist:= MobsDist[i]; // но в катах то расстояния небольшие
result:= i; // если нашли хоть одного моба или несколько возращаем его индекс ближайшего к центру кача
end;
if dist = 10000 then result:= dist; // иначе возвращаем 10000
end;
function AgroTest : integer; // функция проверяет, атакует ли меня кто-нибудь или нет
var
i: integer;
begin
result:=0;
for i:=1 to LastItem do if MobsAgression[i] then // ищем первого попавшегося моба, который нас атакует
begin
result:= i; // возвращаем его индекс по БД
break;
end;
end;
procedure PhisicalAttack; // команда атаки
begin
buf:=#$04; //action
WriteD(TargetID);
WriteD(MyX);
WriteD(MyY);
WriteD(MyZ);
WriteC(0);
SendToServerEx(NickName);
end;
procedure OnTimerCombat (Sender: TObject); // боевой таймер, вся логика поведения бота находится именно здесь!!!
var
Agro, MinDistID: integer;
begin
if LastItem > 0 then // если есть мобы в базе то:
begin
if TargetID = 0 then // если нет текущей цели, то
begin
Agro:= AgroTest; // запускаем алгоритм выбора цели
MinDistID:= GetMinDistID;
if Agro > 0 then // если нас кто-то атакует, то его и выбираем
begin
TargetID:= MobsID[Agro];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0;
end
else if MinDistID <= Radius then // иначе ищем ближайшего
begin
TargetID:= MobsID[MinDistID];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0;
end;
end;
if TargetID > 0 then
begin
case AttackCycle of // валим вражину
1, 5, 6 : PhisicalAttack;
10 : ;
end;
inc(AttackCycle)
end;
end;
if LastItem = 0 then ; // если нет мобов в базе, то по идее надо вернуться в центр кача, пока не разобрался с алгоритмом
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);
textLastItem.text:= inttostr(LastItem);
mainscreen.lines.Clear;
for i:=1 to LastItem do if MobsID[i] > 0 then // выводим БД мобов
begin // алгоритм пока не доделан
mainscreen.lines.add ('-- '+inttostr(i)+' МобID: '+inttostr(MobsID[i])+' дистанция '+inttostr(MobsDist[i]));
end;
end;
procedure CreateLabel (text: string); // процедура автоматизирует создание текстовых меток в форме
var
l: TLabel;
begin
l:= TLabel.Create(panel);
l.caption:=text;
l.parent:=panel;
l.left:=5;
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:=60;
e.top:=10+20*frmParamIndex;
result:= e;
end;
procedure Init; //Вызывается при включении скрипта
begin
ClearDB;
MyID:= 0; // обнуляем ВСЕ данные
MyX:= 0;
MyY:= 0;
MyZ:= 0;
MyID:= 0;
MyHP:= 0;
MyMaxHP:= 0;
MyMP:= 0;
MyMaxMP:= 0;
MyCP:= 0;
MyMaxCP:= 0;
InitMode:= true;
TimerCombat:=TTimer.Create(nil); // создаем таймеры
TimerCombat.OnTimer:=@OnTimerCombat;
TimerCombat.enabled:=false;
TimerCombat.interval:=1000;
TimerForm:=TTimer.Create(nil);
TimerForm.OnTimer:=@OnTimerForm;
TimerForm.enabled:=true;
TimerForm.interval:=1000;
frmParamIndex:=0; // создаем контролы в форме
frm:= TForm.Create(nil);
frm.Caption:= 'BOT info';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=650;
frm.Height:=700;
mainscreen:=TMemo.Create(frm);
mainscreen.parent:=frm;
mainscreen.align:=alLeft;
mainscreen.ReadOnly:=true;
mainscreen.ScrollBars:=2;
mainscreen.Width:=470;
mainscreen.Height:=370;
mainscreen.Lines.Add('Инициализация');
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:=0;
log.Width:=570;
log.Height:=100;
log.Lines.Add('...');
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('Цикл атаки:');
textLastItem:= CreateTextBox('LastItem');
CreateLabel('Элем. БД:');
frm.Show; // выводим форму на экран
end;
procedure Free; //Вызывается при выключении скрипта
begin
mainscreen.free;
log.free;
frm.free;
ClearDB;
TimerForm.free;
TimerCombat.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+44;
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;
end;
begin
if pck = '' then exit;
if (ConnectName = NickName) and FromServer and (not InitMode) then // разбор пакетов от сервера в Боевом режиме
case pck[1] of
#$01: begin // MoveToLocation:h(ObjectID)d(CurX)d(CurY)d(CurZ)d(D estX)d(DestY)d(DestZ)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
updateDB(Povtor, ReadD(2), ReadD(18), ReadD(22), ReadD(26), false);
end;
end;
#$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(Wal kSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed )d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(Move mentSpeedMultiplier)f(AttackSpeedMultiplier)f(Coll isionRadius)f(CollisionHeight)d(HairStyle)d(HairCo lor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCr estId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sittin g)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(M ountType)b(PrivateStoreType)
#$04: if ReadS(22) = NickName then UserInfo; // 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(F eet)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(Ha ir)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accurac y)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef) d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRun Speed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d (FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultipl ier)f(AttackSpeedMultiplier)f(CollisionRadius)f(Co llisionHeight)d(HairStyle)d(HairColor)d(Face)d(Acc essLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d (AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateS toreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cub ics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b ()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLef t)b()b(RecomHave)b()
#$05{, #$48}: begin // 05= Attack:d(AttackerID)d(TargetID)d(Damage)b(Flags)d( X)d(Y)d(Z)h(Hits)
if ReadD(6) = MyID then
begin
Povtor:= TestPovtor(ReadD(2));// 48= MagicSkillUse
if Povtor = 0 then AddtoDB (ReadD(2), ReadD(15), ReadD(19), ReadD(23), true)
else UpdateDB(Povtor, ReadD(2), ReadD(15), ReadD(19), ReadD(23), true);
end;
end;
#$06: begin // Die:d(ChaID)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
if MobsID[povtor] = TargetID then
begin
TargetID:= 0;
// статистика тут должна считаться
// и споил надо делать
end;
DelDBItem(povtor);
end;
end;
#$0C: ; // DropItem:h(PlayerID)h(ObjectID)i(ItemID)d(X)d(Y)d( Z)d(Stackable)d(Count)
#$0E: if MyID=ReadD(2) then StatusUpdate; // StatusUpdate:h(ObjectID)d(Attributes)
{ #$12: begin // DeleteObject:h(ObjectID)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
DelDBItem(povtor);
end;
end;}
#$16: begin // 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(FlRu nSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(Proper Multiplier)f(PAtkSpd)f(CollisionRadius)f(Collision Height)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRun ning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Nam e)s(Title)
if InMobsList(ReadD(6)) and (ReadD(10)=1) and (pck[121]=#$00) then
begin
Povtor:= TestPovtor(ReadD(2));
if Povtor = 0 then AddtoDB (ReadD(2), ReadD(14), ReadD(18), ReadD(22), false)
else UpdateDB(Povtor, ReadD(2), ReadD(14), ReadD(18), ReadD(22), false);
end;
end;
end;
if (ConnectName = NickName) and FromClient and (not InitMode) then // разбор пакетов от клиента в боевом режиме
case pck[1] of
#$04: {TargetID:= ReadD(2)}; // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b( ActionID)
#$38: UserCommandsCombatMode; // Say2:s(Text)d(Type)s(Target)
#$48: begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD(2);
MyY:= ReadD(6);
MyZ:= ReadD(10);
end;
end;
if (ConnectName = NickName) and FromServer and InitMode then // разбор клиентов от сервера в режиме настройки бота
case pck[1] of
#$04: if ReadS(22) = NickName then UserInfo; // 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(F eet)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(Ha ir)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accurac y)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef) d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRun Speed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d (FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultipl ier)f(AttackSpeedMultiplier)f(CollisionRadius)f(Co llisionHeight)d(HairStyle)d(HairColor)d(Face)d(Acc essLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d (AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateS toreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cub ics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b ()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLef t)b()b(RecomHave)b()
#$06: if (ReadD(2) = TargetID) and (MobsListCount <> 0) then // Die:d(ChaID)
if (MobsList[MobsListCount] <> 0) then
begin
SendMsg('Моб №' + inttostr(MobsListCount) + ' добавлен в базу');
log.Lines.Add('Моб №' + inttostr(MobsListCount) + ' добавлен в базу');
MobsListCount:= 0;
TargetID:= 0;
end;
#$16: if (ReadD(2) = TargetID) and (MobsListCount <> 0) then MobsList[MobsListCount]:= ReadD(6);//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(FlRu nSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(Proper Multiplier)f(PAtkSpd)f(CollisionRadius)f(Collision Height)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRun ning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Nam e)s(Title)
end;
if (ConnectName = NickName) and FromClient and InitMode then // разбор пакетов от клиента в режиме настройки бота
case pck[1] of
#$04: TargetID:= ReadD(2); // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b( ActionID)
#$38: UserCommandsInitMode; // Say2:s(Text)d(Type)s(Target)
#$48: begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD(2);
MyY:= ReadD(6);
MyZ:= ReadD(10);
end;
end;
end.
Главный косяк в том что...
1. если тебя застанили то снова мы не атакуем моба..
2. если словили всеже моба за радиусом аггро то тоже не отвечаем ему.. хотя в лог пишет что НАС АТАКУЮТ, в ответ сдачи только не даем...
тестировал на интерлюде работает и забивает мобов в базу отлично...
еше минусы
- что не поднимает дроп :)
- не пьет бутылочки :)
хотя все это можно взять с других скриптов или совместить другие с этим.
ДРУЗЬЯ, частично перечитал топ.. и с ужасом обнаружил что нет нормальной реализации глотания банок ХП, ГХП, ГЦП... тот вариант что предложил МКС предполагает предварительную подготовку скрипта.. т.е. после запуска скрипта следуют самому ручками глотнуть банки в нужной последовательности..
спешу исправить етот пробел в наших знаниях.. хотя тут дело не в знаниях а просто лень было делать многим.. но!.. спешу представиить вышеупомянутый скрипт в более продвинутой модификации.. теперь если у вас даже и нет вовсе ПП ШЕ ЕЕ или БИША то и вы совсем один то всё равно скрипт вам будет полезен ибо он нетребует никаких настроек и будет пить банки ХП ГЦП ГХП при условии что они есть в инвенторе у вас.. скрипт также настроен на то что ети зелья будут пить ваши баферы- (если они у них есть..).. плиз неспрашивайте меня почему не работают елексиры- я пока не разбирался.. в сыром виде их реализовал но они не пашут.. незнаю почему но они никак не влеяют на работоспособность скрипта.. для подготовки скрипта к работе требуется лиш имена поменять на реальные.. в 4-х строчках (188-192), после етого скрипт щитается полностью рабочим и готовым к использованию.. но если вам хочется изменить уровни ХП и МП при которых срабатывает ХИЛ и ЗАЛИВКА МП и ХП то там просто значения исправте.. ну я думаю понятно что в конце скрипта написан код- какие бафы на ково класть там весде вбито АСИСТ ТАРГЕТ. т.е. если вас кто то просит: "БАФНИ ПЛЗ" то просто береш его в таргет и жмеш NO или UNWARE от кнопки будет зависеть буф мага или физика.. нужные бафы перечисляются в конце скрипта кому и что бафать.. вопщем.. отличие етого скрипта от того что я раньше дал в том что командир и баферы глотают банки ГЦП,ХП,ГХП сами- автоматом.. при етом ненужно никаких подготовок скрипта.. ето реализуется очень просто.. 1 умный человек в етом топе сказал что пакет ЮЗЕР ИНФО можно вызвать если отправиить запрос на открытие инвенторя.. я проверил- ето правда.. когда скрипт начинает свою работу на все аки отсылается запрос на открытие инвенторя (автоматически).. из попутного пакета ЮЗЕР ИНФО скрипт сам узнает ИДешники всех.. а из инвенторя скрипт сам ищет БАНКИ с ХП,ГХП и ГЦП.. запоминает их OID и потом когда надо использует..
ты прав :) влом это делать кстате поставь между банками цп 100 и поймай стан. хотя не проверял после разделения моего скрипта на 2 разных врод всё работает а что надо пить банки цп и хп что б запустить скрипт это не главная проблема у МСК в пати скрипт не работает т.е. если в пати у кого то начинает падать цп или хп вы начинаете жрать банки. если кто попросит выложу свои скрипты их 2. не довожу их до ума и не выкладываю только из-за лени вообще в лом ща всё весна что б её.
ДРУЗЬЯ, давайте подумаем как соло рейдов килить.. ну не соло а фулпати на скрипте, без клиентов.. думаю под ету задучу будет отдельный топ отведен.. но вапще хочется же??..
DashKAaa
22.03.2008, 06:46
2 destra pod bd/sws/пофом от се или пп, валят рб 50-60 в лет далее аналогично до 70думаю только подольше
на интерлюде... в с4 все не так .. ибо маги решают
можноли взять в таргет моба но только чтобы он не аттакавал типо как командой "/target и имя моба" ?
buf:=hstr('04') + ObjectID + MyCoordX + MyCoordY + MyCoordZ + hstr('00');
ну я же не знаю ObjectID !!
лови все пакеты NPCINFo и выдирай из них ОбджектИД.
а если моб стоит наместе то пакет NPCINFo не придет же!
Обязательно придет! этот пакет всегда посылается при респауне или появлении в зоне видимости, а так же и просто так, с неопределенной переодичностью. иначи как клиент узнает что моб стоит? :)
Добавлено спустя 2 минуты 27 секунд:
посмотри еще эту тему
viewtopic.php?f=9&t=147 (http://forum.coderx.ru/viewtopic.php?f=9&t=147)
мне нужн опроизвести атаку на моба толкьо с определенным названием как сделать ведь в пакете это не пишиться!
моба толкьо с определенным названием
имя моба = mobID = NPCID, по нему и исчи.
парни помогите срочно!!! можноли взять в таргет моба но только чтобы он не аттакавал типо как командой "/target и имя моба" ?
мышкой по мобу жать пробуй.. а в топ спрашивай вопросы по существу что именно не выходит..
Добавлено спустя 8 минут 7 секунд:
каждый новый очередной-тупой-неграмотнопоставленый вопрос расширяет топ на 3 листа.. сейчас вот люди тока разобрались( спомощью многочисленных вопросов и подсказок тебе) что оказывается тебе нужно объяснить механизм как получает клиент информацию об местоположении мобов.. ну сматри допустим ты в дионе.. твой клиент при етом незнает об местоположении мобов в ЕГ например.. потомучто ето довольно далеко.. еслиб твой клиент занал обо всех мобах на серваке инфу то надо очень мощьный сервер.. когда ты бежиш из ДИОНА в ЕГ.. то мобы которые встретятся у тебя на пути- будут сопровождаться пакетом (НПЦ-ИНФО).. а точнее наоборот.. когда приходят твоему клиенту пакеты НПЦ ИНФО то они у тебя на екране показываются.. и пользуясь етой информацией можно их ИД запомнить (этим пакетом)..
Ворон есть проблемка в твоем скрипте на всех баферов :(
Суть в чем использовал допустим ше скил залив маны и скрипт соответственно поймал его с его ИД и приказал включить бег так вот на окне командира он вроде как бежит за ним а на самом деле он остается стоять хз почему и так можно сказать теряется и когда ему очередной раз приходится заливать или еще чего то он из окна командира просто исчезает (как телепорт ) и появляется там где остался. Это раз.
ну и хилки не пьются, но этот кусок кода я еще не проверял так что может там что то с ИД банок не так. Использую на Ц 4 и подкоректил смещение при отлове хп и мп с 48 на 44, лечит льет нормально бегает с трудом, банки не пьет на счет ЦП не знаю не пробовал. Хочу попробовать еще прикрутить автобаф каждые 20 мин и как то совместить со скриптом ботом на кач переделав его под мага, правда там стока всего что мне даже страшно что то трогать ( я про ТК 64)
И вопрос по ТК 64 походу там дроп не собираеться или очень плохо собирается (
Добавлено спустя 31 минуту 26 секунд:
Откуда такая формула и как ее понять?
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
DashKAaa
27.03.2008, 18:48
Бегает,лечит,заливает, пьет цп,хп на ура, правда задержечка есть при цп...
скорей всего у тебя просто сервак левый особенно с таргетами и пропаданием суппорта за спиной)
Nlopd к тебе вопрос можно переделать скрипт на кач ТК под кач мага, а то я что то пробовал но так тупо віходит ппц, и еще біло бі неплохо чтобі совместить его с использованием скрипта от ворона там где ше пп ее и биш ну и сам соответственно пьет всякие лекарства
My name='NLObP"
Для мага - сложность в дистанционной атаке, очень большая сложность... для меня по крайней мере.
My name='NLObP"
Для мага - сложность в дистанционной атаке, очень большая сложность... для меня по крайней мере.
очень неплохо такая атака реализована в этом скрипте
//Бот_маг with 'Hachling of Star' by NLObP
{
Социальное действие YES включить
Социальное действие NO выключить
Скрипт распространяется как есть, и я не несу ответственности за то, что
ВЫ натворили у себя, его используя.
}
//************************************************** ****************************
Const
Name=''; //имя чара
Pet=''; //имя Пета
max=500; //max количество контролируемых мобов
Radius=1500; //радиус участка для поиска мобов
DeltaZ=250; //глубина/высота до мобов
Distance=600; //дистанция до моба
windstrike=1230; //Wind Strike
//************************************************** ****************************
VAR
NameChar: string;
CharID, PetID, Attacker, ObjectID: integer;
CentrKachX,CentrKachY,CentrKachZ,RadiusKachX,Radiu sKachY: integer;
CentrKachXex,CentrKachYex,RadiusKachXex,RadiusKach Yex: extended;
tempX,tempY, tempLenght: extended;
tempZ, ColvoMobs: integer;
xe,ye: extended;
x,y,z,ox,oy,oz,n: integer;
MobCurHP, MobMaxHP, CurHP, MaxHP, CurMP, MaxMP: integer;
BotCoordX,BotCoordY,BotCoordZ: integer; //координаты бота
BotCoordXext,BotCoordYext,BotCoordZext:extended;
MinPutID: integer; //указывает индекс моба в базе путь до которого самый короткий
MinPutLenght: extended; //расстояния до ближайшего моба
timer1: TTimer; //основной таймер
timer2: TTimer; //вспомогательный
timerA: TTimer; //вспомогательный
i, itm, SocialID: integer; // вспомогательная
time1, time2: integer;
AddMob, UnderAttack, scrready, NeedBackup, fire: boolean;
ItemBase: array[1..4,1..max] of integer; // описатель предметов
CharBase: array[1..4,1..max] of integer; // описатель игроков (которых не атакуем)
MobBase: array[1..4,1..max] of integer; // описатель мобов вокруг
MobBaseExt: array[1..4,1..max] of extended; // описатель мобов вокруг вспомогательная
{ 1 - ID
2 - X
3 - Y
4 - Z}
//************************************************** ****************************
procedure Init; //Вызывается при включении скрипта
begin
UnderAttack:=false;
itm:=0;
NeedBackup:=false;
scrready:=false;
colvomobs:=0;
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1;
timer1.enabled:=False;
timer1.interval:=1500; //каждые 2 сек ищем ближайшего моба для атаки
timerA:=TTimer.Create(nil);
timerA.OnTimer:=@OnTimerA;
timerA.enabled:=False;
timerA.interval:=1500; //каждые 2 сек магическая атака
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2;
timer2.enabled:=false;
timer2.interval:=5000;
//RequestItemList
buf:=hstr('0F');
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure Free; //Вызывается при выключении скрипта
begin
timer1.Free;
timer2.Free;
timerA.Free;
end;
//************************************************** ****************************
//сообщения в приват, на сервер не отправляются
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(Name);
WriteS(msg);
SendToClientEx(Name);
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 ReqGetItem;
begin
if itm=0 then begin
timer1.enabled:=true; //включаем отсчет времени
needbackup:=false;
exit;
end;
timer1.enabled:=false; //выключаем отсчет времени
//перебираем базу
for i:=1 to max do begin
//если нашли, то обнуляем
if (ItemBase[1,i]<>0) then begin //ObjectID
say('ReqGetItem');
//даем команду подобрать вещь
buf:=#$04;
WriteD(ItemBase[1,i]);
WriteD(ItemBase[2,i]);
WriteD(ItemBase[3,i]);
WriteD(ItemBase[4,i]);
WriteH(00);
SendToServerEx(Name);
end;
end;
end;
//************************************************** ****************************
procedure OnTimer2(Sender: TObject);
begin
UnderAttack:=false; //отцепимся от атакуемого
if itm>0 then needbackup:=true;
end;
//************************************************** ****************************
//0E=StatusUpdate:h(ObjectID)d(AttribCount)d(AttrID) d(AttrValue)
procedure StatusUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: MobCurHP:=ReadD(i*8+14);
#$0A: MobMaxHP:=ReadD(i*8+14);
end;
end;
if (MobCurHP<=0) then begin
underattack:=false;
say('Убили!');
end;
end;
//************************************************** ****************************
procedure OnTimer1(Sender: TObject);
begin
//не вычисляем, если уже атакуем
if UnderAttack then exit;
MinPutID:=0;
MinPutLenght:=99999999;
///ищем самого близкого к нам моба
for i:=1 to max do begin
if (MobBaseExt[1,i]<>0) then begin
tempX:=MobBaseExt[2,i];
tempY:=MobBaseExt[3,i];
//расстояние по теореме Пифагора: c^2=a^2+b^2
tempLenght:=int(sqrt((BotCoordXext-tempx)*(BotCoordXext-tempx)+(BotCoordYext-tempy)*(BotCoordYext-tempy)));
if (tempLenght<MinPutLenght) and (PetID<>MobBase[1,i]) and (CharID<>MobBase[1,i]) then begin
MinPutLenght:=tempLenght;
MinPutID:=i;
end;
end;
end;
if (minputid<>0) then begin
Attacker:=MobBase[1,MinPutID];
TargetAttacker(Attacker);
say('Атакуем моба!');
end
else MoveCenter;
end;
//************************************************** ****************************
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
procedure MoveDistance;
begin
xe:=MobBase[2,MinPutID]+Distance/4+round(random*(Distance/4));
ye:=MobBase[3,MinPutID]+Distance/4+round(random*(Distance/4));
x:=round(xe);
y:=round(ye);
z:=MobBase[4,MinPutID];
buf:=#$01;
WriteD(x);
WriteD(y);
WriteD(z);
WriteD(BotCoordx);
WriteD(BotCoordy);
WriteD(BotCoordz);
WriteD(01);
SendToServerEx(Name);
say('держим дистанцию');
end;
procedure MoveCenter;
begin
buf:=#$01;
WriteD(CentrKachx);
WriteD(CentrKachy);
WriteD(CentrKachz);
WriteD(BotCoordx);
WriteD(BotCoordy);
WriteD(BotCoordz);
WriteD(01);
SendToServerEx(Name);
say('бежим в центр');
end;
//************************************************** ****************************
procedure TargetAtt;
begin
buf:=#$04;
WriteD(Attacker);
WriteD(BotCoordX);
WriteD(BotCoordY);
WriteD(BotCoordZ);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** *************
//2F=RequestMagicSkillUse:h(MagicID)d(CtrlPressed)b( ShiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
buf:=#$2F;
WriteD(MagicID);
WriteD(00);
WriteC(00);
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure OnTimerA(Sender: TObject);
begin
MagicSkillUse(windstrike);
MoveDistance;
say('magic attack');
end;
//************************************************** ****************************
procedure TargetAttacker(Attacker: Integer);
begin
TargetAtt;
timerA.enabled:=true;
UnderAttack:=true; //зацепимся за атакуемого
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не пропускаем пустые пакеты
if pck='' then exit;
//************************************************** **************************
//16=NpcInfo:h(ObjectID)d(NpcTypeID)d(IsAttackable)d (X)d(Y)d(Z)d(Heading)d(d)d(Maspd)d(Paspd)d(runSpd) d(walkSpd)d(swimRSpd)d(swimWSpd)d(flRSpd)d(flWSpd) d(FlyRSpd)d(FlyWSpd)f(ProperMul)f(Paspd)f(CollisRa dius)f(CollisHeight)d(RHand)d(d)d(LHand)b(nameabov e)b(isRun)b(isInFight)b(isAlikeDead)b(isSummoned)s (Name)s(Title)d(d)d(d)d(karma?)d(abnEffect)d(d)d(d )d(d)d(d)b(c)b(Team)f(collisRadius)f(collisHeight) d(d)
//NPCInfo, запоминаем мобов
if FromServer and (ConnectName=Name) and (pck[1]=#$16) then begin
AddMob:=true;
//проверка, входит моб в радиус действия?
tempX:=ReadD(14); //x
tempY:=ReadD(18); //y
tempLenght:=sqrt((CentrKachXex-tempX)*(CentrKachXex-tempX)+(CentrKachYex-tempY)*(CentrKachYex-tempY));
//проверям, не под землей ли моб(в катакомбах)
tempZ:=BotCoordZ-ReadD(22);
if tempz<0 then tempZ:=tempz*(-1);
if tempZ<=DeltaZ then begin
if (tempLenght<Radius) then begin
for i:=1 to max do begin
//если нашли Моба в базе, то коректируем его координаты на новые
if (MobBase[1,i]=ReadD(2)) and (CharID<>ReadD(2)) and (PetID<>ReadD(2)) then begin
MobBase[2,i]:=ReadD(14); //x
MobBase[3,i]:=ReadD(18); //y
MobBase[4,i]:=ReadD(22); //z
//Ext массив
MobBaseExt[2,i]:=ReadD(14); //x
MobBaseExt[3,i]:=ReadD(18); //y
MobBaseExt[4,i]:=ReadD(22); //z
AddMob:=false;
end;
end;
//иначе, перебираем базу, ищем свободную ячейку в ней и добавляем нового моба
for i:=1 to max do begin
if (MobBase[1,i]=0) and AddMob and (CharID<>ReadD(2)) and (PetID<>ReadD(2)) then begin
//запоминаем моба в свободную ячейку
MobBase[1,i]:=ReadD(2); //ObjectID
MobBase[2,i]:=ReadD(14); //x
MobBase[3,i]:=ReadD(18); //y
MobBase[4,i]:=ReadD(22); //z
//Ext массив
MobBaseExt[1,i]:=ReadD(2); //ObjectID
MobBaseExt[2,i]:=ReadD(14); //x
MobBaseExt[3,i]:=ReadD(18); //y
MobBaseExt[4,i]:=ReadD(22); //z
inc(colvomobs);
say('Запоминаем координаты Моба'+' ColvoMobs='+inttostr(colvomobs));
break;
end;
end;
end;
end;
end;
//************************************************** **************************
//CharInfo, запоминаем игроков
if FromServer and (ConnectName=Name) and (pck[1]=#$03) then begin
AddMob:=true;
for i:=1 to max do begin
//если нашли чара в базе, то коректируем его координаты на новые
if (CharBase[1,i]=ReadD(18)) then begin
CharBase[2,i]:=ReadD(2); //x
CharBase[3,i]:=ReadD(6); //y
CharBase[4,i]:=ReadD(10); //z
AddMob:=false;
end;
end;
//иначе, перебираем базу, ищем свободную ячейку в ней и добавляем нового чара
for i:=1 to max do begin
if (CharBase[1,i]=0) and AddMob then begin
//запоминаем моба в свободную ячейку
CharBase[1,i]:=ReadD(18); //ObjectID
CharBase[2,i]:=ReadD(2); //x
CharBase[3,i]:=ReadD(6); //y
CharBase[4,i]:=ReadD(10); //z
NameChar:=ReadS(22);
say('Приближается Игрок '+NameChar+'!!!');
break;
end;
end;
for i:=1 to max do begin
//если нашли Чара в базе Мобов, то удаляем его
if (MobBase[1,i]=ReadD(18)) then begin
MobBase[1,i]:=0; //x
MobBase[2,i]:=0; //x
MobBase[3,i]:=0; //y
MobBase[4,i]:=0; //z
//Ext массив
MobBaseExt[1,i]:=0; //x
MobBaseExt[2,i]:=0; //x
MobBaseExt[3,i]:=0; //y
MobBaseExt[4,i]:=0; //z
dec(colvomobs);
say('Нашли Чара в базе Мобов, удаляем его'+' ColvoMobs='+inttostr(colvomobs));
end;
end;
end;
//************************************************** **************************
//MoveToLocation, коректируем координаты мобов в базе
if FromServer and (ConnectName=Name) and (pck[1]=#$01) then begin
AddMob:=true;
//проверка, входит моб в радиус действия?
tempX:=ReadD(6); //x
tempY:=ReadD(10); //y
tempLenght:=sqrt((CentrKachXex-tempX)*(CentrKachXex-tempX)+(CentrKachYex-tempY)*(CentrKachYex-tempY));
tempZ:=BotCoordZ-ReadD(14);
if tempz<0 then tempZ:=tempz*(-1);
if tempZ<=DeltaZ then begin
if (int(tempLenght)<Radius) then begin
//перебираем базу и ищем там моба, который бежит
for i:=1 to max do begin
//если нашли моба в базе, то коректируем его координаты на новые
if (MobBase[1,i]=ReadD(2)) and (CharID<>ReadD(2)) and (PetID<>ReadD(2)) and (CharBase[1,i]<>ReadD(2)) then begin //ObjectID
MobBase[2,i]:=ReadD(6); //x
MobBase[3,i]:=ReadD(10); //y
MobBase[4,i]:=ReadD(14); //z
//Ext массив
MobBaseExt[2,i]:=ReadD(6); //x
MobBaseExt[3,i]:=ReadD(10); //y
MobBaseExt[4,i]:=ReadD(14); //z
AddMob:=false;
end;
end;
//иначе, перебираем базу, ищем свободную ячейку в ней и добавляем нового моба
for i:=1 to max do begin
if (MobBase[1,i]=0) and AddMob and (CharID<>ReadD(2)) and (PetID<>ReadD(2)) then begin
//запоминаем моба в свободную ячейку
MobBase[1,i]:=ReadD(2); //ObjectID
MobBase[2,i]:=ReadD(6); //x
MobBase[3,i]:=ReadD(10); //y
MobBase[4,i]:=ReadD(14); //z
//Ext массив
MobBaseExt[1,i]:=ReadD(2); //ObjectID
MobBaseExt[2,i]:=ReadD(6); //x
MobBaseExt[3,i]:=ReadD(10); //y
MobBaseExt[4,i]:=ReadD(14); //z
inc(colvomobs);
break;
end;
end;
end;
end;
end;
//************************************************** **************************
//MagicSkillUse 48, Attack 05
if FromServer and (ConnectName=Name) and ((pck[1]=#$48) or (pck[1]=#$05)) then begin
if UnderAttack then exit; //сначало убъем одного
Attacker:=ReadD(2);
ObjectID:=ReadD(6);
if (Attacker<>ObjectID) and (CharID=ObjectID) then begin
UnderAttack:=true; //нас атакуют
needbackup:=false;
Say('Нас атакуют!');
TargetAttacker(Attacker);
end;
end;
//************************************************** **************************
//если принят пакет Die
if FromServer and (ConnectName=Name) and (pck[1]=#$06) then begin
//ищем моба в базе
if (Attacker=ReadD(2)) then begin
UnderAttack:=false; //убили атакующего моба
timerA.enabled:=False;
end;
for i:=1 to max do begin
//очишаем запись связанную с етим мобом
if (MobBase[1,i]=ReadD(2)) then begin
dec(colvomobs);
MobBase[1,i]:=0; //ObjectID
MobBase[2,i]:=0; //x
MobBase[3,i]:=0; //y
MobBase[4,i]:=0; //z
//Ext массив
MobBaseExt[1,i]:=0; //ObjectID
MobBaseExt[2,i]:=0; //x
MobBaseExt[3,i]:=0; //y
MobBaseExt[4,i]:=0; //z
break;
end;
end;
end;
//************************************************** **************************
//если принят пакет DeleteObject
if FromServer and (ConnectName=Name) and (pck[1]=#$12) then begin
//ищем моба в базе
//say('DeleteObject');
if (Attacker=ReadD(2)) then begin
UnderAttack:=false; //убили атакующего моба
timerA.enabled:=False;
end;
for i:=1 to max do begin
//очишаем запись связанную с етим мобом
if (MobBase[1,i]=ReadD(2)) then begin
dec(colvomobs);
MobBase[1,i]:=0; //ObjectID
MobBase[2,i]:=0; //x
MobBase[3,i]:=0; //y
MobBase[4,i]:=0; //z
//Ext массив
MobBaseExt[1,i]:=0; //ObjectID
MobBaseExt[2,i]:=0; //x
MobBaseExt[3,i]:=0; //y
MobBaseExt[4,i]:=0; //z
break;
end;
end;
for i:=1 to max do begin
//если нашли в базе, то удаляем
if (CharBase[1,i]=ReadD(2)) then begin
CharBase[2,i]:=0; //x
CharBase[3,i]:=0; //y
CharBase[4,i]:=0; //z
end;
end;
end;
//************************************************** **************************
//ValidatePosition если принят пакет от клиента с моими кординатами то
if FromClient and (ConnectName=Name) and (pck[1]=#$48) then begin
//запоминаем мои координаты
BotCoordX:=ReadD(2);
BotCoordY:=ReadD(6);
BotCoordZ:=ReadD(10);
//ext
BotCoordXext:=ReadD(2);
BotCoordYext:=ReadD(6);
BotCoordZext:=ReadD(10);
end;
//************************************************** **************************
//если от сервака принят пакет с ИД и Координатами членов пати то
if FromServer and (ConnectName=Name) and (pck[1]=#$a7) then begin
//запоминаем ИД командира
CharID:=ReadD(6);
if scrready then exit
else begin
Say('Скрипт готов к работе. Запомнил ИД лидера');
scrready:=true;
end;
end;
//************************************************** **************************
//если от сервака принят пакет с UserInfo
if FromServer and (ConnectName=Name) and (pck[1]=#$04) then begin
//Запоминаем собственный ИД
CharID:=ReadD(18);
if scrready then exit
else begin
Say('Скрипт готов к работе. Запомнил ИД лидера');
scrready:=true;
end;
end;
//************************************************** **************************
//если от сервака принят пакет с PetInfo
if FromServer and (PetID=0) and (ConnectName=Name) and (pck[1]=#$b1) then PetID:=ReadD(6);
//************************************************** **************************
//DropItem - выпала вещь
if FromServer and (ConnectName=Name) and (pck[1]=#$0C) then begin
//чужие вещи не берем
if (Attacker=ReadD(2)) then begin
timer1.enabled:=false; //выключаем бота
AddMob:=true;
//перебираем базу
for i:=1 to max do begin
//если нашли, то корректируем его координаты на новые
if (ItemBase[1,i]=ReadD(6)) then begin //ObjectID
ItemBase[2,i]:=ReadD(14); //x
ItemBase[3,i]:=ReadD(18); //y
ItemBase[4,i]:=ReadD(22); //z
AddMob:=false;
inc(itm);
NeedBackup:=true;
end;
end;
//иначе, перебираем базу, ищем свободную ячейку в ней и добавляем
for i:=1 to max do begin
if (ItemBase[1,i]=0) then begin
//запоминаем в свободную ячейку
ItemBase[1,i]:=ReadD(6); //ObjectID
ItemBase[2,i]:=ReadD(14); //x
ItemBase[3,i]:=ReadD(18); //y
ItemBase[4,i]:=ReadD(22); //z
inc(itm);
NeedBackup:=true;
break;
end;
end;
end;
say('ColvoItm='+inttostr(itm));
end;
//************************************************** **************************
//каждые две сек подбираем предмет
if Wait(time1,2) and NeedBackup and (underAttack=false) then ReqGetItem;
//************************************************** **************************
//определяем реальность поднятия вещи
//GetItem
if FromServer and (ConnectName=Name) and (pck[1]=#$0D) then begin
//перебираем базу
for i:=1 to max do begin
//если нашли, то обнуляем
if (ItemBase[1,i]=ReadD(6)) then begin //ObjectID
ItemBase[1,i]:=0; //x
ItemBase[2,i]:=0; //x
ItemBase[3,i]:=0; //y
ItemBase[4,i]:=0; //z
dec(itm);
//say('Удаляем данные по предмету');
end;
end;
if itm=0 then begin
needbackup:=false;
timer1.enabled:=true;
end;
say('ColvoItm='+inttostr(itm));
end;
//************************************************** ****************************
//StatusUpdate
if FromServer and (ConnectName=Name) and (pck[1]=#$0E) and (Attacker=ReadD(2)) then StatusUpdate;
//************************************************** **************************
if FromClient and (ConnectName=Name) and (pck[1]=#$1B) then begin
SocialID:=ReadD(2);
pck:='';
case SocialID of
//социальное действие Yes для начала
6: begin
//if CharID=0 then exit;
CentrKachX:=BotCoordX;
CentrKachY:=BotCoordY;
CentrKachZ:=BotCoordZ;
CentrKachXex:=BotCoordXext;
CentrKachYex:=BotCoordYext;
Say('Команда Старт!!!');
say('Получили координаты центра');
say('X='+inttostr(BotCoordX)+' Y='+inttostr(BotCoordY));
timer1.enabled:=true;
exit;
end;
//социальное действие No для окончания
5: begin
//if CharID=0 then exit;
timer1.enabled:=false;
timer2.enabled:=false;
timerA.enabled:=False;
underattack:=false;
Say('Команда Стоп!!!');
exit;
end;
end;
end;
end.
Добавлено спустя 3 минуты 34 секунды:
Re:
Бегает,лечит,заливает, пьет цп,хп на ура, правда задержечка есть при цп...
скорей всего у тебя просто сервак левый особенно с таргетами и пропаданием суппорта за спиной)
Какие хроники?
Добавлено спустя 2 минуты 16 секунд:
Сервер довольно неплохой ПТС Ц4
My name='NLObP"
Для мага - сложность в дистанционной атаке, очень большая сложность... для меня по крайней мере.
очень неплохо такая атака реализована в этом скрипте
А мне не очень нравится. Может отбежать не от моба, а мимо него на заданное расстояние.
Ещё. Воин по двойному клику начинает атаковать и можно забыть про него, а маг должен чередоваь магическую атаку и отслеживать сбой в атаке.
Ворон для Ц 4 код на цп и хп пошин такой же будет ?
Добавлено спустя 3 минуты 58 секунд:
В принципе меня этот//Бот_маг with 'Hachling of Star' by NLObP
{
Социальное действие YES включить
Социальное действие NO выключить скрипт вполне устраивает единственное что так это то что он застревает часто когда до цели не может добраться или выпавшая вещь где то где ее никак не взять он тупо будет все время пытаться ее поднять а как добавить допустим чтобы 5-6 раз попытался поднять и забыл потом про эту вещь или моба хз (( и еще когда его бафера бафают то он их за цель принимает )и заклинивается на них )
APXAHGEJI
29.03.2008, 04:26
Не видел исправленной записи ObjectID бутылок предложенной VORON'ом,
поэтому выкладываю исправленное мною.
Работатет под С4.
//************************************************** ************************
//Записываем ObjectID некоторых банок
if pck[1]=#$1B then
for i:= 0 to round((length(pck)- 5)/28) do begin
if (ReadH(i*28+4+8) = 5592) then begin //Greater CP Potion
OidGCP:= ReadD(i*28+8);//ObjectID
NGCP:= ReadH(i*28+4+4+8);//кол-во
end;
if (ReadH(i*28+4+8) = 1539) then begin //Greater Healing Potion
OidGHP:= ReadD(i*28+8);//ObjectID
NGHP:= ReadH(i*28+4+4+8);//кол-во
end;
if (ReadH(i*28+4+8) = 6036) then begin //Greater Magic Haste Potion
OidGMG:= ReadD(i*28+8);//ObjectID
NGMG:= ReadH(i*28+4+4+8);//кол-во
end;
if (ReadH(i*28+4+8) = 1374) then begin //Greater Haste Potion
OidGHS:= ReadD(i*28+8);//ObjectID
NGHS:= ReadH(i*28+4+4+8);//кол-во
end;
if (ReadH(i*28+4+8) = 1375) then begin //Greate Swift Attack Potion
OidGSW:= ReadD(i*28+8);//ObjectID
NGSW:= ReadH(i*28+4+4+8);//кол-во
end;
end;
//************************************************** ************************
DashKAaa
29.03.2008, 14:12
Бегает,лечит,заливает, пьет цп,хп на ура, правда задержечка есть при цп...
скорей всего у тебя просто сервак левый особенно с таргетами и пропаданием суппорта за спиной)
Какие хроники?
Добавлено спустя 2 минуты 16 секунд:
Сервер довольно неплохой ПТС Ц4[/quote]
с4. пробовал и интерлюде, точнее большую часть на интерлюде
APXAHGEJI
29.03.2008, 22:08
У меня на сервере такая же беда с пропаданием саппортов бегущих за мной по таргету.
И такая хрень у нас появилась после того как установили Антибот. Вобщемто стало фиговее работать,
лаги, глюки, ну и сапорты никогда до места не добегают. Но зато у нас, через эти мега расстояния они все спокойно делают,
и хиляют и бафают, главное на них не переключатся.
А вообщемто я подумываю написать скрпитец чтобы они шли не по таргету, а напрямую по координатам чара основного окна.
Где то такое уже писали тут необходимо только добавить смещение небольшое
Добавлено спустя 2 минуты 15 секунд:
Re:
А вообщемто я подумываю написать скрпитец чтобы они шли не по таргету, а напрямую по координатам чара основного окна.
подскажите пожалуйста, у меня программа не воспринимает функцию ReadH, говорит неопознанный идентификатор (((
и в выплывающей подсказке ее нет
подскажите пожалуйста, у меня программа не воспринимает функцию ReadH, говорит неопознанный идентификатор (((
и в выплывающей подсказке ее нет
поддерживаемые функции:
ReadC(var index:integer):byte - читает из переменной pck байт
ReadH(var index:integer):word - читает из переменной pck число (2 байта) (v. 3.1.8+)
ReadD(var index:integer):integer - читает из переменной pck число (4 байта)
ReadF(var index:integer):double - читает из переменной pck число c плавающей запятой(8 байт) (v. 3.1.8+)
ReadS(var index:integer):string - читает из переменной pck строку (в пакете строка unicode нультерминированная, а результирующая строка обычная паскалевская)
Index - начальная позиция чтения, которая модифицируется функцией (сдвигается на число считанных байт)
Есть такая. Может неправильно написал или версия старая?
на 3.2.0 все нормально, ошибку ен выдает, а я пробовал на 3.1.6
только вот с 3.2.0 линяга не входит на серв((
на 3.2.0 все нормально, ошибку ен выдает, а я пробовал на 3.1.6
только вот с 3.2.0 линяга не входит на серв((
3.1.8 ИМХО самая нормальная версия, я ею пользуюсь.
с 3.1.8 тоже не грузится (((
может эту функцию можно обойти другим методом?
с 3.1.8 тоже не грузится (((
может эту функцию можно обойти другим методом?
сравнивай побайтно, с помощью pck[x]
например If ((pck[1]+pck[2]= #$05#$05) then ...
т.е. получается так:
ReadH(i) это тоже самое что и (pck[1+i]+pct[2+i]) так я понял?
APXAHGEJI
01.04.2008, 21:04
ReadH(i) аналогично (pck[i]+pck[i+1]), но это не одно и тоже.
ReadH() возвращает число в десятиричной системе,
а pck[] в шестнадцетиричной.
а есть встроенная функция перевода из шестнадцатиричной в десятичную?
или может быть скрипт
APXAHGEJI
02.04.2008, 00:41
ХМ, так я про что говорю, pck это тупо кусок (1 байт пакета, условно, две циферки подряд в пакете) в 16 системе,
а вот ReadC это тот же кусок (1 байт пакета) тока в 10 системе.
ReadH - 2 байта,
ReadD - 4 байта, и тд.
Добавлено спустя 35 минут 53 секунды:
Уж извините за флуд :oops: , но вдруг кому сгодится :)
Скриптик, отправляет торг сообщения по времени и записывает все приват сообщения,
соответственно на которые можно будет ответить позже.
Еще я там в конце заблочил, ответ на собщения в пм, что типа меня нет, приду отвечу))
У на серве торг боты разрешены)) , а у вас?
//Скрипт торг сообщений by APXAHrEJI
//Всё активируется соц действиями
//Yes - выводит одно торг сообщение
//No - автоматически повторяет сообщение чере некоторый интервал врмени (по умолчанию 30 сек.)
//Unaware - если вам во время вашего отсутствия что-то написали в ПМ
//то, по нажатию клавиши выводится те самые сообщения , одно нажатие одно сообщение.
//Applaud - удаляет все сообщения
Const
Name = 'Ник Перса';
Yahoo= ' Сюда торг сообщение '+
' если не поместилось туда мона и сюда ';
Var
TimerToSay: TTimer;
Flag: boolean;
N, M: Integer;
SaveMsg: array of String;
SaveNick: array of String;
Procedure Init;
begin
TimerToSay:=TTimer.Create(nil);
TimerToSay.OnTimer:=@SayByTime;
TimerToSay.Enabled:= False;
TimerToSay.Interval:= 30000;//интервал повторения сообщения
Flag:= False;
N:= 0;
M:= 0;
end;
procedure Free;
begin
TimerToSay.Free;
SetLength (SaveMsg, 0);
SetLength (SaveNick, 0);
end;
procedure PrivatSay;
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(SaveNick[M]);
WriteS(SaveMsg[M]);
SendToClientEx(Name);
end;
Procedure Say;
begin
buf:= #$38;
WriteS(Yahoo);
WriteD(8);
SendToServerEx (Name);
end;
Procedure Palevo;
begin
buf:= #$38;
WriteS('Меня нет. Отвечу позже.');
WriteD(2);
WriteS(SaveNick[N-1]);
SendToServerEx(Name);
end;
Procedure SayByTime(Sender: TObject);
begin
Say;
end;
Begin
If pck='' then exit;
if FromClient and (ConnectName=Name) and (pck[1]=#$1B) then begin
case ReadD(2) of
6: Say;
5: If Flag then begin
Flag:= False;
TimerToSay.enabled:=false;
end
else begin
Say;
Flag:= True;
TimerToSay.enabled:=True;
end;
8: If (N <> 0) then begin
PrivatSay;
If (M<(N-1))then Inc(M) else M:=0;
end;
11: begin
M:=0;
N:=0;
SetLength (SaveMsg, N);
SetLength (SaveNick, N);
end;
end;
pck:= '';
end;
If FromServer and (ConnectName=Name) then
if (pck[1]= #$4A) and (pck[6]=#$02) then begin
Inc(N);
SetLength (SaveMsg, N);
SetLength (SaveNick, N);
SaveNick[N-1]:= ReadS(10);
SaveMsg[N-1]:= ReadS(2*Length(SaveNick[N-1])+2 +10);
//Palevo; //раскоментарив, бот будет отвечать на сообщения в ПМ
end;
End.
понял, ReadH(i) = ReadC(i)+ReadC(i+1)
APXAHGEJI
02.04.2008, 01:05
Угумс :ROFL:
Добавлено спустя 4 минуты 52 секунды:
Хотя нет, сдесь же перевод идет :) из ситемы в систему
Добавлено спустя 6 минут 40 секунд:
тоесть допусти пакет 2F 22 05 00 00, в нем
Pck[1]=2F
pck[2]=22
Pck[1]+pck[2]= 2F 22
ReadH= 8751, но
ReadC(1)= 47
ReadC(2)= 22
RaedC(1)+Read(2)=69
Сдесь же перевод идет из системы в систему, а переводишь число получаетсся по частям.
Добавлено спустя 2 минуты 42 секунды:
Ошибочка таам у меня ReadC(2)= 34
и соответственно
ReadC(1)+Read(2)= 81
но сути это не меняет
млин. получается без нее никак.
и почему ГГ с 3.1.8 не грузит, а с 3.1.6 все норм?
APXAHGEJI
02.04.2008, 01:21
У меня например иногда тоже персы не грузятся, если пнх работает,
но обычно достаточно перезапустить клиент или сам пнх и все норм.
А может ты где-то галочку лишнюю поставил, или наоборот не поставил, в разделе основное.
ReadH(i) аналогично (pck[i]+pck[i+1]), но это не одно и тоже.
ReadH() возвращает число в десятиричной системе,
а pck[] в шестнадцетиричной.
ИМХО одинаково, что десятичные сложить, что шестнадцатеричные сложить в итоге одно и тоже число должно быть, только в своей системе исчисления.
HEX -> #$0A+#$10=#$1A (=26) или DECimal -> 10+16=26
Кароче я нифига не понял шо вы там считаете но что то мне подсказывает что NLObP прав )
APXAHGEJI
02.04.2008, 13:06
NLObP, ага правильно, а вот если принять pck[1]=#$0A, а pck[2]=#$10, то pck[1]+pck[2]=#$0A#$10
NLObP, ага правильно, а вот если принять pck[1]=#$0A, а pck[2]=#$10, то pck[1]+pck[2]=#$0A#$10
Строку HEX символов получим '0A10'?
APXAHGEJI
02.04.2008, 16:39
Да. Например проверку что это пакет использование скила, и зажата CTRL можно реализовать так
If ((pck[1]+pck[6])=#$2F#$01) then
иначе это выглядит так
if (pck[1]= #$2F) and (pck[6]=#$01) then
Люди помогите плиз, пытался найти этот скрипт переписаный под камаель, не получилось...
//Автоматизация заточки предметов до необходимого уровня by NLObP
//Затачиваем поочереди все предметы с Weapon ID пока не переломаем или не заточим
//Работа проверена на L2C4 Protocol 660 LocalServer "L2J FORTRESS"
//Необходимо затариться оружием, заточками и валерьянкой
//Открываем инвентарь для инициализации скрипта
//Социальное действие YES начать
//Социальное действие NO остановиться
//Enjoy!
{Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.}
//************************************************** ****************************
const
Name='NLObP';
Scroll=957; // 957 - ItemID Crystall Scroll Enchant Weapon (Grade D)
Weapon=129; // 129 - ItemID Sword of Revolution D-grade
MaxEnchLvl=20; //max уровень заточки
max=250; //max количество предметов в базе
var
// WpnObjID: array[1..maxwpn,1..maxwpn] of integer; //Weapon ObjID
WpnBase: array[1..2,1..max] of integer; //Weapon ObjID,lvl
ScrlBase: array[1..max] of integer; //Scroll ObjID
add: boolean; //прошла заточка?
timer: TTimer;
CurEnchLvl, ColvoWpn, ColvoScrl, CurWpn, CurScrl: integer;
//************************************************** ****************************
procedure Init; //Вызывается при включении скрипта
var
i:integer;
begin
//Enchant:=false;
CurEnchLvl:=0;
timer:=TTimer.Create(nil);
timer.OnTimer:=@OnTimerHP;
timer.enabled:=false;
timer.interval:=2500; //время задержки
Say('Для инициализации скрипта, откройте инвентарь');
end;
//************************************************** ****************************
procedure Free; //Вызывается при выключении скрипта
begin
WpnBase:=nil;
ScrlBase:=nil;
timer.Free;
end;
//************************************************** ****************************
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(Name);
WriteS(msg);
SendToClientEx(Name);
end;
//************************************************** ****************************
procedure CreateItemBase; //пакет 1B, Создает базу ObjectID по ItemID
var
i, ss, ww, j, ObjID, ItemID, lvl, ListCount: integer;
begin
ss:=1; //индекс в массиве скроллов
ww:=1; //индекс в массиве предметов
j:=4; //смещение для ListCount
ListCount:=ReadH(j); //количество итемов не должно превышать max!
if ListCount>max then ListCount:=max;
j:=8; //смещение для ObjectID
//Пробегаем по Инвентарю и сохраняем ObjectID соответствующие необходимым ItemID
for i:=1 to ListCount do begin
ObjID:=ReadD(j); //ObjectID
ItemID:=ReadD(j); //ItemID
j:=j+14;
Lvl:=ReadD(j); //Level
case ItemID of
scroll: begin
ScrlBase[ss]:=ObjID;
ss:=ss+1;
//Say('ColvoScrl='+IntToStr(ss));
end;
weapon: begin
WpnBase[1,ww]:=ObjID;
WpnBase[2,ww]:=lvl;
ww:=ww+1;
//Say('ColvoWpn='+IntToStr(ww));
end;
end;
j:=j+2; //для С4
// j:=j+10; //для Интерлюдии
end;
ColvoWpn:=ww-1;
ColvoScrl:=ss-1;
Say('>ColvoWpn='+IntToStr(ColvoWpn)+' ColvoScrl='+IntToStr(ColvoScrl)+' CurEnchLvl='+IntToStr(CurEnchLvl));
end;
//************************************************** ****************************
procedure UpdateItemBase; //пакет 27, Создает базу ObjectID по ItemID
var
i, ii, j, ss, ww, ObjID, ItemID, Lvl, ListCount, UpdType: integer;
begin
ListCount:=ReadH(2); //количество итемов
//Пробегаем по Инвентарю и сохраняем пары ObjectID - Lvl
j:=4; //смещение для действия с предметом 1-добавлен 2-изменен 3-удален
// Say('Апдейт базы!');
for i:=1 to ListCount do begin
UpdType:=ReadH(j);
j:=j+2;
ObjID:=ReadD(j);
ItemID:=ReadD(j);
j:=j+14;
Lvl:=ReadH(j);
// Say('Предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItemID));
case UpdType of
1:case ItemID of
weapon: begin
ColvoWpn:=ColvoWpn+1;
//Say('Добавили предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(weapon));
for ii:=1 to max do
if WpnBase[1,ii]=0 then begin WpnBase[1,ii]:=ObjID; WpnBase[2,ii]:=lvl; end;
end;
scroll: begin
ss:=ss+1;
//Say('Добавили скролл! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(scroll));
for ii:=1 to max do
if ScrlBase[ii]=0 then ScrlBase[ii]:=ObjID;
end;
end;
2:case ItemID of
weapon:
for ii:=1 to max do
if WpnBase[1,ii]=ObjID then WpnBase[2,ii]:=lvl;
scroll:
//Say('Внимание! Изменения в скролле!?');
end;
//удален
3:case ItemID of
weapon: begin
ColvoWpn:=ColvoWpn-1;
for ii:=1 to max do
if WpnBase[1,ii]=ObjID then begin WpnBase[1,ii]:=0; WpnBase[2,ii]:=0; end;
//Say('Удаляем предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(weapon));
end;
scroll: begin
ColvoScrl:=ColvoScrl-1;
for ii:=1 to max do
if ScrlBase[ii]=ObjID then ScrlBase[ii]:=0;
//Say('Удаляем скролл! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(scroll));
end;
end;
end;
j:=j+2; //для С4
// j:=j+10; //для Интерлюдии
end;
Say('>>ColvoWpn='+IntToStr(ColvoWpn)+' ColvoScrl='+IntToStr(ColvoScrl)+' CurEnchLvl='+IntToStr(CurEnchLvl));
end;
//************************************************** ****************************
function GetNextWeapon: integer; //Выдает ObjID предмета, если не найден в базе, выдает -1,
//достигли макс уровня заточки -2, подбираем мин текущий уровень заточки -3
var
i: integer;
begin
Result:=-1;
if CurEnchLvl>=MaxEnchLvl then begin
Result:=-2;
exit;
end;
for i:=1 to max do begin
//находим первый подходящий предмет
if (WpnBase[1,i]<>0) and (WpnBase[2,i]=CurEnchLvl) then begin
Result:=WpnBase[1,i];
exit;
end;
end;
CurEnchLvl:=CurEnchLvl+1;
Result:=-3;
end;
//************************************************** ****************************
function GetNextScroll: integer; //Выдает ObjID скролла, если не найден в базе, выдает -1
var
i: integer;
begin
Result:=-1;
for i:=1 to max do begin
//находим первый подходящий предмет
if (ScrlBase[i]<>0) then begin
Result:=ScrlBase[i];
exit;
end;
end;
end;
//************************************************** ****************************
procedure UseItem(ObjectID: integer);
begin
buf:=#$14;
WriteD(ObjectID);
WriteD(0);
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure RequesEnchantItem(ObjectID: integer);
begin
buf:=#$58;
WriteD(ObjectID);
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure OnTimerHP(Sender: TObject);
var
wpn, scrl:integer;
begin
if ColvoScrl=0 then begin
Say('Кончились скроллы! Прервано!');
timer.enabled:=false;
exit;
end;
if ColvoWpn=1 then begin
Say('Остался последний предмет! Прервано!');
timer.enabled:=false;
exit;
end;
Scrl:=GetNextScroll;
if scrl=-1 then begin
Say('Нет такой заточки! Прервано!');
timer.enabled:=false;
exit;
end;
Wpn:=GetNextWeapon;
case wpn of
-1: begin
Say('Нет такого предмета! Прервано!');
timer.enabled:=false;
exit;
end;
-2: begin
Say('Достигли максимальный уровень заточки! Прервано!');
timer.enabled:=false;
exit;
end;
-3: begin
//Say('Подбираем текущий уровень заточки!');
timer.enabled:=true;
exit;
end;
end;
//************************************************
UseItem(Scrl);
RequesEnchantItem(Wpn);
//************************************************
Say('Заточили предмет! Weapon='+IntToStr(Wpn));
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
//социальное действие yes для начало точки
if FromClient and (ConnectName=Name) and (pck=HStr('1B 06 00 00 00')) then begin
CurEnchLvl:=0;
Say('Команда Старт!!!');
timer.enabled:=true;
end;
//************************************************** **************************
//социальное действие no для начало точки
if FromClient and (ConnectName=Name) and (pck=HStr('1B 05 00 00 00')) then begin
Say('Команда Стоп!!!');
timer.enabled:=false;
end;
//************************************************** **************************
//ItemList
if FromServer and (ConnectName=Name) and (pck[1]=#$1B) then CreateItemBase; //создание базы предметов
// if (ColvoWpn=0) or (ColvoScrl=0) then exit; //если нет базы итемов, скрипт дальше не пустит
//************************************************** **************************
//если удалились предметы, стираем в базе предметов пары ObjectID - ItemID
if FromServer and (ConnectName=Name) and (pck[1]=#$27) then UpdateItemBase; //Обновление базы, если принят пакет на удаление предмета
end.
При запуске скрипта вылетает табличка Access violation at address 0052B595 in module "l2phx.exe". Read of address 45453338
Откуда такая формула и как ее понять?
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
элементарно ватсон-))..
пакет который приходит от сервера с описанием ИНВЕНТОРЯ- цикличен.. его длина зависит напрямую от кол-ва предметов в инвенторе.. в начале пакета 8 байтов отводится под описание ИД ПАКЕТА+КОЛВО ПРЕДМЕТОВ+ЕЩЕ ЧЕТА.. 8 байтов- описание.. после етих 8ми байтов следует цикличное описание каждого итема в инвенторе.. каждый итем описывается 36-ю байтами.. каждый блок описываемый айтем в инвенторе начинается с ОИД предмета.. после чего идет ИТЕМ ИД предмета.. т.е. если в инвенторе всего 1 предмет то длина пакета будет 8+36 бафйтов.. с 8-го байта там будет храниться ОБЖЕКТ ИД итема.. с 12-го будет записан его ИТЕМ ИД.. потом будет указано кол-во в стопке етих предметов.. и там еще чето то.. поетому.. если у нас 2 предмета в инвенторе 1-предмет ЦП банка второй предмет ГХП банка то наш синтаксис сработает так:
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
для первого итема получится:
for i:= 0 to 2 do
begin
if (pck[12]+pck[13] = hstr('25 04')) then OidHPPotion0:=pck[8]+pck[9]+pck[10]+pck[11];
ну а для второго:
for i:= 0 to 2 do
begin
if (pck[12+36]+pck[13+36] = hstr('25 04')) then OidHPPotion0:=pck[8+36]+pck[9+36]+pck[10+36]+pck[11+36];
таким образом мы запоминаем из инвенторя ГХП и ЦП банки так инвентарь имеет не 2 позиции а забит до отказа то применяем то что я дал:
for i:= 0 to round(length(pck)/36) do
begin
if (pck[i*36+4+8]+pck[i*36+5+8] = hstr('25 04')) then OidHPPotion0:=pck[i*36+8]+pck[i*36+1+8]+pck[i*36+2+8]+pck[i*36+3+8];
APXAHGEJI
08.04.2008, 09:02
Ток вычисления у тебя помоему не правильные,
У тебя самого этот скрипт работатет?
Люди помогите плиз, пытался найти этот скрипт переписаный под камаель, не получилось...
При запуске скрипта вылетает табличка Access violation at address 0052B595 in module "l2phx.exe". Read of address 45453338
Ты константы под себя настраивал?
const
Name='NLObP'; // - здесь имя чара для которого запускаем скрипт!!!
Scroll=957; // 957 - ItemID Crystall Scroll Enchant Weapon (Grade D) - здесь ItemID заточки!!!
Weapon=129; // 129 - ItemID Sword of Revolution D-grade - здесь ItemID затачиваемой вещи!!!
MaxEnchLvl=20; //max уровень заточки - здесь максимальный уровень заточки
max=250; //max количество предметов в базе (инвентаре), для гнома до 250, для других - 80
PS: Не надо забывать что скрипт для С4, а в Камаэле, наверняка, пакеты отличаются, не забудь найти отличия и подправить смещения.
Ток вычисления у тебя помоему не правильные,
У тебя самого этот скрипт работатет?
я невыкладываю то что непротестировано..
я выкладываю то чем сам пользуюсь и то что работает 100%..
кстатти моё- для интерлюда..
возможно твоё для ц4..
Ксати, неплохо было бы бота для рыбалки приучить к автоматической конверсии бутылочек, при наличии соответствующих рецептов, фиш оил в греатер фиш оил, а греатер фиш оил в премиум фиш оил прямо во время рыбалки, чтобы экономить время.
Server *yss:
Пакет на FO -> GFO
AF A8 02 00 00
Пакет на GFO -> PFO
AF A9 02 00 00
Ксати, неплохо было бы бота для рыбалки приучить к автоматической конверсии бутылочек, при наличии соответствующих рецептов, фиш оил в греатер фиш оил, а греатер фиш оил в премиум фиш оил прямо во время рыбалки, чтобы экономить время.
Server *yss:
Пакет на FO -> GFO
AF A8 02 00 00
Пакет на GFO -> PFO
AF A9 02 00 00
ОК. Попробую сделать.
to Voron вы писали 16.03.2008, 00:48 --->
ДРУЗЬЯ, частично перечитал топ.. и с ужасом обнаружил что нет нормальной реализации глотания банок ХП, ГХП, ГЦП... тот вариант что предложил МКС предполагает предварительную подготовку скрипта.. т.е. после запуска скрипта следуют самому ручками глотнуть банки в нужной последовательности..
так вот скрипт суперский! Пасиба! Есть над чем подумать 8)
вот например, бафать баферы начинют все вместе! Со стороны палево полное. Дальше нету банок мп, я например играю боевым магом, мне сешка нужна как заливка + баф. Сешка-шилка сама себе не регенит манку, те у нее есть скил инвок например, + лопала б банки мп. И вот еще я играю в связке пп+se+бд. ставлю вместо ее - бд, скрипт зависает, тода как сешка в связке с пп бегают намано. Если можно дополнить скрипт, добавить в него бд, был бы полноценный скрипт. А так нареканий нету. Вчера укокошил варовскую патьку один 8))))) Правда был под бд друга 8) Хилит, ману льет как нужно. Хотя нет, не настроить для вара лечилку. те что бы начинали лечить при 95% хп. не понял как, при варе это жизнено важно 8) (буду еще искать)
ОГРОМНОЕ ПАСИБА ЗА ТВОЙ ТРУД! ЗА ТВОЙ СКРИПТ! ОН ЛУЧШИЙ!
ту Voron.
вопросец по твоему куску скрипта:
//YES- РУТ ПО АССИСТУ (4-я кнопка) либо переделать в какойто дебаф от каждого бафера он свой.. по ассисту все баферы какуюто куйню кинут на цель по ассисту..
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 06') then
begin
pck:='';
buf:= hstr('14') + OidgcpPotion0 + hstr('00 00 00 00'); // обычную хилку
if (OidgcpPotion0 <> '') then SendToServerEX(NameKom);
{ buf:=hstr('04') + IDAssistTarget + Bot1X + Bot1Y + Bot1Z + hstr('00');
if NameBot1<>'' then SendToServerEX(NameBot1);
buf:=hstr('04') + IDAssistTarget + Bot2X + Bot2Y + Bot2Z + hstr('00');
if NameBot2<>'' then SendToServerEX(NameBot2);
buf:=hstr('04') + IDAssistTarget + Bot3X + Bot3Y + Bot3Z + hstr('00');
if NameBot3<>'' then SendToServerEX(NameBot3);
buf:=hstr('2F B1 04 00 00 00 00 00 00 00');
if NameBot1<>'' then SendToServerEX(NameBot1);
buf:=hstr('2F B1 04 00 00 00 00 00 00 00');
if NameBot2<>'' then SendToServerEX(NameBot2);
buf:=hstr('2F B1 04 00 00 00 00 00 00 00');
if NameBot3<>'' then SendToServerEX(NameBot3);}
exit;
end;
что не так? баферы не кидают рут
подскажите я ещё токо седня начал разбираться я всё сделал по интрукции скрипта Бот - локомотив от Alexus
версия : 0.3 (бета)
дата: 08.04.08
Но при нажатии старт пишет не все параметры заданы
в чём же может дело Хотя я всё сделал как надо
Хроники6 клиент
Ой Ура разобрался
Желаю всем успехов по написанию ботов :) вы спасаите многих :)
Да ещё хотел добавить нехватает бафера-бота полноценного к примеру пп :) что бы просто ввести ник за кем бегать и бафать определёнными бафами ( просто и со вкусом )
boroda, все есть, поиск в руки........
ту Voron по поводу рута, очень нужный пункт оказался в твоем скрипте. Вроде все правильно на первый взгляд, но не работает этот кусок.
Alan, скобки фигурные убери { } - такие вот
Alan, скобки фигурные убери { } - такие вот
логично
Пасиба, ща буду тестить, Voron с возвращеницем 8)
Потестил, вместо рута жрет банки сп. нужно поменять пакет наверное, если ты еще тут подскажи какой, чичаз буду искать его.
АЛАН ну ты голова вапще...
ну сам подумай над текстом кода приведенным тобой.. кусок кода с киданием ДЕБАФА (рута и фикни всякой) закоментирован.. а лишний явно кусок кода ето выпивание ЦП (или ХП там) банок..
я думаю так что 2 строки относящиеся к выпивани. ХП-ЦП пробирок- там явно лишнии.. а то что закоменчено- явно- нужное..
почему так вышло? ну когда я функцию глотания банок внедрял то тестировал на принудительном выпивании етих пробирок и вот закоментил кусок кода с РУТам и вместо них вбил 2 строки принудительного глотания ЦП и ХП банок.. а когда всё сделал забыл стереть ети 2 строки и раскоментить то что в скобках..
VORON, +1 ответ кульный слав богу скрипта твоего не видел, он снова для всего и вся?
2F EF 03 00 00 00 00 00 00 00 chant of battle
48 A0 C7 00 00 9B 98 02 00 91 EC FF FF C1 92 00 00 00 00 00 00 chant of sheilding
это из пакета реквест меджик скилл юс... то это или я где то ошибся?
Добавлено через 8 часов 23 минуты
всё понял ошибку , для начинающих , каждый скил начинаеться с "2F", затем в 16-ом код скила:)
cat,
const
PPbafer = 'НИК';// ник бафера
buff =
['2F 3D 04 00 00 00 00 00 00 00 ', //Acumen
'2F 26 04 00 00 00 00 00 00 00 ', //BtS
'2F 15 04 00 00 00 00 00 00 00 ', //BtB
'2F 2C 04 00 00 00 00 00 00 00 ', //Might
'2F 10 04 00 00 00 00 00 00 00 ', //Shield
'2F 36 04 00 00 00 00 00 00 00 ', //concentration
'2F 35 04 00 00 00 00 00 00 00 ', //Focus
'2F DA 04 00 00 00 00 00 00 00 ', //DW
'2F D8 04 00 00 00 00 00 00 00 ', //Точночть
'2F B4 04 00 00 00 00 00 00 00 ', //WW
'2F 0C 04 00 00 00 00 00 00 00 ', // MB
'2F 0B 04 00 00 00 00 00 00 00 ', // Mental
'2F 3E 04 00 00 00 00 00 00 00 ', // Haste
'2F 48 05 00 00 00 00 00 00 00 ', // EP
'2F DB 04 00 00 00 00 00 00 00 ']; // щит
SS=0;
var
prof,x,y, SkilID, SkilHIT,PPbaferID : integer;
timer1, timer2: TTimer;
Target: string;
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(PPbafer);
WriteS(msg);
SendToClientEx(PPbafer);
end;
procedure Init; //Вызывается при включении скрипта
begin
//делаем таймер
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1;
timer1.enabled:=false;//по начал не баффаемся, толко по команде
timer1.interval:=200;// 0,2 секунды - начальный интервал таймера
end;
procedure InitStats;
begin
PPbaferID:=ReadD(18);
//Say('ID'+inttostr(PPbaferID));
end;
procedure OnTimer1(Sender: TObject);
begin
if x = 1 then
Say('Начинаем баффаццо');
buf:=hstr(buff[x]); //берем нужный элемент из массива
SendToServerEx(PPbafer);
inc(x); //увеличиваем х на 1
if x = 15 then
begin Say('Баффаццо вроде закончили');
Timer1.Enabled:=False; //закончили баффаццо - таймер отключили
x:=0;
end;
// Say('x='+inttostr(x))// так что б мониторить измение в чате
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer1.enabled:=false;
timer1.Free;
x:=0;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
if pck='' then exit;
if FromServer and (ConnectName=PPbafer) and (pck[1]=#$04) then InitStats;
if FromServer and (ConnectName=PPbafer) and ((pck[1]=#$48) and (ReadD(18)=SS)) then exit ;
if FromServer and (ConnectName=PPbafer) and (pck[1]=#$48)and (ReadD(2)=PPbaferID) then
begin
SkilHIT:=ReadD(18);
SkilID:= ReadD(10);
Timer1.Interval:=SkilHit+100; //ставим время отката скила +100 константа смешения тупо что б паузу сделать маленькую
// Say('Скил='+inttostr(SkilID)); // иди скрипта так для самопроверке кстате можно тестить бафы на ускорение каста и шмот
// Say('Откат='+inttostr(SkilHIT)); //время каста скила
end;
if FromClient and (pck[1]+pck[2]=#$38#$31) and (ConnectName=PPbafer)and(pck[3]=#$00) and (pck[4]=#$00) and (pck[5]=#$00)and (pck[6]=#$09) then //1- нажимаем в любой чат окуратней я пакет не убил
begin
pck:='';
prof:=1;
Timer1.Enabled:=True; //врубаем таймер
end;
// if prof=1 then begin
// y:=1;
// prof:=0;
// end;
end.
вот тут каст сдлан по изменению скорости каста скилов :) варк не самый быстрый но не надо парится с таймером
ну вообщем то бафает , хилит , теперь бы реализовать баф каждые 20 мин :) возможно ли ?:)
типа этого добавь:
var
timer3: TTimer;
procedure Init;
begin
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnBuff; //
timer3.enabled:=false; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
end;
procedure OnBuff(Sender: TObject); //баффы
begin
if (MyID<>0) and (sit=false) then begin
timer3.interval:=1 200 000; //каждые 20 мин (за вычетом времени самих бафов)
timer1.enabled:=true; //вкл. бафы
end;
end;
Нужен скрипт на спойлера, чтобы сам бегал спойлил и свипал мобов один, а не в парти с командиром.
напиши... или попробуй поиском воспользоваться ну так для разнообразия
20 мин баф так и не хочет работать, может кто подскажет где косячу :)
var
Bot1X,Bot1Y,Bot1Z:string; //координаты варки
IDAssistTarget:string; //таргет командира
rnd:integer; // вспомогательная для случайного события
bafWC: array [1..100] of string; //список бафов WС
NameKom,NameBot1:string; //имена чаров учавствующих в процессе
MaxHPKom,MaxHPBot1:integer; //максимальные уровни ХП (лимиты)
CurHPKom,CurHPBot1:integer; //текущие значения ХП
IDKomandos,IDbot1:string; // идешники командира и варки
timer4,timer3:TTimer; //таймеры бафа
i,x:integer;
tempS:String;
///////////////////////////////////////// buff's//////////////////////////////////////////////
procedure OnTimer4 (Sender: TObject);
begin
case x of
1: begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
SendToServerEX(NameBot1);
buf:=bafWC[6];
SendToServerEx(NameBot1);
x:=x+1;
end;
2: begin
buf:=bafWC[1];
SendToServerEx(NameBot1);
x:=x+1;
end;
3: begin
buf:=bafWC[2];
SendToServerEx(NameBot1);
x:=x+1;
end;
4: begin
buf:=bafWC[3];
SendToServerEx(NameBot1);
x:=x+1;
end;
5: begin
buf:=bafWC[4];
SendToServerEx(NameBot1);
x:=x+1;
end;
6: begin
buf:=bafWC[5];
SendToServerEx(NameBot1);
x:=x+1;
end;
7: begin
buf:=bafWC[7];
SendToServerEx(NameBot1);
x:=0;
timer4.enabled:=false;
end;
end;
end;
/////////////////////////
// buff 20min
procedure OnTimer3 (Sender: TObject); //баффы через 20 мин
begin
timer3.interval:=1150000; //каждые 20 мин (за вычетом времени самих бафов)
timer4.enabled:=true;//вкл. бафы
end;
//*************************БЕЖИМ ЗА ЛИДЕРОМ*******************************************
//процедура заставляет бежать ботов за лидером
procedure BotBeg;
begin
//проверяем условие чтоб координаты ботов небыли равными '' и ИД был перехвачен
if IDKomandos <> '' then
begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
end;
end;
procedure Init; //Вызывается при включении скрипта
begin
NameKom:='XXX'; //командир
NameBot1:='XXX'; //варка
//список бафов:
//само собой вы его можете расширить новыми бафами которых тут нет..
//это те бафы кторые я использую от ПП
bafWC[1]:=hstr('2F EF 03 00 00 00 00 00 00 00'); //chant of battle
bafWC[2]:=hstr('2F E5 04 00 00 00 00 00 00 00'); //chant of rage
bafWC[3]:=hstr('2F F1 03 00 00 00 00 00 00 00'); //chant of sheilding
bafWC[4]:=hstr('2F E4 04 00 00 00 00 00 00 00'); //chant of evansion
bafWC[5]:=hstr('2F EE 03 00 00 00 00 00 00 00'); //chant of fire ( m def )
bafWC[6]:=hstr('2F EA 03 00 00 00 00 00 00 00'); //flame chant ( acum )
bafWC[7]:=hstr('2F 1E 05 00 00 00 00 00 00 00'); // vampiric
//при старте скрипта значения переменных =0
//поетому скрипт подумает что у всех 0 ХП и начнется хаос.. все начнут друг друга хилить без остановки
//чтоб избежать етого выставим начальные значения.. то что ХП у нас- дожопы.. много.. 15к.. т.е. хилить ненадо.
//а потом скрипт сам захватит текущее знасение.. и всё коректно будет...
CurHPKom:=15000;
CurHPBot1:=15000;
//дело в том что скрипт расчитывает хилить или нет в зависимости от % от шкалы.. если вся шкала =0 (по дефолту)
//то ето както некоректно там будет хотя вроде пофиг..
//но для коректности понимания процесса мы пишем что максимальная шкала ХП у нас оч маленькая а текущие значения- оч большие..
//поетому никакие хилы небудут происходить при старте скрипта..
MaxHPKom:=10;
MaxHPBot1:=10;
//новый баф кастовать через 4 секунды
timer4:=TTimer.Create(nil);
timer4.OnTimer:=@OnTimer4; //
timer4.enabled:=false; //
timer4.interval:=5300; //5300 для варки
// добавляем функцию что бы бафал сам каждые 20 мин ( NLobP )
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3; //
timer3.enabled:=true; // таймер по умолчанию выключен
timer3.interval:=60000; // первый баф через 60 сек
// ЗАПРОС НА ОТКРЫТИЕ ИНВЕНТОРЯ!!!! ДЛЯ ЗАХВАТА ИДЕШНИКА!
// чтобы принудительно вызвать от сервера пакет ЮЗЕР ИНФО в котором ИД указан
//а также для того чтобы захвватить ИД банок для питья
buf:=hstr('0F');
SendToServerEX(NameKom);
SendToServerEX(NameBot1);
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer4.Free;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//для тго чтоб 2-3 скрипта коректно работали одновременно..
if pck='' then exit; // нех пустые пакеты обрабатывать типа
//*******************ЗАХВАТ КООРДИНАТ***************************************** **********
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot1 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot1X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot1Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot1Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//********************ОСТСЛЕЖИВАЕМ ТРУПАКИ******************************************* *************
//если кто то умер то приходит пакет DIE.. то хилить его ненадо...
//нефиг трупы хилить...
//для того чтоб трупяков боты не хилили ставим кодом то что ХП (текущее) у них до жопы... т.е. 15к
if FromServer then
if ConnectName=NameKom then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDKomandos then
CurHPKom:=15000;
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot1 then
CurHPBot1:=15000;
//*************************УЗНАЕМ ЛИМИТЫ ХП и МП и ИД***********************************************
//из пакета UserInfo который приходит во время бафа и не только
//как тока скрипт начинает свою работу то он на все аки отправляет запрос на открытие ИНВЕНТОРЯ
//вместе с ответом сервера всегда приходит пакет ЮЗЕР ИНФО.. из етого замечательного пакета мы считываем максимальные значения ХП и МП
//а так жэ ИД чара (бота- бафера)
//КОМАНДИР
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$04 then
begin
IDKomandos:=pck[18]+pck[19]+pck[20]+pck[21]; //тут выдергиваем ИД чара
i:=22;
tempS:=readS(i); // ето используем для удобства.. имя типа пропускаем.. потому как каждый раз оно из разного кол-ва букв состоит.. в скобках переменная автоматом увеличивается на кол-во букв (ну там по формуле.. в юникоде 1 буква=2 байта, и символ окончания строки еще 00 00)
i:=i+48; // через 48 байтофъ после имени указывается лимиты и текущие значения для ХП и МП
//запоминаем их.. тут нам не особо важны текущие значения.. хотя лишний раз не помешают
//но важно- максимальное значение- ЛИМИТЫ
MaxHPKom:=readD(i);
CurHPKOM:=readD(i);
end;
//1-й бот
if FromServer then
if ConnectName = NameBot1 then
if pck[1]=#$04 then
begin
IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot1:=readD(i);
CurHPBot1:=readD(i);
end;
//*************************СЛЕДИМ ЗА ХП и МП******************************************
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$0e then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$04) then
begin
//считываем текущее состояние ХП!!-)
CurHPKom:=ReadD(14);
//ну собственно ето уже можно править под желания каждого:
//если жизни текущие меньше 0,5 от шкалы (50%) то..
if (CurHPKom < round(MaxHPKom*0.5)) then
begin
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
SendToServerEX(NameBot1);
buf:=hstr('2F CD 04 00 00 00 00 00 00 00'); // chant of life
SendToServerEX(NameBot1);
end;
end;
//socialHELLO буф Война не по ассисту а по ИДкомандира т.е самого его
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 02') then // 02 - socialHELLO
begin
//убиваем этот пакет, чтоб сервер его не получил
pck:='';
// бафы
timer4.enabled:=true;
x:=1;
exit;
end;
end.
P.S велосипед не изобретал ;) --> VORON, Grinch, NLOpP (c)
хм извени твой скрипт для меня великовать не могу концов найти для смотри скрипт БД танцует нонстоп:
const //баффы
b1='2F 0F 01 00 00 00 00 00 00 00'; // Wариор
b2='2F 13 01 00 00 00 00 00 00 00 '; // Хаст БД
b3='2F 36 01 00 00 00 00 00 00 00';
var
IDPartyMember, IDAssistTarget: String; //ИД командира и ИД его таргета и Собственный ИД
CoordBufX, CoordBufY, CoordBufZ :String; //координаты бота
NameBuffer, NameKomandos : String; // Имена
x: integer;
timer1: TTimer;
timer2: TTimer;
// ну процедура бега как я понял тупо таргет по командиру :)
procedure bRun;
begin
if (CoordBufX <> '') and (IDPartyMember <> '') then
begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDPartyMember + CoordBufX + CoordBufY + CoordBufZ + hstr('00');
SendToServerEX(NameBuffer);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDPartyMember + CoordBufX + CoordBufY + CoordBufZ + hstr('00');
SendToServerEX(NameBuffer);
end;
end;
//сам ребаф таймер и колисество наращиваем сами только копируя под цифрой один и ставим перед
// цифрой 3 ну и перебиваем соответвено что б не повторялись цыфры
procedure OnTimer(Sender: TObject);
begin
case x of
1: begin
buf:=hstr(b1);
SendToServerEx(NameBuffer);
x:=x+1;
end;
2: begin
buf:=hstr(b2);
SendToServerEx(NameBuffer);
x:=x+1;
end;
3: begin
buf:=hstr(b3);
SendToServerEx(NameBuffer);
x:=x+1;
end;
4: begin
bRun;
SendToServerEx(NameBuffer);
x:=x+1;
timer1.enabled:=false;
end;
5: begin
SendToServerEx(NameBuffer);
x:=0;
timer2.enabled:=false;
timer1.enabled:=false;//стацевали самое смешное как мне казалось реденса не должно быть
end;
end;
end;
procedure OnTimer2(Sender: TObject);
begin
timer1.enabled:=true;
x:=1;
end;
procedure Init; //Вызывается при включении скрипта
begin
NameBuffer:='xxZZxxZZxx'; //ну имя БД или свс у кого что есть
NameKomandos:='yyZZyyZZyy'; //командоса имя
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer;
timer1.enabled:=false;
timer1.interval:=3000;
x:=0;
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2;
timer2.enabled:=false;
timer2.interval:=127000; // тут короче по формуле что б мана не летела у свса или бд
// кол. песен в бафе * 2000 +1000+120000 =2*2000+1000+120000=125000
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer1.Free;
timer2.Free;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
// это часть для меня осталась тайна
begin
if pck='' then exit;
//если от сервака принят пакет с ИД и Координатами членов пати то
if FromServer and (pck[1]=#$a7) then
begin
//запоминаем ИД командира
IDPartyMember:=pck[6] + pck[7] + pck[8] + pck[9];
end;
//если принят пакет от клиента с кординатами бафера то
if FromClient and (ConnectName=NameBuffer) and (pck[1]=#$48) then
begin
//запоминаем координаты
CoordBufX:= pck[6] + pck[7] + pck[8] + pck[9];
CoordBufY:= pck[10] + pck[11] + pck[12] + pck[13];
CoordBufZ:= pck[14] + pck[15] + pck[16] + pck[17];
end;
//далее идут управляющие команды
// если КОМАНДИР пишет в пати чат цифру "4" (ребаф) как я понял это (pck[6]=#$03)
// ксли убрать этот байт то в любой, но кому как мне так удобней
if FromClient and (ConnectName=NameKomandos)and (pck[1]=#$38) then
if (pck[2]=#$31) and (pck[3]=#$00) and (pck[4]=#$00) and (pck[5]=#$00)and (pck[6]=#$03) then
begin
//убиваем этот пакет, чтоб сервер его не получил
pck:='';
//Бафер БЕЖИТ за КОМАНДИРОМ
bRun;
//выйти из рабочей части скрипта чтобы другие услови не проверяли убитый пакет нулевой длинны
exit;
end;
// если КОМАНДИР пишет в пати чат цифру "4" (ребаф) как я понял это (pck[6]=#$03)
// ксли убрать этот байт то в любой, но кому как мне так удобней
if FromClient and (ConnectName=NameKomandos)and (pck[1]=#$38) then
if (pck[2]=#$34) and (pck[3]=#$00) and (pck[4]=#$00) and (pck[5]=#$00)and (pck[6]=#$03) then
begin
//убиваем этот пакет, чтоб сервер его не получил
pck:='';
timer1.enabled:=true;
timer2.enabled:=true;
x:=1;
//выйти из рабочей части скрипта чтобы другие услови не проверяли убитый пакет нулевой длинны
exit;
end;
// вырубаем скрипт
if FromClient and (ConnectName=NameKomandos)and (pck[1]=#$38) then
if (pck[2]=#$30) and (pck[3]=#$00) and (pck[4]=#$00) and (pck[5]=#$00)and (pck[6]=#$03) then
begin
//убиваем этот пакет, чтоб сервер его не получил
pck:='';
timer1.enabled:=false;
timer2.enabled:=false;
x:=1;
//выйти из рабочей части скрипта чтобы другие услови не проверяли убитый пакет нулевой длинны
exit;
end;
end.[/CODE]
Добавлено через 8 минут
и по пунктам напиши что делает твой скрипт с первого приближения твои задачи можно проще реализовать.
вообщем весь прикол что при старте таймера на 20 мин баф , не передавал значение x:=1; вот и всё )) "смотрим в книгу , видим фигу" :)
работает вместе с LxAssistent )
надо отладить до конца, затем выложу :)
var
Bot1X,Bot1Y,Bot1Z:string; //координаты варки
IDAssistTarget:string; //таргет командира
rnd:integer; // вспомогательная для случайного события
bafWC: array [1..100] of string; //список бафов WС
NameKom,NameBot1:string; //имена чаров учавствующих в процессе
MaxHPKom,MaxHPBot1:integer; //максимальные уровни ХП (лимиты)
CurHPKom,CurHPBot1:integer; //текущие значения ХП
IDKomandos,IDbot1:string; // идешники командира и варки
timer4,timer3,timer5:TTimer; //таймера бафа
i,x:integer;
tempS:String;
///////////////////////////////////////// buff's//////////////////////////////////////////////
procedure OnTimer4 (Sender: TObject);
begin
case x of
1: begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
SendToServerEX(NameBot1);
buf:=bafWC[6];
SendToServerEx(NameBot1);
x:=x+1;
end;
2: begin
buf:=bafWC[1];
SendToServerEx(NameBot1);
x:=x+1;
end;
3: begin
buf:=bafWC[2];
SendToServerEx(NameBot1);
x:=x+1;
end;
4: begin
buf:=bafWC[3];
SendToServerEx(NameBot1);
x:=x+1;
end;
5: begin
buf:=bafWC[4];
SendToServerEx(NameBot1);
x:=x+1;
end;
6: begin
buf:=bafWC[5];
SendToServerEx(NameBot1);
x:=x+1;
end;
7: begin
buf:=bafWC[7];
SendToServerEx(NameBot1);
x:=0;
timer4.enabled:=false;
end;
end;
end;
/////////////////////////
// buff 20min
procedure Buff (Sender: TObject); //баффы через 20 мин
begin
x:=1;
timer4.enabled:=true;//вкл. бафы
timer3.interval:=1150000; //каждые 20 мин (за вычетом времени самих бафов)
end;
procedure heal (Sender: TObject);
begin
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
SendToServerEX(NameBot1);
buf:=hstr('2F CD 04 00 00 00 00 00 00 00'); // chant of life
SendToServerEX(NameBot1);
timer5.enabled:=false;
end;
procedure Init; //Вызывается при включении скрипта
begin
NameKom:='XXX'; //командир
NameBot1:='XXX'; //варка
//список бафов:
//само собой вы его можете расширить новыми бафами которых тут нет..
//это те бафы кторые я использую от ПП
bafWC[1]:=hstr('2F EF 03 00 00 00 00 00 00 00'); //chant of battle
bafWC[2]:=hstr('2F E5 04 00 00 00 00 00 00 00'); //chant of rage
bafWC[3]:=hstr('2F F1 03 00 00 00 00 00 00 00'); //chant of sheilding
bafWC[4]:=hstr('2F E4 04 00 00 00 00 00 00 00'); //chant of evansion
bafWC[5]:=hstr('2F EE 03 00 00 00 00 00 00 00'); //chant of fire ( m def )
bafWC[6]:=hstr('2F EA 03 00 00 00 00 00 00 00'); //flame chant ( acum )
bafWC[7]:=hstr('2F 1E 05 00 00 00 00 00 00 00'); // vampiric
//при старте скрипта значения переменных =0
//поетому скрипт подумает что у всех 0 ХП и начнется хаос.. все начнут друг друга хилить без остановки
//чтоб избежать етого выставим начальные значения.. то что ХП у нас- дожопы.. много.. 15к.. т.е. хилить ненадо.
//а потом скрипт сам захватит текущее знасение.. и всё коректно будет...
CurHPKom:=15000;
CurHPBot1:=15000;
//дело в том что скрипт расчитывает хилить или нет в зависимости от % от шкалы.. если вся шкала =0 (по дефолту)
//то ето както некоректно там будет хотя вроде пофиг..
//но для коректности понимания процесса мы пишем что максимальная шкала ХП у нас оч маленькая а текущие значения- оч большие..
//поетому никакие хилы небудут происходить при старте скрипта..
MaxHPKom:=10;
MaxHPBot1:=10;
//новый баф кастовать через 4 секунды
timer4:=TTimer.Create(nil);
timer4.OnTimer:=@OnTimer4; //
timer4.enabled:=false; //
timer4.interval:=5300; //5300 для варки
timer5:=TTimer.Create(nil);
timer5.OnTimer:=@heal;
timer5.enabled:=false;
timer5.interval:=3000; // делаем задержку между лечениями 30 сек
// добавляем функцию что бы бафал сам каждые 20 мин ( NLobP )
//баффы
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@Buff; //
timer3.enabled:=True; // таймер по умолчанию выключен
timer3.interval:=30000; // первый баф через 60 сек
// ЗАПРОС НА ОТКРЫТИЕ ИНВЕНТОРЯ!!!! ДЛЯ ЗАХВАТА ИДЕШНИКА!
// чтобы принудительно вызвать от сервера пакет ЮЗЕР ИНФО в котором ИД указан
//а также для того чтобы захвватить ИД банок для питья
buf:=hstr('0F');
SendToServerEX(NameKom);
SendToServerEX(NameBot1);
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer4.Free;
timer3.Free;
timer5.Free;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//для тго чтоб 2-3 скрипта коректно работали одновременно..
if pck='' then exit; // нех пустые пакеты обрабатывать типа
//*******************ЗАХВАТ КООРДИНАТ***************************************** **********
//если принят пакет от клиента с кординатами бота то
if FromClient then
if ConnectName=NameBot1 then
if pck[1]=#$48 then
begin
//запоминаем координаты
Bot1X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot1Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot1Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
//********************ОСТСЛЕЖИВАЕМ ТРУПАКИ******************************************* *************
//если кто то умер то приходит пакет DIE.. то хилить его ненадо...
//нефиг трупы хилить...
//для того чтоб трупяков боты не хилили ставим кодом то что ХП (текущее) у них до жопы... т.е. 15к
if FromServer then
if ConnectName=NameKom then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDKomandos then
CurHPKom:=15000;
if FromServer then
if ConnectName=NameBot1 then
if pck[1]=#$06 then
if pck[2] + pck[3] + pck[4] + pck[5] = IDBot1 then
CurHPBot1:=15000;
//*************************УЗНАЕМ ЛИМИТЫ ХП и МП и ИД***********************************************
//из пакета UserInfo который приходит во время бафа и не только
//как тока скрипт начинает свою работу то он на все аки отправляет запрос на открытие ИНВЕНТОРЯ
//вместе с ответом сервера всегда приходит пакет ЮЗЕР ИНФО.. из етого замечательного пакета мы считываем максимальные значения ХП и МП
//а так жэ ИД чара (бота- бафера)
//КОМАНДИР
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$04 then
begin
IDKomandos:=pck[18]+pck[19]+pck[20]+pck[21]; //тут выдергиваем ИД чара
i:=22;
tempS:=readS(i); // ето используем для удобства.. имя типа пропускаем.. потому как каждый раз оно из разного кол-ва букв состоит.. в скобках переменная автоматом увеличивается на кол-во букв (ну там по формуле.. в юникоде 1 буква=2 байта, и символ окончания строки еще 00 00)
i:=i+48; // через 48 байтофъ после имени указывается лимиты и текущие значения для ХП и МП
//запоминаем их.. тут нам не особо важны текущие значения.. хотя лишний раз не помешают
//но важно- максимальное значение- ЛИМИТЫ
MaxHPKom:=readD(i);
CurHPKOM:=readD(i);
end;
//1-й бот
if FromServer then
if ConnectName = NameBot1 then
if pck[1]=#$04 then
begin
IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot1:=readD(i);
CurHPBot1:=readD(i);
end;
//*************************СЛЕДИМ ЗА ХП и МП******************************************
if FromServer then
if ConnectName = NameKom then
if pck[1]=#$0e then
if (pck[2] + pck[3] + pck[4] + pck[5] + pck[6] = IDKomandos + #$04) then
begin
//считываем текущее состояние ХП!!-)
CurHPKom:=ReadD(14);
//ну собственно ето уже можно править под желания каждого:
//если жизни текущие меньше 0,7 от шкалы (50%) то..
if (CurHPKom < round(MaxHPKom*0.5)) then
timer5.enabled:=true;
end;
//socialHELLO буф Война не по ассисту а по ИДкомандира т.е самого его
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 02') then // 02 - socialHELLO
begin
//убиваем этот пакет, чтоб сервер его не получил
pck:='';
// бафы
timer4.enabled:=true;
x:=1;
exit;
end;
//"Bow" (ПОКЛОН)- включаем автобаф
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 07') then
begin
pck:='';
timer3.enabled:=true;
exit;
end;
end.
Щас орк подрастёт, добавлю весь баф ) привязывать следование за командиром и остальное не стал, хорошо работает LxAssistent так что вот :) Бот умеет только , сам лечить на 50% хп (можно поставить по желанию) и бафать каждые 20 мин ) Думаю кому надо , могут ввести проверки на наличие маны, не сидит ли бот , и т.п. возможно пойже выложу )
cat, тебя чем предыдущий скрипт не устраивает? Чуть перенастроил под варка и вперед, а так - совсем нерационально получилось.
QaK, с мягким знаком =) точней Квак мягко выразился держать константы в масиве динамическом эт изврат я конечно не программер, но эт из зенитници по воробьям
да нет в нем ни каких извратов :) массив только ... остальное заимствовано, для лечения , и нормально работает ) ... осталось , как я уже говорил, добавить проверки на ману.
cat, проверь скрипт плиз
var
Bot1X,Bot1Y,Bot1Z:string; //координаты варки
IDAssistTarget:string; //таргет командира
rnd:integer; // вспомогательная для случайного события
bafWC: array [1..100] of string; //список бафов WС
NameKom,NameBot1 : string; //имена чаров учавствующих в процессе
MaxHPKom,MaxHPBot1 : integer; //максимальные уровни ХП (лимиты)
CurHPKom,CurHPBot1 : integer; //текущие значения ХП
IDKomandos,IDbot1:string; // идешники командира и варки
timer1,timer2 : TTimer; //таймеры бафа
i,x:integer;
tempS:String;
procedure Init; //Вызывается при включении скрипта
begin
NameKom:='XXX'; //командир
NameBot1:='XXX'; //варка
//список бафов:
//само собой вы его можете расширить новыми бафами которых тут нет..
//это те бафы кторые я использую от ПП
bafWC[1]:=hstr('2F EF 03 00 00 00 00 00 00 00'); //chant of battle
bafWC[2]:=hstr('2F E5 04 00 00 00 00 00 00 00'); //chant of rage
bafWC[3]:=hstr('2F F1 03 00 00 00 00 00 00 00'); //chant of sheilding
bafWC[4]:=hstr('2F E4 04 00 00 00 00 00 00 00'); //chant of evansion
bafWC[5]:=hstr('2F EE 03 00 00 00 00 00 00 00'); //chant of fire ( m def )
bafWC[6]:=hstr('2F EA 03 00 00 00 00 00 00 00'); //flame chant ( acum )
bafWC[7]:=hstr('2F 1E 05 00 00 00 00 00 00 00'); //vampiric
//при старте скрипта значения переменных =0
//поэтому скрипт подумает что у всех 0 ХП и начнется хаос.. все начнут друг друга хилить без остановки
//чтоб избежать етого выставим начальные значения.. то что ХП у нас- дожопы.. много.. 15к.. т.е. хилить ненадо.
//а потом скрипт сам захватит текущее знасение.. и всё коректно будет...
CurHPKom:=15000;
CurHPBot1:=15000;
//дело в том что скрипт расчитывает хилить или нет в зависимости от % от шкалы.. если вся шкала =0 (по дефолту)
//то ето както некоректно там будет хотя вроде пофиг..
//но для коректности понимания процесса мы пишем что максимальная шкала ХП у нас оч маленькая а текущие значения- оч большие..
//поетому никакие хилы небудут происходить при старте скрипта..
MaxHPKom:=10;
MaxHPBot1:=10;
// добавляем функцию что бы бафал сам каждые 20 мин ( NLobP )
//баффы
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@Ontimer1;
timer1.enabled:=true; // таймер по умолчанию выключен
timer1.interval:=60000; // первый баф через 60 сек
//новый баф кастовать через 4 секунды
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@Ontimer2; //
timer2.enabled:=false; //
timer2.interval:=5300; //5300 для варки
// ЗАПРОС НА ОТКРЫТИЕ ИНВЕНТОРЯ!!!! ДЛЯ ЗАХВАТА ИДЕШНИКА!
// чтобы принудительно вызвать от сервера пакет ЮЗЕР ИНФО в котором ИД указан
//а также для того чтобы захвватить ИД банок для питья
buf:=hstr('0F');
SendToServerEX(NameKom);
SendToServerEX(NameBot1);
end;
procedure Free; //Вызывается при выключении скрипта
begin
timer1.Free;
timer2.Free;
end;
/////////////////////////
// buff 20min
procedure Ontimer1 (Sender: TObject); //баффы через 20 мин
begin
timer1.interval:=1200000; //каждые 20 мин (за вычетом времени самих бафов)
x:=1;
timer2.enabled:=true;//вкл. бафы
end;
///////////////////////////////////////// buff's//////////////////////////////////////////////
procedure Ontimer2 (Sender: TObject);
begin
case x of
1: begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04')+IDKomandos+Bot1X+Bot1Y+Bot1Z+hstr( '00');
SendToServerEX(NameBot1);
buf:=bafWC[6];
SendToServerEx(NameBot1);
inc(x);
end;
2: begin
buf:=bafWC[1];
SendToServerEx(NameBot1);
inc(x);
end;
3: begin
buf:=bafWC[2];
SendToServerEx(NameBot1);
inc(x);
end;
4: begin
buf:=bafWC[3];
SendToServerEx(NameBot1);
inc(x);
end;
5: begin
buf:=bafWC[4];
SendToServerEx(NameBot1);
inc(x);
end;
6: begin
buf:=bafWC[5];
SendToServerEx(NameBot1);
inc(x);
end;
7: begin
buf:=bafWC[7];
SendToServerEx(NameBot1);
x:=0;
timer2.enabled:=false;
end;
end;
end;
//*************************БЕЖИМ ЗА ЛИДЕРОМ*******************************************
//процедура заставляет бежать ботов за лидером
procedure BotBeg;
begin
//проверяем условие чтоб координаты ботов небыли равными '' и ИД был перехвачен
if IDKomandos <> '' then begin
//выделяем командира, эмулируя щелчек мыши
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
//бежим за командиром эмулируя повторный щелчек мыши по таргету
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
if IDBot1<>'' then SendToServerEX(NameBot1);
end;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//************************************************** **************************
//для того чтоб 2-3 скрипта коректно работали одновременно..
if pck='' then exit; // нех пустые пакеты обрабатывать типа
//************************************************** **************************
if (ConnectName=NameBot1) and FromClient then begin
case pck[1] of
//*******************ЗАХВАТ КООРДИНАТ***************************************** **********
//если принят пакет от клиента с кординатами бота то
#$48: begin
//запоминаем координаты
Bot1X:= pck[2] + pck[3] + pck[4] + pck[5];
Bot1Y:= pck[6] + pck[7] + pck[8] + pck[9];
Bot1Z:= pck[10] + pck[11] + pck[12] + pck[13];
end;
#$1B: begin
case ReadD(2) of
//социальное действие Hello для начала ловли
2: begin
//вкл. бафы
timer1.enabled:=true;
//убиваем этот пакет, чтоб сервер его не получил
pck:='';
exit;
end;
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=NameKom) and FromServer then begin
case pck[1] of
//********************ОСТСЛЕЖИВАЕМ ТРУПАКИ******************************************* *************
//если кто то умер то приходит пакет DIE.. то хилить его ненадо...
//нефиг трупы хилить...
//для того чтоб трупяков боты не хилили ставим кодом то что ХП (текущее) у них до жопы... т.е. 15к
//КОМАНДИР
#$06: begin
if pck[2]+pck[3]+pck[4]+pck[5]=IDKomandos then CurHPKom:=15000;
end;
//*************************УЗНАЕМ ЛИМИТЫ ХП и МП и ИД***********************************************
//из пакета UserInfo который приходит во время бафа и не только
//как тока скрипт начинает свою работу то он на все аки отправляет запрос на открытие ИНВЕНТОРЯ
//вместе с ответом сервера всегда приходит пакет ЮЗЕР ИНФО.. из етого замечательного пакета мы считываем максимальные значения ХП и МП
//а так жэ ИД чара (бота- бафера)
//КОМАНДИР
#$04: begin
IDKomandos:=pck[18]+pck[19]+pck[20]+pck[21]; //тут выдергиваем ИД чара
i:=22;
tempS:=readS(i); //ето используем для удобства.. имя типа пропускаем.. потому как каждый раз оно из разного кол-ва букв состоит.. в скобках переменная автоматом увеличивается на кол-во букв (ну там по формуле.. в юникоде 1 буква=2 байта, и символ окончания строки еще 00 00)
i:=i+48; //через 48 байтофъ после имени указывается лимиты и текущие значения для ХП и МП
//запоминаем их.. тут нам не особо важны текущие значения.. хотя лишний раз не помешают
//но важно- максимальное значение- ЛИМИТЫ
MaxHPKom:=readD(i);
CurHPKOM:=readD(i);
end;
//*************************СЛЕДИМ ЗА ХП и МП******************************************
#$0E: begin
if (pck[2]+pck[3]+pck[4]+pck[5]+pck[6]=IDKomandos+#$04) then begin
//считываем текущее состояние ХП!!-)
CurHPKom:=ReadD(14);
//ну собственно ето уже можно править под желания каждого:
//если жизни текущие меньше 0,5 от шкалы (50%) то..
if (CurHPKom < round(MaxHPKom*0.5)) then begin
buf:=hstr('04') + IDKomandos + Bot1X + Bot1Y + Bot1Z + hstr('00');
SendToServerEX(NameBot1);
buf:=hstr('2F CD 04 00 00 00 00 00 00 00'); //chant of life
SendToServerEX(NameBot1);
end;
end;
end;
end;
end;
//************************************************** **************************
if (ConnectName=NameBot1) and FromServer then begin
case pck[1] of
//********************ОСТСЛЕЖИВАЕМ ТРУПАКИ******************************************* *************
//если кто то умер то приходит пакет DIE.. то хилить его ненадо...
//нефиг трупы хилить...
//для того чтоб трупяков боты не хилили ставим кодом то что ХП (текущее) у них до жопы... т.е. 15к
//БОТ1
#$06: begin
if pck[2]+pck[3]+pck[4]+pck[5]=IDBot1 then CurHPBot1:=15000;
end;
//*************************УЗНАЕМ ЛИМИТЫ ХП и МП и ИД***********************************************
//из пакета UserInfo который приходит во время бафа и не только
//как тока скрипт начинает свою работу то он на все аки отправляет запрос на открытие ИНВЕНТОРЯ
//вместе с ответом сервера всегда приходит пакет ЮЗЕР ИНФО.. из етого замечательного пакета мы считываем максимальные значения ХП и МП
//а так жэ ИД чара (бота- бафера)
//БОТ1
#$04: begin
if pck[1]=#$04 then begin
IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
i:=22;
tempS:=readS(i);
i:=i+48;
MaxHPBot1:=readD(i);
CurHPBot1:=readD(i);
end;
end;
end;
end;
end.
в каком смысле проверь, на работоспасобность? , на глаз вижу что это старый который я выкладывал неотлаженый ... :) нет таймера на лечение, у орка каст спид маловат, да и лечение , не лечение а реген , по этому надо вводить задержку, себе поставил 3сек... можно увеличить до 5-6, фунция с (bow) оставлена ибо если timer3 по умолчанию выключить, то включать его надо же чем то ) и функцию BotBeg можно удалить :) она не используеться, так сказать это остатки от эволюции ^^
Проверить на факт бафанья каждые 20 минут. Ты же это просил?
Ребят, вы чего огород городите?
///////////////////////////////////////// buff's//////////////////////////////////////////////
procedure Ontimer2 (Sender: TObject);
begin if x=1 then begin //выделяем командира, эмулируя щелчек мыши
buf:=hstr('04')+IDKomandos+Bot1X+Bot1Y+Bot1Z+hstr( '00');
SendToServerEX(NameBot1);
inc(x);
end
else begin buf:=bafWC[x-1];
SendToServerEx(NameBot1);
inc(x);
if x=9 then begin x:=0;
timer2.enabled:=false;
end;
end;
end;
так не проще?
Друзья.. а цель какая создовать скрипт- "СБОРНАЯ СССР".. с мира по нитке заточеный под варка?.. цель моего скрипта выложеного тут была объединить общим подходом ПП+ШЕ+ЕЕ+БИШ.. если вы делаете что то под себя и скрипт вас неустраивает сделайте так чтоб старые функции сохранить а новые- добавить а не то что 70% скрипта удалить и сделать привязку тока к варкраеру.. уж если делаете то делать надо скрипт универсальный.. чтоб запуская его не париться каой набор баферов в данный момент используется.. чтоб скрипт работал норм при любом наборе баферов.. (включаяя варкраера)..
че толку милион версий одной фикни плодить?.. если уж делаеш ребаф через 20 минут то неудаляй функции от прежнего скрипта а наоборот доработай его сохранив работоспособность всех функций тех что были уже...
VORON, тут ты не прав для многих людей наличие левого кода функций и т.д. лишнее напряжение копчика и мозгов, лично меня не прёт отлаживать скрипт в 500 строк когда то что мне нужно занимает 50.
дык хрен с ним с мозгом, а вот нервы на копчике не восстановить.
Добавлено через 4 минуты
работу с длл прикрутить нормальную тогда можно будет думать об универсальных скриптах от авто банок цп тупо до встраивания в авто цп и до автокача, т.е. бота писать.
Понравился ботик -->
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
Вот вопрос:
1) - Подскажите как сделать чтоб бот выбирал по базе, атакавать ближних мобов от чара а не случайно выбраного?
2) - Подскажите пакетик на количество адены в инвентаре?
Заранее спасибо (извиняюсь за ошибки в тексте)
VORON, тут ты не прав для многих людей наличие левого кода функций и т.д. лишнее напряжение копчика и мозгов, лично меня не прёт отлаживать скрипт в 500 строк когда то что мне нужно занимает 50.
дык хрен с ним с мозгом, а вот нервы на копчике не восстановить.
ну есть такое.. код под себя проще обрезать (готовый) и немного дополнить.. но топик превращается непоймеш во что в таком случае.. общго вектора развития нету.. я бы хотел чтоб появился скрипт запуская который не париться для каково именно он сапорта разработан или для кково набора сапортов..
получается щас так что.. новые функция для скрипта придуманы- (ребаф через 20 минут) но ето привязано тока к варку.. и как следствие после етого будем одижидать еще 7 версий скрипта с етой функцией (ребафа) привязанной для других проф.. топ мусорится одним и темже..
предлагаю всётки взять за основу что то, и именно дополнять то что есть уже.. доделывать не удаляя куски кода..
тогда хоть какаято хронология будет видна в развитии топа..
ГРИНИЧ, неспорю тяжело чужой код читать.. но в помощ- знания руссково языка.. и знак "//" вапще не люблю код чужой который непрокоментирован нужным образом.. сидиш поорой 10 минут для того чтобы понять что означает переменная ХХХ.. я сторался всегда свой код максимально коментить для понимания другими.. и тогоже жду от других..
выход должен быть.. плодить милион версий одного и тогоже в етом топе- смысла не имеет..
ну есть такое.. код под себя проще обрезать (готовый) и немного дополнить.. но топик превращается непоймеш во что в таком случае.. общго вектора развития нету.. я бы хотел чтоб появился скрипт запуская который не париться для каково именно он сапорта разработан или для кково набора сапортов..
получается щас так что.. новые функция для скрипта придуманы- (ребаф через 20 минут) но ето привязано тока к варку.. и как следствие после етого будем одижидать еще 7 версий скрипта с етой функцией (ребафа) привязанной для других проф.. топ мусорится одним и темже..
предлагаю всётки взять за основу что то, и именно дополнять то что есть уже.. доделывать не удаляя куски кода..
тогда хоть какаято хронология будет видна в развитии топа..
ГРИНИЧ, неспорю тяжело чужой код читать.. но в помощ- знания руссково языка.. и знак "//" вапще не люблю код чужой который непрокоментирован нужным образом.. сидиш поорой 10 минут для того чтобы понять что означает переменная ХХХ.. я сторался всегда свой код максимально коментить для понимания другими.. и тогоже жду от других..
выход должен быть.. плодить милион версий одного и тогоже в етом топе- смысла не имеет..
ну дык я без особой необходимости не выкладываю свои скрипты, просто так выкладывал только 2, на определения принадлежности к многоугольнику, и на ускореный каст на примере пп, но ускореный каст к пп мало отношение имеет к баферам если честно он ращитан на реюз скилов магом :) в том случае когда у нас танци и сонги есть на откат и т.д. что б не париться с константами вот а так не вижу смысла выкладывать общий скрипт на ребаф т.к. я его ещё не писал жду 4-й версии программки. вот есть скрипт на отображения реюза скилов в систем чате нужен разве кому вот и не выкладываю :)
APXAHGEJI
11.05.2008, 21:42
Незнаю канечно, нодумаю что чем чем жирнее скрипт тем дольше он выполянется, в нем больше багов и тд и тп.
Хотя бесспорно идея глобального скрипта объединяющего всех
баферов и множество других функций хороша.
Так может сделать его более модульным, распределить всё по ДЛЛкам
чтобы можно было подключать только при надобности.
кол-во строк невлияет по сути на быстродействие.. важна общааяя политика написания скрипрта..
сматрите.. вот например код
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
BEGIN
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 04') then then
begin end;
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 04') then then
begin end;
if FromClient then
if ConnectName=NameKom then
if pck[1]+pck[2]=hstr('1B 04') then then
begin end;
END.
все скрипты мы именно по такой схеме делаем.. причем ифы- проверяют входящий или исходящий пакет..
и конект проверяют.. можно сделать в скрипте блоки= что существенно ускорит процесс..
например:
BEGIN
if FromClient then
begin
if ConnectName=NameKom then
begin
/// // // // //
end;
if ConnectName=NameBot then
begin
/// // // // //
end;
end;
if FromSERVER then
begin
if ConnectName=NameKom then
begin
/// // // // //
end;
if ConnectName=NameBot then
begin
/// // // // //
end;
end;
END.
и все обработчики пакета помешать внутри блока таким образом мы економим быстродействие компа..
по сути за 1 проход скрипт всеголиш 2 обработчика принять должен ВХОДЯЩИЙ ИЛИ ИСХОДЯЩИЙ..
далее внутри каждого блока- обработать КОНЕКТ НЕЙМ.. а уже далее выполнить код..
т.е. если сделать такую вот блочность.. то быстродействие скрипта повысится за счет того что скрипт каждый раз не будет проверять 30 ИФОВ.. 50% скорости- обеспечено за счет того что ифа всего 2 вначале- КЛИЕНТ ИЛИ СЕРВЕР.. всё остальное- в блоках предназначенных для етого направления..
быстродействие скрипта повысится.. но.. станет сложнее куски кода периносить из одного скрипта в другой..
nezabudkin
12.05.2008, 13:59
Столкнулся я тут вот с чем...
В своем боте решил попробовать вести базу всех мобов в области видимости самого клиента, в общем запоминать всех мобов о которых сообщает сервер.
Для добавления моба отслеживаю пакет #$16: NpcInfo
Для изменения координат моба #$01: MoveToLocation
Для удаления моба из базы #$12: DeleteObject
И вот на что нарвался, что постепенно в течении нескольких часов база мобов растет и растет до неприличных размеров, так например. Когда входишь в каты, мобов в области видимости примерно 60, если тупо постоять там часа 3, мобов становится уже 120 - 150.
Может я какой-нить пакет не знаю с удалением моба?
В самом скрипте ошибок вроде нет...
Вот думаю добавлять к описанию моба засечки по времени последнего обновления, и например, мобов которые не шелохнулись в течении 20 минут, удалать из базы...
Прав ли я?
Или все же у меня скрипт глюки ловит?
Скорее всего где-то в скрипте косяк. Мой намана мобов добавляет/удаляет ... могу сюда кинуть, если надо кому-то, только у мну заготовка для другого дела ... так что сыроватая она, но рабочая =)
APXAHGEJI
12.05.2008, 17:13
VORON, да я согласен что блоки ускоряют работу, и более того я
в своих скриптах только так и делаю.
Но если взять к примеру мой сраный автосвип (нацеленый на полеарм оружие), то в случае когда мобы умирали одновременно парою ни все из них вносились в базу и в итоге...
Добавлено через 24 минуты
Кстати увидит ли свет новая версия твоего замечательного срипта уже с переделанной скоростью бафа под каст баферов и ребафом по таймеру?
А может и с какими то иными крутыми фишками.
Добавлено через 11 минут
И у меня еще вопрос.
Влияет ли на скорость работы скрипта использование стринговых переменных вместо интовых? Например I:= pck[1]+pck[2] вместо I:=ReadH(1) и тд.
Базы вещей, мобов, координат и тд в виде строк мне кажется использовать не экономично по отноению к памяти, а вот быстродействие как?
nezabudkin
12.05.2008, 19:34
Скорее всего где-то в скрипте косяк. Мой намана мобов добавляет/удаляет ...
А может ли скрипт до окончания обработки предыдущего пакета (какой-нить длинный цикл) начать обрабатывать следующий пришедший пакет?
Или например, пришел пакет, который надо долго обрабатывать, и тут сработал один из таймеров?
Что произойдет?
И вообще, если мы в катах сидим, то сколько примерно мобов мы будем мониторить?
А может ли скрипт до окончания обработки предыдущего пакета (какой-нить длинный цикл) начать обрабатывать следующий пришедший пакет?
Или например, пришел пакет, который надо долго обрабатывать, и тут сработал один из таймеров?
Что произойдет?
И вообще, если мы в катах сидим, то сколько примерно мобов мы будем мониторить?
про пакеты и обработку вопрос к xkor
а в катах если сидим ну смотря в каких, ну примерно от 100 мобов как минумум я вижу :) через стены тока, а сколько на поверхности боюсь предположить.
как понять универсальный скрипт? что то вроде вкл. выбора баферов, в константете SE:=1 // включаем скрипт для СЕ , типо так что ли? а если СЕ маленький лвлом, т.е у него нет такого бафа ещё... это как реализовывать? проверкой наличия скила?:) я конечно понимаю... но помоему слишком много придеться писать, ради того что бы тот же самый варка 1 раз бафнул в парти... Сам по себе варка в парти с СЕ и ПП уже не "пришей к ххх рукав", зачем его засовывать в твой скрипт , если смысла от него там 0
про пакеты и обработку вопрос к xkor
а в катах если сидим ну смотря в каких, ну примерно от 100 мобов как минумум я вижу :) через стены тока, а сколько на поверхности боюсь предположить.
угу..
а про пакеты ничего сложного
1 екземляр скипта запускается для каждого пакета входящего и исходящиго...
быстрдействия скрипта заключается в том чтобы 100 ифов не обрабатывать ч каждым пакетом.. чтобы ето ускорить в 2 раза то надо 2 блока сдалать для исходящкго и вхродящего трафика.. но в 90% случаев тормозит не скрипт а комп дурацкий... если комп нормальный то 100 ифов каждый раз при приходе пакета обрабатывается норм
сделав блочность в скрипте немного повысит быстродействие..
(в 2 раза работу скрипта ускорит)
Столкнулся я тут вот с чем...
И вот на что нарвался, что постепенно в течении нескольких часов база мобов растет и растет до неприличных размеров, так например. Когда входишь в каты, мобов в области видимости примерно 60, если тупо постоять там часа 3, мобов становится уже 120 - 150.
Может я какой-нить пакет не знаю с удалением моба?
В самом скрипте ошибок вроде нет...
Тоже с таким эффектом сталкнулся. Мне кажется, некоторых мобов клиент удаляет автоматически после смерти, независимо от того, пришел делетеобжект или нет. Просто ждёт какоето время и удаляет
APXAHGEJI
14.05.2008, 22:01
Нет, всё делается тока с разрешения серва))
Удаляются тока после прихода пакета ObjectDelete, но это после смерти.
А вот что происходит если моб находится на границе видимости и приходит ли этот самый пакеты, когда он не умирает а всего лишь выходит из зоны видимости не знаю.
Нет, всё делается тока с разрешения серва))
Удаляются тока после прихода пакета ObjectDelete, но это после смерти.
А вот что происходит если моб находится на границе видимости и приходит ли этот самый пакеты, когда он не умирает а всего лишь выходит из зоны видимости не знаю.
приходит 100% но зона видимости это понятие размытое прописаное в л2ини помоему. и ещё всё что делает клиент и показывает говорит ему сервер или л2пнх или подобная програмка.
я като давно задовался вопросом.. то что когда лаги какието (по разным причинам инет лагает или скрипт громоздкий) скрипт некоректно ведет себя.. но XKOR однозначно ответил что при любых лагах- неодин пакет мимо обработчика пакетхака непройдет.. неможет пакет потеряться и пройти мимо пакетхака и не обработаться скриптом- независимо от лагов и быстродействия скрипта..
некоректное поведение скрипта при лагах - обычно связано с работой таймера.. (у меня так было).. таймер не тормозит а инет (к примеру) тормозит.. например: имеем 3 окна.. 1 командир+2 бафера-бота.. скрипт сделан (к примеру) так что таймер хилит бефером- командира до тех пор пока не получит пакет об том что ХП- много.. 1 окно получает то что в пати окошки с ХП изменились.. а второе окно етот пакет получить может порой через 20 секунд аж.. выглядит на екране ето так: нас подранили.. бафр начинает хилить.. хп у нас полное стало а бафер еще 20-30 сек хилит и хилит..
ну ето лиш пример.. но работа таймера реально может привести к разным странностям в работе скрипта особенно при наличии лагов..
ещё бывает винда или антивирь начинает некорректно работать там хард дрочить просто так или на вири проверять, при этом скрипт бывает просто тупо ничего не делает.
Denis63RUS
28.05.2008, 13:50
Мне стало очень интересен вопрос о Мамоне, идёт ли какая нибудь информация с сервера о том где мамон сидит или куда он телепортируется? Надоело каждый раз бегать и искать этих двух неуловимых мстителей:) Если есть у кого соображения или наработки по этому вопросу поделитесь плиз!
APXAHGEJI
28.05.2008, 20:10
Информация о мамоне придет только если поблизости от него находишся, тоесть сидя в городе ты не узнаешь где мамон (да вообщето похожая тема поднималаст про РБ).
Едиственно сдесь мона сделать так чтобы в сами каты не спускаться, а палить рядом с поверхности.
Как называтся пакет в котором инфа а вашей попытке здать манор?
ChiterEPT
29.05.2008, 01:46
приходит 100% но зона видимости это понятие размытое прописаное в л2ини помоему. и ещё всё что делает клиент и показывает говорит ему сервер или л2пнх или подобная програмка.
Какая бы зона видимости ни была прописана в л2ини или Options.ini пакеты все равно приходят все, просто клиент не все обрабатывает.
пакеты все равно приходят все, просто клиент не все обрабатывает.О_О что бы это значило? Ты хочешь сказать, что тебе летит инфа о состоянии ВСЕХ мобов/нпц/плееров на серваке? Нифига подобного.
Какая бы зона видимости ни была прописана в л2ини или Options.ini пакеты все равно приходят все, просто клиент не все обрабатывает.
:cray: без комментариев отснифай пакеты мобов, если хоть один моб будет дальше зоны видимости относительно тебя и понятно всё в 1 момент времени то флаг тебе в руки. :confused:или ты считаешь что когда ты допустим на осаде, а одновременно идёт штуки 4 осад то представляешь как у тя тупил бы клиент в любом месте карты если было бы так как ты говоришь, блин а всё-таки откомментировать :o
Помойму он имел в виду, что при изменении (уменьшении) зоны видимости в л2.ини происходит изменение дальности отображения персонажей только в клиенте, а сервер по прежнему шлет все пакеты для стандартного радиуса. И это так.
APXAHGEJI
29.05.2008, 22:17
Ну тогда по такой логике снижение радиуса не давало бы снижение лагов.
dmitry501
30.05.2008, 18:49
Оно и не дает. Если у тебя так, то меняй железо - видеокарту, процессор,память.
APXAHGEJI
31.05.2008, 03:37
Я имею ввиду тормоза сети и серва, а не тормаза графики.
Добавлено через 4 минуты
Я не думаю, что с моим железом могут быть тормаза в такой далеко не самой технологичной и навороченной вплане графики и физике игре.
Какая бы зона видимости ни была прописана в л2ини или Options.ini пакеты все равно приходят все, просто клиент не все обрабатывает.
очередной бредок..
попробуй уменьшить зону видимости клиента через утилиты любые или ручками...
поставь там для прикола=10 вметсто =1000 или вместо =10000
думаеш никово не увидиш? -))
и трафик секономиш? нет конечно.. радиус общета игроков прописан не у тебя на клиенте а на серваке..
сервер тебе всё равно запихнет информацию об мобах и нпц и игроках и предметах на полу в определенном радиусе вокруг тебя...
ты ето не можеш контролировать..
впринципе наверно мы об од одном и томже говорим.. просто твоя фраза:
просто клиент не все обрабатывает.
смутила.. он все обрабатывает еще как... ему тока дай инфу-).. он всё обработает-)
для примера такая бага есть во всех версиях ЛА2:
если найти место где нет никаво- (например на рейтах х100 приползти на пиратский остров) то есть возможность собрать паравоз- и увести их за собой далеко.. и огда уведеш- далеко- то вторым чаром который там остался- наблюдать что будет?
тот кто увел паравоз- должен просто выйти из игры когда увел парик или БСОЕ..
оказывается если НПЦ (которые пронумерованы- каждый под определенным ИД идет в базе сервака.. ) не попадают в зону общета неодного из персонажа- то сервер про них забывает...
просто сервер економит быстродейтствие на них.. нефик общитывать НПЦ (мобов) которые вне зоны видимости у персонажей живых...
как тока любопытный нос решит навестить уведенных мобов то мобы сразу начнут общитываться серваком и реснутся на месте респауна.. но если их не тревожить своим пресутствием то они там замрут- надолго пока их неразбудит рестарт или живой чар..
Denis63RUS
03.06.2008, 16:45
Т.е. если кто то находиться в катах рядом с мамоном, то другой челоек который находиться скажем в гиране может уловить инфу о том что мамон гдето реснулся и присутствует? Нее, что то тут не так помоему. Скорее всего Если про то что сервак забывает о мобах и начинает их обробатывать только тогда когда появляеться какой либо чар правда, то скорее ксего обработка эта идёт как раз только для тех кто находиться в той локации, и данные об этом не идут в другие локации, иначе бы все обработке слились бы в одну большую кашу, ну это чисто моё мнение конечно!
Т.е. если кто то находиться в катах рядом с мамоном, то другой челоек который находиться скажем в гиране может уловить инфу о том что мамон гдето реснулся и присутствует?
нет это не так
Breadfan
04.06.2008, 15:51
нет это не так
ну а в случае если оба перса ( в катах и в городе) запущены на одном компе и под пх ?) тогда инфу о мамоне можно получить)
ну а в случае если оба перса ( в катах и в городе) запущены на одном компе и под пх ?) тогда инфу о мамоне можно получить)
конечно можно :) можно даже если не на одном компе, инфу на автомате передать через пм :) пнх для этого заточен даже.
Несмотря на то, что в этой ветке уже многократно выкладывались всяческие хилеры-баферы, я посчитал своим долгом "вернуть в копилку OpenSource" то что взял оттуда :)
Итак, Пати Лекарь-Бафер Клерик 35 лвл.
Работа скрипта "как есть" гарантируется при выученных скилах соответствующих этому классу на 35 уровне и выше. Скрипт проверялся только на Интерлюде в пати с живым хозяином и локомотивом от nezabudkin (в катах без бега).
{
Cleric party healer-buffer from MHz
v0.4.2
Благодарности:
Изначально делался из бота
mks "SE party healer" http://coderx.ru/showpost.php?p=2252&postcount=176
Идея каста последовательности скилов
Grinch "Бешенный бафер" http://coderx.ru/showpost.php?p=7169&postcount=513
Окно лога
VORON http://coderx.ru/showpost.php?p=2648&postcount=217
Бег прицепом и разные фишки
nezabudkin "БОТ - Воин помошник от Alexus" http://coderx.ru/showpost.php?p=6348&postcount=1
Инструкция по использованию
Вписываем в скрипт имена клера и командира, дополнительно можно подкорректировать время перебафа и
пороговые значения HP, свободно можно уменьшить константу LogicTimerInterval до 500, что сделает клера более "активным".
Запускаем скрипт.
Если клер еще не в пати, зовем его в пати (вообще-то должен работать и оффпати но я так его не проверял).
В окне командира появляются надписи "Now in party NNN members", кидаем на сопартийцев какой-нибудь полезный баф
типа ВВ пока кол-во NNN не будет соответствовать реальному кол-ву членов в пати.
Теперь бот готов к работе. Бот управляется социальными действиям со стороны командира. В ответ на социальные действия
бот переключает свои режимы
1. Режим хиляния. Если включен, то клер мониторит здоровье сопартийцев и при падении здоровья до 1-й границы хиляет
Heal, при падении здоровья ниже 2-й границы хиляет подряд Battle Heal + Heal
2. Режим бега. При включении клер "даблкликает" по командиру. Больше по командиру не долбит, поэтом в принципе может
отцепиться, если это произошло, снова выключите-включите режим бега. При выключении режима бега клер встает на том
месте где стоял и никуда больше не бегает.
3. Режим перебафа. При включении клер перебафывает всю пати в соответствии со своими "настройками" вообще имеет 3 вида
бафов "самобаф", баф бойца и баф "прицепа" (более детально см. листинг). Далее клер запоминает когда кого бафал и
перебафывает по мере необходимости. Режим перебафа менее приоритетен чем хил, т.е. если есть выбор хилять или бафать,
то клер будет хилять. Клер помнит когда кого бафал последний раз, так что можете свободно включать-выключать этот режим
дабы клер не "сорвался" с места и не побежал вас перебафывать потому что посчитал что пора.
4. Принудительный перебаф всей пати.
}
const
BotName = 'Cleric'; // Имя бота
MasterName = 'Master'; // Имя командира
AssistantName = 'Assistant'; // Необязательный ассистент
RebuffTime = 1000*60*18; // Время перебафывания в миллисекундах
HP1=1000; // Порог HP для Heal
HP2=300; // Порог HP для Battle Heal + Heal
tt_MillisecondsInDay = 86400000;
LogicTimerInterval = 1000;
Chaos=100;
SkillDelay = 10;
DEBUG = False;
//************************************************** **************************************************
// Инфомационная таблица по скилам
SkillsSize = 32; // Максимальная длина последовательности кастуемых скилов
cst_BattleHeal = 1015;
cst_Heal = 1011;
cst_SelfHeal = 1216;
cst_WindWalk = 1204;
cst_Shield = 1040;
cst_Might = 1068;
cst_Focus = 1077;
cst_Acumen = 1085;
cst_HolyWeapon = 1043;
cst_MentalShield = 1035;
cst_Concentration = 1078;
cst_ResistFire = 1191;
cst_Regeneration = 1044;
cst_BerserkerSpirit = 1062;
// Смещения инфы о касте в пакте 48 MagicSkillUse
cstc_DoerIdOffset = 2;
cstc_SkillIdOffset = 10;
cstc_SkillTimeOffset = 18;
cstc_ReuseDelayOffset = 22;
var
frm: Tform;
memo: Tmemo;
//************************************************** **************************************************
// Таблица каста
Skills: array [1..SkillsSize] of Integer; // Собственно буфер
SkillsLastIndex: Integer; // Используется записей
SkillsCurIndex: Integer; // Текущая запись
EndCastTimer: TTimer; // Таймер, разматывающий таблицу каста
ImCasting: Boolean; // Признак что я нахожусь в состоянии каста
CurRebuffedChar: Integer; // Индекс перебафываемого чара
TimeBeginRebuff: Integer; // Время начала перебафа тек. чара
OldRunKey: Boolean; // Старое состояние флага бега, чтобы при перецеливани при перебафе не сбивался прицел
AlreadyDoubleClicked: Boolean; // Флаг что уже дабликнули по мастеру
//************************************************** **************************************************
// Эти переменные возможно используются в других модулях
BotId: Integer; // Id бота
BotIdx: Integer; // Индекс бота в массиве пати
BotTargetId: Integer; // Id цели бота
MyX, MyY, MyZ: Integer; // Координаты бота
MasterId: Integer; // Id командира
//************************************************** **************************************************
// От se_healer
PartyCount: Integer; // Текущее кол-во обслуживаемых персов
CharName: array[1..9] of string;
CharID: array[1..9] of integer;
CurHP: array[1..9] of integer;
MaxHP: array[1..9] of integer;
CurMP: array[1..9] of integer;
MaxMP: array[1..9] of integer;
//Dev: array[1..9] of extended; // Пока не используется это % здоровья
LastBuffTime: array[1..9] of integer;
//xe, ye: extended;
e,t,x,y,z: integer;
HealKey, RunKey, BuffKey: boolean; // Флажки режимов: Лечения, Бега и Перебафа
LogicTimer: TTimer; // Таймер, организующий "разум" бота
//************************************************** **************************************************
// "Разум" бота
// Подготовить посл скилов для бойцового бафа
procedure FighterBuffSequence;
begin
Skills[1] := cst_Shield;
Skills[2] := cst_Might;
Skills[3] := cst_WindWalk;
Skills[4] := cst_Focus;
Skills[5] := cst_HolyWeapon;
Skills[6] := cst_MentalShield;
Skills[7] := cst_ResistFire;
Skills[8] := cst_Regeneration;
Skills[9] := cst_BerserkerSpirit;
SkillsLastIndex := 9;
end;
// Подготовить посл скилов для мага
procedure WizardBuffSequence;
begin
Skills[1] := cst_Acumen;
Skills[2] := cst_Shield;
Skills[3] := cst_WindWalk;
Skills[4] := cst_MentalShield;
Skills[5] := cst_Concentration;
Skills[6] := cst_ResistFire;
Skills[7] := cst_Regeneration;
SkillsLastIndex := 7;
end;
// Подготовить посл скилов для "прицепа" сидящего в коридоре
procedure SitterBuffSequence;
begin
Skills[1] := cst_Shield;
Skills[2] := cst_WindWalk;
SkillsLastIndex := 2;
end;
// Выбираем как будем лечить и лечим
procedure Heal(idx: Integer);
begin
if (CurHP[idx] <= HP2) then begin
Skills[1] := cst_BattleHeal;
Skills[2] := cst_Heal;
SkillsLastIndex := 2;
CastSequence;
end else begin
Cast(cst_Heal);
end;
end;
// Выбираем как будем бафать и бафаем
procedure Rebuff(idx: Integer);
begin
// Здесь выбор варианта бафов по имени перса
if CharName[idx] = BotName then
WizardBuffSequence
else if (CharName[idx] = MasterName) or (CharName[idx] = AssistantName) then
FighterBuffSequence
else
SitterBuffSequence;
CurRebuffedChar := idx;
TimeBeginRebuff := GetTime;
CastSequence;
end;
// Поиск нуждающегося в лечении (возвращает его индекс)
function WhoNeedHPIndex: Integer;
var
i: Integer;
curMinHP, curNeeded: Integer;
begin
curMinHP := 100000;
curNeeded := -1;
for i:=1 to PartyCount do begin
if (CurHP[i] > 0) and (CurHP[i] <= HP1) and (CurHP[i] < MaxHP[i]) then begin
if CurHP[i] < curMinHP then begin
curNeeded := i;
curMinHP := CurHP[i];
end;
end;
end;
Result := curNeeded;
end;
// Поиск нуждающегося в перебафе (возвращает его индекс)
function WhoNeedBuffIndex: Integer;
var
i: Integer;
curTime: Integer;
curDeltaTime: Integer;
curMinTime: Integer;
curNeeded: Integer;
begin
curNeeded := -1;
curTime := GetTime;
curMinTime := 2147483647;
for i:=1 to PartyCount do begin
if CurHP[i] > 0 then begin
curDeltaTime := curTime - LastBuffTime[i];
if curDeltaTime > RebuffTime then begin
if curDeltaTime < curMinTime then begin
curNeeded := i;
curMinTime := curDeltaTime;
end;
end;
end;
end;
Result := curNeeded;
end;
// Выработка "общей" линии поведения бота (обработчик таймера логики)
procedure OnLogicTimer(Sender: TObject);
var
selectedForHeal: Integer;
selectedForBuff: Integer;
begin
if PartyCount <= 0 then exit; // Если еще ничего не знаем ни о ком, ничего не делаем
for t:=1 to PartyCount do begin // Id командира и бота
if CharName[t]=MasterName then MasterId:=CharID[t];
if CharName[t]=BotName then begin
BotID:=CharID[t];
BotIdx:=t;
end;
end;
if MyHP = 0 then exit; // Если я мертв - то все пофигу
// Если я что-то кастую, то докастую и будем выбирать что делать дальше
if ImCasting then begin
AddLog('************ Im casting ****************');
exit;
end;
// Не прерываем последовательность перебафа!
if CurRebuffedChar > 0 then begin
AddLog('************ Im rebuffing char ' + CharName[CurRebuffedChar] + '****************');
exit;
end;
// Если включен режим лечения, то это приоритетная задача, сначала займемся ей
if HealKey then begin
selectedForHeal := WhoNeedHPIndex;
if selectedForHeal > 0 then begin
if CharID[selectedForHeal] <> BotTargetId then // Проверяем прицел если надо переставляем его
Action(CharID[selectedForHeal]); // но не контролируем результат,
Heal(selectedForHeal); // и сразу ХИЛ!
exit; // Щас бой, не до бафов, оббафаю потом
end;
end;
// Если включен режим перебафа и время пришло, то запускаем перебаф
if BuffKey then begin
selectedForBuff := WhoNeedBuffIndex;
if selectedForBuff > 0 then begin // Нашелся перс для перебафа
AddLog('Im going to rebuff ' + CharName[selectedForBuff]);
OldRunKey := RunKey;
RunKey := False;
if BotTargetId = CharID[selectedForBuff] then // Не бафаем кого попало! Убеждаемся что выбрана правильная
Rebuff(selectedForBuff) // цель
else
Action(CharID[selectedForBuff]);
end;
end;
end;
//************************************************** **************************************************
// Отладка и тестирование
procedure PrintLastBuffTime;
var
i: Integer;
begin
AddLog('');
PrintFlag('BuffKey', BuffKey);
PrintFlag('ImCasting', ImCasting);
AddLog('СurRebufedChar='+IntToStr(CurRebuffedChar) );
AddLog('Time='+IntToStr(GetTime));
for i:=1 to PartyCount do begin
AddLog('Member='+CharName[i]+' Time='+IntToStr(LastBuffTime[i]));
end;
end;
procedure PrintFlag(caption: String; flag: Boolean);
begin
if flag then
AddLog(caption + '=True')
else
AddLog(caption + '=False');
end;
//************************************************** **************************************************
// OnEndCastTimer
procedure OnEndCastTimer(Sender: TObject);
begin
AddLog('End casting');
// Выключаем таймер потому что не знаем сколько продлится следующий каст. Таймер включает обработчик MagicSkillUse
EndCastTimer.Enabled := False;
ImCasting := False;
Inc(SkillsCurIndex);
if SkillsCurIndex <= SkillsLastIndex then begin // Если еще есть касты в последовательности, то отправляем их дальше
Cast(Skills[SkillsCurIndex]);
end else begin
// Если последовательность кончилась, то проверяем, если это был режим перебафа,
// то фиксируем его окончание и окончательно фиксируем время когда начинали бафать перса
if CurRebuffedChar > 0 then begin
LastBuffTime[CurRebuffedChar] := TimeBeginRebuff;
TimeBeginRebuff := 0;
CurRebuffedChar := 0;
RunKey := OldRunKey; // Перебаф окончен, если надо, можно бегать
AlreadyDoubleClicked := False;
end;
end;
end;
// Обработчик получения инфы о текущем касте
procedure OnMagicSkillUse;
var
skillId, skillTime, reuseDelay: Integer;
curTime: Integer;
skillIndex: Integer;
begin
if (pck[1] <> #$48) or (ReadD(cstc_DoerIdOffset) <> BotID) then // Блокируем затупления
exit;
ImCasting := True;
skillId := ReadD(cstc_SkillIdOffset);
skillTime := ReadD(cstc_SkillTimeOffset);
reuseDelay := ReadD(cstc_ReuseDelayOffset);
AddLog('');
AddLog('MagicSkillUse');
AddLog('Id=' + IntToStr(skillId));
AddLog('Time=' + IntToStr(skillTime));
AddLog('Delay=' + IntToStr(reuseDelay));
EndCastTimer.Interval := skillTime + SkillDelay;
EndCastTimer.Enabled := True;
end;
procedure OnActionFail;
begin
AddLog('ActionFail');
end;
function MyHP: Integer;
begin
if BotIdx <= 0 then
Result := 0
else
Result := CurHP[BotIdx];
end;
// Кастуй последовательность скилов описаную в Skills массиве
procedure CastSequence;
begin
SkillsCurIndex := 1;
Cast(Skills[1]);
end;
procedure Init; //Вызывается при включении скрипта
var
i: Integer;
begin
if DEBUG then begin
frm := TForm.Create(nil);
frm.Caption := 'Chat';
frm.BorderStyle := bsSizeable;
frm.Position := poScreencenter;
frm.Width:=600;
frm.Height:=700;
//frm.FormStyle:=FsStayOnTop;
frm.Show;
memo :=TMemo.create(nil);
memo.parent:=frm;
memo.align:=alClient;
end;
AddLog('Init');
BotId := 0;
BotIdx := 0;
// Очистка содержимого таблиц
BotTargetId := 0; // Если сначала если бот дважды кликнет по кому-то то нестрашно
PartyCount := 0;
for i:=1 to 9 do begin
CharName[i] := '';
CharID[i] := 0;
CurHP[i] := 0;
MaxHP[i] := 0;
CurMP[i] := 0;
MaxMP[i] := 0;
LastBuffTime[i] := 0;
end;
ClearLastBuffTime;
BuffKey := False;
HealKey := False;
RunKey := False;
AlreadyDoubleClicked := False;
ImCasting := False;
CurRebuffedChar := 0;
TimeBeginRebuff := 0;
EndCastTimer := TTimer.Create(nil);
EndCastTimer.OnTimer := @OnEndCastTimer;
EndCastTimer.Enabled := False;
LogicTimer:=TTimer.Create(nil);
LogicTimer.OnTimer:=@OnLogicTimer;
LogicTimer.Interval:=LogicTimerInterval;
LogicTimer.Enabled:=True;
end;
procedure ClearLastBuffTime;
var
i: Integer;
begin
for i:=1 to 9 do begin
LastBuffTime[i] := 0;
end;
end;
// Взять цель в таргет или мочить ее пухой
procedure Action(targetId: integer);
begin
AddLog('Action on ID=' + IntToStr(targetId));
buf:=#$04;
WriteD(targetId);
WriteD(MyX);
WriteD(MyY);
WriteD(MyZ);
WriteC(0);
SendToServerEx(BotName);
end;
procedure Cast(skillId: integer);
begin
// Формируем пакет на каст и отправляем его
buf:=hstr('2F 00 00 00 00 00 00 00 00 00');
WriteD(skillId, 2);
SendToServerEx(BotName);
//ImCasting := True;
end;
function GetTime: Integer;
begin
Result := Round(Time*tt_MillisecondsInDay);
end;
procedure AddLog(msg: string);
begin
if DEBUG then
memo.Lines.Add(IntToStr(GetTime) + '; ' + msg);
end;
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(BotName);
WriteS(msg);
SendToClientEx(MasterName);
end;
procedure Free; //Вызывается при выключении скрипта
begin
if DEBUG then begin
memo.Free;
frm.Free;
end;
EndCastTimer.Free;
LogicTimer.free;
PartyCount:=0;
HealKey:=false;
RunKey:=false;
BuffKey:=False;
end;
procedure OnPartySmallWindowUpdate;
var
i, f: Integer;
exist: Boolean;
begin
exist := False;
i:=6;
for f:=1 to (PartyCount+1) do begin
exist := CharID[f]=ReadD(2);
if exist=true then begin
CharName[f]:=ReadS(i);
i:=i+8;
CurHP[f]:=ReadD(i);
MaxHP[f]:=ReadD(i);
CurMP[f]:=ReadD(i);
MaxMP[f]:=ReadD(i);
//Dev[f]:=CurHP[f]/MaxHP[f]; // Пока не используется это % здоровья
break;
end;
end;
if exist=false then begin
PartyCount:=PartyCount+1;
Say('Now in party '+IntToStr(PartyCount) + ' members');
f:=PartyCount;
CharID[f]:=ReadD(2);
CharName[f]:=ReadS(i);
i:=i+8;
CurHP[f]:=ReadD(i);
MaxHP[f]:=ReadD(i);
CurMP[f]:=ReadD(i);
MaxMP[f]:=ReadD(i);
//Dev[f]:=CurHP[f]/MaxHP[f]; // Пока не используется это % здоровья
end;
end;
procedure FollowMaster;
begin
if AlreadyDoubleClicked then // Не тычем по 100 раз в хозяина
exit;
if BotTargetId = MasterId then
Action(MasterId)
else begin
Action(MasterId); Action(MasterId);
end;
AlreadyDoubleClicked := True;
end;
procedure OnValidatePosition;
begin
MyX:=ReadD(2);
MyY:=ReadD(6);
MyZ:=ReadD(10);
end;
//************************************************** **************************************************
// Обработка пакетов скриптом
begin
if pck='' then exit;
// Управление составом пати
if FromServer and (pck[1]=#$52) and ((ConnectName=MasterName) or (ConnectName=BotName)) then begin
OnPartySmallWindowUpdate;
exit;
end;
if FromClient and (ConnectName=MasterName) and (pck[1]=#$01) then begin
if RunKey and (not ImCasting) then // Прицепляемся в хвост только если включен режим, и ничего не кастуем
FollowMaster;
// Остаемся в скрипте
end;
// Обновляем свои координаты
if FromClient and (ConnectName=BotName) and (pck[1]=#$48) then begin
OnValidatePosition;
end;
if FromServer and (ConnectName = BotName) then begin
case pck[1] of
#$04: BotId:=ReadD(18); // StatusUpdate
#$48: begin // MagicSkillUse
if ReadD(cstc_SkillTimeOffset) = 0 then
exit;
if ReadD(cstc_DoerIdOffset) = BotId then begin
OnMagicSkillUse;
exit;
end;
end;
#$25: OnActionFail;
#$A6: begin //TargetSelected
BotTargetId := ReadD(2);
AddLog('Selected target ID=' + IntToStr(BotTargetId));
end;
#$2A: begin //TargetUnselected
BotTargetId := 0;
AddLog('UnSelected target');
end;
end;
end;
// Управление ботом со стороны командира через соц. действия
if FromClient and (ConnectName=MasterName) and (pck[1] = #$1B) then begin
case pck[2] of
#$02: begin
pck := '';
HealKey:=not(HealKey);
Case HealKey of
true: Say('Heal mode ON');
false: Say('Heal mode OFF');
end;
end;
#$03: begin
pck := '';
RunKey:=not(RunKey);
if RunKey then begin
Say('Run mode ON');
AlreadyDoubleClicked := False;
end else begin
Say('Run mode OFF');
Action(BotId); // Прицеливаемся на себя чтобы сбить "привязку хвостом к командиру"
Action(BotId);
end;
end;
#$04: begin
pck := '';
BuffKey:=not(BuffKey);
if BuffKey then begin
Say('Buff mode ON');
end else begin
Say('Buff mode OFF');
end;
end;
#$05: begin
pck := '';
ClearLastBuffTime;
Say('Buffs times table cleared');
end;
end;
end;
end.
Для тех, кто "асилил".
Основная сложность в написании скриптов для баферов это то, что у разных расс разные бафы. Что касается лекарей, то основные споры идут вокруг "принятия решения о том кого хилять". В вышеприведенном скрипте все эти "спорные" моменты выделены в отдельные функции, таким образом "заточка" под конкретные нужды не представляется проблематичной.
В боте расширена и "зарефакторена" идея каста последовательности скилов из бота Grinch, так что бот кастует практически со скоростью макроса.
Бот очень "трепетно" следит за своим таргетом. Возможно я чересчур уделил этому внимание и "перегрузил" код, если вы считаете это излишним, то можете выкинуть эту часть кода и значительно упростить логику.
Бот в отличие от других "не долбит" по командиру в ответ на каждое его перемещение. Я посчитал что это более "правильно" и менее палевно. Опять же вернуть код как в "помощнике от nezabudkin не составит труда.
Для тех, кто "асилил".
Основная сложность в написании скриптов для баферов это то, что у разных расс разные бафы. Что касается лекарей, то основные споры идут вокруг "принятия решения о том кого хилять". В вышеприведенном скрипте все эти "спорные" моменты выделены в отдельные функции, таким образом "заточка" под конкретные нужды не представляется проблематичной.
В боте расширена и "зарефакторена" идея каста последовательности скилов из бота Grinch, так что бот кастует практически со скоростью макроса.
Бот очень "трепетно" следит за своим таргетом. Возможно я чересчур уделил этому внимание и "перегрузил" код, если вы считаете это излишним, то можете выкинуть эту часть кода и значительно упростить логику.
Бот в отличие от других "не долбит" по командиру в ответ на каждое его перемещение. Я посчитал что это более "правильно" и менее палевно. Опять же вернуть код как в "помощнике от nezabudkin не составит труда.
Где ты такие макросы видел ;) в моём скрипте 12 бафов пп кидает на 5 секунд быстрей, примерно, чем через макрос.
Где ты такие макросы видел ;) в моём скрипте 12 бафов пп кидает на 5 секунд быстрей, примерно, чем через макрос.
Значит еще быстрей чем у тебя :) Я твою константу "задержки" уменьшил до 10 мс :)
cst_BattleHeal = 1015;
cst_Heal = 1011;
cst_SelfHeal = 1216;
cst_WindWalk = 1204;
cst_Shield = 1040;
cst_Might = 1068;
cst_Focus = 1077;
cst_Acumen = 1085;
cst_HolyWeapon = 1043;
cst_MentalShield = 1035;
cst_Concentration = 1078;
cst_ResistFire = 1191;
cst_Regeneration = 1044;
cst_BerserkerSpirit = 1062;
Не могли бы вы подсказать пакеты для других бафов?
Death Wishper
Greater Might
Greater Shield
Не могли бы вы подсказать пакеты для других бафов?
Death Wishper
Greater Might
Greater Shield
берёшь л2пнх врубаешь вкладку просмотр пакетов делаешь фильтр пакетов 2F от клиента, и смотришь, после 2F следующие 4 байта и буду ID скила.
Добавлено через 1 минуту
Значит еще быстрей чем у тебя :) Я твою константу "задержки" уменьшил до 10 мс :)
можно и без задержки если честно. задержка это моя паранойя :D
-=Ma}{imuS=-
08.06.2008, 20:50
begin
buf:=HStr('2F 0F 01 00 00 00 00 00 00 00');
SendToServer;
end;
как сделать чтоб этот пакет отправлялся каждые 20 минут?
как сделать чтоб этот пакет отправлялся каждые 20 минут?засунуть этот код в таймер, интервал таймера поставить 20 минут
Denis63RUS
09.06.2008, 22:19
У меня появился небольшой вопросик, из-за чего мошут быть тормоза в клиенте при большом скоплении народа? Т.е. если я ползуюсь LPacketHack, в нем работает скрипт, например на самоупотребление банок на ЦП/ХП, то при походе на осаду или на РБ начинаються жуткие тормоза. 100% это не из-за железа, т.к. оно просто пока ещё не может тормозить:), насчёт интернета я не уверен но без программы всё вроде бы норм, бывают "подвесы" но не сильные, инет 128 кБ/с. Кто может поделиться советами по этому поводу? (изменение графики с минимальных на максимальные настройки в игре ниго не даёт)
Из-за скрипта очень даже может тормозить, если неоптимизировать его. Еще можно отключать запись лога в пакетхаке. Проверь со скриптом и без и все станет ясно из-за чего тормозит.
самоупотребление банок на ЦП/ХП, то при походе на осаду или на РБ начинаються жуткие тормоза.Скорее всего некорректно реализован именно этот алгоритм.
У меня появился небольшой вопросик, из-за чего мошут быть тормоза в клиенте при большом скоплении народа? Т.е. если я ползуюсь LPacketHack, в нем работает скрипт, например на самоупотребление банок на ЦП/ХП, то при походе на осаду или на РБ начинаються жуткие тормоза.
Я, когда играю в несколько окон и использую много скриптов, процессу LPacketHack ставлю повышенный приоритет. Лагов становится меньше.
для запуска клиентов можно применить батничек с командами понижения приоритета каждому окну, а пакетхаку повыше:
@echo off
start /ABOVENORMAL l2phx.exe
start /belownormal l2.exe
start /belownormal l2.exe
start /belownormal l2.exe
еще можно использовать MultiWin.exe (в разделе файлов лежит)
vovanchik
10.06.2008, 16:09
> IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
что за извращенство? ))) разве IDBot1:=readd(18); не проще?
а понил, вероятно для совместимости со старыми версями
> IDBot1:=pck[18]+pck[19]+pck[20]+pck[21];
что за извращенство? ))) разве IDBot1:=readd(18); не проще?
а понил, вероятно для совместимости со старыми версями
Не, это просто, кому как нравится.
DashKAaa
11.06.2008, 09:07
У меня появился небольшой вопросик, из-за чего мошут быть тормоза в клиенте при большом скоплении народа? Т.е. если я ползуюсь LPacketHack, в нем работает скрипт, например на самоупотребление банок на ЦП/ХП, то при походе на осаду или на РБ начинаються жуткие тормоза. 100% это не из-за железа, т.к. оно просто пока ещё не может тормозить:), насчёт интернета я не уверен но без программы всё вроде бы норм, бывают "подвесы" но не сильные, инет 128 кБ/с. Кто может поделиться советами по этому поводу? (изменение графики с минимальных на максимальные настройки в игре ниго не даёт)
у меня 9 окон на пакет хаке, в местах больших скоплений мобов, не каких лагов не наблюдал вообще, если только спустя 2 дня без рестарта и постоянного ботерства в 12 валкеров и 9пакет хак-окон.
конфиг своего железа скажи, какой скрпт на цп юзаешь и под какие хроники?
Добавлено через 2 минуты
Не могли бы вы подсказать пакеты для других бафов?
Death Wishper
Greater Might
Greater Shield
не проще самому отловить ?
hstr('2F DA 04 00 00 00 00 00 00 00'); // ДЕФ ВИСПЕР
hstr('2F 6C 05 00 00 00 00 00 00 00'); // гритер ПА
hstr('2F 6D 05 00 00 00 00 00 00 00'); // гритер ПД
Denis63RUS
11.06.2008, 14:17
конфиг своего железа скажи, какой скрпт на цп юзаешь и под какие хроники?
Конфиг железа:
Корпус: АТХ
БП: Термалтейк 600 ВТ
Мать: ASUS P5K Premium/AP
Проц: Intel Q6600 (степинг B3 :( )c кулером Термалтейк BT
Видео: GF 8800 GTS (640)
Память: 2х1 GB Corsar C4
Жесткий: 320 GB Seageate SATA2
Система не разогнана!
Скрипт:
//by mks
//помошник в PvP и PK.
//пьет CP и HP пробирки в нужное время(можно добавить и MP для пвп серваков), и освобождает вас от небоходимости зажатия клавиши Ctrl, которая так меня раздражает!(думаю это раздражает и не только меня)
///////////////////////////////////////////////////////
///////////////Master PvP by MKS v.1.0/////////////////
///////////////////////////////////////////////////////
//после активации скрипта необходимо выпить сначала банку CP, потом HP для получения их ID
const
Name='BblXyX0Jlb'; //ник перса
var
CurHP,MaxHP,CurCP,MaxCP: integer;
CPuse,HPuse,ObName: string;
TimerCP,TimerHP: TTimer;
procedure Init; //Вызывается при включении скрипта
begin
TimerCP:=TTimer.Create(nil);
TimerCP.OnTimer:=@OnTimerCP;
TimerCP.enabled:=false;
TimerCP.interval:=800; //интервал 1сек, т.к. чаще пить CP всеравно не будет, дабы не засорять трафик
TimerHP:=TTimer.Create(nil);
TimerHP.OnTimer:=@OnTimerHP;
TimerHP.enabled:=false;
TimerHP.interval:=13000; //интервал 15сек, т.к. действие одной бутылки = 15сек
end;
procedure OnTimerCP(Sender: TObject);
begin
buf:=CPuse;
SendToServerEx(Name);
end;
procedure OnTimerHP(Sender: TObject);
begin
buf:=HPuse;
SendToServerEx(Name);
end;
procedure Free; //Вызывается при выключении скрипта
begin
TimerCP.free;
TimerHP.free;
HPuse:='';
CPuse:='';
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//пьем сначала CP, потом HP банку что б запомнить их ID(я решил взять эти пакеты целиком, дабы не усложнять)
if FromClient and (ConnectName=Name) and (pck[1]=#$14) and (CPuse='') then CPuse:=pck;
if FromClient and (ConnectName=Name) and (pck[1]=#$14) and (CPuse<>pck) and (HPuse='') then HPuse:=pck;
if FromServer and (ConnectName=Name) and (pck[1]=#$04) then
ObName:=pck[18]+pck[19]+pck[20]+pck[21];
//считываем текущие и максимальные значения CP и HP
if FromServer and (pck[1]+pck[6]=#$0E#$04) and (pck[2]+pck[3]+pck[4]+pck[5]=ObName) then
begin
CurHP:=ReadD(14);
MaxHP:=ReadD(22);
CurCP:=ReadD(30);
MaxCP:=ReadD(38);
end;
end.
На сервере стоит интерлюдия
Добавлено через 7 минут
Да и чуть не забыл, играю обычно через 1,79 ИГ валкер, + 5 ботов через 10.8.6 ООГ валкер. LPacketHack перехватывает только клиента, ООГ идут естественно через WP 5,07. Вот, вроде всё выложил:)
А скрипт у тебя работате? Что-то я не вижу чтобы он лечил и восстанавливал СР. Нет проверок, что пора пить банки. И сами таймеры выключены.
А скрипт у тебя работате? Что-то я не вижу чтобы он лечил и восстанавливал СР. Нет проверок, что пора пить банки. И сами таймеры выключены.
спс а то думал что я уже чего то не понимаю.
Denis63RUS
11.06.2008, 16:48
А скрипт у тебя работате? Что-то я не вижу чтобы он лечил и восстанавливал СР. Нет проверок, что пора пить банки. И сами таймеры выключены.
:DDDDD
Извеняюсь, скрипт скапировал неправильно , а я и непосмотрел даже^^
Вот полный:
//by mks
//помошник в PvP и PK.
//пьет CP и HP пробирки в нужное время(можно добавить и MP для пвп серваков), и освобождает вас от небоходимости зажатия клавиши Ctrl, которая так меня раздражает!(думаю это раздражает и не только меня)
///////////////////////////////////////////////////////
///////////////Master PvP by MKS v.1.0/////////////////
///////////////////////////////////////////////////////
//после активации скрипта необходимо выпить сначала банку CP, потом HP для получения их ID
const
Name='XakuM'; //ник перса
var
CurHP,MaxHP,CurCP,MaxCP: integer;
CPuse,HPuse,ObName: string;
TimerCP,TimerHP: TTimer;
procedure Init; //Вызывается при включении скрипта
begin
TimerCP:=TTimer.Create(nil);
TimerCP.OnTimer:=@OnTimerCP;
TimerCP.enabled:=false;
TimerCP.interval:=800; //интервал 1сек, т.к. чаще пить CP всеравно не будет, дабы не засорять трафик
TimerHP:=TTimer.Create(nil);
TimerHP.OnTimer:=@OnTimerHP;
TimerHP.enabled:=false;
TimerHP.interval:=13000; //интервал 15сек, т.к. действие одной бутылки = 15сек
end;
procedure OnTimerCP(Sender: TObject);
begin
buf:=CPuse;
SendToServerEx(Name);
end;
procedure OnTimerHP(Sender: TObject);
begin
buf:=HPuse;
SendToServerEx(Name);
end;
procedure Free; //Вызывается при выключении скрипта
begin
TimerCP.free;
TimerHP.free;
HPuse:='';
CPuse:='';
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//пьем сначала CP, потом HP банку что б запомнить их ID(я решил взять эти пакеты целиком, дабы не усложнять)
if FromClient and (ConnectName=Name) and (pck[1]=#$14) and (CPuse='') then CPuse:=pck;
if FromClient and (ConnectName=Name) and (pck[1]=#$14) and (CPuse<>pck) and (HPuse='') then HPuse:=pck;
if FromServer and (ConnectName=Name) and (pck[1]=#$04) then
ObName:=pck[18]+pck[19]+pck[20]+pck[21];
//считываем текущие и максимальные значения CP и HP
if FromServer and (pck[1]+pck[6]=#$0E#$04) and (pck[2]+pck[3]+pck[4]+pck[5]=ObName) then
begin
CurHP:=ReadD(14);
MaxHP:=ReadD(22);
CurCP:=ReadD(30);
MaxCP:=ReadD(38);
end;
//если вы используете не грэйтер CP то вместо 200 подставьте кол-во CP сколько восстанавливает 1 банка
if (CurCP<MaxCP-200) and (CPuse<>'') then TimerCP.enabled:=true else TimerCP.enabled:=false;
if (CurHP<MaxHP) and (HPuse<>'') then TimerHP.enabled:=true else TimerHP.enabled:=false;
end.
Добавлено через 9 минут
Да, и ещё один вопрос, который начинал обсуждаться в ветке пакеты, но там ответа я не нашёл. Хочу написать скрипт на сигнализациюю о появлении в области досягаемости врага (т.е. клан вара), только никак немогу найти в каком пакете приходит информация о них:( Я думал что в CharInfo, но пока там ненашёл, можно конечно сделать и проще, через Пакет CharInfo и через совпадение по названию клана, но хотелось бы по всё по уму:)
DashKAaa
11.06.2008, 19:22
Этот скрипт под интерлюду на ЦП не пашет вообще
Этот скрипт под интерлюду на ЦП не пашет вообще
Скорее всего только из-за неправильных смещений
CurHP:=ReadD(14);
MaxHP:=ReadD(22);
CurCP:=ReadD(30);
MaxCP:=ReadD(38);
а так должен работать. Почему бы не работать? Руками пьются бутылки СР?
Silmaril
12.06.2008, 16:08
Denis63RUS, посмотри SiedgeFlag в пакете 03, вроде оно
Вопрос, а каким образом лучше реализовать автодетект наличия на себе селф бафов(ака Батл Роар, Рэйдж у дестроера) и соответсвенно при обнаружении отсутсвия таковых и при условии что бафы откатились,юзать их снова?
//мб вопрос ламерский и не в то теме Оо
Denis63RUS
13.06.2008, 14:46
Denis63RUS, посмотри SiedgeFlag в пакете 03, вроде оно
Странно, но у меня такого нет в описании пакета:( Вылажи плиз своё описание пакета 03
Silmaril
13.06.2008, 15:39
из пакетс.ини
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(Wal kSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed )d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(Move mentSpeedMultiplier)f(AttackSpeedMultiplier)f(Coll isionRadius)f(CollisionHeight)d(HairStyle)d(HairCo lor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCr estId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sittin g)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(M ountType)b(PrivateStoreType)
на шоках работает
256-односторонний вар, 257-двусторонний
на ближайших осадах остальные значения выясню
Вопрос, а каким образом лучше реализовать автодетект наличия на себе селф бафов(ака Батл Роар, Рэйдж у дестроера) и соответсвенно при обнаружении отсутсвия таковых и при условии что бафы откатились,юзать их снова?
//мб вопрос ламерский и не в то теме Оо
если я не ошибаюсь.. то... клиент от сервера получает инфу об наличии бафов тока в момент их наложения.. в пакете ЭБНОРМАЛ СТАТУС АПДЕЙТ.. возможно етот пакет приходит еще когдато.. тока хз когда.. в нем циклом перечисляются наложенные бафы и время до их окончания.. и еще чета.. стартонув скрипт в момент когда уже бафы- лежат- неимеет смысла так как ты неполучиш пакет ЭБНОРМАЛ СТАТУС АПДЕЙТ.. имеет смысл скрипт запускать заранее.. перед бафом.. тогда возможно отслеживать все наложенные бафы..
ПВП помошник, 4 в одном: таргет(при ударе), цп, контрл, радар
автоцп- пьет банки если цп на Delta меньше макс.
автоконтрл - контрол постоянно зажат
автотаргет - берет на таргет того кто тя стукнул (выключаеться когда ты сам у себя на таргете)
авторадар - синяя стрлочка над головой показывающая на цель.
Включение/выключение функций в клиенте ("Соц. Да").
const
Name='Mamy';
var
CurHP,CurCP,MaxCP,MyID,TargetID,o,x,y,z,Delta: integer;
CPuse,action,Msg: string;
TimerCP,TimerHP: TTimer;
AutoCtrl,AutoCP,AutoTarget,AutoRadar: boolean;
procedure Init;
begin
TimerCP:=TTimer.Create(nil);
TimerCP.OnTimer:=@OnTimerCP;
TimerCP.enabled:=false;
//configs
TimerCP.interval:=1000; //cpuse delay
AutoCtrl:=true; //autoctrl default
AutoCP:=true; //autocp default
AutoTarget:=false; //autotarget default
AutoRadar:=true; //autoradar default
Delta:=200; //if (currentCP)<(maxCP-delta) then cpuse
Say;
end;
procedure OnTimerCP(Sender: TObject);
begin
buf:=CPuse;
SendToServerEx(Name);
end;
procedure Free;
begin
TimerCP.free;
CPuse:='';
end;
function booleantostr(b:boolean):string;
begin
if b then
result:='True'
else
result:='False';
end;
procedure Say;
var s:string;
begin
if autoctrl then
s:='<tr><td>AutoCtrl=<a action="bypass autoctrl_off">'+booleantostr(autoctrl)+'</a></td></tr>'
else
s:='<tr><td>AutoCtrl=<a action="bypass autoctrl_on">'+booleantostr(autoctrl)+'</a></td></tr>';
if autocp then
s:=s+'<tr><td>AutoCP=<a action="bypass autocp_off">'+booleantostr(autocp)+'</a></td></tr>'
else
s:=s+'<tr><td>AutoCP=<a action="bypass autocp_on">'+booleantostr(autocp)+'</a></td></tr>';
if autotarget then
s:=s+'<tr><td>AutoTarget=<a action="bypass autotarget_off">'+booleantostr(autotarget)+'</a></td></tr>'
else
s:=s+'<tr><td>AutoTarget=<a action="bypass autotarget_on">'+booleantostr(autotarget)+'</a></td></tr>';
if autoradar then
s:=s+'<tr><td>AutoRadar=<a action="bypass autoradar_off">'+booleantostr(autoradar)+'</a></td></tr>'
else
s:=s+'<tr><td>AutoRadar=<a action="bypass autoradar_on">'+booleantostr(autoradar)+'</a></td></tr>';
s:=s+'<tr><td><br><center><img src="L2UI_CH3.herotower_deco" width=256 height=32></center><br><br></td></tr>';
if cpuse='' then
s:=s+'<tr><td>CPuse=<font color="LEVEL">[!] Выпей бутыль ЦП [!]</font></td></tr>'
else
s:=s+'<tr><td>CPuse=<a action="bypass autouse">'+strtohex(cpuse)+'</a></td></tr>';
buf:=hstr('0F 01 00 00 00');
WriteS('<html><title>PVP помошнегг (с) raid</title><body><center><img src="L2UI_CH3.herotower_deco" width=256 height=32></center><br><table width=100%>'+s+'</table><br><br><br><br><br><br>'+
'<br><center><img src="L2UI_CH3.herotower_deco" width=256 height=32><br><br><br><br><br><br>(c) raid aka Mamy</center></body></html>');
WriteD(0);
SendToClientEx(Name);
end;
function StrToHex(packet: string):string;
var
i:integer;
tmp:byte;
function ByteToHex(b: byte): Char;
begin
if b<10 then result:=chr(b+$30)
else result:=chr(b+$37);
end;
begin
result:='';
for i:=1 to length(packet) do begin
tmp:=ord(packet[i]) div 16;
result:=result+ByteToHex(tmp);
tmp:=ord(packet[i]) - tmp*16;
result:=result+ByteToHex(tmp)+' ';
end;
end;
begin
if FromClient and (ConnectName=Name) and (pck[1]=#$14) and (CPuse='') then begin
CPuse:=pck;
Say;
pck:='';
exit;
end;
if FromServer and (pck[1]+pck[6]=#$0E#$04) then
begin
MyID:=ReadD(2);
CurHP:=ReadD(14);
CurCP:=ReadD(30);
MaxCP:=ReadD(38);
end;
if FromServer and (pck[1]=#$A6) then begin
TargetID:=ReadD(2);
end;
{ взятие на таргет, когда берут на таргет вас (заменитьна то что ниже)
if FromServer and (pck[1]=#$29) and autotarget then begin
o:=ReadD(2);
if (ReadD(6)=MyID)and(o<>MyID)and(o<>TargetID) then begin
x:=ReadD(10);
y:=ReadD(14);
z:=ReadD(18);
delay(100);
buf:=hstr('04');
WriteD(o);
WriteD(x);
WriteD(y);
WriteD(z);
WriteC(0);
SendToServerEx(Name);
end;
end;
}
if FromServer and (pck[1]=#$05) and autotarget then begin
o:=ReadD(2);
if (ReadD(6)=MyID)and(o<>MyID)and(o<>TargetID) then begin
x:=ReadD(15);
y:=ReadD(19);
z:=ReadD(23);
delay(100);
buf:=hstr('04');
WriteD(o);
WriteD(x);
WriteD(y);
WriteD(z);
WriteC(0);
SendToServerEx(Name);
end;
end;
if (CurCP<MaxCP-Delta)and(CPuse<>'')and(CurHP>0)and AutoCP then
TimerCP.enabled:=true
else
TimerCP.enabled:=false;
if FromClient and (ConnectName=Name) and (pck=HStr('1B 06 00 00 00')) then begin
Say;
pck:='';
exit;
end;
if FromServer and(pck[1]=#$61)and AutoRadar then begin
x:=ReadD(6);
y:=ReadD(10);
z:=ReadD(14);
buf:=#$EB;
WriteD(0);
WriteD(1);
WriteD(x);
WriteD(y);
WriteD(z);
SendToClientEx(Name);
end;
if FromClient and (ConnectName=Name) and (pck[1]=#$2F) and AutoCtrl then
pck[6]:=#$01;
if FromClient and (ConnectName=Name) and (pck[1]=#$21) then begin
action:=ReadS(2);
if pos('auto',action)>0 then begin
if action='autocp_on' then autocp:=true;
if action='autocp_off' then autocp:=false;
if action='autoctrl_on' then autoctrl:=true;
if action='autoctrl_off' then autoctrl:=false;
if action='autotarget_on' then autotarget:=true;
if action='autotarget_off' then autotarget:=false;
if action='autoradar_on' then autoradar:=true;
if action='autoradar_off' then begin
autoradar:=false;
buf:=#$EB;
WriteD(0);
WriteD(1);
WriteD(0);
WriteD(0);
WriteD(0);
SendToClientEx(Name);
end;
if action='autouse' then CPuse:='';
Say;
pck:='';
end;
end;
end.
интересно а когда тя несколько бьют то таргет с одного на другого всёвремя прыгает?
интересно а когда тя несколько бьют то таргет с одного на другого всёвремя прыгает?
Транс самое то кидать...
nikolas666
02.07.2008, 02:31
Как узнать ID предмета с данного сервера
Как узнать ID предмета с данного сервера
Бросить его на землю, придет пакет от сервера
27=InventoryUpdate:w(count)w(1add2mod3remove)w(ite mType1)d(ObjectID)i(ItemId)d(Count)...
nikolas666
02.07.2008, 15:33
Еще один маленький вопросик))Запускаю точку все работает точит а когда все предметы ломаются и становятся на +0 все виснет и прога не отвечает(((:confused:Что надо изменить в скрипте /Автоматизация заточки предметов до необходимого уровня by NLObP
//version 0.4 от 27.06.2008г.
и еще разок напишите плз как скорость менять и куда енто вписывать,?
DashKAaa
02.07.2008, 17:32
А зачем нужна ета прога на точку? Только для тех кому лень точить вручную или даёт какиета преимущества?
для пвп сервера.. где точек как говна
А зачем нужна ета прога на точку? Только для тех кому лень точить вручную или даёт какиета преимущества?
Да, для ленивых. И ради спортивного интереса.
Добавлено через 3 минуты
Еще один маленький вопросик))Запускаю точку все работает точит а когда все предметы ломаются и становятся на +0 все виснет и прога не отвечает(((:confused:Что надо изменить в скрипте /Автоматизация заточки предметов до необходимого уровня by NLObP
//version 0.4 от 27.06.2008г.
и еще разок напишите плз как скорость менять и куда енто вписывать,?
Прочитай темку про точку, я там показывал что надо изменить, если точишь кристаллическими точками и оружие не ломается про неудаче, то есть заточка сбрасывается в 0. И вдруг, если хочешь, точить только один предмет.
Не совсем из того скрипта, но время можно менять здесь
timer.interval:=1000; //время задержки
Добавлено через 1 минуту
Куда скрипты ложить надо папку создавать или где нужно заливать скрипт?
в составе пакетхака уже есть папка SCRIPTS с примерами скриптов, туда и ложи свои.
Ребят, какая команда "возврат в город" в скрипте? Нужно что бы бо после проверки ХП, если меньше 1, делал "возврат в город"
Примерно так:
CharStatus(HP,<,1)
{
SAY(Что я тебе сделал? :'() //бот ЭМО =)
*команда возврат в город* //как её прописать?
}
Ребят, какая команда "возврат в город" в скрипте? Нужно что бы бо после проверки ХП, если меньше 1, делал "возврат в город"
Примерно так:
CharStatus(HP,<,1)
{
SAY(Что я тебе сделал? :'() //бот ЭМО =)
*команда возврат в город* //как её прописать?
}
отправлять UseItem с бсое,
или если умер то словить пакет при нажатии на кнопку "В город" или др.
Ребят, какая команда "возврат в город" в скрипте? Нужно что бы бо после проверки ХП, если меньше 1, делал "возврат в город"
Примерно так:
CharStatus(HP,<,1)
{
SAY(Что я тебе сделал? :'() //бот ЭМО =)
*команда возврат в город* //как её прописать?
}
пакет клиента 6D=RequestRestartPoint:d(PointType)
все коды PointType только не помню, если 00, то после смерти в город
пакет клиента 6D=RequestRestartPoint:d(PointType)
все коды PointType только не помню, если 00, то после смерти в город
Спасибку тыкнул =)
А как это прописать на месте *возврат в город*? =)
CharStatus(HP,<,1)
{
SAY(Что я тебе сделал? :'() //бот ЭМО =)
*команда возврат в город* //как её прописать?
}
Спасибку тыкнул =)
А как это прописать на месте *возврат в город*? =)
CharStatus(HP,<,1)
{
SAY(Что я тебе сделал? :'() //бот ЭМО =)
*команда возврат в город* //как её прописать?
}
У меня реализовано так, в основном цикле отлавливаю пакет Die
//************************************************** *************
//пакет Die (моб умер)
//06=Die:h(CharID)d(d)d(HAsHideout)d(HasCastle)d(fla gs)d(sweepable)d(access)
#$06: begin
if (MyOID=ReadD(2)) then begin
msg.Lines.Add('Нас убили в '+TimeToStr(time));
underattack:=false;
inc(death1);
fishin.enabled:=false;
isFishing:=false; //сейчас не ловим
{---->} RequestRestartPoint; //оживаем после смерти в городе
end;
end;
а сам возврат
//************************************************** *************
procedure RequestRestartPoint;
begin
buf:=#$6D;
WriteD(00);
SendToServerEx(Name);
MoveTimer.Interval:=10000;
end;
Будет ли возвращаться в город если еще живой не знаю.
Map 1.0 Final
Форма: на ней перс по центру, показываеться куда направлена голова, и рядом лежащие айтемы и их иды. Для поисковых ивентов...
При клике по форме перс в игре бежит в эту точку (Z не меняеться).
Лог(прописываеться Drop(кинули)/Spawn(лежало)/Delete(удалили)/Move to(при клике на мапе, x/y относительные), прописываеться айди и название вещи из ItemsID.ini).
const
Name='Mamy';
max=100;
size=320; //размер
ratio=20; // zoom: 100% - size/16; 200% - size/16/2
// настройки отображения внизу.
var
Form: TForm;
Memo: TMemo;
ItemBase: TStrings;
ItemsPlace: array[0..max,0..1] of integer;
ItemsID: array[0..max,0..1] of integer;
ItemsName: array[0..max] of string;
MyX,MyY,MyZ,MyH,ii: integer;
procedure Init;
var i: integer;
begin
Form:=TForm.Create(nil);
// //default postion
// Form.Position:=poDesigned;
// Form.Top:=0;
// Form.Left:=0;
Form.Caption:='Map by raid | '+Name;
Form.BorderStyle:=bsToolWindow;
Form.ClientWidth:=size;
Form.ClientHeight:=2*size;
Form.OnMouseDown:=@FormMouseDown;
Form.Show;
Memo:=TMemo.Create(Form);
Memo.Parent:=Form;
Memo.Left:=0;
Memo.Top:=size;
Memo.Width:=size;
Memo.Height:=size;
Memo.ReadOnly:=True;
Memo.ScrollBars:=ssVertical;
Memo.Visible:=True;
ItemBase:=TStringList.Create;
ItemBase.LoadFromFile('ItemsID.ini');
Log('ItemBase='+inttostr(ItemBase.Count));
for i:=0 to max do begin
ItemsPlace[i,0]:=0;
ItemsPlace[i,1]:=0;
ItemsID[i,0]:=0;
ItemsID[i,1]:=0;
ItemsName[i]:='';
end;
ii:=0;
ShowMap;
end;
procedure Free;
var i:integer;
begin
Memo.Free;
ItemBase.Free;
Form.Free;
MyX:=0;
MyY:=0;
MyZ:=0;
MyH:=0;
ii:=0;
for i:=0 to max do begin
ItemsPlace[i,0]:=0;
ItemsPlace[i,1]:=0;
ItemsID[i,0]:=0;
ItemsID[i,1]:=0;
ItemsName[i]:='';
end;
end;
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
x:=MyX+(x-size div 2)*ratio;
y:=MyY+(y-size div 2)*ratio;
buf:=#$01;
WriteD(x);
WriteD(y);
WriteD(MyZ);
WriteD(MyX);
WriteD(MyY);
WriteD(MyZ);
WriteD(1);
SendToServerEx(Name);
Log('Move to: x='+inttostr(x)+', y='+inttostr(y));
end;
procedure Dot(x,y:integer;text:string);
begin
Form.Canvas.Ellipse(x-1,y-1,x+2,y+2);
Form.Canvas.TextOut(x+2,y+2,text);
end;
procedure ShowMap;
var i,x,y,x1,y1,p:integer;
begin
Form.Caption:='Map by raid | '+Name+' | Items: '+inttostr(ii);
Form.Canvas.Rectangle(0,0,size,size);
p:=MyH-15;
x:=round((size div 2)*(cos(p*pi/180)+1));
y:=round((size div 2)*(1-sin(p*pi/180)));
p:=MyH+15;
x1:=round((size div 2)*(cos(p*pi/180)+1));
y1:=round((size div 2)*(1-sin(p*pi/180)));
Form.Canvas.MoveTo(size div 2,size div 2);
Form.Canvas.LineTo(x,y);
Form.Canvas.LineTo(x1,y1);
Form.Canvas.LineTo(size div 2,size div 2);
Dot(size div 2,size div 2,Name);
x:=MyX div ratio-size div 2;
y:=MyY div ratio-size div 2;
for i:=0 to ii-1 do
Dot(ItemsPlace[i,0]-x,ItemsPlace[i,1]-y,ItemsName[i]);
end;
procedure Log(text:string;const name:string='');
begin
if name<>'' then
Memo.Lines.Add(TimeToStr(Time)+': '+text+' '+name)
else
Memo.Lines.Add(TimeToStr(Time)+': '+text);
end;
procedure SetMy(x,y,z,h:integer);
begin
MyH:=360-(h div 190);
MyX:=x;
MyY:=y;
MyZ:=z;
ShowMap;
end;
procedure AddItem(x,y,oid,id:integer;const name:string='');
var i:integer;
begin
if ii=max then begin Log('Warning: max items!');exit;end;
for i:=0 to ii-1 do
if ItemsID[i,0]=oid then
exit;
if name='' then begin
i:=ItemBase.IndexOfName(inttostr(id));
if i>-1 then
name:=ItemBase.Strings[i]
else
name:=inttostr(id);
end;
ItemsPlace[ii,0]:=x div ratio;
ItemsPlace[ii,1]:=y div ratio;
ItemsID[ii,0]:=oid;
ItemsID[ii,1]:=id;
ItemsName[ii]:=name;
inc(ii);
case pck[1] of
#$0B: Log('Spawn',name);
#$0C: Log('Drop',name);
#$03: Log('Char',name);
#$16: Log('NPC',name);
end;
ShowMap;
end;
procedure DelItem(oid:integer);
var i,k:integer;
begin
k:=-1;
for i:=0 to ii-1 do
if ItemsID[i,0]=oid then
k:=i;
if k>-1 then begin
Log('Delete',ItemsName[k]);
for i:=k to ii-2 do begin
ItemsPlace[i,0]:=ItemsPlace[i+1,0];
ItemsPlace[i,1]:=ItemsPlace[i+1,1];
ItemsID[i,0]:=ItemsID[i+1,0];
ItemsID[i,1]:=ItemsID[i+1,1];
ItemsName[i]:=ItemsName[i+1];
end;
ItemsPlace[ii,0]:=0;
ItemsPlace[ii,1]:=0;
ItemsID[ii,0]:=0;
ItemsID[ii,1]:=0;
ItemsName[ii]:='';
dec(ii);
ShowMap;
end;
end;
begin
if (ConnectName=Name) and FromClient then
if (pck[1]=#$48) then
SetMy(ReadD(2),ReadD(6),ReadD(10),ReadD(14));
if (ConnectName=Name) and FromClient and (pck[1]=#$46) then begin
for ii:=0 to max do begin
ItemsPlace[ii,0]:=0;
ItemsPlace[ii,1]:=0;
ItemsID[ii,0]:=0;
ItemsID[ii,1]:=0;
ItemsName[ii]:='';
end;
ii:=0;
Log('Delete all items');
end;
if (ConnectName=Name) and FromServer then case pck[1] of
//************************************************** ********
//Комментируем не нужные пакеты
//************************************************** ********
//03=CharInfo
#$03: AddItem(ReadD(2),ReadD(6),ReadD(18),0,ReadS(22));
//16=NpcInfo
#$16: AddItem(ReadD(14),ReadD(18),ReadD(2),ReadD(6),Read S(123));
//0B=SpawnItem
#$0B: AddItem(ReadD(10),ReadD(14),ReadD(2),ReadD(6));
//0C=DropItem
#$0C: AddItem(ReadD(14),ReadD(18),ReadD(6),ReadD(10));
//************************************************** ********
//************************************************** ********
#$04: SetMy(ReadD(2),ReadD(6),ReadD(10),ReadD(14));
#$12: DelItem(ReadD(2));
end;
end.
http://ipicture.ru/uploads/080705/9077/thumbs/tWgjaoj1jN.jpg (http://ipicture.ru/Gallery/Viewfull/3124749.html)http://ipicture.ru/uploads/080705/9077/thumbs/q0V2FJZ2Gu.jpg (http://ipicture.ru/Gallery/Viewfull/3127043.html)
Maybe Cooming Soon: Map 2.0 Dll Edition (Beta)
Map 1.0 Final
Форма: на ней перс по центру, показываеться куда направлена голова, и рядом лежащие айтемы и их иды. Для поисковых ивентов...
При клике по форме перс в игре бежит в эту точку (Z не меняеться).
прикольный скрипт.. но.. опять повторюсь что коментарии- сила.. хочется сесть и прочесть твой скрипт на руссском языке.. чтоб по коментариям было понятно как он работает и где его слабые места.. я прошу каждый раз об етом авторов.. хотя конечно лучше что то чем ничего но посторайся коментить почти каждую строчку кода-) хорошо прокоментированые скрипты безоговорочно будут прикреплены к началу поста.. иначе смысла нет.. люди не поймут.. (новечки) ..
мыж тут все друг у друга чемуто да учимся.. приёмам разным.. такчто коментарии не лишнии.. лениво 500 строк кода на паскале вдумываться... коменть-)
Полезный скрипт. Хотел спросить - а можно ли как то с помощью него определять Chest и Box сундуки? И если да, то как убрать отображение всех НПЦ, мобов и Итемов и оставить только сундуки? Если реально и недолго сделать, напиши пожалуйста, буду очень благодарен.
п.с.: а в будущем планируешь встроить карту месности на заднем плане твоего радара ? ) Если да, то супер.
коменть-)
Тама вроде и так всё понятно) Я комментирую тока то что надо доделать) У меня ведь всё по функциям разложено, как по полочкам, функции с говорящими именами.
И обычно все комменты чужих скриптов тоже удаляю...
Полезный скрипт. Хотел спросить - а можно ли как то с помощью него определять Chest и Box сундуки? И если да, то как убрать отображение всех НПЦ, мобов и Итемов и оставить только сундуки? Если реально и недолго сделать, напиши пожалуйста, буду очень благодарен.
п.с.: а в будущем планируешь встроить карту месности на заднем плане твоего радара ? ) Если да, то супер.
внизу скрипта закоментиheq(перед строчкой поставь "//") на нежные пакеты) пока время нету...
будет)
Данный пост важен для более-менее опытных скриптописателей.
В данных скриптах на пример бафера кота за адены показана работа Пати, Продажи и процесс ожидания действий другого персоонажа.
charly911
22.07.2008, 23:52
Hello ppl, im new in the forum. Sry i dont know Russian... im from Argentina (South America).
First of all i would like to tell u that i love this forum and l2phx :D best botting tool ever :D :D
I know little programming, but i could write some scripts that worked excelent.
I have a problem with one script posted in this thread, i cant understand this:
---------------------------------------------------------------------
for i:= 1 to 100 do
begin
if MobID[i] <> '' then
begin
tempX1:=ord(MobX[i][3])*256*256 + ord(MobX[i][2]) * 256 + ord(MobX[i][1]);
tempY1:=ord(MobY[i][3])*256*256 + ord(MobY[i][2]) * 256 + ord(MobY[i][1]);
if (MobX[i][4] = #$FF) then tempX1:=16777215-tempX1;
if (MobY[i][4] = #$FF) then tempY1:=16777215-tempY1;
tempLenght:= sqrt((MyCoordXex-tempx1)*(MyCoordXex-tempx1) + (MyCoordYex-tempy1)*(MyCoordYex-tempy1));
if (tempLenght<MinPutLenght) then
begin
MinPutLenght:=tempLenght;
MinPutID:=i;
end;
end;
end;
------------------------------------------------------------------
Can someone tell me what does it do???? what is "ord" for??? Why is MobID,MobX, etc string and not integer??? o.O
Thnx, Charly.
raid, эт он про твою мапу или про чью-то другую?
for i:= 1 to 100 do
begin
if MobID[i] <> '' then
begin
tempX1:=ord(MobX[i][3])*256*256 + ord(MobX[i][2]) * 256 + ord(MobX[i][1]);
tempY1:=ord(MobY[i][3])*256*256 + ord(MobY[i][2]) * 256 + ord(MobY[i][1]);
if (MobX[i][4] = #$FF) then tempX1:=16777215-tempX1;
if (MobY[i][4] = #$FF) then tempY1:=16777215-tempY1;
tempLenght:= sqrt((MyCoordXex-tempx1)*(MyCoordXex-tempx1) + (MyCoordYex-tempy1)*(MyCoordYex-tempy1));
if (tempLenght<MinPutLenght) then
begin
MinPutLenght:=tempLenght;
MinPutID:=i;
end;
end;
end;
This part of the script show, how to calculate relative distance from objects to your char.
Why is MobID,MobX, etc string and not integer??? o.O because the autor of this script this want =)
what is "ord" for? function ord is for conversion between string-type and integer-type variables. Read the synthax of Pascal and Delphi.
P.S. Sorry for my poor English.
QaK, нет. у меня нету MobX)
raid,ясно,пасиб. charly911, where did you see this code? Which script do you try ti use?
Can someone tell me what does it do???? what is "ord" for??? Why is MobID,MobX, etc string and not integer??? o.O
this part finding mob with minimal distance between mob and you.
ord - get ineteger from string.
maybe memory economy.
raid,ясно,пасиб. charly911, where did you see this code? Which script do you try ti use?
Это КАЧ БОТ "ЛОКОМОТИВ" by VORON
Это КАЧ БОТ "ЛОКОМОТИВ" by VORONОй блиин, ппц парниша попал =)
НЛО спасибо =)
charly911
24.07.2008, 07:48
Hi, thanks QaK for your answer, but when i asked for and explanation i wanted to know in detail what does it do, because once i tried to do something different but it didn't worked... Here is some piece of code:
--------------------------------------------------------
NpcID: array[1..100] of integer; // <-- integer, NOT STRING!!!
NpcX: array[1..100] of integer;
NpcY: array[1..100] of integer;
NpcZ: array[1..100] of integer;
------//-----
NpcID[i]:=ReadD(2);
NpcX[i]:=ReadD(14);
NpcY[i]:=ReadD(18);
NpcZ[i]:=ReadD(22);
----------------------------------------------------
If i tried to do this using string array i got an "incompatibility error".... Only this way worked.
Also i wanted to calculate distance using Pythagoras (sqrt((x*x)+(y*y)), but sometimes i got erros (negative values, theoricaly impossible), thas why i wanted to understand it better.
----
"function ord is for conversion between string-type and integer-type variables. Read the syntax of Pascal and Delphi."
why don't you use StrToInt?????
Thanks, Charly.
charly911, if you use Script by Voron ("Бот кач локомотив") there is o lot of errrs in this script,because olny Voron (as I known) use and test this script, so if something did'nt work correct - try to fix by yourself.
Also i wanted to calculate distance using Pythagoras (sqrt((x*x)+(y*y)), but sometimes i got erros (negative values, theoricaly impossible), thas why i wanted to understand it better.Put there a code of the function to calculate distance, and example, where and how do you use it?
metalFan
24.07.2008, 12:12
воть это мой третий скрипт по счету, который висит окошкоми показывает статы, можно добавить все что угодно :) пишитеа еще лучше, кто подправит ошибку при выключении - пирожокinvalid pointer operation :(а так все путем //монитор, показывает хп\мп\вес\имя :)
//мспользуется в процессах когда нужно nofreeondisconect
//ну или когда вам захочется//тестировался на l2c6 alpha
//v0.1b - первая версия
//v0.2b - изменет алгоритм принудительного обновления
//(c)metalFan
const
name = 'metalFan' ;
//Warning! Не поставишь имя - вылетишь из игры! xD
var frm: TForm; m: TMemo; Button: TButton; MaxHP,CurHP,MaxMP,CurMP,CurLoad,MaxLoad,i: integer;
CharName: string;
procedure Init;
begin
//формочка
frm := TForm.Create(nil);
frm.Caption := 'Info by metalFan v0.2b';
frm.BorderStyle := bsDialog;
frm.Position := poScreenCenter;
frm.Width:=250;frm.Height:=125;
frm.OnClose := @FormClose;
m:=TMemo.Create(frm);
m.parent:=frm;
m.align:=alClient;
m.ReadOnly:=true;
m.ScrollBars:=ssBoth;
Button := TButton.Create(frm);
Button.Parent := frm;
Button.Caption := 'Refresh';
Button.Left := 125;
Button.Top := 15;
Button.onClick := @ForceUpdate;
frm.show;
end;
//закрываем формочку
procedure free;
begin
m.free;
Button.Free;
frm.free;
end;
//принудительное обновление
procedure ForceUpdate;
begin buf:=Hstr('45 01 00 00 00 00 00 00 00 00');
SendToServerEx(name);
delay(50); buf:=Hstr('45 01 00 00 00 00 00 00 00 00');
SendToServerEx(name);
end;
//(c)NLObP скажи нет случайному закрытию формы
procedure FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caNone;
end;
procedure OnDisconnect(WithClient: Boolean); //Вызывается при установке соединения
begin
NoFreeOnClientDisconnect;
NoFreeOnServerDisconnect;
end;
//думалка
begin
if FromServer and (ConnectName=name) and (pck[1]=#$04) then begin
i:=22; CharName:=ReadS(i); i:=i+48; MaxHP:=ReadD(i); CurHP:=ReadD(i); MaxMP:=ReadD(i); CurMP:=ReadD(i); i:=i+4; CurLoad:=ReadD(i); MaxLoad:=ReadD(i);
//выводим на экран это дело
m.lines.add('Name ' + CharName);
m.lines.add('Health ' + inttostr(CurHP) +'\' + inttostr(MaxHP));
m.lines.add('Mana ' + inttostr(CurMP)+'\' + inttostr(MaxMP));
m.lines.add('Load ' + inttostr(CurLoad)+'\' + inttostr(MaxLoad)); end;
end.
Добавлено через 6 минут
кстати как код вставлять а не цитату?
//закрываем формочку
procedure free;
begin m.free;
frm.free;
Button.Free;
end;
Неправильный порядок вызова процедур.
Уничтожение формы, последнее что должно быть в нашем случае. Мне так кажеться, что frm.free достаточно одной. Сделай так:
procedure free;
begin
m.free;
Button.Free;
frm.free;
end;
Добавлено через 2 минуты
кстати как код вставлять а не цитату?
Самая правая решётка. Пишишь туда - delphi, и будет такое обрамление кода [ HIGHLIGHT = " delphi " ][ / HIGHLIGHT ]
metalFan
24.07.2008, 15:34
//монитор, показывает хп\мп\вес\имя
//мспользуется в процессах когда нужно nofreeondisconect
//ну или когда вам захочется//тестировался на l2c6 alpha
//v0.1b - первая версия
//v0.2b - изменет алгоритм принудительного обновления
//v0.3b - исправлена ошибка закрытия хандлера
//(c)metalFan
const
name=('metalFan');
//Warning! Не поставишь имя - вылетишь из игры! xD
var frm: TForm; m: TMemo; Button: TButton; MaxHP,CurHP,MaxMP,CurMP,CurLoad,MaxLoad,i: integer;
CharName: string;
procedure Init;
begin
//формочка
frm := TForm.Create(nil);
frm.Caption := 'Info by metalFan v0.3b';
frm.BorderStyle := bsDialog;
frm.Position := poScreenCenter;
frm.Width:=250;frm.Height:=125;
frm.OnClose := @FormClose;
m:=TMemo.Create(frm);
m.parent:=frm;
m.align:=alClient;
m.ReadOnly:=true;
m.ScrollBars:=ssBoth;
Button := TButton.Create(frm);
Button.Parent := frm;
Button.Caption := 'Refresh';
Button.Left := 125;
Button.Top := 15;
Button.onClick := @ForceUpdate;
frm.show;
end;
//закрываем формочку
procedure free;
begin
m.free;
Button.Free;
frm.free;
end;
//принудительное обновление
procedure ForceUpdate;
begin buf:=Hstr('45 01 00 00 00 00 00 00 00 00');
SendToServerEx(name);
delay(50); buf:=Hstr('45 01 00 00 00 00 00 00 00 00');
SendToServerEx(name);
end;
//(c)NLObP скажи нет случайному закрытию формы
procedure FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caNone;
end;
procedure OnDisconnect(WithClient: Boolean); //Вызывается при установке соединения
begin
NoFreeOnClientDisconnect;
NoFreeOnServerDisconnect;
end;
//думалка
begin
if FromServer and (ConnectName=name) and (pck[1]=#$04) then begin
i:=22; CharName:=ReadS(i); i:=i+48; MaxHP:=ReadD(i); CurHP:=ReadD(i); MaxMP:=ReadD(i); CurMP:=ReadD(i); i:=i+4; CurLoad:=ReadD(i); MaxLoad:=ReadD(i);
//выводим на экран это дело
m.lines.add('Name ' + CharName);
m.lines.add('Health ' + inttostr(CurHP) +'\' + inttostr(MaxHP));
m.lines.add('Mana ' + inttostr(CurMP)+'\' + inttostr(MaxMP));
m.lines.add('Load ' + inttostr(CurLoad)+'\' + inttostr(MaxLoad)); end;
end.
:D так определенно лучше
charly911
25.07.2008, 07:21
Hello :D
charly911, if you use Script by Voron ("Бот кач локомотив") there is o lot of errrs in this script,because olny Voron (as I known) use and test this script, so if something did'nt work correct - try to fix by yourself.
Put there a code of the function to calculate distance, and example, where and how do you use it?
Here is the code i tried to use to calculate the nearest Mob in the area:
---------------------------------------------------------------------
const PJname='UlTrApLeX';
var r,i,j,jMax,Listo,KNpcID,MoveID,MoveX,MoveY,MoveZ,P JID,PJY,PJX,PJZ,PJlvl,PJMaxHP,PJCurHP,PJMaxMP,PJCu rMP,IDTemp:integer;
NpcNameStr,PJNames:string;
frm:TForm;
m:TMemo;
penel:TPanel;
button:TButton;
Label1:TLabel;
NpcID: array[1..100] of integer;
NpcName: array[1..100] of string;
NpcX: array[1..100] of integer;
NpcY: array[1..100] of integer;
NpcZ: array[1..100] of integer;
DisNpc: array[1..100] of integer;
{MoveX: array[1..100] of integer;
MoveY: array[1..100] of integer;
MoveZ: array[1..100] of integer;}
procedure Init; //Вызывается при включении скрипта
begin
frm := TForm.Create(nil);
frm.Caption := 'NPC Info - '+PJName+' - by ..::Charly::..';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=360;
frm.Height:=900;
m:=TMemo.Create(frm);
m.parent:=frm;
m.align:=alClient;
m.ReadOnly:=true;
m.ScrollBars:=ssBoth;
penel:=TPanel.Create(frm);
penel.parent:=frm;
penel.align:=alBottom;
penel.Width:=150;
penel.height:=30;
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=45;
button.caption:='Buscar';
button.onClick:=@buscar;
button.hint:='busca el bicho mas cercano.';
Label1:=TLabel.Create(penel);
Label1.parent:=penel;
Label1.align:=alRight;
Label1.Width:=50;
Label1.Caption:=' 0 ';
i:=1;
j:=1;
jMax:=1;
Listo:=0;
frm.Show;
for i:=1 to 100 do
begin
NpcID[i]:=0;
NpcName[i]:='';
NpcX[i]:=0;
NpcY[i]:=0;
NpcZ[i]:=0;
end;
end;
procedure Free;
begin
frm.Free;
end;
procedure buscar;
begin
IDTemp:=999999999;
for i:=1 to 100 do
begin
if (DisNpc[i] > 0) and (DisNpc[i] < IDTemp) then
begin
IDTemp:=i;
end;
end;
if (DisNpc[IDTemp]>0) and (DisNpc[IDTemp]<>999999999) then
begin
buf:=#$01;
WriteD(NpcX[i]);
WriteD(NpcY[i]);
WriteD(NpcZ[i]);
WriteD(PJX);
WriteD(PJY);
WriteD(PJZ);
SendToServerEx(PJName);
m.Lines.Add('@%@% El bicho mas cercanos es: '+inttostr(IDTemp));
Label1.Caption:=' '+inttostr(i);
end;
end;
begin
if FromServer and (ConnectName=PJName) and (pck[1]=#$04) then
begin
PJX:=ReadD(2);
PJY:=ReadD(6);
PJZ:=ReadD(10);
PJID:=ReadD(18);
PJNames:=ReadS(22);
PJlvl:=ReadD(54);
PJMaxHP:=ReadD(86);
PJCurHP:=ReadD(90);
PJMaxMP:=ReadD(94);
PJCurMP:=ReadD(98);
m.Lines.Add('Nombre:'+(PJNames)+'.');
m.Lines.Add('->Coordenadas: X:'+inttostr(PJX)+' - Y:'+inttostr(PJY)+' - Z:'+inttostr(PJZ)+'.');
m.Lines.Add('->ID:'+inttostr(PJID)+'.');
m.Lines.Add('->lvl:'+inttostr(PJlvl)+'.');
m.Lines.Add('->MaxHP:'+inttostr(PJMaxHP)+'.');
m.Lines.Add('->CurHP'+inttostr(PJCurHP)+'.');
m.Lines.Add('->MaxMP'+inttostr(PJMaxMP)+'.');
m.Lines.Add('->CurMP'+inttostr(PJCurMP)+'.');
end;
//******************** -Pck-16- -NPC Info-***********************
if FromServer and (ConnectName=PJName) and (pck[1]=#$16) then
begin
listo:=0;
i:=1;
Repeat
i:=i+1;
if (NpcID[i]=0)and (Listo=0) then
begin
NpcID[i]:=ReadD(2);
NpcX[i]:=ReadD(14);
NpcY[i]:=ReadD(18);
NpcZ[i]:=ReadD(22);
DisNpc[i]:=((PJX-NpcX[i])*(PJX-NpcX[i]));
Listo:=1;
m.Lines.Add('-->NpcID: '+inttostr(NpcID[i]));
m.Lines.Add('-->NpcX: '+inttostr(NpcX[i])+' - NpcY: '+inttostr(NpcY[i])+' - NpcZ: '+inttostr(NpcZ[i]));
m.Lines.Add('-->Posicion: '+inttostr(i));
m.Lines.Add('-->Distancia del PJ: '+inttostr(DisNpc[i]));
m.Lines.Add('');
end;
if i=100 then Listo:=1;
until Listo=1;
end;
//************************************************** ********
//********************* -Pck-12- -NPC Delete-***************
if FromServer and (ConnectName=PJName) and (pck[1]=#$12) then
begin
KNpcID:=ReadD(2);
listo:=0;
i:=0;
Repeat
i:=i+1;
if (NpcID[i]=KNpcID)and (Listo=0) then
begin
NpcID[i]:=0;
NpcX[i]:=0;
NpcY[i]:=0;
NpcZ[i]:=0;
DisNpc[i]:=0;
Listo:=1;
m.Lines.Add('-----> Posicion '+inttostr(i)+' liberada.');
m.Lines.Add('');
end;
if i=100 then Listo:=1;
until Listo=1;
end;
//************************************************** *****
//******************** -Pck-01- -NPC Move- **************
if FromServer and (ConnectName=PJName) and (pck[1]=#$01) then
begin
MoveID:=ReadD(2);
MoveX:=ReadD(18);
MoveY:=ReadD(22);
MoveZ:=ReadD(26);
listo:=0;
i:=0;
if MoveID<>PJID then
begin
Repeat
i:=i+1;
if (MoveID<>0) and (NpcID[i]=MoveID)and (Listo=0) then
begin
NpcX[i]:=MoveX;
NpcY[i]:=MoveY;
NpcZ[i]:=MoveZ;
DisNpc[i]:=((PJX-NpcX[i])*(PJX-NpcX[i]));
Listo:=1;
m.Lines.Add('> NPC '+inttostr(NpcID[i])+' actualizado.');
m.Lines.Add('> X:'+inttostr(NpcX[i])+' - Y:'+inttostr(NpcY[i])+' - Z:'+inttostr(NpcZ[i])+'.');
m.Lines.Add('> Posicion:'+inttostr(i)+'.');
end;
if i=100 then Listo:=1;
until Listo=1;
end;
end;
if FromServer and (ConnectName=PJName) and (pck[1]=#$01) then
begin
MoveID:=ReadD(2);
MoveX:=ReadD(18);
MoveY:=ReadD(22);
MoveZ:=ReadD(26);
if MoveID=PJID then
begin
PJX:=MoveX;
PJY:=MoveY;
PJZ:=MoveZ;
m.Lines.Add('## Mi pos actualizada.')
end;
end;
end.
--------------------------------------------------------------------------
This is just a test i made, its all a mess :P
What i wanted to do was to create a data base of Mobs position, determine the nearest, and when i pressed the button, the PJ (Player) run to that location. Result: only some times worked, why? i don't know. :'(
I have to re-write it, but i have not enought time as i am working and i have to study.
Maybe this weekend i'll do it, with the corresponding explanation.
I made this script to add it into another, that worked. This is the main working script:
--------------------------------------------------------------------------
{This is very stupid bot, that works fine :D
The way it search mobs is very simple.
He moves to one of four secific points, and all the time uses /targetnext
When he finaly targets a mob, he atacks, until mod is dead.
Then he try to target another, and if no mob is targeted he goes to another position.
If his HP goes less than 55%, he drinks a greater Healing Pot, and if it is lower than 10% he dispears (not log off, but mobs cant atack)
until his HP goes more than 1/2.
He also try to use skills every time he can.
To select the four positions, the only thing that must be made, is to clic one button (Pos1/2/3/4), an then clic on the place you want
to set it.
}
const PJName='UlTrApLeX';
var act,PotID1,PotID2,PotID3,PotID4:integer; me1:char; me2:char; me3:char; me4:char; nm:integer; t1:char; t2:char; t3:char; t4:char; nt:integer; shade:integer; mz:integer; pz:integer; tz:integer; hz:integer; MaxHP,CurHP,MaxMP,Shadow,CurMP,MaxCP,CurCP,ATT,TS, MyCorX,MyCorY,MyCorZ,CoordPpalX,CoordPpalY,CoordPp alZ,Contador,Posicion,Coord,Activo,Activo2,CoordX, CoordY,CoordZ,i: integer;
CoordX1,CoordX2,CoordX3,CoordY1,CoordY2,CoordY3,Co ordZ1,CoordZ2,CoordZ3,CoordX4,CoordY4,CoordZ4,Espe ra,Esperando,AutoSelect,AutoSelect2,PJInfoAct,PJIn foAct2,p,RaceID,SexID,ClassID,MoveOK,MoveOK2,Usand oPot:integer;
m,m2,m3:TMemo; frm,frm2,frm3:TForm; Message,NombreDelPJ,Name,Sex,Race, Class: string;
button: tbutton;
etext3: TEdit;
IDdelPJ,VerificarID,Accuracy,Vicio,ShadowEterno,Bi chosMuertos:integer;
timer1,timer2,timer3: TTimer;
MiID,IDObtenida,IDTemporal,IDActualizable,NeedLoc, Comienzo:integer;
UltimaX,UltimaY,UltimaZ,UltimaXa,UltimaYa,UltimaZa ,Memorizar,LocX1,LocX2,LocX3,LocX4,LocY1,LocY2,Loc Y3,LocY4,LocZ1,LocZ2,LocZ3,LocZ4:integer;
penel,penel2,penel3:TPanel;
ProgressBar1: TProgressBar;
Label1: TLabel;
penel4,penel0: TPanel;
statusBar: TStatusbar;
//
//00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000
//
procedure Init;
begin
frm := TForm.Create(nil);
frm.Caption := 'Movimiento';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=210;
frm.Height:=900;
m:=TMemo.Create(frm);
m.parent:=frm;
m.align:=alClient;
m.ReadOnly:=true;
m.ScrollBars:=ssBoth;
penel:=TPanel.Create(frm);
penel.parent:=frm;
penel.align:=alBottom;
penel.Width:=150;
penel.height:=30;
penel2:=TPanel.Create(frm);
penel2.parent:=frm;
penel2.align:=alBottom;
penel2.Width:=150;
penel2.height:=30;
penel3:=TPanel.Create(frm);
penel3.parent:=frm;
penel3.align:=alBottom;
penel3.Width:=150;
penel3.height:=30;
penel4:=TPanel.Create(frm);
penel4.parent:=frm;
penel4.align:=alBottom;
penel4.Width:=150;
penel4.height:=17;
{penel0:=TPanel.Create(frm);
penel0.parent:=frm;
penel0.align:=alBottom;
penel0.Width:=150;
penel0.height:=30;
StatusBar:=TStatusBar.Create(penel0);
StatusBar.parent:=penel0;
StatusBar.Width:=200; }
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=25;
button.caption:='ID';
button.onClick:=@VerifID;
button.hint:='Verifica ID del PJ.';
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=30;
button.caption:='1';
button.onClick:=@Memo1;
button.hint:='Memoriza ubicacion 1.';
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=30;
button.caption:='2';
button.onClick:=@Memo2;
button.hint:='Memoriza ubicacion 2.';
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=30;
button.caption:='3';
button.onClick:=@Memo3;
button.hint:='Memoriza ubicacion 3.';
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=30;
button.caption:='4';
button.onClick:=@Memo4;
button.hint:='Memoriza ubicacion 4.';
button:=tbutton.Create(penel);
button.parent:=penel;
button.align:=alLeft;
button.Width:=55;
button.caption:='Contador';
button.onClick:=@ContBichos;
button.hint:='Verifica ID del PJ.';
button:=tbutton.Create(penel2);
button.parent:=penel2;
button.align:=alLeft;
button.Width:=50;
button.caption:='Ir a 1';
button.onClick:=@IrMemo1;
button.hint:='Ir a ubicacion 1.';
button:=tbutton.Create(penel2);
button.parent:=penel2;
button.align:=alLeft;
button.Width:=50;
button.caption:='Ir a 2';
button.onClick:=@IrMemo2;
button.hint:='Ir a ubicacion 2.';
button:=tbutton.Create(penel2);
button.parent:=penel2;
button.align:=alLeft;
button.Width:=50;
button.caption:='Ir a 3';
button.onClick:=@IrMemo3;
button.hint:='Ir a ubicacion 3.';
button:=tbutton.Create(penel2);
button.parent:=penel2;
button.align:=alLeft;
button.Width:=50;
button.caption:='Ir a 4';
button.onClick:=@IrMemo4;
button.hint:='Ir a ubicacion 4.';
button:=tbutton.Create(penel3);
button.parent:=penel3;
button.align:=alLeft;
button.Width:=50;
button.caption:='On / Off';
button.onClick:=@ActDes;
button.hint:='Activa / Desactiva el BOT.';
button:=tbutton.Create(penel3);
button.parent:=penel3;
button.align:=alLeft;
button.Width:=70;
button.caption:='Auto Target';
button.onClick:=@AutoSel;
button.hint:='Auto Target On/Off.';
button:=tbutton.Create(penel3);
button.parent:=penel3;
button.align:=alLeft;
button.Width:=60;
button.caption:='Movimiento';
button.onClick:=@PMoveOK;
button.hint:='Movimiento automatico.';
button:=tbutton.Create(penel3);
button.parent:=penel3;
button.align:=alLeft;
button.Width:=20; ////////////////////////////////////
button.caption:='R';
button.onClick:=@Reset;
button.hint:='Resetea contador de Bichos matados.';
Label1:=TLabel.Create(penel4);
Label1.parent:=penel4;
Label1.align:=alLeft;
Label1.Width:=20;
Label1.Caption:=' HP: ';
Progressbar1:= tprogressbar.create(penel4);
Progressbar1.parent:=penel4;
Progressbar1.align:=alLeft;
Progressbar1.Width:=175;
Progressbar1.Height:=20;
Progressbar1.Step:=1;
Progressbar1.Max:=100;
Progressbar1.Min:=0;
//ProgressBar1.PbColor:=Red;
frm.Show; // Initialice Variables
MiID:=0;
Activo:=0;
Activo2:=1;
PjinfoAct:=0;
PJInfoAct2:=1;
AutoSelect:=0;
AutoSelect2:=1;
MoveOK:=0;
MoveOK2:=1;
ShadowEterno:=1;
UsandoPot:=0;
BichosMuertos:=0;
Progressbar1.Position:=0;
//******************
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1;
timer1.enabled:=true;
timer1.interval:=500;
//*****************
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2;
timer2.enabled:=true;
timer2.interval:=500;
//******************
timer3:=TTimer.Create(nil);
timer3.OnTimer:=@OnTimer3;
timer3.enabled:=true;
timer3.interval:=1000;
//******************
end;
procedure Free;
begin
m.Free;
frm.Free;
timer1.Free;
timer2.Free;
timer3.Free;
end;
procedure VerifID; // verify if i got my player ID
begin
if (IDObtenida=1) and (MiID<>0) then m.Lines.Add('ID obtenida correctamente. ID: '+inttostr(MiID));
end;
procedure Memo1;
begin
Memorizar:=1;
NeedLoc:=1;
end;
procedure Memo2;
begin
Memorizar:=2;
NeedLoc:=1;
end;
procedure Memo3;
begin
Memorizar:=3;
NeedLoc:=1;
end;
procedure Memo4;
begin
Memorizar:=4;
NeedLoc:=1;
end;
procedure IrMemo1; // move to memory location 1
begin
buf:=#$01;
WriteD(LocX1);
WriteD(LocY1);
WriteD(LocZ1);
WriteD(UltimaXa);
WriteD(UltimaYa);
WriteD(UltimaZa);
SendToServerEx(PJName);
m.Lines.Add('Ir Loc 1.');
end;
procedure IrMemo4; // move to memory location 4
begin
buf:=#$01;
WriteD(LocX4);
WriteD(LocY4);
WriteD(LocZ4);
WriteD(UltimaXa);
WriteD(UltimaYa);
WriteD(UltimaZa);
SendToServerEx(PJName);
m.Lines.Add('Ir Loc 4.');
end;
procedure IrMemo2; // move to memory location 2
begin
buf:=#$01;
WriteD(LocX2);
WriteD(LocY2);
WriteD(LocZ2);
WriteD(UltimaXa);
WriteD(UltimaYa);
WriteD(UltimaZa);
SendToServerEx(PJName);
m.Lines.Add('Ir Loc 2.');
end;
procedure IrMemo3; // move to memory location 3
begin
buf:=#$01;
WriteD(LocX3);
WriteD(LocY3);
WriteD(LocZ3);
WriteD(UltimaXa);
WriteD(UltimaYa);
WriteD(UltimaZa);
SendToServerEx(PJName);
m.Lines.Add('Ir Loc 3.');
end;
procedure ActDes; // Bot On/Off
begin
if Activo=1 then
begin
Activo:=0;
Activo2:=0;
Message:='Bot desactivado';
m.Lines.Add(Message);
end;
if (Activo=0) and (Activo2=1) then
begin
Activo:=1;
Message:='Bot activado';
m.Lines.Add(Message);
end;
Activo2:=1;
end;
procedure Reset; //not use :P
begin
end;
procedure PMoveOK; // Automatic movement On/Off
begin
if MoveOK=1 then
begin
MoveOK:=0;
MoveOK2:=0;
Message:='Movimiento automatico desactivado.';
m.Lines.Add(Message);
end;
if (MoveOK=0) and (MoveOK2=1) then
begin
MoveOK:=1;
Message:='Movomiento automatico activado.';
m.Lines.Add(Message);
end;
MoveOK2:=1;
end;
procedure AutoSel; // Auto Target On/Off
begin
if AutoSelect=1 then
begin
AutoSelect:=0;
AutoSelect2:=0;
Message:='Auto Select desactivado';
m.Lines.Add(Message);
end;
if (AutoSelect=0) and (AutoSelect2=1) then
begin
AutoSelect:=1;
Message:='Auto Select activado';
m.Lines.Add(Message);
end;
AutoSelect2:=1;
end;
//************************************************** ********************
// SKILL
//
procedure OnTimer1(Sender: TObject); // Skill use
begin
if (TS=1) and (ATT=1) then
begin
{buf:=Hstr('2F 10 00 00 00 00 00 00 00 00 ');
SendToServer;
buf:=Hstr('45 02 00 00 00');
SendToServer;}
buf:=Hstr('2F 07 01 00 00 00 00 00 00 00');
SendToServerEx(PJName);
buf:=Hstr('45 02 00 00 00');
SendToServerEx(PJName);
end;
end;
//*************************************************
// AUTO SELECT
//
procedure OnTimer2(Sender: TObject); // Targetnext
begin
if (TS=0) and (AutoSelect=1) {and (Espera=0)} then
begin
buf:=Hstr('45 04 00 00 00'); // Selecciona.
SendToServerEx(PJName);
end;
end;
//*************************************************
// ATACAR!!!
//
procedure OnTimer3(Sender: TObject); // Atackkk
begin
if (Ts=1) then
begin
buf:=Hstr('45 02 00 00 00'); // Ataca.
SendToServerEx(PJName);
ATT:=1;
end;
end;
//*********************************************
procedure ContBichos; // Shows number of killed mobs
begin
m.lines.Add('.........................');
m.lines.Add('Total de Bichos matados: '+inttostr(BichosMuertos));
m.lines.Add('.........................');
end;
//
//00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000
//
begin
// Obtener ID del PJ - Obtain Players ID
if FromServer and (ConnectName=PJName) and (pck[1]=#$04) then
begin
MiID:=ReadD(18);
IDObtenida:=1;
end;
// ************************************************** ***************************
if FromServer and (ConnectName=PJName) and (pck[1]=#$01) then // Update Pos
begin
IDTemporal:=ReadD(2);
if IDTemporal=MiID then
begin
UltimaXa:=ReadD(6);
UltimaYa:=ReadD(10);
UltimaZa:=ReadD(14);
UltimaX:=ReadD(18);
UltimaY:=ReadD(22);
UltimaZ:=ReadD(26);
{m.Lines.Add('Recibido correctamente...');
m.Lines.Add('Coordenadas:');
m.Lines.Add(' Xa:'+inttostr(UltimaXa));
m.Lines.Add(' Ya:'+inttostr(UltimaYa));
m.Lines.Add(' Za:'+inttostr(UltimaZa));
m.Lines.Add(' X:'+inttostr(UltimaX));
m.Lines.Add(' Y:'+inttostr(UltimaY));
m.Lines.Add(' Z:'+inttostr(UltimaZ));}
IDActualizable:=1;
if NeedLoc=1 then
begin
if Memorizar=1 then // Updates memory Loc1
begin
LocX1:=UltimaXa;
LocY1:=UltimaYa;
LocZ1:=UltimaZa;
Memorizar:=0;
m.Lines.Add('Memoria 1 actualizada.');
end;
if Memorizar=2 then // Updates memory Loc2
begin
LocX2:=UltimaXa;
LocY2:=UltimaYa;
LocZ2:=UltimaZa;
Memorizar:=0;
m.Lines.Add('Memoria 2 actualizada.');
end;
if Memorizar=3 then // Updates memory Loc3
begin
LocX3:=UltimaXa;
LocY3:=UltimaYa;
LocZ3:=UltimaZa;
Memorizar:=0;
m.Lines.Add('Memoria 3 actualizada.');
end;
if Memorizar=4 then // Updates memory Loc4
begin
LocX4:=UltimaXa;
LocY4:=UltimaYa;
LocZ4:=UltimaZa;
Memorizar:=0;
m.Lines.Add('Memoria 4 actualizada.');
end;
end;
end;
end;
//************************************************** ****************************
if Activo=1 then
begin
// Guarda valores de HP y MP - Update HP and MP Values
// -----------------------------
if FromServer and (ConnectName=PJName) and (pck[1]+pck[6]=#$0E#$04) then
begin
CurHP:=ReadD(14);
MaxHP:=ReadD(22);
CurCP:=ReadD(30);
MaxCP:=ReadD(38);
if (CurHP<MaxHP/8) then // Me queda muy poca HP - If very little HP, Disapear!!
begin
Shadow:=1;
end;
if (CurHP<MaxHP/1.8) and (UsandoPot=0) and (Shadow<>10) then // Little HP, Drink Pot
begin
buf:=Hstr('14 54 D6 13 40 00 00 00 00'); // Poco HP ---- CAMBIAR CAMBIAR CAMBIAR CAMBIAR CAMBIAR
SendToServerEx(PJName);
//Message:='Menos de 66% de HP, tomo Pot';
m.Lines.Add('Tengo '+inttostr(CurHP)+'HP, tomo pot..');
UsandoPot:=1;
end;
if (CurHP=MaxHP) then // Tengo todo el HP - Full HP :D
begin
Message:='HP al 100%';
m.Lines.Add(Message);
end;
if (CurCP<MaxCP/2) then // Me quieren PKear - Player ataks me, Desapear!!
begin
Shadow:=3;
end;
Progressbar1.Position:=trunc((CurHP/MaxHp)*100);
end;
//************************************************** **
//************************************************** ******************
// Muy poca vida
// -----------------------
if Shadow=1 then // Disapear!!
begin
buf:=Hstr('14 54 D6 13 40 00 00 00 00'); // Poco HP ---- CAMBIAR CAMBIAR CAMBIAR CAMBIAR CAMBIAR
SendToServerEx(PJName);
shade:=1;
buf:=#$48#$00#$00#$FE#$FF#$7F#$AB#$03#$00#$E9#$F1# $FF#$FF#$88#$D4#$00#$00#$00#$00#$00#$00;
SendToServerEx(PJName);
Message:='Menos del 10% de HP, desaparezco!';
m.Lines.Add(Message);
TS:=0;
ATT:=0;
Shadow:=10;
end;
//------------------------------------------------------------
if Shadow=10 then // Return
begin
if (CurHP>MaxHP/2) then Shadow:=2;
end;
//************************************************** ***********************
// Volver de Shadowmelt
// --------------------------
if Shadow=2 then // Return
begin
shade:=0;
buf:=#$30#$00#$00;
SendToServerEx(PJName);
Message:='REcupere HP, volvi!';
m.Lines.Add(Message);
Shadow:=0;
Shadoweterno:=1;
end;
//************************************************** **************************
// Me PKean
// ------------
if Shadow=3 then // Player atackss
begin
buf:=#$38;
WriteS('Chau PT!!!');
WriteD(0);
SendToServerEx(PJName);
shade:=1;
buf:=#$48#$00#$00#$FE#$FF#$7F#$AB#$03#$00#$E9#$F1# $FF#$FF#$88#$D4#$00#$00#$00#$00#$00#$00;
SendToServerEx(PJName);
Message:='Me ataco otro PJ y desapareci.';
m.Lines.Add(Message);
TS:=0;
ATT:=0;
delay (10000);
Shadow:=10;
end;
//************************************************** ************************
//************************************************** *****************
// Muerte
// ----------------
if FromServer and (ConnectName=PJName) and (pck[1]=#$06) then // Mob died
begin
ATT:=0; // No ataca
TS:=0; // No tiene nada seleccionado
buf:=Hstr('45 05 00 00 00'); // Levantar drop
SendToServerEx(PJName);
m.Lines.Add('------------ Bicho muerto.........');
BichosMuertos:=BichosMuertos+1;
end;
//************************************************** *********************
// Selecciono?????
// ----------------------
if FromServer and (ConnectName=PJName) and (pck[1]=#$A6) then // Target selected
begin
TS:=1;
end;
//************************************************** *******************
// Unselected???
// ----------------
if FromServer and (ConnectName=PJName) and (pck[1]=#$A2) then //Target not selected, Select!!
begin
TS:=0;
ATT:=0;
buf:=Hstr('45 04 00 00 00'); // selecciona. (Target Next)
SendToServerEx(PJName);
end;
if TS=0 then
begin
buf:=Hstr('45 04 00 00 00'); // selecciona. (Target Next)
SendToServerEx(PJName);
buf:=Hstr('45 05 00 00 00'); // Levantar drop
SendToServerEx(PJName);
end;
if MoveOK=1 then
begin
if (Contador=1) and (TS=0) then IrMemo1; // Move to locations...
if (Contador=100) and (TS=0) then IrMemo2;
if (Contador=200) and (TS=0) then IrMemo3;
if (Contador=300) and (TS=0) then IrMemo4;
end;
Contador:=Contador+1;
IF Contador>400 then Contador:=0;
if shade = 1 then
begin
if FromClient and (pck[1]=#$30) then pck:='';
end;
//if FromServer and (pck[1]+pck[2]+pck[3]=#$7f#$00#$00) then UsandoPot:=0;
if FromServer and (ConnectName=PJName) and (pck[1]+pck[2]+pck[3]+pck[4]+pck[5]+pck[6]+pck[7]+pck[8]+pck[9]+pck[10]+pck[11]+pck[12]+pck[13]+pck[14]+pck[15]+pck[16]+pck[17]+pck[18]+pck[19]+pck[20]+pck[21]=Hstr('64 5C 00 00 00 01 00 00 00 04 00 00 00 F5 07 00 00 01 00 00 00')) then UsandoPot:=0;
if FromServer and (ConnectName=PJname)and (pck[1]=#$27) and (pck[12]=#$03) and (pck[13]=#$06)then
begin
PotID1:=ReadC(6);
PotID2:=ReadC(7);
PotID3:=ReadC(8);
PotID4:=ReadC(9);
m.Lines.Add('Greater Healing Potion');
m.Lines.Add('ObjectID='+inttostr(PotID1)+inttostr( PotID2)+inttostr(PotID3)+inttostr(PotID4));
end;
end;
end.
--------------------------------------------------------------------------
I know it is a dissaster but it finished like that because it started as a little simple script, but then i added some lines, then other and other and other... :confused: I have to re-write it also, but it requires time, that i don't have...
Maybe some parts are useful to some body, that is why i posted it...
If some one have some question about the scripts, just ask ;)
Charly.
P.S.: i entered the code using CODE between [], and at the end /CODE, also between [], but the reserved words as "procedure" didn't appeared highlighted, am i doing it well???
--> Edited, now it's ok :D
--> New edit, i added some explanations of the code....
P.S.: i entered the code using CODE between [], and at the end /CODE, also between [], but the reserved words as "procedure" didn't appeared highlighted, am i doing it well???Use tags [ HIGHLIGHT = "delphi" ] [ / HIGHLIGHT ]
Как обычно: Только опытным скриптописателям
Есть интересные задумки не всё рабочее, в основном для пвп-сервера.
Почитайте, иногда интересно)
Breadfan
22.08.2008, 02:06
А вот полезная мелочь)) тупо пересылает пмы:
const
name=''; //ник командира
var
i:integer;
msg:string;
procedure SendMsg(msg:string);
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(Name);
end;
begin
if fromserver and (pck[1]=#$4a) and (pck[6]=#$02) and (connectname<>name)then
begin
i:=10;
msg:=('Incoming Message: From: '+ReadS(i)+' To: '+connectname+' >> '+ReadS(i));
sendmsg(msg);
end;
end.
Хроники: Камаель
Правда сообщения дублируются )
Кстати, я не ошибаюсь что функция StrtoHex теперь вшита в пакетхак? (в версиях 3.3.х)
Глянул аттач Raid (кстати спс за скрипт), жжоте))
if (PartyNick='Corey')or(PartyNick='SaKpa') then begin
buf:=#$38;
WriteS('Ignored you)');
Кстати, я не ошибаюсь что функция StrtoHex теперь вшита в пакетхак? (в версиях 3.3.х)
По ctl+shift показывает функции, которые можно применить (экспортируются из пакетхака).
function StrToHex(StrToHex: string): string;
обратная ей
function HStr(hex: string): string;
Ребят, надеюсь тут появились хорошие люди со вреени моего последнего визита. Есть 2 прозьбы. Вылоджите пожалуйста скрипт на рыбалку желательно что бы сам в ВХ клал адаптированый под шоки и так же скрипт на ТТ рец, тоже с диалогами адаптированными под шок. В своё время я тоже как то выложил абсолютно бескорыстно скрипт на ТТ рец. Щас времени нет заниматься этим :\
Благодарю за внимание.
улыбатор.. рука не поднимается щас удалять.. пускай другие почитают-)
потом вместе с етим постом в корзину-))
Добавлено через 26 минут
Hello ppl, im new in the forum. Sry i dont know Russian... im from Argentina (South America).
First of all i would like to tell u that i love this forum and l2phx :D best botting tool ever :D :D
I know little programming, but i could write some scripts that worked excelent.
I have a problem with one script posted in this thread, i cant understand this:
---------------------------------------------------------------------
for i:= 1 to 100 do
begin
if MobID[i] <> '' then
begin
tempX1:=ord(MobX[i][3])*256*256 + ord(MobX[i][2]) * 256 + ord(MobX[i][1]);
tempY1:=ord(MobY[i][3])*256*256 + ord(MobY[i][2]) * 256 + ord(MobY[i][1]);
if (MobX[i][4] = #$FF) then tempX1:=16777215-tempX1;
if (MobY[i][4] = #$FF) then tempY1:=16777215-tempY1;
tempLenght:= sqrt((MyCoordXex-tempx1)*(MyCoordXex-tempx1) + (MyCoordYex-tempy1)*(MyCoordYex-tempy1));
if (tempLenght<MinPutLenght) then
begin
MinPutLenght:=tempLenght;
MinPutID:=i;
end;
end;
end;
------------------------------------------------------------------
Can someone tell me what does it do???? what is "ord" for??? Why is MobID,MobX, etc string and not integer??? o.O
Thnx, Charly.
i`m author of this script.. i tell all that it is thery simple, but it work corectly.. it is calculate the mob , the distance to mob with the minimum distance.. that is apply when we are select the target to attack. we are know ID of MOB from here.. MobID,MobX in string becorse we must apply it in future code.. and all variables we must convert to string to send server in a packet.. so i do it.. we are read from incoming packet in string format and send in string format.. so all calculations we do with this format, it isnot so hard, you see..
but, of course, the programmer can apply the REAd and WRITE procedure to work this integer format.. but the ERROR is take place when we work with the coordination system.. becourse the sign "-" is present.. to make different calculations with sign "-" we must remember values in "EXTENDED" format.. so it can`t apply in "WRITE" procedure (only integer) so i do the string and work with it..
Ой блиин, ппц парниша попал =)
НЛО спасибо =)
you is ZLODEY!!
Hi, thanks QaK for your answer, but when i asked for and explanation i wanted to know in detail what does it do, because once i tried to do something different but it didn't worked... Here is some piece of code:
--------------------------------------------------------
NpcID: array[1..100] of integer; // <-- integer, NOT STRING!!!
NpcX: array[1..100] of integer;
NpcY: array[1..100] of integer;
NpcZ: array[1..100] of integer;
------//-----
NpcID[i]:=ReadD(2);
NpcX[i]:=ReadD(14);
NpcY[i]:=ReadD(18);
NpcZ[i]:=ReadD(22);
----------------------------------------------------
If i tried to do this using string array i got an "incompatibility error".... Only this way worked.
Also i wanted to calculate distance using Pythagoras (sqrt((x*x)+(y*y)), but sometimes i got erros (negative values, theoricaly impossible), thas why i wanted to understand it better.
----
"function ord is for conversion between string-type and integer-type variables. Read the syntax of Pascal and Delphi."
why don't you use StrToInt?????
Thanks, Charly.
YOU try to remember values with sign "-" in integer.. so you have error.. coordinates are often take negative values.. so try EXTENDED format.. but you wiln`t can apply it in WRITE procedure.. so after calculations with extended format you must convert it to "string" by self.. you must read values in STRING when sign "-" is take place.. when you must convert to EXTENDED for calculation.. and then convert to STRING to apply in POST PROCEDURES..
Breadfan
31.08.2008, 14:58
Хроники Камаель.
Вобщем, в очередной раз сунувшись в кх и обнаружив полное отсутствие свитков для ТП решил посадить там перса с вот таким скриптом
//Включить автоскупку - Да, выключить - Нет
const
name='';
var
OIDnpc:integer;
MyX,MyY,Myz:integer;
start:boolean;
startsk,startcmd:ttimer;
kolvocmd,i,j,jj,x,step,st,itemID,itemcount,count,I Dlist:integer;
Buy:array[1..15,1..2] of integer; //массив для хранения ID и количества итемов в Buy-листе
CmdNpc:array[1..50] of string;
findt,oldpck,cmd,itemIDstr,countstr:string;
Ste:array[1..3] of integer; //в этом массиве содержится последовательность номеров нажимаемых кнопок в меню
procedure Init;
begin
OIDnpc:=0; //Ввести OID нпс кланхолла
startcmd:=TTimer.Create(nil); //счетчик для отсылки команд
startcmd.OnTimer:=@scmd;
startcmd.enabled:=false;
startcmd.interval:=1500;
startsk:=TTimer.Create(nil); //счетчик для частоты пробы покупки
startsk.OnTimer:=@skupka;
startsk.enabled:=false;
startsk.interval:=1000*60*1;
Ste[1]:= 3;
Ste[2]:= 4;
ste[3]:= 1;
step:=0;
count:=0;
end;
procedure Free;
begin
startsk.free;
end;
procedure scmd;
begin
sendmsg(cmd);
RequestByPassToServer(cmd);
startcmd.enabled:=false;
end;
procedure SendMsg(msg:string);
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(Name);
end;
procedure Skupka;
begin
target(OIDnpc);
delay(800);
target(OIDnpc);
delay(800);
end;
procedure Target(Attacker: Integer);
begin
buf:=#$1f;
WriteD(Attacker);
WriteD(MyX);
WriteD(MyY);
WriteD(MyZ);
WriteC(00);
SendToServerEx(Name);
end;
procedure CmdNpcParc;
Begin
kolvocmd:=0;
for j:=1 to 50 do begin
CmdNpc[j]:='';
end;
for j:=1 to length(oldpck) do begin
for x:=0 to 9 do begin
findt:=findt+oldpck[j+x];
end;
if findt='bypass -h ' then begin
for x:=10 to 25 do begin
CmdNpc[kolvocmd+1]:=CmdNpc[kolvocmd+1]+oldpck[j+x];
end;
kolvocmd:=kolvocmd+1;
end;
findt:='';
end;
end;
procedure RequestByPassToServer(cmd:string);
begin
buf:=#$23;
WriteS(cmd);
SendToServerEx(Name);
end;
procedure RequestBuyItem;
begin
buf:=#$40;
WriteD(IDlist);
WriteD(count);
for i:=1 to count do begin
WriteD(buy[i,1]);
WriteD(buy[i,2]);
end;
SendToServerEx(Name);
end;
//----------------------------------------------------------
begin
if FromClient and (ConnectName=name) and (pck[1]=#$59) then
begin
MyX:=ReadD(6);
MyY:=ReadD(10);
MyZ:=ReadD(14);
end;
if FromClient and (ConnectName=name) and (pck[1]=#$34) and (pck[2]=#$06) then startsk.enabled:=true;
if FromClient and (ConnectName=name) and (pck[1]=#$34) and (pck[2]=#$05) then startsk.enabled:=false;
if fromserver and (ConnectName=name) and (pck[1]=#$19) then begin
oldpck:=ReadS(6);
CmdNpcParc;
if not startcmd.enabled then step:=step+1;
if step=4 then step:=1;
cmd:=CmdNpc[ste[step]];
startcmd.enabled:=true;
end;
if fromserver and (ConnectName=name) and (pck[1]=#$07) then begin
IDlist:=ReadD(6);
jj:=1;
for j:=1 to 15 do begin //берем первые 15 итемов из buy-листа, мне более ненужно
i:=18+((j-1)*64);
itemID:=ReadD(i);
itemcount:=ReadD(i);
if (itemID=5858) or (itemid=1829) or (itemid=7134) or (itemid=7126) then begin //здесь ID вещей которые хотелось бы купить
buy[jj,1]:=ItemID;
buy[jj,2]:=itemcount;
count:=count+1;
inc(jj,1);
end;
end;
if count<>0 then begin
RequestBuyItem;
count:=0;
end;
end;
end.
Прошу вашей помощи в оптимизации скрипта, он как-то вышел кривобоко ппц ;)
поначалу отписал ето в КРУЖКЕ НУБОВ но думаю тут ето уместней.. перенес сюда..
у вас 10 окон расставлены как артилерия на поле.. хаотично или по порядку.. вы можете с етих окон сделать РЕДИРЕКТ ИНФЫ на основного чара об том где кто ково видет.. и на основном чаре ты станеш видеть всё поле! прикинь! и ето реально сделать! город на осаде окружить трупами- хотябы 3-4 чарами.. и редирект сделать!
и ты станеш виедеть за 3 километра всех кто там в замке- бегает... жесть
таково еще я неделал но думаю ето несложно.. думаю хорошобы 4 трупа вокруг замка вплотную к стене уложить и сних инфу РЕДИРЕКТИТЬ на основного чара.. а еще думаю во время осады сделать РЕНЕЙМ НИКОВ ВАРОВ.. те налету на основном чаре переделывать ник (либо подпись) в что то типа ПРОФА,ШМОТ, и возможно состояние- типа УД.. удобно было бы.. видиш толпу мясо на осаде а в подписях у всех профа написана.. и буква означающая А или Б или Ы сет.. сразу видно кто папко а кто нет.. имхо удобно..
также думаю было бы неплохо какнибудь автоматизировать процес выделения в таргет варов.. ну не автоматически конечно но хотябы както.. лично у меня большая проблема во время осады с тем что в толпе мяса где вары со своими в перемешку- таргет взять врага.. думаю можно над бошкой стрелочку рисовать которая укажет направление откуда по тебе нанесли удар.. а также в дополнение к етому запрограмировать какоето социальное действие на то чтобы взять в таргет того кто по тебе нанес удар- последним.. если по тебе сразу 2-3 бьют то стрелочка над головой будет крутиться и показывать направление последнего удара.. и при желании нажав на социальное действия тот кто бил последним возьмется в таргет.. думаю ето удобно было бы.. также думаю что еще необходимо выделить както тех кто по тебе стреляет.. типа их НИК или подпись переделывать в что то типа "!!АХТУНГ!!" и плюс к етому состояние ПК вешать на него чтоб ник красным был , чтоб он в толпе не потерялся.. на него укажет и стрелочка и ник будет изменен и прижелании нажав кнопку- выделится в таргет
как вам идея? вроде похожее никто пока невыкладывал? может займемся? полноценным помошником на осаде?
dmitry501
10.09.2008, 05:37
Идея отстой.
Попробуй прийти на осаду с включенам пакетхаком.
Думаю ты неприятно удивишся задержками.
ПВПшится нереально, даже с простейшими скриптами.
ПВПшится нереально, даже с простейшими скриптами.пвпшится реально со скриттами средней сложности, я сам проверял на пвп серве.
APXAHGEJI
10.09.2008, 15:24
Согласен c QaK'ом, вполне можно использовать скрипт на спам HP и СР банок, авто CTRL. В моем пвп боте для ШК еще реализовано быстрая смена пух, маг и файтерской для разных видов скилов + добавил свою систему макросов, без задержек и прерываний использующую скилы и вещи. И вроде ниче так робит, даже на осадах.
А по предложению VORON'а не могу сказать что-то определенное,
может прокатит, а может и нет. Зависит от серва, канала, мощности компа, тоесть скрипт не для всех получится. ИМХО.
Согласен c QaK'ом, вполне можно использовать скрипт на спам HP и СР банок, авто CTRL.
у меня был скрипт на авто цп/мп/хп + мониторинг бовов и чаров в округе с отображением уровня заточенности пухи и профы. Работало норм. Вороновская идея нереализуема т.к. трафа будет жраться очень много и не у каждого есть такой толщины канал,хотя, можно на серваке (если вы одмин=)) запустить свех трупов, написать прогу, которая аккумулирует сведенья и высылает на ваш домашний комп только нужное.
Breadfan
10.09.2008, 16:42
эээ а почему трафа то много? точно также как и несколько окон )
Потому, что осада и несколько окон.
Breadfan
10.09.2008, 17:00
Это вобщем каждый сам решать должен по возможностям своей системы, а насчет трафа: у меня в месяц входящего на 4-4,5Gb - это много или мало? фильмы не тяну, музыку тож, но регулярно бегаю фулпатями набивая очки. на осадах со мной бегут бд и варк, но лагать не начинаю даже в толпе. Так что это не нереализуемо, хотя лагать может сам серв и вот тут уже ничего неподелаешь
Идея отстой.
Попробуй прийти на осаду с включенам пакетхаком.
Думаю ты неприятно удивишся задержками.
ПВПшится нереально, даже с простейшими скриптами.
ну дело обстоит так.. играя на Ц4 3-4 окна на скрипте (боты атакующие по асисту) я имел комп АТЛОН ХП 2600+ лагов впринципе небыло задержек неошутимо.. с появлением 3,2,0 пакетхака и переходом на интерлюд обнаружил задержки при использования скрипта доходящие порой до 10-15 секунд.. и чтоб быстро прокачать етот лаг нужно было переключиться из окна с игрой в пакетхак.. и снова в окно с игрой.. такое поведение пакетхака навело на мысль что ему тупо нехватает быстродействия.. помогло: в диспетчре задач понизить приоритет окон с игрой до минимума а приоритет пакетхака- до максимума.. лаговать перестало.. 2 недели назад купил 4-х ядерный комп- теперь ненужно никакие приоритеты менять всё и так летает..
дале про толщину канала думаю так: труп без пати жрет трафика довольно мало.. даже на осаде.. живой чар в пати особенно если в пати БД СВС и овер еще рядом бафает- вот ето основные тормоза которые нагружают канал связи на осаде.. при любом массовом бафе тебе на клиент передается 8 огромных пакетов которые перечисляют все бафы которые наложены на каждом члене в пати.. в етот момент даже при 2-х ( а порой при одном чаре ) канал 256 КБИТ/СЕК - лагает на несколько секунд.. при использовании бафа овера на 60+ человек лаг тоже прошибает.. но ето некритично думаю.. 3-4 трупа без пати сильно траф ненагрузят думаю.. ну в крайнем случае и 2 трупа хватит.. главное найти для них место грамотное чтоб они максимум территории замка захватывали обзором..
DashKAaa
15.09.2008, 09:55
траф кушается если ты простым клиентом стоишь рядом с варовским овером и он начинает буфф, ну с варком так же...
у меня 5 дней =22 гигобайта, это ботов 20штук окон от 5-6 штук, ну и качь разных мувиков.
недавно играл на радаре в 3 окна на осаде в количестве осаждающих в сумме было 100-120 человек не ощущал не единого лага, при 3 окнах рядом с собой бегающих и 20ботов в раскиданных по всей карте в том числе и городе.
charly911
27.09.2008, 07:34
VOROM = GOD :D
Many many thanks. i have spent many hours looking for the error.
ill use extended var, in a way diffrent to your script, i think it will work.
Then ill post it here.
ThnxThnxThnxThnxThnxThnxThnx
Charly.
charly911
29.09.2008, 02:33
I think this should work:
begin // Get Mob Info
if (FromServer) and (ConnectName=PJName) and (pck[1]=#$16) then
begin
MobID[i]:=ReadD(2); // String
MobX[i][1]:=Read(14); // Integer
MobX[i][2]:=Read(15);
MobX[i][3]:=Read(16);
MobX[i][4]:=Read(17);
MobY[i][1]:=Read(18);
MobY[i][2]:=Read(19);
MobY[i][3]:=Read(20);
MobY[i][4]:=Read(21);
MobZ[i][1]:=Read(22);
MobZ[i][2]:=Read(23);
MobZ[i][3]:=Read(24);
MobZ[i][4]:=Read(25);
end;
end;
//************************************************** **********************************************
begin
MobXTot[i]:=MobX[i][1]+MobX[i][2]+MobX[i][3]+MobX[i][4];
MobYTot[i]:=MobY[i][1]+MobY[i][2]+MobY[i][3]+MobY[i][4]; // MobXTot, MobYTot, MobZTot : extended
MobZTot[i]:=MobZ[i][1]+MobZ[i][2]+MobZ[i][3]+MobZ[i][4];
Distance[i]:=sqr((MobXTot[i]-MyX)*(MobXTot[i]-MyX)+(MobYTot[i]-MyY)*(MobYTot[i]-MyY)); // Extended
end;
//************************************************** ***********************************************
begin // Find Nearest Mob
Nearest:=0;
for i:=1 to 100 do
begin
If Distance[i]<Distance[Nearest] then Nearest:=i;
end;
end;
//************************************************** **********************************************
begin // Atack
buf:=#$0A;
WriteD(MobX[i][1]+MobX[i][2]+MobX[i][3]+MobX[i][4]);
WriteD(MobY[i][1]+MobY[i][2]+MobY[i][3]+MobY[i][4]);
WriteD(MobZ[i][1]+MobZ[i][2]+MobZ[i][3]+MobZ[i][4]);
end;
I just keep the "raw" mob location, an use the variable Distance[i] to convert the int to ext...
I can not test it because im at work -.-
Then ill tell you the results.
Charly.
Привет всем я на етом форуме новичек. Возникла небольшая проблемка, немогу понять в чем проблема. Пытаюсь составить пакет для продажи предметов.
buf:=Hstr('37 00 00 00 00 01 00 00 00');
writeD(raedD(8);)
WriteS(Hstr('УУ УУ УУ УУ 01 00 00 00'));
SendMsg('ok');
SendToServer;
end;
покет продажи выглядит так:
37 00 00 00 00 01 00 00 00 ХХ ХХ ХХ ХХ УУ УУ УУ УУ 01 00 00 00
где х - ид у ид предмета
ок приходит и ниче не просходит
buf:=Hstr('37 00 00 00 00 01 00 00 00');
writeD(raedD(8);)
WriteS(Hstr('УУ УУ УУ УУ 01 00 00 00'));
SendMsg('ok');
SendToServer;
end;
Смотри, красным выделил. Надо писать READD()
Как совет. Отсылай сначала пакет, а потом пиши сообщение ОК.
37=RequestSellItem:d(ListID)d(ListSize:Loop.01.000 3)d(ObjectID)d(ItemID:Get.Func01)d(Count)
21=InventoryUpdate:h(ListSize:Loop.01.0021)h(Chang e)h(ItemType1)d(ObjectID)d(ItemID:Get.Func01)d(Loc ation)d(Count)h(ItemType2)h(CustomType1)h(isEquipp ed)d(BodyPart)h(EnchantLevel)h(CustType2)d(Augment ationBonus)d(Mana)d(AttackAttrElement)d(AttackAttr ElementVal)d(DefAttrFire)d(DefAttrWater)d(DefAttrW ind)d(DefAttrEarth)d(DefAttrHoly)d(DefAttrUnholy)
надрал кусков из скриптов выложеных на форуме, получилось вот так:
if (pck[1]=#$21) and Fromserver and (pck[2]=#$01) and (pck[4]=#$01) and (pck[12]=#$58) and (pck[13]=#$02) then
begin
j:=4;
T:=ReadH(j);
j:=j+2;
myoid:=ReadD(j);
// msg('start');
buf:=#$37;
WriteD(0);
WriteD(1);
WriteD(myoid);
WriteD(600);
WriteD(1);
SendToServerEx(ConnectName);
вроде работает.
[QUOTE=NLObP;16514] Надо писать READ()QUOTE]
А как действует функция read?
Да и где-то тут видел код для отключения от клиента, но немогу найти. поиск результатов не дал, да и ключеве слова подобрать сложно, а очистить оперативы очень хочеться
Да и где-то тут видел код для отключения от клиента, но немогу найти. поиск результатов не дал, да и ключеве слова подобрать сложно, а очистить оперативы очень хочеться
Посмотреть можно в моём скрипте рыбалки и еще где-то на форуме точно есть. C отключением клиента, не всё так просто. И Neting надо отлавливать и с движением проблемы. Допустим в той же рыбалке, пока стоит - ловит, а вот ходить не может. Пакеты на движение клиент шлет, а его мы выгружаем, значит сами должны их формировать.
//Автоматизация заточки предметов до необходимого уровня by NLObP
//Адаптированая под Gracia by CreaDo
//Затачиваем поочереди все предметы с Weapon ID пока не переломаем или не заточим
//Работа проверена на L2C4 Protocol 660 LocalServer "L2J FORTRESS"
//Необходимо затариться оружием, заточками и валерьянкой
//Открываем инвентарь для инициализации скрипта
//Социальное действие YES начать
//Социальное действие NO остановиться
//Enjoy!
{Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.}
//************************************************** ****************************
const
Name='Fatish';
Scroll=959; // 959 - ItemID Scroll Enchant Weapon (Grade S)
Weapon=9866; // 9866 - ItemID Dinasty dager focus (Grade S80)
MaxEnchLvl=10; //max уровень заточки
max=100; //max количество предметов в базе
var
// WpnObjID: array[1..maxwpn,1..maxwpn] of integer; //Weapon ObjID
WpnBase: array[1..2,1..max] of integer; //Weapon ObjID,lvl
ScrlBase: integer; //Scroll ObjID
add: boolean; //прошла заточка?
timer: TTimer;
CurEnchLvl, ColvoWpn, ColvoScrl, CurWpn, CurScrl: integer;
//************************************************** ****************************
procedure Init; //Вызывается при включении скрипта
var
i:integer;
begin
//Enchant:=false;
CurEnchLvl:=0;
timer:=TTimer.Create(nil);
timer.OnTimer:=@OnTimerHP;
timer.enabled:=false;
timer.interval:=2500; //время задержки
Say('Для инициализации скрипта, откройте инвентарь');
end;
//************************************************** ****************************
procedure Free; //Вызывается при выключении скрипта
begin
WpnBase:=nil;
ScrlBase:=nil;
timer.Free;
end;
//************************************************** ****************************
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(Name);
WriteS(msg);
SendToClientEx(Name);
end;
//************************************************** ****************************
procedure CreateItemBase; //пакет 1B, Создает базу ObjectID по ItemID
var
i, ss, sc, ww, j, ObjID, ItemID, lvl, ListCount: integer;
begin
ss:=1; //индекс в массиве скроллов
ww:=1; //индекс в массиве предметов
j:=4; //смещение для ListCount
ListCount:=ReadH(j); //количество итемов не должно превышать max!
if ListCount>max then ListCount:=max;
j:=8; //смещение для ObjectID
//Пробегаем по Инвентарю и сохраняем ObjectID соответствующие необходимым ItemID
for i:=1 to ListCount do begin
ObjID:=ReadD(j); //ObjectID
ItemID:=ReadD(j); //ItemID
j:=j+4;
sc:=readD(j);
j:=j+10;
Lvl:=ReadH(j); //Level
say(inttostr(lvl));
case ItemID of
scroll: begin
ss:=sc;
ScrlBase:=ObjID;
// Say('ColvoScrl='+IntToStr(ss));
end;
weapon: begin
WpnBase[1,ww]:=ObjID;
WpnBase[2,ww]:=lvl;
ww:=ww+1;
// Say('ColvoWpn='+IntToStr(ww));
end;
end;
j:=j+44 //Gracia
// j:=j+2; //для С4
// j:=j+10; //для Интерлюдии
end;
ColvoWpn:=ww-1;
ColvoScrl:=ss;
Say('>ColvoWpn='+IntToStr(ColvoWpn)+' ColvoScrl='+IntToStr(ColvoScrl)+' CurEnchLvl='+IntToStr(CurEnchLvl));
end;
//************************************************** ****************************
procedure UpdateItemBase; //пакет 27, Создает базу ObjectID по ItemID
var
i, ii, j, ss, sc, ww, ObjID, ItemID, Lvl, ListCount, UpdType: integer;
begin
ListCount:=ReadH(2); //количество итемов
//Пробегаем по Инвентарю и сохраняем пары ObjectID - Lvl
j:=4; //смещение для действия с предметом 1-добавлен 2-изменен 3-удален
// Say('Апдейт базы!');
for i:=1 to ListCount do begin
UpdType:=ReadH(j);
j:=j+2;
ObjID:=ReadD(j); //ObjectID
ItemID:=ReadD(j); //ItemID
j:=j+4;
sc:=readD(j);
j:=j+10;
Lvl:=ReadH(j); //Level
// Say('Предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItemID));
case UpdType of
1:case ItemID of
weapon: begin
ColvoWpn:=ColvoWpn+1;
//Say('Добавили предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(weapon));
for ii:=1 to max do
if WpnBase[1,ii]=0 then begin WpnBase[1,ii]:=ObjID; WpnBase[2,ii]:=lvl; end;
end;
scroll: begin ss:=ss+1;
if ScrlBase=0 then ScrlBase:=ObjID;
end;
end;
2:case ItemID of
weapon:
for ii:=1 to max do
if WpnBase[1,ii]=ObjID then begin WpnBase[2,ii]:=lvl; say(inttostr(WpnBase[2,ii])); end;
scroll: sc:=ss;
//Say('Внимание! Изменения в скролле!?');
end;
//удален
3:case ItemID of
weapon: begin
ColvoWpn:=ColvoWpn-1;
for ii:=1 to max do
if WpnBase[1,ii]=ObjID then begin WpnBase[1,ii]:=0; WpnBase[2,ii]:=0; end;
//Say('Удаляем предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(weapon));
end;
scroll: begin
ColvoScrl:=ColvoScrl-1;
for ii:=1 to max do
if ScrlBase=ObjID then ScrlBase:=0;
//Say('Удаляем скролл! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(scroll));
end;
end;
end;
j:=j+44;
// j:=j+2; //для С4
// j:=j+10; //для Интерлюдии
end;
// Say('>>ColvoWpn='+IntToStr(ColvoWpn)+' ColvoScrl='+IntToStr(ColvoScrl)+' CurEnchLvl='+IntToStr(CurEnchLvl));
end;
//************************************************** ****************************
function GetNextWeapon: integer; //Выдает ObjID предмета, если не найден в базе, выдает -1,
//достигли макс уровня заточки -2, подбираем мин текущий уровень заточки -3
var
i: integer;
begin
Result:=-1;
if CurEnchLvl>=MaxEnchLvl then begin
Result:=-2;
exit;
end;
for i:=1 to max do begin
//находим первый подходящий предмет
if (WpnBase[1,i]<>0) and (WpnBase[2,i]<=CurEnchLvl) then begin
Result:=WpnBase[1,i];
exit;
end;
end;
CurEnchLvl:=CurEnchLvl+1;
Result:=-3;
end;
//************************************************** ****************************
function GetNextScroll: integer; //Выдает ObjID скролла, если не найден в базе, выдает -1
var
i: integer;
begin
Result:=-1;
for i:=1 to max do begin
//находим первый подходящий предмет
if (ScrlBase<>0) then begin
Result:=ScrlBase;
exit;
end;
end;
end;
//************************************************** ****************************
procedure UseItem(ObjectID: integer);
begin
buf:=#$19;
WriteD(ObjectID);
WriteD(0);
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure RequesEnchantItem(ObjectID: integer);
begin
buf:=#$5F;
WriteD(ObjectID);
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure OnTimerHP(Sender: TObject);
var
wpn, scrl:integer;
begin
if ColvoScrl=0 then begin
Say('Кончились скроллы! Прервано!');
timer.enabled:=false;
exit;
end;
if ColvoWpn=1 then begin
Say('Остался последний предмет! Прервано!');
timer.enabled:=false;
exit;
end;
Scrl:=GetNextScroll;
if scrl=-1 then begin
Say('Нет такой заточки! Прервано!');
timer.enabled:=false;
exit;
end;
Wpn:=GetNextWeapon;
case wpn of
-1: begin
Say('Нет такого предмета! Прервано!');
timer.enabled:=false;
exit;
end;
-2: begin
Say('Достигли максимальный уровень заточки! Прервано!');
timer.enabled:=false;
exit;
end;
-3: begin
//Say('Подбираем текущий уровень заточки!');
timer.enabled:=true;
exit;
end;
end;
//************************************************
UseItem(Scrl);
RequesEnchantItem(Wpn);
//************************************************
Say('Заточили предмет! Weapon='+IntToStr(Wpn));
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
//социальное действие yes для начало точки
if FromClient and (ConnectName=Name) and (pck=HStr('34 06 00 00 00')) then begin
CurEnchLvl:=0;
Say('Команда Старт!!!');
timer.enabled:=true;
end;
//************************************************** **************************
//социальное действие no для начало точки
if FromClient and (ConnectName=Name) and (pck=HStr('34 05 00 00 00')) then begin
Say('Команда Стоп!!!');
timer.enabled:=false;
end;
//************************************************** **************************
//ItemList
if FromServer and (ConnectName=Name) and (pck[1]=#$11) then CreateItemBase; //создание базы предметов
// if (ColvoWpn=0) or (ColvoScrl=0) then exit; //если нет базы итемов, скрипт дальше не пустит
//************************************************** **************************
//если удалились предметы, стираем в базе предметов пары ObjectID - ItemID
if FromServer and (ConnectName=Name) and (pck[1]=#$21) then UpdateItemBase; //Обновление базы, если принят пакет на удаление предмета
end.
Протестил все работает
Скрипт начал писать для того, чтобы поднатаскать себя в понимании l2phx. Может кому и пригодится....
Бот не умеет мочить моба и подбирать с него дроп, НО он автоматом находит в инвентаре бутылки с хилкой и хиляется ими, а также юзает соски под грейд удочки, если находит.
Для показа меню нада написать 'f' в пати чат, без кавычек.
//Автоматизация ловли рыбы by VerWolF
//Скрипт ловит рыбу и хиляется когда вылавливает монстра.
//Работа проверена на L2C6 Protocol 750 la2.theabyss.ru x3
//Необходимо затариться удочкой и крючками, выучить соответствующие скиллы,
//потеплей одется :D желательно в хэви, ловить советую какким-н толстозадым гномом.
//Бот сам находит соски в инвентаре, которые подходят под грейд удочки и автоматически их использует.
//Бот сам находит Банки для хила в инвентаре и автоматически их использует, когда его атакует моб.
//Бот распознает 3 вида банок для хила: обычные, GHP и QHP и юзает их в соответствии с ситуацией.
//Рыба будет ловиться как с сосками, так и без них, без,
//соответственно, дольше...
//Если вас забанили, то автор ответственности не несет!
//Используйте скрипт на ваш страх и риск!
//Для работы нужно задать константе NAME чара, которым будете рыбачить.
const
fish='2F 20 05 00 00 00 00 00 00 00';
pump='2F 21 05 00 00 00 00 00 00 00';
reel='2F 22 05 00 00 00 00 00 00 00';
NAME='Popka';//Имя чара, который рыбачит.
HPBottleID=1061; //ID бутылок с хилкой
GHPBottleID=1539;
QHPBottleID=1540;
{необходимо уточнить ItemID для своего сервера!!!
1060=Lesser Healing Potion
1061=Healing Potion
1539=Greater Healing Potion
1540=Quick Healing Potion}
HealInterval=15000; //Интервал, через который будет питься бутылко. 15сек. На QHP не распространяется.
FishingIterval=100; //Задержка между закидованием удочки.
HTML='<html><body><center>'+
'<img src="L2UI_CH3.herotower_deco width=256 height=32>'+
'<img src="L2UI.SquareWhite" width=280 height=1>'+
'<img src="L2UI.SquareBlank" width=260 height=4><br>'+
'<font color="04fbfb">.::FiShInG v0.3 by VerWolF::.</font><br>'+
'<font color="04fbfb">.::[Написано на основе кода QaK и NLObP]::.</font><br>'+
'<button value="Start Fishing!" action="bypass -h StartFishing" width=100 height=15 back="sek.cbui94" fore="sek.cbui92">'+
'<button value="Stop Fishing" action="bypass -h StopFishing" width=100 height=15 back="sek.cbui94" fore="sek.cbui92">'+
'<img src="L2UI.SquareWhite" width=260 height=1>'+
'<img src="L2UI.SquareBlank" width=260 height=4><br>'+
'</center></body></html>';
//================================================== ================================================== ==================
var
FishCycleTimer : TTimer;
HealReuseTimer : TTimer;
Status : Boolean;
CharObjID : Integer;
SocialID : Integer;
bypass : String;
MaxHP : Integer;
CurrentHP : Integer;
FSoulshotID : Integer;
FSoulshotObjID : Integer;
ItemCount : Integer; //количество занятых слотов/количество вещей
Inventory: array[1..250,1..10]of integer; //массив инвентаря
//инвентарь
//1 - ItemType1
//2 - ObjectID
//3 - ItemID
//4 - ItemCount
//5 - ItemType2
//6 - CustType1
//7 - IsEquipped
//8 - BodyPart
//9 - EnchantLevel
//10 - CustType2
procedure Init; //Вызывается при включении скрипта
begin
MaxHP:=0;
CurrentHP:=0;
FSoulshotID:=0;
FSoulshotObjID:=0;
ItemCount:=0;
CharObjID:=0;
Status:=false;
FishCycleTimer:=TTimer.Create(nil);
FishCycleTimer.OnTimer:=@OnFishCycleTimer;
FishCycleTimer.enabled:=false;
FishCycleTimer.interval:=FishingIterval;
HealReuseTimer:=TTimer.Create(nil);
HealReuseTimer.OnTimer:=@OnHealReuseTimer;
HealReuseTimer.enabled:=false;
HealReuseTimer.interval:=HealInterval;
Say('Для вывода меню набрать в пати-чате букву f');
end;
procedure Free; //Вызывается при выключении скрипта
begin
FishCycleTimer.Free;
HealReuseTimer.Free;
end;
//процедура для отображения диалога управления ботом.
procedure ShowHTML( _html : string );
begin
buf:=#$00f;
WriteD(5);
WriteS(_HTML);
SendToClientEX(NAME);
end;
//посылаем сообщение, которое видно только в окне бота
//можно использовать для отладки
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(NAME);
WriteS(msg);
SendToClientEx(NAME);
end;
//процедура считывания параметров одного предмета
procedure ItemAction(var Counter:integer; CurrentSlot:integer);
//Counter - Позиция считываемая из пакета, модифицируется функциями ReadC,ReadD
//CurrentSlot - Индекс в массиве Inventory (от 1 до 250)
var
c1:integer;
begin
for c1:=1 to 10 do
begin //Если значение однобайтное
if (c1=1)or(c1=5)or(c1=6)or(c1=7)or(c1=9) then begin
Inventory[CurrentSlot,c1]:=ReadH(Counter);
end;
//Если значение четырехбайтное
if (c1=2)or(c1=3)or(c1=4)or(c1=8) then begin
Inventory[CurrentSlot,c1]:=ReadD(Counter);
end;
//Если значение последнее
if c1=10 then begin
Inventory[CurrentSlot,c1]:=ReadH(Counter);
Counter:=Counter+8;
end;
end;
end;
//Пакет от сервера 1В - создаем или модифицируем весь инвентарь
procedure CreateItemBase;
var
i,j: integer;
begin
ItemCount:=ReadH(4);//Считываем количество вещей в инвентаре
j:=6;
for i:=1 to ItemCount do ItemAction(j,i);
end;
//Пакет от сервера 27 - действия (доавить/изменить/удалить) над одним/несколькими предметами
procedure UpdateItemBase;
var
i,ij,ijk:integer; //простые счетчики для перебора значений
j:integer; //Текущая позиция, откуда считываем значения из пакета
count:integer; //Количество изменяемых предметов
Action: integer; //Действие над предметом
k:boolean; //Нашли ли мы удаляемый предмет?
begin
k:=false;
count:=ReadH(2);//Считываем количество изменяемых предметов
j:=4;
for i:=1 to count do begin
Action:=ReadH(j);//Считываем действие
case Action of
1:begin //ADD
Inc(ItemCount);//Увеличиваем количество занятых слотов
ItemAction(j,ItemCount); //Добавляем предмет
end;
2:begin //UPDATE
for ij:=1 to ItemCount do //Ищем изменяемый предмет по ObjectID
If Inventory[ij,2]=ReadD((j-1)*30+8) then begin //Если нашли
ItemAction(j,ij); //Изменяем данные о нем
exit; //Больше проверять не надо - выходим из цикла
end;
end;
3:begin //DELETE
for ij:=1 to ItemCount-1 do begin //Ищем удаляемый предмет
If Inventory[ijk,2]=ReadD((j-1)*30+8) then k:=true; //Если нашли,фиксируем это
If k then //если найден удаляемы объект
for ijk:=1 to 10 do //то сдвигаем элементы массива-инвентаря
Inventory[ij,ijk]:=Inventory[ij+1,ijk];
end;
Dec(ItemCount);//Уменьшаем количество занятых слотов
end;
end;
end;
end;
//Получить ObjectID предмета, зная его ItemID
function GetInfo(ItemID:integer):integer;
var
c1:integer;
begin Result:=-1;
for c1:=1 to ItemCount do
if (ItemID=Inventory[c1,3]) then begin
Result:=Inventory[c1,2];
exit;//Если нашли - выходим из цикла
end;
end;
//Проверяем, одет ли предмет по ItemID
function IsEquipped(ItemID:integer):integer;
var
c1:integer;
begin Result:=-1;
for c1:=1 to ItemCount do
if (ItemID=Inventory[c1,3]) and (Inventory[c1,7]=1) then begin
Result:=1;
exit;
end;
end;
//Использовать предмет с заданным ItemID
procedure UseItem(ItemID:integer);
var
c1:integer;
begin
for c1:=1 to ItemCount do
if (ItemID=Inventory[c1,3]) then begin
buf:=#$14;
WriteD(Inventory[c1,2]);
WriteD(0);
SendToServerEX(NAME);
exit; //Чтоб не использовать несколько предметов с одинаковым ItemID (например заточки)
end;
end;
//Используем рыбное соско.....
procedure UseSoulshot(ObjID:integer);
begin
buf:=#$14;
WriteD(ObjID);
WriteD(0);
SendToServerEX(NAME);
end;
//Процедура для отсылки пакета о начале или окончании рыбалки.
//Также определяет по одетой на чара удочке ID и ObjectID сосок,
//которые нада юзать и юзает их в дальнейшем автоматически.
{ Проверьте эти значения для своего сервера!!!
6529=Baby Duck Rod (NG) 6535=Fishing Shot: non-grade
6530=Albatross Rod (D) 6536=Fishing Shot: D-grade
6531=Pelican Rod (C) 6537=Fishing Shot: C-grade
6532=KingFisher Rod (B) 6538=Fishing Shot: B-grade
6533=Cygnus Pole (A) 6539=Fishing Shot: A-grade
6534=Triton Pole (S) 6540=Fishing Shot: S-grade
}
procedure Fishing;
var
i : Integer;
begin
if (FSoulshotID=0) and (FSoulshotObjID=0) then begin
for i:=6529 to 6534 do
begin
if IsEquipped(i)=1 then begin
FSoulshotID:=(i+6);
FSoulshotObjID:=GetInfo(FSoulshotID);
if (FSoulshotObjID<>-1) then begin
Say('Соски будут использоваться автоматически.');
end
else begin
FSoulshotID:=0;
FSoulshotObjID:=0;
end;
end;
end;
end;
buf:=HStr(fish);
SendToServerEX(NAME);
end;
//юзаем Pumping вместе с соской
procedure Pumping;
begin
if (FSoulshotObjID<>-1) then UseSoulshot(FSoulshotObjID);
buf:=HStr(pump);
SendToServerEX(NAME);
end;
//юзаем Reeling вместе с соской
procedure Reeling;
begin
if (FSoulshotObjID<>-1) then UseSoulshot(FSoulshotObjID);
buf:=HStr(reel);
SendToServerEX(NAME);
end;
//пьем банко как только пройдет 15 секунд
procedure OnHealReuseTimer(Sender: TObject);
begin
if (CurrentHP < MaxHP) and (CurrentHP > (MaxHP/2)) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
if (CurrentHP < (MaxHP/2)) and (CurrentHP > ((MaxHP/100)*10)) then begin
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
end;
if (CurrentHP < ((MaxHP/100)*10)) then begin
if (GetInfo(QHPBottleID)<>-1) then UseItem(QHPBottleID);
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
end;
end;
//начинаем рыбачить как только щелкнет таймер
procedure OnFishCycleTimer(Sender: TObject);
begin
Fishing;
FishCycleTimer.enabled:=false;
end;
//************************************************** ****************************
// Тело скрипта.
//************************************************** ****************************
begin
//не обрабатываем пустые пакеты
if pck='' then exit;
//Если скрипт ничего не знает о содержимом инвентаря, то вынуждаем его узнать о нем.
if ItemCount=0 then begin
buf:=#$0F;
SendToServerEX(NAME);
end;
//************************************************** **************************
//РАЗБОР ПАКЕТОВ ОТ СЕРВЕРА:
if FromServer then begin
//создаем или обновляем описание предметов в инветаре.
case pck[1] of
#$1B:begin
CreateItemBase;
end;
#$27:begin
UpdateItemBase;
end;
end;
//Получаем пакет UserInfo, вынимаем оттуда свой ObjectID
if (pck[1]=#$04) and (ReadS(22)=ConnectName) and (CharObjID=0) then begin
CharObjID:=ReadD(18);
end;
//Хиляемся..... СНачала обычными банками, потом, когда хп меньше половины - GHP, а когда хп - 10% - QHP
if (pck[1]=#$0E) and (pck[6]=#$04) then begin
CurrentHP:=ReadD(14);
MaxHP:=ReadD(22);
if (CurrentHP < MaxHP) and (CurrentHP > (MaxHP/2)) and (HealReuseTimer.enabled=false) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=true;
end;
if (CurrentHP < (MaxHP/2)) and (CurrentHP > ((MaxHP/100)*10)) and (HealReuseTimer.enabled=false) then begin
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=true;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=true;
end;
end;
if (CurrentHP < ((MaxHP/100)*10)) and (HealReuseTimer.enabled=false) then begin
if (GetInfo(QHPBottleID)<>-1) then UseItem(QHPBottleID);
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=true;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=true;
end;
end;
end;
//Рыбачим.....
if Status=true then begin
if (ReadH(1)=5886) and (pck[16]=#$00) and (ReadD(4)=CharObjID) then Pumping;
if (ReadH(1)=5886) and (pck[16]=#$01) and (ReadD(4)=CharObjID) then Reeling;
if (ReadH(1)=5374) and (ReadD(4)=CharObjID) then FishCycleTimer.enabled:=true;
end
else
exit;
end;
//РАЗБОР ПАКЕТОВ ОТ КЛИЕНТА:
if FromClient then begin
if (pck[1]=#$21) then begin
bypass:=ReadS(2);
case bypass of
'StartFishing':begin
if (Status=false) then begin
Status:=true;
Fishing;
end;
end;
'StopFishing':begin
if Status=true then Fishing;
Status:=false;
FishCycleTimer.enabled:=false;
end;
end;
end;
if (pck[1]=#$38) and (ReadS(2)='f') and (ReadD(6)=3) then ShowHTML(HTML);
end;
end.
Долго мучисля, но все таки научил его спойлить. Выкладываю правленый скрипт бота от Alexus.
Огромное спасибо QaK за оказаную помощь и проявленное терпение=)
{################################################# ############################
Бот - локомотив от Alexus edit by VismuT (Научился спойлить)
версия : 0.3 (бета)
дата: 08.04.08
Описание:
Бот для кача в принципе любого война. По функциональности это еще не Волкер, но скрипт уже довольно умный :)
Охотиться только на заданных мобов.
Возможности:
- запоминает центр и радиус кача
- запоминает список мобов на которых надо охотиться!
- запоминает и затем подбирает дроп, упавший с убитых им мобов
- умеет лечиться банками (тип банки легко настраивается), ведется учет количества оставшихся банок
- управляется из окна чата в самом клиенте
- имеет окно для вывода всех параметров и статистики
- если моб по какой-то причине стал недосягаемым (стоит за деревом), то через 1 мин БОТ переключится на другого моба.
- если бот умирает, то не палимся и прекращаем рыпаться...(скоро появиться возможность логаута)
- работает под С4 и С6
Недостатки: (со временем будет исправлено)
- бот не умеет обходить препядствия
- бот может увязаться за атаковавшим его другим игроком
Инструкция:
1. Запускаем ПакетХак, запускаем игрового клиента
2. Внимательно НАСТРАИВАЕМ параметры в секции настройки, жмем кнопку "Сохранить" и запускаем скрипт.
3. Добираемся до места кача
4. Выбираем в таргет моба на которого хотим охотится и отправляем в общий чат-> 1
5. Валим моба. Если все правильно сделали будет выдано сообщение в чате что моб добавлен.
6. Выбираем следующего моба отправляем в общий чат цифру 2, валим его и т.д. можно выбрать до 10 разных тварей.
7. Становимся в центр кача и отправляем в общий чат-> pos , если все правильно то в чате будет выдано сообщение, что координаты заданы.
8. Бежим к краю радиуса кача и отправляем в общий чат-> dist, в чате вылезет сообщение от системы, что радиус задан.
9. Валим как можно больше мобов в округе, становимся примерно в центр и отправляем в общий чат-> start ,
если все сделано верно, то будет выдано соответствующее сообщение.
10. Если бот поймал моба в таргет и побежал его атаковать, то можно свернуть окно игры
и смотреть на информационное окно скрипта.
################################################## ###########################}
const
//################### Сеция настройки бота ############################################
NickName = 'HiliH'; // Твой ник в игре
Interlude = true; // C4 - false, C6 - true;
HPMedium = 40; // Уровень жизни, при котором начинаем глотать банки
HPBottleID = 1061; // ItemID 1060=Lesser Healing Potion; 1061=Healing Potion; 1539=Greater Healing Potion;
Vertical = 300; // Вертикальный радиус кача
InvRazmer = 99; // Размер инвентаря -1 (т.е. если инвентарь 80, то пишем сюда 79)
//############# Секция расширенной настройки для опытных ботоводеров :) ###################################
TimerCombat_Interval = 1000; // частота срабатывания таймера атаки в милисекундах, чем меньше это число, тем быстрее бот будет думать.
TimerPickUp_Interval = 750; // частота срабатывания таймера сбора дропа, чем меньше это число, тем быстрее бот будет думать.
TimerForm_Interval = 10000; // частота срабатывания таймера обновления формы, чем меньше это число, тем быстрее будут обновляться данные в форме.
DrinkDelay = 14; // минимальное время задержки повторного питься бутылки (10 - 20 сек)
Attack_Time = 60; // Время на убивание моба в секундах.
PickUp_Time = 30; // Врямя на поднятие дропа в секундах.
OblastVidimosti = 1000; // Приращение к радиусу кача, для мобов которые стоят прямо на границе радиуса (изменять от 100 до 1000)
maximumItems = 100; // Размер базы мобов и дропа
//################################################## ######################################
NpcTypeID_List_Razmer = 10; // Размер списка мобов (не трогать!)
OX = 1; OY = 2; OZ= 3; // Служебные константы
var
InitMode, PickUpMode, SpoilMode : boolean;
//-------------------------------------- БД --------------------------------------------------
MobsID : array [1..maximumItems] of integer;
MobsDist : array [1..maximumItems] of integer; // Расстояние от центра кача
MobsXYZ : array [1..maximumItems, 1..3] of integer; // Координаты
MobsAgression : 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)
HPBottleObjID, HPBottleCount : integer; // ObjID и количество HP-бутылей
TargetID, LastKilledMobObjID : integer; // Текущая цель, последний убитый моб
MobsKilled : integer; // счетчик убитых мобов
Povtor: integer;
CenterX, CenterY, CenterZ : integer; // Центр кача
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;
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, textMobsKilled: TEdit;
//----------------------------------------------------------
TimerForm, TimerCombat, TimerPickUp : TTimer; // таймеры
time1: integer;
Calculated_AttackTime, Calculated_PickUpTime : integer;
AttackCycle: integer; // Цикл атаки
//################################################## ############################################
procedure Init; //Вызывается при включении скрипта
begin
ClearDB;
MyID:= 0; // обнуляем ВСЕ данные
MyX:= 0;
MyY:= 0;
MyZ:= 0;
MyID:= 0;
MyHP:= 0;
MyMaxHP:= 0;
MyMP:= 0;
MyMaxMP:= 0;
MyCP:= 0;
MyMaxCP:= 0;
time1:=1;
SpoilMode:= true;
Calculated_AttackTime:= round (1000 / TimerCombat_Interval * Attack_Time);
Calculated_PickUpTime:= round (1000 / TimerPickUp_Interval * PickUp_Time);
HPlevelProcent:= 0;
HPBottleObjID:= 0;
HPBottleCount:= 0;
InitMode:= true;
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;
frmParamIndex:=0; // создаем контролы в форме
frm:= TForm.Create(nil);
frm.Caption:= 'BOT by Alexus ver: 0.3 beta';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=650;
frm.Height:=700;
MobsDBscreen:=TMemo.Create(frm);
MobsDBscreen.parent:=frm;
MobsDBscreen.ReadOnly:=true;
MobsDBscreen.ScrollBars:=2;
MobsDBscreen.Top:=1;
MobsDBscreen.Width:=460;
MobsDBscreen.Height:=285;
MobsDBscreen.Lines.Add('Мобы');
ItemsDBscreen:=TMemo.Create(frm);
ItemsDBscreen.parent:=frm;
ItemsDBscreen.ReadOnly:=true;
ItemsDBscreen.ScrollBars:=2;
ItemsDBscreen.Top:=286;
ItemsDBscreen.Width:=460;
ItemsDBscreen.Height:=285;
ItemsDBscreen.Lines.Add('Дроп');
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('...');
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('Цикл атаки:');
textMobsKilled:= CreateTextBox('MobsKilled');
CreateLabel('Убито моб:');
frm.Show; // выводим форму на экран
buf:= #$0F; // принудительно вызываем пакеты инвентаря и userinfo
SendToServerEx(NickName);
end;
procedure ClearDB; // Очистка БД
var // Надо все занулять, иначе там хрень всякая вылезает или старые данные
i, n: word;
begin
MobsLastIndex:= 0; // Очищаем переменные
ItemsLastIndex:= 0;
TargetID:= 0;
LastKilledMobObjID:= 0;
MobsKilled:= 0;
Povtor:= 0;
CenterX:= 0;
CenterY:= 0;
CenterZ:= 0;
Radius:= 0;
AttackCycle:= 0;
for i:=1 to NpcTypeID_List_Razmer do NpcTypeID_List[i]:= 0;
NpcTypeID_List_Count:= 0;
NpcTypeID_CurrentMob:= 0;
for i:=1 to maximumItems do // Очищаем базу
begin
MobsID[i]:= 0;
MobsDist[i]:= 0;
MobsXYZ[i, OX]:= 0;
MobsXYZ[i, OY]:= 0;
MobsXYZ[i, OZ]:= 0;
MobsAgression[i]:= false;
Items_ObjectID[i]:= 0;
Items_ItemID[i]:= 0;
Items_XYZ[i, OX]:= 0;
Items_XYZ[i, OY]:= 0;
Items_XYZ[i, OZ]:= 0;
end;
for i:=0 to InvRazmer do for n:=0 to 9 do Inventory[i, n]:= 0;
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
if interlude then offset:= 8 else offset:=0;
for i:=0 to InvRazmer do
if (i<ReadH(4)) then begin
Inventory[i,0]:=ReadH(i*(28+offset)+6); // itemType1
Inventory[i,1]:=ReadD(i*(28+offset)+8); // ObjectId
Inventory[i,2]:=ReadD(i*(28+offset)+12); // ItemID
Inventory[i,3]:=ReadD(i*(28+offset)+16); // count
Inventory[i,4]:=ReadH(i*(28+offset)+20); // itemType2
Inventory[i,5]:=ReadH(i*(28+offset)+22); // CustType1
Inventory[i,6]:=ReadH(i*(28+offset)+24); // isEquipped
Inventory[i,7]:=ReadD(i*(28+offset)+26); // BodyPart
Inventory[i,8]:=ReadH(i*(28+offset)+30); // EnchantLevel
Inventory[i,9]:=ReadH(i*(28+offset)+32); // CustType2
end else
for k:=0 to 9 do Inventory[i,k]:=0; // забиваем нулями
end;
procedure InventoryUpdate;
var
i,j,k, offset: integer;
begin
if interlude then offset:= 8 else offset:=0;
for j:=0 to (ReadH(2)-1) do
begin
case pck[j*(30+offset)+4] of
#$01: k:=0; // add item, запишет на пустую ячейку
#$02: k:=ReadD(j*(30+offset)+8); // mod item
#$03: begin // remove item, обнулит ячейки удаленного предмета
k:=ReadD(j*(30+offset)+8);
for i:=0 to InvRazmer do if (Inventory[i,0]=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*(30+offset)+6); // itemType1
Inventory[i,1]:=ReadD(j*(30+offset)+8); // ObjectId
Inventory[i,2]:=ReadD(j*(30+offset)+12); // ItemID
Inventory[i,3]:=ReadD(j*(30+offset)+16); // count
Inventory[i,4]:=ReadH(j*(30+offset)+20); // itemType2
Inventory[i,5]:=ReadH(j*(30+offset)+22); // CustType1
Inventory[i,6]:=ReadH(j*(30+offset)+24); // isEquipped
Inventory[i,7]:=ReadD(j*(30+offset)+26); // BodyPart
Inventory[i,8]:=ReadH(j*(30+offset)+30); // EnchantLevel
Inventory[i,9]:=ReadH(j*(30+offset)+32); // 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 InvRazmer 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); //Использовать предмет с заданным ItemID
begin
buf:=#$14;
WriteD(ItemObjID);
WriteD(0);
SendToServerEx(NickName);;
end;
//################################################## ##########################################
function rastoyanie(NpcX, NpcY, NpcZ : integer) : integer; // вычисление растояния между 2 точками
var
dx,dy,dz, summa : integer;
begin
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 + 5000; // добавляем коррекцию по вертикали
end;
procedure AddDroppedItem (ObjID, ItemID, X, Y, Z: integer); // Процедура добавляет дропнутую вещь в БД
begin
inc (ItemsLastIndex);
if ItemsLastIndex > maximumItems then exit;
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, x,y,z : integer; agression : boolean); // Процедура добавляет в БД нового моба
var
i:integer;
dist: integer;
begin
dist:= rastoyanie (x,y,z); // вычиляем расстояние от центра кача до моба
if dist > (Radius + OblastVidimosti) then exit; // если моб слишко далеко то ничего не делаем
inc (MobsLastIndex); // увеличиваем размер БД
log.Lines.Add('Моб добавлен, индекс в БД: '+ inttostr(i));
if agression then log.Lines.Add('На нас напала какая-то вражина.');
MobsID[MobsLastIndex]:= id; // Записываем моба
MobsDist[MobsLastIndex]:= dist;
MobsXYZ[MobsLastIndex, OX]:= x;
MobsXYZ[MobsLastIndex, OY]:= y;
MobsXYZ[MobsLastIndex, OZ]:= z;
MobsAgression[MobsLastIndex]:= agression;
end;
procedure UpdateDB (i:integer; id, x,y,z : integer; agression : boolean); // Процедура обновляет данные в БД по мобу
var
dist: integer;
begin
if (MOBSXYZ[i, OX] = x) and (MOBSXYZ[i, OY] = y) and (MobsAgression[i] = agression) then exit; // проверяем, а надо ли чего нить менят
dist:= rastoyanie (x,y,z);
if dist > (Radius + 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;
MobsAgression[i]:= agression;
end;
end;
procedure DelDBItem (i: integer); // процедура удалаяет моба из БД
var
n: integer;
begin
log.Lines.Add('Моб удален, индекс в БД: '+ inttostr(i));
MobsID[i]:= 0;
MobsDist[i]:= 0;
MobsXYZ[i, OX]:= 0;
MobsXYZ[i, OY]:= 0;
MobsXYZ[i, OZ]:= 0;
MobsAgression[i]:= false;
if i < MobsLastIndex then for n:= i+1 to MobsLastIndex do // если надо, производим циклический сдвиг данных в массивах
begin
MobsID[n-1]:= MobsID[n];
MobsDist[n-1]:= MobsDist[n];
MobsXYZ[n-1, OX]:= MobsXYZ[n, OX];
MobsXYZ[n-1, OY]:= MobsXYZ[n, OY];
MobsXYZ[n-1, OZ]:= MobsXYZ[n, OZ];
MobsAgression[n-1]:= MobsAgression[n];
end;
dec (MobsLastIndex); // уменьшаем размер БД
end;
procedure DelDroppedItem (i: integer); // процедура удалаяет вещь из БД
var
n: 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 for n:= i+1 to ItemsLastIndex do
begin
Items_ObjectID[n-1]:= Items_ObjectID[n];
Items_ItemID[n-1] := Items_ItemID[n];
Items_XYZ[n-1, OX]:= Items_XYZ[n, OX];
Items_XYZ[n-1, OY]:= Items_XYZ[n, OY];
Items_XYZ[n-1, OZ]:= Items_XYZ[n, 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 MobsID[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(msg:string); // отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(NickName);
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
SendMsg('Все начальные параметры заданы и проверены!');
log.Lines.Add('Все начальные параметры заданы и проверены!');
result:= true;
end
else
begin
SendMsg('Ошибка задания начальных параметров!');
log.Lines.Add('Ошибка задания начальных параметров!');
result:= false;
end;
end;
procedure UserCommandsInitMode; // комманды пользователя для режима настройки бота
begin // если комманда обработана удачно, то в чат сообщение не попадет, а будет выдано системное сообщение прямо в клиент
case (ReadS(2)) of
'pos' : if MyX <> 0 then // центр кача
begin
CenterX:= MyX;
CenterY:= MyY;
CenterZ:= MyZ;
SendMsg('Центр кача задан успешно!');
log.Lines.Add('Центр кача задан успешно!');
pck:='';
end;
'dist' : if (CenterX <> 0) and (MyX <> 0) then // радиус кача
begin
Radius:= rastoyanie (MyX,MyY,MyZ);
SendMsg('Радиус кача задан успешно');
SendMsg('R= '+ inttostr(Radius));
log.Lines.Add('Радиус кача задан успешно, R = '+ inttostr(Radius));
pck:='';
end;
'reset': begin // сброс параметров
ClearDB;
SendMsg('БД очищена, введите заново все параметры');
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('Добавлять мобов можно тока по очереди 1, 2, 3...');
pck:='';
exit;
end;
NpcTypeID_CurrentMob:= strtoint(ReadS(2));
SendMsg('Добавляем моба № '+ ReadS(2));
pck:='';
end;
'start': begin // собственно запуск бота
if ValidateData and InitMode then
begin
SendMsg('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
log.Lines.Add('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
TargetID:=0;
InitMode:= false;
TimerCombat.enabled:=true; // запускаем таймер
end
else
begin
SendMsg('Еще не все параметры заданы. Проверьте параметры...');
log.Lines.Add('Еще не все параметры заданы. Проверьте параметры...');
end;
pck:='';
end;
end;
end;
procedure UserCommandsCombatMode; // комманды пользователя для боевого режима
begin // команды говорят сами за себя)
case (ReadS(2)) of
'pause' : begin
TimerCombat.enabled:= not(TimerCombat.enabled);
pck:='';
if TimerCombat.enabled then
begin
SendMsg('Искуственный интелект запущен!');
log.Lines.Add('Искуственный интелект запущен!');
end
else
begin
SendMsg('Искуственный интелект приостановлен.');
log.Lines.Add('Искуственный интелект приостановлен.');
end
end;
'stop' : begin
pck:='';
SendMsg('Искуственный интелект остановлен.');
log.Lines.Add('Искуственный интелект остановлен.');
StopGame;
end;
end;
end;
procedure StopGame; // остановка кача
begin
TimerCombat.enabled:= false;
// InitMode:= true;
TimerPickUp.enabled:=false;
TargetID:= 0;
ClearDB;
end;
function GetMinDistID : integer; // функция поиска ближайшего моба в БД
var
i, dist : integer;
begin
dist:=10000; // задаем заранее нереальную дистанцию
for i:=1 to MobsLastIndex do if (MobsID[i] <> 0) and (MobsDist[i] < dist) then
begin // фишка в том, что в базе хранятся расстояния не до меня, а до центра кача
dist:= MobsDist[i]; // но в катах то расстояния небольшие
result:= i; // если нашли хоть одного моба или несколько возращаем его индекс ближайшего к центру кача
end;
if dist = 10000 then result:= 0; // иначе возвращаем 0 (ничего не найдено)
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:=#$04; //action
WriteD(TargetID);
WriteD(MyX);
WriteD(MyY);
WriteD(MyZ);
WriteC(0);
SendToServerEx(NickName);
if SpoilMode=true then begin
buf:=hstr('2F FE 00 00 00 00 00 00 00 00');
SendToServerEX(NickName);
end;
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 OnTimerPickUp (Sender: TObject); // таймер поднятия дропа
var
povtor: integer;
begin
if (AgroTest > 0) and (TargetID = 0) then
begin
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: integer;
begin
if MobsLastIndex = 0 then // если нет мобов в базе, то
begin
if ItemsLastIndex > 0 then InitPickUpMode(true); // надо дроп подбирать
exit; // выходим от сюда
end;
if TargetID > 0 then // если в прицеле есть моб, то
begin // валим вражину
if ((AttackCycle mod 5) = 0) then PhisicalAttack;
inc(AttackCycle);
if AttackCycle > Calculated_AttackTime then // если валим моба больше минуты, значит это баг...
begin
Povtor:= TestPovtor(TargetID);
if Povtor <> 0 then DelDBItem(Povtor);
TargetID:= 0;
end;
exit;
end;
Agro:= AgroTest; // если есть мобы в базе и нет текущей цели, то
MinDistID:= GetMinDistID; // запускаем алгоритм выбора цели
if Agro > 0 then // если нас кто-то атакует, то его и выбираем
begin
TargetID:= MobsID[Agro];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0;
exit;
end;
if ItemsLastIndex > 0 then // если чего-то валяется на земле, то
begin
InitPickUpMode(true); // надо дроп подбирать
exit;
end;
if MobsDist[MinDistID] <= Radius then // иначе ищем ближайшего #################################################
begin
TargetID:= MobsID[MinDistID];
PhisicalAttack; // берем вражину в таргет
AttackCycle:= 0;
exit;
end
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);
textMobsKilled.text:= inttostr(MobsKilled);
MobsDBscreen.lines.Clear;
for i:=1 to MobsLastIndex do // выводим БД мобов
begin
if TargetID = MobsID[i] then MobsDBscreen.lines.add ('-> '+inttostr(i)+' МобID: '+inttostr(MobsID[i])+' дистанция '+inttostr(MobsDist[i]))
else if MobsAgression[i] then MobsDBscreen.lines.add ('<- '+inttostr(i)+' МобID: '+inttostr(MobsID[i])+' дистанция '+inttostr(MobsDist[i]))
else MobsDBscreen.lines.add ('-- '+inttostr(i)+' МобID: '+inttostr(MobsID[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]));
end;
procedure CreateLabel (text: string); // процедура автоматизирует создание текстовых меток в форме
var
l: TLabel;
begin
l:= TLabel.Create(panel);
l.caption:=text;
l.parent:=panel;
l.left:=5;
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:=60;
e.top:=10+20*frmParamIndex;
result:= e;
end;
procedure Free; //Вызывается при выключении скрипта
begin
MobsDBscreen.free;
ItemsDBscreen.free;
log.free;
frm.free;
ClearDB;
TimerForm.free;
TimerCombat.free;
TimerPickUp.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);
if interlude then i:=i+48 else i:=i+44;
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)*HPMedium);
end;
procedure DrinkBottle; // пьем бутылки и следим за их количеством
begin
if HPBottleCount > 0 then
begin
UseItemObjID(HPBottleObjID);
dec (HPBottleCount);
end;
end;
begin
if pck = '' then exit;
if (Connectname=nickname) and FromServer and (pck=HStr('64 64 02 00 00 00 00 00 00')) then
begin
SpoilMode:=false;
end;
if (ConnectName = NickName) and FromServer and (not InitMode) then // разбор пакетов от сервера в Боевом режиме
case pck[1] of
#$01: begin // MoveToLocation:h(ObjectID)d(CurX)d(CurY)d(CurZ)d(D estX)d(DestY)d(DestZ)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
updateDB(Povtor, ReadD(2), ReadD(18), ReadD(22), ReadD(26), false);
end;
end;
// #$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(Wal kSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed )d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(Move mentSpeedMultiplier)f(AttackSpeedMultiplier)f(Coll isionRadius)f(CollisionHeight)d(HairStyle)d(HairCo lor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCr estId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sittin g)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(M ountType)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(F eet)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(Ha ir)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accurac y)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef) d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRun Speed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d (FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultipl ier)f(AttackSpeedMultiplier)f(CollisionRadius)f(Co llisionHeight)d(HairStyle)d(HairColor)d(Face)d(Acc essLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d (AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateS toreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cub ics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b ()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLef t)b()b(RecomHave)b()
begin
UserInfo;
if MyHP = 0 then // Проверка не убили ли нас...
begin
SendMsg('Нас убили...');
log.Lines.Add('Нас убили...');
StopGame;
end;
end;
#$05{, #$48}: begin // 05= Attack:d(AttackerID)d(TargetID)d(Damage)b(Flags)d( X)d(Y)d(Z)h(Hits)
if ReadD(6) = MyID then
begin
Povtor:= TestPovtor(ReadD(2));// 48= MagicSkillUse
if Povtor = 0 then AddtoDB (ReadD(2), ReadD(15), ReadD(19), ReadD(23), true)
else UpdateDB(Povtor, ReadD(2), ReadD(15), ReadD(19), ReadD(23), true);
end;
end;
#$06: begin // Die:d(ChaID)
povtor:= TestPovtor(ReadD(2));
if Povtor > 0 then
begin
if MobsID[povtor] = TargetID then
begin
LastKilledMobObjID:=TargetID;
inc (MobsKilled); // подводим статистику
SpoilMode:=true;
TargetID:= 0;
buf:=hstr('2F 2A 00 00 00 00 00 00 00 00');
SendToServerEX(NickName);
// споил надо делать тута
end;
DelDBItem(povtor);
end;
end;
#$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('Нас убили...');
log.Lines.Add('Нас убили...');
StopGame;
end;
end;
#$12: begin // DeleteObject:h(ObjectID)
if LastKilledMobObjID = ReadD(2) then LastKilledMobObjID:= 0
else begin
Povtor:= CheckItems(ReadD(2));
if Povtor <> 0 then DelDroppedItem(Povtor);
end;
end;
#$16: begin // 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(FlRu nSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(Proper Multiplier)f(PAtkSpd)f(CollisionRadius)f(Collision Height)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRun ning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Nam e)s(Title)
if InMobsList(ReadD(6)) and (ReadD(10)=1) and (pck[121]=#$00) then
begin
Povtor:= TestPovtor(ReadD(2));
if Povtor = 0 then AddtoDB (ReadD(2), ReadD(14), ReadD(18), ReadD(22), false)
else UpdateDB(Povtor, ReadD(2), ReadD(14), ReadD(18), ReadD(22), false);
end;
end;
end;
if (ConnectName = NickName) and FromClient and (not InitMode) then // разбор пакетов от клиента в боевом режиме
case pck[1] of
// #$04: {TargetID:= ReadD(2)}; // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b( ActionID)
#$38: UserCommandsCombatMode; // Say2:s(Text)d(Type)s(Target)
#$48: begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD(2);
MyY:= ReadD(6);
MyZ:= ReadD(10);
end;
end;
if (ConnectName = NickName) and FromServer and InitMode then // разбор пакетов от сервера в режиме настройки бота
case pck[1] of
#$04: if ReadS(22) = NickName then UserInfo; // 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(F eet)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(Ha ir)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accurac y)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef) d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRun Speed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d (FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultipl ier)f(AttackSpeedMultiplier)f(CollisionRadius)f(Co llisionHeight)d(HairStyle)d(HairColor)d(Face)d(Acc essLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d (AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateS toreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cub ics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b ()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLef t)b()b(RecomHave)b()
#$06: if (ReadD(2) = TargetID) and (NpcTypeID_CurrentMob <> 0) then // Die:d(ChaID)
if (NpcTypeID_List[NpcTypeID_CurrentMob] <> 0) then
begin
SendMsg('Моб №' + inttostr(NpcTypeID_CurrentMob) + ' добавлен в базу');
log.Lines.Add('Моб №' + inttostr(NpcTypeID_CurrentMob) + ' добавлен в базу');
inc(NpcTypeID_List_Count);
NpcTypeID_CurrentMob:= 0;
TargetID:= 0;
end;
#$16: if (ReadD(2) = TargetID) and (NpcTypeID_CurrentMob <> 0) then NpcTypeID_List[NpcTypeID_CurrentMob]:= ReadD(6);//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(FlRu nSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(Proper Multiplier)f(PAtkSpd)f(CollisionRadius)f(Collision Height)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRun ning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Nam e)s(Title)
#$1B: begin
InventoryCreate; // Инвентарь
HPBottleObjID:= getinv(HPBottleID, 2,1);
HPBottleCount:= getinv(HPBottleID, 2,3);
end;
#$27: begin
InventoryUpdate;
HPBottleCount:= getinv(HPBottleID, 2,3);
end;
end;
if (ConnectName = NickName) and FromClient and InitMode then // разбор пакетов от клиента в режиме настройки бота
case pck[1] of
#$04: TargetID:= ReadD(2); // Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b( ActionID)
#$38: UserCommandsInitMode; // Say2:s(Text)d(Type)s(Target)
#$48: begin // ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
MyX:= ReadD(2);
MyY:= ReadD(6);
MyZ:= ReadD(10);
end;
end;
end.
nezabudkin
14.11.2008, 19:12
Долго мучисля, но все таки научил его спойлить. Выкладываю правленый скрипт бота от Alexus.
Огромное спасибо QaK за оказаную помощь и проявленное терпение=)
Извини VismuT, но твой вариант спойла палевом попахивает. Процедура PhisicalAttack при атаке моба вызывается раз в 1 сек. А после твоих модификаций получается, что сразу за пакетом 04=Action, посылается пакет 2F=RequestMagicSkillUse, и так раз в секунду, пока моба не добьешь. Не думаю что это хорошо...
-=Ma}{imuS=-
28.11.2008, 00:35
на руссоффе бот не запускается даже, тыкаеш галочку, она тут же исчезает, появляется ошибка "List index out of bounds (17)"
ошибка в строке 494 - procedure SendMsg(msg:string);
Народ у меня есть 4 окна. Я играю магом как мне в пати прикрепить к себе 3 ботов се что бы бафал регенил мп и хп, что бы пп бафал и бд танцевал??? укого есть готовые пакеты выложите пожалуйста!!:o И что бы дробь подбирал.
Народ у меня есть 4 окна. Я играю магом как мне в пати прикрепить к себе 3 ботов се что бы бафал регенил мп и хп, что бы пп бафал и бд танцевал??? укого есть готовые пакеты выложите пожалуйста!! И что бы дробь подбиралв первом посте данного топа куча скриптов под всяких баферов/хилеров и т.д. бери, разбирайся.
-=Ma}{imuS=-
13.12.2008, 02:26
есть бот для русофа?
Всем привет.
Поюзал поиск не смог найти один скрипт и прошу выложить у кого есть.
А скрипт такой: когда противник(не моб) берёт вас в таргет скрипт каким то образом сбрасывает таргет. Я его де то здесь видел но повторно найти не смог :(
Благодарю за внимание.
есть бот для русофа?
для ру офа скрипты теже самые.. весь впорос с шифрацией офф серваков обсуждается в разделе "ШИФРАЦИИ СЕРВАКОВ".. там общайся с собеседниками и вместе ломайте шифр
Всем привет.
Поюзал поиск не смог найти один скрипт и прошу выложить у кого есть.
А скрипт такой: когда противник(не моб) берёт вас в таргет скрипт каким то образом сбрасывает таргет. Я его де то здесь видел но повторно найти не смог
Благодарю за внимание.Данный скрипт прилагается к ПНХ, не помню, в новых версиях его оставили или нет. НО!!! Он уже давно нигде не работает, если только на кривых явах. Так что забудь.
Добавлено через 22 секунды
И вообще это - не читерский форум.
RayTraceR
30.12.2008, 20:16
Вопрос, можно привести пример кода, проверяющий не был ли взят моб в таргет другим игроком, если был взят то меняем значение переменной, иначе меняем значение переменной.
Я так думаю это берется с пакета TargetSelected в котором мы берем ObjectId(Атакующий) и TargetId(Сама цель) и сравниваем с моим ID
или же берем пакеты Attack и MagicSkillUse и сверяем ObjectId с моей целью?
Заранее благодарен!
RayTraceR, скорее мониторим пакет TargetSelect или ведем массив, куда записываем все ObjectID, которые являются выделенными объектами, и удаляем из массива, если получили пакет DeleteObject. А также при выделяешь ты(из того же Target Select) и если ObjID присутствует в списке выделенных - то все гуд, если нет - берем в таргет следующую цель. Воть примерный алгоритм - реализуй сам, мне лень =) С наступающим новым годом всех =)
RayTraceR
31.12.2008, 00:28
RayTraceR, скорее мониторим пакет TargetSelect или ведем массив, куда записываем все ObjectID, которые являются выделенными объектами, и удаляем из массива, если получили пакет DeleteObject. А также при выделяешь ты(из того же Target Select) и если ObjID присутствует в списке выделенных - то все гуд, если нет - берем в таргет следующую цель. Воть примерный алгоритм - реализуй сам, мне лень =) С наступающим новым годом всех =)
Хмм интересно, обнаружил что пакет TargetSelected присылается только при выделении другими игроками моба\игрока. А для своего чара приходит другой пакет: MyTargetSelected, в котором и хранится ID моего чара.
Теперь попробую разобраться, если получится прикреплю кусок кода, может кому и пригодится....
vBulletin® v3.6.11, Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot