Вернуться   CoderX :: Forums > Lineage II > L2PacketHack > Скриптинг
Войти через OpenID

Скриптинг Форум посвещенный созданию скриптов для L2PacketHack

Чат (Новых сообщений с момента вашего последнего визита нет)
Загрузка...
Задавайте ваши вопросы на форуме. Чат предназначен для небольших разговоров.
 
Ответ
 
Опции темы Опции просмотра
Старый 29.02.2008, 01:49   #271
Гость
 
Сообщений: n/a
По умолчанию --

p.s. если мало денег то определити цену попрашу народ на другом форуме - за такое скинутся
(ведь если исключить манор со скрипта то простенький скриптбот очень неплохо раскупят)

думаю даже Вороновски подошел бы тока достроить его до манора и тока на соло
(кчему лишнее) и растолковать по пунктам что надо делать...вот за это и хочу платить..
  Ответить с цитированием
Старый 29.02.2008, 02:40   #272
Рыцарь
 
Аватар для VORON
 
Регистрация: 06.08.2007
Сообщений: 209
Сказал Спасибо: 6
Имеет 67 спасибок в 34 сообщенях
VORON пока неопределено
По умолчанию

выкладываю более менее универсальный скрипт на баферов.. у вас ШЕ ПП БИШ ЕЕ?
впринципе независимо от сотава- скрипт переделок не требует.. запускаете и всё работет..
но! ваши пожелания в (когда и каму хилить и каким скилом ) учитываются там.. я коменты вставил- где править надо..
скрипт хорош тем что нетребует переделок если увас нет ШЕ ПП БИШ и ЕЕ одновременно а есть кто то 1..
етот скрипт исползует и баф и реген и хил.. для любого состава бафера точнее он написан для состава БИШ+ПП+ШЕ+ЕЕ- но подрузумевает в себе что их нет одновременно..
Код:
var
Bot1X,Bot1Y,Bot1Z,Bot2X,Bot2Y,Bot2Z,Bot3X,Bot3Y,Bot3Z,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:integer; //максимальные уровни ХП (лимиты)
MaxMPKom,MaxMPBot1,MaxMPBot2,MaxMPBot3,MaxMPBot4:integer; //максимальные уровни МП (лимиты)

//текущее значение ХП и МП
CurHPKom,CurMPKom,CurHPbot1,CurMPbot1,CurHPbot2,CurMPbot2,CurHPbot3,CurMPbot3,CurHPbot4,CurMPbot4:integer;

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.
__________________
Цитата:
Сообщение от pybukon
прежде чета попросить я немнога раскажу чтоб вы понили как мне плоха
Цитата:
Сообщение от Byrger
А как сделать мой скрипт бесконечным?
Цитата:
Сообщение от XKOR
.. каждый день ионизированной ногой протирает больную)
Цитата:
Сообщение от PsyR
Вылоджите пожалуйста скрипт на рыбалку желательно что бы сам в ВХ клал адаптированый под шоки и так же скрипт на ТТ рец, тоже с диалогами
VORON вне форума   Ответить с цитированием
Старый 29.02.2008, 05:38   #273
Рыцарь
 
Аватар для NLObP
 
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
NLObP пока неопределено
По умолчанию Re: ДА БУДЕТ БОТ!

Бот для кача ТК 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(targetZ)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)+','+inttostr(targety)+','+inttostr(targetz)+')');
end;

//***************************************************************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:extended):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(ShiftPressed)
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.
__________________
| Для самых ленивый | Телепаты в отпуске |Мы работаем над этим |
Не умеешь - учись, не хочешь учиться - плати © Суровый Закон Жизни


NLObP вне форума   Ответить с цитированием
Старый 01.03.2008, 02:33   #275
Рыцарь
 
Аватар для VORON
 
Регистрация: 06.08.2007
Сообщений: 209
Сказал Спасибо: 6
Имеет 67 спасибок в 34 сообщенях
VORON пока неопределено
По умолчанию

да.. скажу вам честно- "ЛЁД ТРОНУЛСЯ- ГОСПОДА ПРИСЯЖНЫЕ!" .. а то на месте буксовали-)
NLObP:=+1
надо вникнуть протестить.. если не лень добавь еще коментов плиз.. некоторые куски при беглом осмотре непонятны.. чтоб не вникая в код было понятно как ето всё пашет.. если не трудно плиз сделай и закрепим тогда к первому посту.. хотя и в таком варианте тожэ прикрепим но хочется еще более доступный вид.. -)
пока не проверял в работе но вижу работа огромная проделана-) даже миникарта создана-)) супер.. и лог действий-)..
можно какнить обощить всех физиков в 1 скрипт? чтоб было несколько строк тока для переделки.. чтоб скрипт улавливал какието параметры (ХП,МП,состояние атаки, скока противников нас бьют одновременно) и от в зависимости от них инициализировался запуск процедуру- в теле которой что хатим то сами под себя и напишем, под каждую профу.. ну например: мало ХП, нас атакуют сразу 3= запускаем процедуру, в теле которой ТАНКИ- пропишут себе УД, СПЕЛСИНГЕР- пропишет ФЛЕШ- массовый что все убежали, ну чета такое например бы сделать.. хотя в любом случае твой скрипт надо брать за основу.. и доделывать уж его под жэлания каждого.. то что выкладывал я давным давно конечножэ в сравнение не идет с етим-)..
также в идеале, в качестве готового решения, надо сделать 2 скрипта 1 из которых управляет баферами, второй- мозг- управляет командиром.. впринципе сыровато пока но уже есть то что будет работать.. то что я выложил для баферов- неможет автоматом перебафывать командира.. но добавив 5 строк (в управляющий блок кода , в конце скрипта) можно заставить скрипт реагировать и выполнять ребаф по каманде в приват сообщение, присланное от бота- командира типа твоего.. вот ето будет савсем уж весело тогда-).. чтоб командир следил- каму и что делать в какихто неординарных случаях приказывал ботам неординарные приказы..-) а боты- баферы чтоб в своём скрипте неукаснительно их выполняли-)..
спасибо еще раз-) буду изучать терь то что ты напрогал..
__________________
Цитата:
Сообщение от pybukon
прежде чета попросить я немнога раскажу чтоб вы понили как мне плоха
Цитата:
Сообщение от Byrger
А как сделать мой скрипт бесконечным?
Цитата:
Сообщение от XKOR
.. каждый день ионизированной ногой протирает больную)
Цитата:
Сообщение от PsyR
Вылоджите пожалуйста скрипт на рыбалку желательно что бы сам в ВХ клал адаптированый под шоки и так же скрипт на ТТ рец, тоже с диалогами
VORON вне форума   Ответить с цитированием
Старый 01.03.2008, 21:57   #276
Рыцарь
 
Аватар для Grinch
 
Регистрация: 29.02.2008
Сообщений: 928
Сказал Спасибо: 127
Имеет 130 спасибок в 93 сообщенях
Grinch пока неопределено
По умолчанию

при беглом просмотре понял что львиная часть скрипта это панельки и карты, которые я не как не могу понять ктонить популярно логику отображения в окошке может объяснить? :) а в целом за пару дней можно переделать для сумонера :) блага логика простая тока надо проверку добавить на хп сумона и проверку кто кого атакует + ко всему этому задержку между атакой сумона и сомонером ну что б сумонер первым не атакавал.
Grinch вне форума   Ответить с цитированием
Старый 03.03.2008, 23:29   #277
Рыцарь
 
Аватар для NLObP
 
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
NLObP пока неопределено
По умолчанию Re:

Цитата:
Сообщение от Grinch
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 вне форума   Ответить с цитированием
Старый 04.03.2008, 14:47   #278
Рыцарь
 
Аватар для Grinch
 
Регистрация: 29.02.2008
Сообщений: 928
Сказал Спасибо: 127
Имеет 130 спасибок в 93 сообщенях
Grinch пока неопределено
По умолчанию Re: Re:

Цитата:
Сообщение от NLObP
Цитата:
Сообщение от Grinch
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-х угольник, скрипт работает всегда для того что б можно было хотя б убежать подальше возрат в точку ребафа, постараюсь что б он делал это не приводя парик, но пока слабо представляю как это сделать, начну с зоны там увидим
Grinch вне форума   Ответить с цитированием
Старый 04.03.2008, 23:33   #279
Гость
 
Сообщений: n/a
По умолчанию Re: ДА БУДЕТ БОТ!

Цитата:
Сообщение от NLObP
Бот для кача ТК 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(targetZ)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)+','+inttostr(targety)+','+inttostr(targetz)+')');
end;

//***************************************************************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:extended):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(ShiftPressed)
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") или вернется в центр зоны?
  Ответить с цитированием
Старый 05.03.2008, 04:46   #280
Рыцарь
 
Аватар для NLObP
 
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
NLObP пока неопределено
По умолчанию Re: ДА БУДЕТ БОТ!

Немного модернизированная версия Бота

Код:
//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(targetZ)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)+','+inttostr(targety)+','+inttostr(targetz)+')');
end;

//***************************************************************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:extended):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(ShiftPressed)
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 вне форума   Ответить с цитированием
Ответ

  CoderX :: Forums > Lineage II > L2PacketHack > Скриптинг


Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 00:54.

vBulletin style designed by MSC Team.
Powered by vBulletin® Version 3.6.11
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Locations of visitors to this page
Rambler's Top100

Вы хотите чувствовать себя в безопасности? чоп Белган обеспечит её!