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

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

Чат (Новых сообщений с момента вашего последнего визита нет)
Загрузка...
Задавайте ваши вопросы на форуме. Чат предназначен для небольших разговоров.
 
Ответ
 
Опции темы Опции просмотра
Старый 18.03.2008, 15:25   #301
Заблокирован
 
Регистрация: 10.03.2008
Адрес: Тула
Сообщений: 1,098
Сказал Спасибо: 188
Имеет 108 спасибок в 60 сообщенях
DashKAaa
По умолчанию Re: ДА БУДЕТ БОТ!

Цитата:
Сообщение от NLObP
Залил рабочий скрипт бота. Пробуйте.
- поправил питьё Алакрити пошн
- показывает центр кача
В твоем боте есть недочет так же как и в версии skay.
Если бот напал на 2-3 мобов бить начинает то одного то другого(в итоге он всех убивает но всеже) -это раз.
Если бот бьет моба и рядом с магии моб в него стреляет и тут же появляется еще 1 моб (рядом респнулся) то тут же не добив тех 2 мобов он кидается бить нового, убив нового он убивает первого но не того кто стрелят с магии(он его как будто не замечает хотя на карте отмечается что моб рядом стоит) -так часто дохнул бот! тупо стоял и получал магические удары от моба и не бив его, либо просто бегая в заданном радиусе на хвосте с мобом.

а так все вполне играбельно в сочетание с вороновским буфф скриптом, можно и уже парти запускать на кач )
спасибо за скрипты :good:
DashKAaa вне форума   Ответить с цитированием
Старый 18.03.2008, 17:12   #302
Рыцарь
 
Аватар для NLObP
 
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
NLObP пока неопределено
По умолчанию Re: ДА БУДЕТ БОТ!

Цитата:
Сообщение от DashKAaa
Цитата:
Сообщение от NLObP
Залил рабочий скрипт бота. Пробуйте.
- поправил питьё Алакрити пошн
- показывает центр кача
В твоем боте есть недочет так же как и в версии skay.
Если бот напал на 2-3 мобов бить начинает то одного то другого(в итоге он всех убивает но всеже) -это раз.
Если бот бьет моба и рядом с магии моб в него стреляет и тут же появляется еще 1 моб (рядом респнулся) то тут же не добив тех 2 мобов он кидается бить нового, убив нового он убивает первого но не того кто стрелят с магии(он его как будто не замечает хотя на карте отмечается что моб рядом стоит) -так часто дохнул бот! тупо стоял и получал магические удары от моба и не бив его, либо просто бегая в заданном радиусе на хвосте с мобом.

а так все вполне играбельно в сочетание с вороновским буфф скриптом, можно и уже парти запускать на кач )
спасибо за скрипты :good:
Похожие недочеты из-за того, что я делал на основе его скрипта. :)
Нет защелки на одного моба, нужно добавить. Про магическую атаку я знаю. Нападение проверяется, только если нас бьют физической атакой.
__________________
| Для самых ленивый | Телепаты в отпуске |Мы работаем над этим |
Не умеешь - учись, не хочешь учиться - плати © Суровый Закон Жизни


NLObP вне форума   Ответить с цитированием
Старый 20.03.2008, 22:34   #303
Заблокирован
 
Регистрация: 10.03.2008
Адрес: Тула
Сообщений: 1,098
Сказал Спасибо: 188
Имеет 108 спасибок в 60 сообщенях
DashKAaa
По умолчанию

после двух дневного теста.. еще парочку недочетов выявил!
у нас 2 окна.
1 окно тот кто крошит мобов
2 окно хеллера(буффера работающего оффпарти) СЕ в нашем случае ( скрипт ворона )

воин бежит долбит мобов цеплят на себя рядом 2-3 мобов его хп начинают падать (се начинает лечить по скрипту ворона) лечит и агрит на себя 2 мобов. воин убивает 1 моба и бежит за другими мобами которые в радиусе (на этих которые возле него и долбят СЕ он 0 внимания)
т.е не всегда он ищет ближайшего к себе моба и атакует его.

Аналогично бывает при каче и одному т.е бьет 2-3 сразу мобов раздает им люлей не половину или почти что убивает мобов и сразуже выделяет другого не всегда скрпит что моб умер проверяется...судя по всему.. ну кидается он на других рядом мобов убивает их и иногда возвращается и добивает моба которого не добил.

ну и еще недочет один.. радиус запоминаем допустим 1500 он бегает долбит мобов в этом радиусе когда все убил он не всегда кидается на мобов которые появились в этом радиусе, видет только и атакует которые рядом с ним нарисовались.. пробовал активировать бежать в центр радиуса если мобов нет.. что-то не прокатило

Добавлено спустя 19 часов 6 минут 12 секунд:
Re: ДА БУДЕТ БОТ!
Цитата:
Сообщение от NLObP
Новая версия бота. Проверяет координату Z. Подрихтовал миникарту.
Код:
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!

{Бот для кача ТК 64+ лвл

Скрипт распространяется как есть, и я не несу ответственности
за то, что ВЫ натворили у себя, его используя.

Возможности скрипта:
- работает на С4 и Интерлюде;
- миникарта, усл. обозн.:
  - зеленые в зоне Radius кача;
  - белые вне DeltaZ;
  - синие вне зоны Radius кача;
  - розовые нас атакуют;
  - красный мы атакуем;
- панель с инфой;
- сам бафается;
- сам юзает кубики;
- сам юзает алакрити;
- сам лечит себя хил пошинами и элементал хилом;
- проверка координаты Z для кача в катакомбах;}

//***************************************************************
const
  name='NLObP'; //имя чара для которого включен скрипт

  //установить константу в зависимости от типа игры (С4 или Интерлюд)
  IL=false; //true - IL, false - C4

  max=100; //максимальное значение массива
  Radius=1500;    //радиус участка для поиска мобов
  DZ=200;        //глубина/высота до мобов
  PercentHP=70; //при каком количестве хп в % юзать бутылку лечения
  MEsit=55;    //при каком количестве хп в % надо сесть и подкопить хп
  MEup=90;    //при каком количестве хп в % надо встать после отдыха

  buff1=91;        //бафф defense aura
  buff2=77;       //бафф attack aura
  buff3=112;     //бафф deflect arrow
  buff4=230;    //бафф sprint
  buff5=123;   //бафф spirit barrier
  cubicstorm=10;
  cubiclife=67;
  elementalheal=58;

//***************************************************************
var
  frm : TForm;  //панель информации
  info, msg, stats : TMemo;
  splitter1, splitter2 : Tsplitter;
  map : Tform; //виртуальная карта
  xm, ym : integer; //координаты на карте
  offs1 : integer; //смещение для типа игры Ил или С4

  StartTime: TDateTime; //ведем подсчет времени
  EndTime: TDateTime;

  death1, mob1 : integer; //подсчитываем смерти
  underAttack : boolean; //нас атакуют

  heal, kill : string;
  MaxHP, MyZpos, CurHP, ObjID, ID, xpos, ypos, skill, MyID : integer;
  but, sud, bst, attackIDMinID, attackID, zpos: integer;

  cvaX, cvaY, cvaZ: integer; //координата центра кача

  Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
  sit, povtor, tame, gdo, npc, stop: Boolean;
  attackk, bfi, atck, hpi, i, ii: integer; //индексы различных циклов
  last : integer; //последняя запись в массиве, для ускорения скрипта
  //массив мобов
  MobsObjID: array[1..max] of integer;
  MobsID: array[1..max] of integer;
  MobsName: array[1..max] of string;
  MobsRAS: array[1..max] of integer;
  MobsX: array[1..max] of integer;
  MobsY: array[1..max] of integer;
  MobsZ: array[1..max] of integer;
  NPCid: array[1..max] of integer;
  Aggro: array[1..max] of Boolean;

  TTShpC : Tshape; //центр кача на карте
  TTShape: array [0..max] of Tshape; //объекты на карте
  TTLabel: array [0..max] of Tlabel; //подписи к объектам

  timer1: TTimer;
  timer2: TTimer;
  timer3: TTimer;
  timer4: TTimer;

//***************************************************************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
var
  i: integer;
begin

  if il then begin
    //CharInfo
    offs1:=48;   //44 для С4, 48 для IL
  end else begin
    offs1:=44;
  end;

  StartTime:=time;
  underattack:=false; //атакован?
  stop:=true; //откл. атака

  atck:=0; //кол-во неуспешных атак после которых пробуем сменить таргет, здесь инициализация =0
  hpi:=0;
  bfi:=60; //60 сек
  ii:=1;
  last:=1; //начальное значение
  //ПАНЕЛЬКА
  frm := TForm.Create(nil);
  frm.Caption := 'BOT '+name;
  frm.BorderStyle := bsSizeable;
  frm.Position := poScreenCenter;
  frm.Width:=600;
  frm.Height:=800;
  //информация
  info:=TMemo.Create(frm);
  info.parent:=frm;
  info.align:=alLeft;
  info.ReadOnly:=true;
  info.ScrollBars:=0;
  info.Width:=450;
  info.Height:=370;
  //статистика
  stats:=TMemo.Create(frm);
  stats.parent:=frm;
  stats.align:=alClient;
  stats.ReadOnly:=true;
  stats.ScrollBars:=0;
  stats.Width:=150;
  stats.Height:=100;
  //сообщения
  msg:=TMemo.Create(frm);
  msg.parent:=frm;
  msg.align:=alBottom;
  msg.ReadOnly:=true;
  msg.ScrollBars:=2;
  msg.Width:=600;
  msg.Height:=100;
  msg.Lines.Add('...');
  //разделители
  splitter1:=Tsplitter.Create(frm);
  splitter1.parent:=frm;
  splitter1.Top:=0;
  splitter1.Width:=3;
  splitter1.Left:=470;
  splitter1.align:=alLeft;
  //разделители
  splitter2:=Tsplitter.Create(frm);
  splitter2.parent:=frm;
  splitter2.Left:=0;
  splitter2.Height:=3;
  splitter2.align:=alBottom;

  frm.Show;
  //карта
  map := TForm.Create(nil);
  map.Caption:='MiniMap: '+name;
  map.BorderStyle:=bsSizeable;
  map.Position:=poScreencenter;
  map.Width:=300;
  map.Height:=300;
  map.FormStyle:=FsStayOnTop;
  map.Show;

  heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); //  СИДЕТЬ!!!

  //атака и прочее
  timer1:=TTimer.Create(nil);
  timer1.OnTimer:=@OnAttack;
  timer1.enabled:=false;  //таймер по умолчанию выключен
  timer1.interval:=1000; //через каждые 1сек будем обновлять

  //вывод в форму
  timer2:=TTimer.Create(nil);
  timer2.OnTimer:=@OnView;
  timer2.enabled:=true;   //таймер по умолчанию включен
  timer2.interval:=1000; //через каждые 1сек будем обновлять

  //баффы
  timer3:=TTimer.Create(nil);
  timer3.OnTimer:=@OnBuff; //
  timer3.enabled:=false; // таймер по умолчанию выключен
  timer3.interval:=60000; // первый баф через 60 сек

  //рисуем карту
  timer4:=TTimer.Create(nil);
  timer4.OnTimer:=@OnMap;
  timer4.enabled:=true;   //таймер по умолчанию включен
  timer4.interval:=1000; //через каждые 1сек будем обновлять

  for i:= 1 to max do begin
    Aggro[i]:=false;
    //готовим точки МОБов
    TTShape[i]:=Tshape.create(nil); //для мобов
    TTShape[i].parent:=map;
    TTShape[i].Brush.Color:=clBlue; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
    TTShape[i].shape:=stCircle;
    TTShape[i].left:=-70; //координаты
    TTShape[i].top:=-70;
    TTShape[i].width:=7; //размеры
    TTShape[i].height:=7;
    //Готовим названия
    TTlabel[i]:=Tlabel.create(nil);
    TTlabel[i].parent:=map;
    TTlabel[i].left:=TTShape[i].left+4; //координаты
    TTlabel[i].top:=TTShape[i].top+4;
    TTlabel[i].caption:=inttostr(i);
    TTlabel[i].font.size:=7;
    TTlabel[i].font.color:=clBlue;
  end;

  //Готовим точку для центра кача
  TTShpC:=Tshape.create(nil); //для моего чара
  TTShpC.parent:=map;
  TTShpC.shape:=stCircle;
  TTShpC.Brush.Color:=clYellow;
  TTShpC.left:=-70; //координаты
  TTShpC.top:=-70;
  TTShpC.width:=3; //размеры
  TTShpC.height:=3;

  //Готовим точку для ГГ
  TTshape[0]:=Tshape.create(nil); //для моего чара
  TTshape[0].parent:=map;
  TTshape[0].shape:=stCircle;
  TTshape[0].Brush.Color:=clBlack;
  TTshape[0].left:=-70; //координаты
  TTshape[0].top:=-70;
  TTshape[0].width:=5; //размеры
  TTshape[0].height:=5;
  //готовим имя ГГ
  TTlabel[0]:=Tlabel.create(nil); //для моего чара
  TTlabel[0].parent:=map;
  TTlabel[0].left:=TTShape[0].left+4; //координаты
  TTlabel[0].top:=TTShape[0].top+4;
  TTlabel[0].caption:=name;
  TTlabel[0].font.size:=7;
  TTlabel[0].font.color:=clBlack;
end;

//***************************************************************
procedure GameToMap(x, y : integer);
//Пока ничего умнее не придумал =(
//преобразуем игровые координаты в координаты карты
var
  masshtabx, masshtaby:integer;
begin
  masshtabx:=radius*map.Width div 200;
  masshtaby:=radius*map.Height div 200;
  xm:=Round(((X-myXpos)*map.Width/masshtabx)+(map.Width/2));
  //коэфф. 0.9 для попадания точки X,Y=0 в центр карты
  ym:=Round(((Y-myYpos)*map.Height/masshtaby)+(map.Width/2)*0.9);
end;

//***************************************************************
//RequestRestartPoint
procedure RequestRestartPoint;
begin
  buf:=#$6D;
  WriteD(00);
  SendToServerEx(Name);
end;

//***************************************************************
procedure ViewInfo;
var
  i: integer;
begin
  info.Lines.Clear;
  stats.Lines.Clear;
  stats.Lines.Add('Имя чара :'+Name);
  stats.Lines.Add('Время старта :'+TimeToStr(starttime));
  stats.Lines.Add('Время работы :'+TimeToStr(time-starttime));
  stats.Lines.Add('Убили МОБов: '+IntToStr(mob1)+' шт.');
  stats.Lines.Add('Погибли: '+IntToStr(death1)+' раз');
  stats.Lines.Add('MaxHP :'+IntToStr(MaxHP));
  stats.Lines.Add('CurHP :'+IntToStr(CurHP));
  stats.Lines.Add('MyID :'+IntToStr(MyID));
  stats.Lines.Add('MyXpos :'+IntToStr(MyXpos));
  stats.Lines.Add('MyYpos :'+IntToStr(MyYpos));
  stats.Lines.Add('MyZpos :'+IntToStr(MyZpos));
  stats.Lines.Add('PercentHP :'+IntToStr(PercentHP)+' %хп');
  stats.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
  stats.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
  stats.Lines.Add('Radius :'+IntToStr(RADIUS));
  stats.Lines.Add('DeltaZ :'+IntToStr(DZ));
  stats.Lines.Add('cvaX :'+IntToStr(cvaX));
  stats.Lines.Add('cvaY :'+IntToStr(cvaY));
  stats.Lines.Add('cvaZ :'+IntToStr(cvaZ));
  stats.Lines.Add('but :'+IntToStr(but)+' бутылки');
  stats.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
  stats.Lines.Add('bst :'+IntToStr(bst)+' встать');
  stats.Lines.Add('ObjID :'+IntToStr(ObjID)+' кто ходит');
  stats.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
  stats.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
  stats.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
  stats.Lines.Add('sit :'+VarToStr(sit));
  stats.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
  stats.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
  stats.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
  stats.Lines.Add('atck :'+IntToStr(atck)+' цикл выбора другой цели');
  stats.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
  stats.Lines.Add('SummaAR :'+IntToStr(Summ(MobsObjID))+' всего в бд');
  stats.Lines.Add('rezu :'+IntToStr(DeltaXY(MyXpos, MyYpos, xpos, ypos))+' рез ближ');
  stats.Lines.Add('MaxX :'+IntToStr(MaxX));
  stats.Lines.Add('MaxID :'+IntToStr(MaxID));
  stats.Lines.Add('MinX :'+IntToStr(MinX));
  stats.Lines.Add('MinID :'+IntToStr(MinID));
  stats.Lines.Add('povtor :'+VarToStr(povtor));
  stats.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
  stats.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
  stats.Lines.Add('Hpotion: '+inttostr(Hpotion));
  stats.Lines.Add('Apotion: '+inttostr(Apotion));
  stats.Lines.Add('xm :'+IntToStr(xm));
  stats.Lines.Add('ym :'+IntToStr(ym));
  if (MyID<>0) then begin
    info.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
    info.Lines.Add('HP:'+IntToStr(CurHP)+' из '+IntToStr(MaxHP)+' Цикл1='+IntToStr(attackk)+' Цикл2='+IntToStr(atck)+' Цикл бафа='+IntToStr(bfi));
    if (Hpotion=0) then info.Lines.Add('Юзать HP бутылки?: НЕТ!');
    if (Hpotion<>0) then info.Lines.Add('Юзать HP бутылки?: ДА!');
    if (Apotion=0) then info.Lines.Add('Юзать AP бутылки?: НЕТ!');
    if (Apotion<>0) then info.Lines.Add('Юзать AP бутылки?: ДА!');
    if (sit=false) then info.Lines.Add('Бот стоит!');
    if (sit=true) then info.Lines.Add('Бот сидит!');
    for i:= 1 to last do begin
      if (MobsObjID[i]<>0) then begin
        if (attackIDMinID<>i) then info.Lines.Add('--'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
        if (attackIDMinID=i)  then begin
          info.Lines.Add('->'+IntToStr(i)+' ID МОБа:'+IntToStr(MobsObjID[i])+' расстояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(Aggro[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
          TTShape[i].Brush.Color:=clRed;
        end;
      end;
    end;
  end else info.Lines.Add('Для инициализации Бота используй или брось и подбери аптечку!');
end;

//***************************************************************
procedure Free;
begin
  DelALL;
end;

//***************************************************************
procedure StatsUpdate;
var
  i: integer;
begin
  for i:=0 to ReadD(6)-1 do begin
    case pck[i*8+10] of
      #$09: CurHP:=ReadD(i*8+14);
      #$0A: MaxHP:=ReadD(i*8+14);
    end;
  end;
  if (MaxHP<>0) then        // вычисляем процентное соотношение хп
  begin
    but:=Round((MaxHP/100)*PercentHP);   // при каком количестве хп юзать бутылку лечения
    sud:=Round((MaxHP/100)*MEsit);   // при каком количестве хп надо сесть и подкопить хп
    bst:=Round((MaxHP/100)*MEup);   // при каком количестве хп надо встать после отдыха
  end;
end;

//***************************************************************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
  //01=MoveBackwardToLocation:d(targetX)d(targetY)d(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 DeltaXY(targetx, targety, MyXpos, MyYpos)<=distanciya
     then result:=true else result:=false;
end;

//***************************************************************
//возвращает растоянием между двумя точками
function DeltaXY(xpos1, ypos1, xpos2, ypos2:extended):integer;
begin
  result:=Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;

//***************************************************************
//возвращает растоянием между двумя координатами Z
function DeltaZ(Zpos1, Zpos2 : extended) : integer;
begin
  result:=Round(abs(Zpos1-Zpos2));
end;

//***************************************************************
procedure DelElArr(ele:integer);  //удаляет моба!
begin
  MobsObjID[ele]:=0;
  MobsID[ele]:=0;
  MobsName[ele]:='';
  MobsRAS[ele]:=0;
  MobsX[ele]:=0;
  MobsY[ele]:=0;
  MobsZ[ele]:=0;
  Aggro[ele]:=false;

  TTShape[ele].left:=-70; //координаты
  TTShape[ele].top:=-70;
  TTShape[ele].Brush.Color:=clBlue;
  TTlabel[ele].left:=TTShape[ele].left+4; //координаты
  TTlabel[ele].top:=TTShape[ele].top+4;
  TTlabel[ele].caption:='';
  TTlabel[ele].font.color:=clBlue;
end;

//***************************************************************
procedure DelALL;  //обнуляем всю базу!
var
  i: integer;
begin
  for i:= 1 to max do begin
    NPCid[i]:=0;
    MobsObjID[i]:=0;
    MobsID[i]:=0;
    MobsName[i]:='';
    MobsRAS[i]:=0;
    MobsX[i]:=0;
    MobsY[i]:=0;
    MobsZ[i]:=0;
    Aggro[i]:=false;
    TTshape[i].free;
    TTlabel[i].free;
  end;
  TTShpC.free;
  TTShape[0].free;
  TTLabel[0].free;
  timer1.Free;
  timer2.Free;
  timer3.Free;
  timer4.Free;
  splitter1.free;
  splitter2.free;
  info.Free;
  msg.Free;
  frm.Free;
  map.Free;
end;

//***************************************************************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
var
  minras, i: integer;
begin
  MinX:=5000;
  MinID:=0;
  MaxX:=0;
  MaxID:=0;
  for i:= 1 to last do begin
    //проверяем что расстояние до моба в радиусе кача и по высоте не глубоко
    if (DeltaXY(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius) and (DeltaZ(Mobsz[i],cvaz)<=DZ) then begin
      if (arra[i]<=MinX) and (arra[i]<>0) then begin
        MinX:=arra[i];
        MinID:=i;
      end;
      if (arra[i]>=MaxX) then begin
        MaxX:=arra[i];
        MaxID:=i;
      end;
    end;
  end;
end;

//***************************************************************
function ETOpovtor(chislo: integer; arra:array of integer):boolean;
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
var
  i: integer;
begin
  Result:=false;
  for i:= 1 to last do begin
    if (arra[i]=chislo) then Result:=true;
  end;
end;

//***************************************************************
procedure attackt(mobus:integer);
begin
  buf:=#$04; //action
  WriteD(MobsObjID[mobus]);
  WriteD(MyXpos);
  WriteD(MyYpos);
  WriteD(MyZpos);
  WriteC(0);
  SendToServerEx(Name);
end;

//***************************************************************
function Summ(sum:array of integer):integer;
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
  Summa: integer;
  i: integer;
begin
  Result:=0;
  for i:= 1 to max do begin
    if (sum[i]<>0) then inc(Result);
  end;
end;


//***************************************************************
procedure OnMap(Sender: TObject); //рисуем карту
begin
  if (myxpos=0) and (myypos=0) then exit;
  for i:= 1 to last do begin
    if (MobsObjID[i]<>0) then begin
      //красим мобов на карте
      if   stop=true then
        if (DeltaXY(Mobsx[i],Mobsy[i],MyXpos,MyYpos)<=Radius)
        then
          if (DeltaZ(Mobsz[i],MyZPos)<=DZ)
            then
              TTShape[i].Brush.Color:=clGreen
            else
              TTShape[i].Brush.Color:=clWhite
        else
          if (DeltaZ(Mobsz[i],cvaz)<=DZ)
            then
              TTShape[i].Brush.Color:=clBlue
            else
              TTShape[i].Brush.Color:=clWhite;
      if   stop=false then
        if (DeltaXY(Mobsx[i],Mobsy[i],cvaX,cvaY)<=Radius)
        then
          if (DeltaZ(Mobsz[i],cvaz)<=DZ)
            then
              TTShape[i].Brush.Color:=clGreen
            else
              TTShape[i].Brush.Color:=clWhite
        else
          if (DeltaZ(Mobsz[i],cvaz)<=DZ)
            then
              TTShape[i].Brush.Color:=clBlue
            else
              TTShape[i].Brush.Color:=clWhite;
      if Aggro[i]=true then begin
        TTShape[i].Brush.Color:=clPurple;
        TTlabel[i].font.color:=clPurple;
      end;
      //ставим точку МОБа
      GameToMap(MobsX[i],MobsY[i]);
      TTShape[i].left:=xm; //координаты моба
      TTShape[i].top:=ym;
      TTlabel[i].left:=TTShape[i].left+4; //координаты
      TTlabel[i].top:=TTShape[i].top+4;
      TTlabel[i].caption:=inttostr(i);
    end;
  end;
  //ставим точку ГГ
  GameToMap(MyXpos,MyYpos);
  TTShape[0].left:=xm; //координаты чара
  TTShape[0].top:=ym;
  TTlabel[0].left:=TTShape[0].left+4; //координаты надписи
  TTlabel[0].top:=TTShape[0].top+4;
  TTlabel[0].caption:=name;
  //ставим точку центра кача
  GameToMap(cvaX,cvaY);
  TTShpC.left:=xm; //координаты ГГ
  TTShpC.top:=ym;
end;

//***************************************************************
procedure OnAttack(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА  МОБА!
begin
  if (MinID>0) then begin
    if (sit=false) then begin
      case attackk of
        0: begin
          attackID:=MobsObjID[MinID];
          msg.Lines.Add('Атакую! '+IntToStr(attackID));
          attackIDMinID:=MinID;
          attackt(attackIDMinID); //target
        end;
        //делаем паузу
        1: begin
          attackt(attackIDMinID); //attack
        end;
        6: begin
          attackt(attackIDMinID); //target
        end;
        //делаем паузу
        7: begin
          attackt(attackIDMinID); //attack
          attackk:=1;
          inc(atck);
        end;
      end;
      //пробуем сместиться
      case atck of
        9: begin
          MobsRAS[attackIDMinID]:=5000;
          attackk:=-1;
          atck:=0;
        end;
      end;
      inc(attackk);
    end;
  end;
end;

//***************************************************************
procedure OnView(Sender: TObject); //вывод данных в форму
begin

  //контролируем бафы
  dec(bfi);
  if bfi<0 then begin
    timer3.interval:=1000; //пытаемся начать бафы каждые 1 сек
    bfi:=1200;  //20 мин
  end;

  //выводим в форму
  ViewInfo;

  GetMinMaxX(MobsRAS);
  if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
    //если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
    msg.Lines.Add('Мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
    DelElArr(MaxID);
  end;

  //идем в центр если нет мобов
//  if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
    //if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
//  end;

  if (MyID<>0) and (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
    msg.Lines.Add('Использую Elemental Heal!');
    MagicSkillUse(elementalheal);
  end;

  if (CurHP<but) and (Hpotion<>0) then begin
    if hpi=5 then begin
      UseItem(Hpotion);
      hpi:=0;
    end else inc(hpi);
  end;
  if (CurHP<sud) and (Summ(Aggro)=0) and (sit=false) then begin
    msg.Lines.Add('Всё, я отдыхаю!'+TimeToStr(time));
    buf:=heal;
    SendToServerEx(Name);
    sit:=true;
  end;
  if (CurHP>bst) and (sit=true) then begin
    msg.Lines.Add('Пора за работу!'+TimeToStr(time));
    buf:=heal;
    SendToServerEx(Name);
    attackk:=0;
    atck:=0;
    sit:=false;
  end;

end;

//***************************************************************
procedure OnBuff(Sender: TObject); //баффы
begin
  if (MyID<>0) and (Summ(Aggro)=0) and (sit=false) then begin
    case ii of
      1: begin
        timer1.enabled:=false; //откл. атаку
        msg.Lines.Add('Бафаюсь Defense aura!');
        //бафф
        MagicSkillUse(buff1);
        inc(ii);
        timer3.interval:=6000; //каждые 6 сек
      end;
      2: begin
        msg.Lines.Add('Бафаюсь Attack aura!');
        MagicSkillUse(buff2);
        inc(ii);
      end;
      3: begin
        msg.Lines.Add('Бафаюсь Deflect arrow!');
        MagicSkillUse(buff3);
        inc(ii);
      end;
      4: begin
        msg.Lines.Add('Бафаюсь Sprint!');
        MagicSkillUse(buff4);
        inc(ii);
      end;
      5: begin
        msg.Lines.Add('Бафаюсь Spirit barrier!');
        MagicSkillUse(buff5);
        inc(ii);
        timer3.interval:=10000; //каждые 10 сек
      end;
      6: begin
        msg.Lines.Add('Бафаюсь Storm cubic!');
        MagicSkillUse(cubicstorm);
        inc(ii);
      end;
      7: begin
        msg.Lines.Add('Бафаюсь Life cubic!');
        MagicSkillUse(cubiclife);
        inc(ii);
      end;
      8: begin
        if Apotion<>0 then begin
          msg.Lines.Add('Пью Potion of Alacrite!');
          UseItem(Apotion);
        end;
        inc(ii);
      end;
      9: begin
        ii:=1;
        timer3.interval:=1150000; //каждые 20 мин
        bfi:=1150;
        timer1.enabled:=true; //вкл. атаку
      end;
    end;
  end;
end;

//***************************************************************
procedure AddBD(objid, posx, posy, posz:integer;);    //добавляем моба в базу данных
var
  i: integer;
begin
  for i:=1 to last do begin //перебираем базу и ищем свободную ячейку в ней
    if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
      if (ETOpovtor(objid, MobsObjID)=false) then begin
        MobsObjID[i]:=objid; //ид моба
        if id<>0 then MobsID[i]:=id; //ид моба
        MobsRAS[i]:=DeltaXY(MyXpos, MyYpos, posx, posy); //растояние до этого моба
        MobsX[i]:=posx;
        MobsY[i]:=posy;
        MobsZ[i]:=posz;
        msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
        break;
      end;
    end;
  end;
  //если нет свободного места ищем дальше
  for i:=last+1 to max do begin //перебираем базу и ищем свободную ячейку в ней
    if (MobsObjID[i]=0) then begin //запоминаем моба в свободную ячейку
      if (ETOpovtor(objid, MobsObjID)=false) then begin
        MobsObjID[i]:=objid; //ид моба
        if id<>0 then MobsID[i]:=id; //ид моба
        MobsRAS[i]:=DeltaXY(MyXpos, MyYpos, posx, posy); //растояние до этого моба
        MobsX[i]:=posx;
        MobsY[i]:=posy;
        MobsZ[i]:=posz;
        msg.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsObjID[i])+'-ras-'+IntToStr(MobsRAS[i]));
        last:=i;
        break;
      end;
    end;
  end;
end;

//***************************************************************
function ISnpc(id: integer;): boolean;
var
  i: integer;
begin
  result:=false;
  for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;

//***************************************************************
procedure UseItem(ItemObjID:integer);
begin
  buf:=#$14;
  WriteD(ItemObjID);
  WriteD(00);
  SendToServerEx(Name);
end;

//***************************************************************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(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
      #$01: begin
          msg.Lines.Add('S>C $01 Move');
          if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
            i:=2;
            ObjID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
            ID:=0; //кто-то рыпнулся с места надо это записать...
            xpos:=ReadD(i);
            ypos:=ReadD(i);
            zpos:=ReadD(i);
            if not ISnpc(ObjID) {and (DeltaXY(cvaX,cvaY,xpos,ypos)<=Radius)} then AddBD(ObjID,xpos,ypos,zpos);
          end;
      end;
      #$03: begin
          msg.Lines.Add('S>C $03 Char');
          if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
            for i:=last to max do begin
              if (NPCid[i]=0) then begin
                if (ETOpovtor(ReadD(18),NPCid)=false) then begin
                  NPCid[i]:=ReadD(18);
                  msg.Lines.Add('ДОБАВЛЕН ИГРОК:'+ReadS(22)+'-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
                  break;
                end;
              end;
            end;
          end;
      end;
      #$04: begin
          msg.Lines.Add('S>C $04 CharInfo');
          //пакет с инфой о моём чаре
          i:=2;
          MyXpos:=ReadD(i); //получаю координату х моего чара
          MyYpos:=ReadD(i); //получаю координату у моего чара
          MyZpos:=ReadD(i); //получаю координату z моего чара
          //Запоминаем ИД
          i:=18;
          MyID:=ReadD(i); //получаю ид моего чара
          //смещение переменное, зависит от имени (LenName*2+2)
          i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
          MaxHP:=ReadD(i);
          CurHP:=ReadD(i);
          //лупить всех без разбора, в пределах радиуса
          {if (gdo=false) then begin //задаем центр окружности кача
            cvaX:=MyXpos;
            cvaY:=MyYpos;
            gdo:=true;
          end;}

          for i:=1 to last do begin //перебираем базу и ищем себя
            if (ETOpovtor(MyID, MobsObjID)=true) then begin
              DelElArr(i);
              msg.Lines.Add('Удаляем себя из базы МОБов!!!');
              if isnpc(myID)=false then begin
                for i:= last to max do begin
                  if (NPCid[i]=0) then begin
                    NPCid[i]:=MyID;
                    break;
                  end;
                end;
              end;
            end;
          end;
      end;
      //MagicSkillUse 48, Attack 05
      #$05: begin
          msg.Lines.Add('S>C $05 Attack');
           if (ReadD(6)=MyID) then begin
           //меня ударили
             sit:=false;
             {if myxpos<>0 then begin
               cvaX:=MyXpos;
               cvaY:=MyYpos;
               cvaZ:=MyZpos;
             end;}
             if (ETOpovtor(ReadD(2),MobsObjID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
             for i:=1 to last do begin
               if (MobsObjID[i]=ReadD(2)) then begin  //если моб записан в базе данных
                 msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(MobsObjID[i]));
                 Aggro[i]:=true;  // стал агрессор
                 if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
                   attackIDMinID:=i;
                   //вкл. атаку
                   timer1.enabled:=true;
                   stop:=false; //вкл. атака
                 end;
                 if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
                 break;
               end;
             end;
           end;
      end;
      //принят пакет Die
      #$06: begin
          msg.Lines.Add('S>C $06 Die');
          //нас убили
          if (myID=ReadD(2)) then begin
            //остановить атаку
            timer1.enabled:=false;
            msg.Lines.Add('Нас убили в '+TimeToStr(time));
            inc(death1);
            RequestRestartPoint; //оживаем после смерти
            //мы в городе, снимаем атрибут атаки на нас
            for i:= 1 to max do begin
              Aggro[i]:=false;
              TTShape[i].Brush.Color:=clBlue;
              TTlabel[i].font.color:=clBlue;
            end;
          end else begin
            //моб сдох! выкидываем его из базы and (attackID=ReadD(2))
            for i:=1 to last do begin
              if (MobsObjID[i]=ReadD(2)) then begin
                msg.Lines.Add('Убили очередного МОБа в '+TimeToStr(time));
                inc(mob1);
                DelElArr(i);
                attackk:=0;
                atck:=0;
                if (i=last) and (last<>1) then dec(last);
                //timer1.enabled:=true;
                break;
              end;
            end;
          end;
      end;
      #$0C: begin
          msg.Lines.Add('S>C $0C DropItem');
          if (MyXpos<>0) then begin
            if (DeltaXY(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
              msg.Lines.Add('Выпала вещь!!!');
              timer1.enabled:=false;
              buf:=#$04;
              WriteD(ReadD(6));
              WriteD(ReadD(14));
              WriteD(ReadD(18));
              WriteD(ReadD(22));
              WriteC(0);
              SendToServerEx(Name);
              msg.Lines.Add(' Пробую поднять!!!');
              delay(1000);
              timer1.enabled:=true;
            end;
          end;
      end;
      #$0E: begin
          msg.Lines.Add('S>C $0E StatsUpdate');
          if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
      end;
      //принят пакет DeleteObject
      #$12: begin
          msg.Lines.Add('S>C $12 DeleteObject');
          //выкидываем из базы
          for i:=1 to last do begin
            if (MobsObjID[i]=ReadD(2)) then begin
              DelElArr(i);
              msg.Lines.Add('Удаляю из базы:'+IntToStr(i));
              if (i=last) and (last<>1) then dec(last);
              break;
            end;
          end;
      end;
      #$16: begin
          msg.Lines.Add('S>C $16 NPC');
          if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
            msg.Lines.Add('Вижу NPC!');
            if (ReadD(10)=0) then begin  //если нельзя атаковать
              for i:=last to max do begin
                 if (NPCid[i]=0) then begin
                   if (ETOpovtor(ReadD(2), NPCid)=false) then begin
                     NPCid[i]:=ReadD(2);
                     msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
                     break;
                   end;
                 end;
              end;
            end;
            if (ReadD(10)=1) and (pck[120]=#$00) then begin  //если можно атаковать
                id:=ReadD(6);
                AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
                msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
            end;
          end;
      end;
      //InventoryUpdate
      #$27: begin
          msg.Lines.Add('S>C $27 InventoryUpdate');
          if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
            Hpotion:=ReadD(8);
            msg.Lines.Add('ID бутылок H.Potion:'+inttostr(Hpotion));
          end;
          if ReadD(12)=735 then begin //Potion of Alacrity
            Apotion:=ReadD(8);
            msg.Lines.Add('ID бутылок A.Potion:'+inttostr(Apotion));
          end;
      end;
    end;
  end;

  //****************************************************************************
  if (ConnectName=Name) and FromClient then begin
    case pck[1] of
      #$1B: begin
        msg.Lines.Add('C>S $1B Yes');
        case ReadD(2) of
          //социальное действие Yes для начала
          $06: begin
            //не передаем серверу
            pck:='';
            msg.Lines.Add('C>S $1B Yes');
            //устанавливаем центр кача
            cvaX:=MyXpos;
            cvaY:=MyYpos;
            cvaZ:=MyZpos;
            //переменные циклов сбрасываем
            attackk:=0;
            atck:=0;
            msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты центра ОБНОВЛЕНЫ!!');
            //вкл. атаку
            timer1.enabled:=true;
            //вкл. бафы
            timer3.enabled:=true;
            stop:=false; //вкл. атака
          end;
          //социальное действие No для окончания
          $05: begin
            //не передаем серверу
            pck:='';
            msg.Lines.Add('C>S $1B No');
            //откл. атаку
            timer1.enabled:=false;
            //откл. бафы
            timer3.enabled:=false;
            stop:=true; //откл. атака
            msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
          end;
          //социальное действие Sorrow - удаляем текущую запись в базе
          $0D: begin
            //не передаем серверу
            pck:='';
            msg.Lines.Add('C>S $1B Sorrow');
            ObjID:=MobsObjID[attackIDMinID];
            DelElArr(attackIDMinID);
            attackk:=0;
            atck:=0;
            msg.Lines.Add('Удаляем текущую запись в базе!!!');
            for i:= last to max do begin
              if (NPCid[i]=0) then begin
                NPCid[i]:=ObjID;
                msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
                break;
              end;
            end;
          end;
        end;
      end;
      //ValidatePosition пакет от клиента с моими кординатами
      #$48: begin
        msg.Lines.Add('C>S $48 ValidatePosition');
        //обновляем ВСЕ растояния в BD если мы сошли с места
        MyXpos:=ReadD(2); //получаю координату х моего чара
        MyYpos:=ReadD(6); //получаю координату у моего чара
        MyZpos:=ReadD(10); //получаю координату z моего чара
        //пересчитываем расстояние до мобов
        for i:=1 to last do begin
          if MobsObjID[i]<>0 then begin
            //до атакующих нас мобов всегда расстояние 1
              MobsRAS[i]:=DeltaXY(MyXpos,MyYpos,MobsX[i],MobsY[i]);
            end;
          end;
        end;
      end;
    end;
end.
еще 1 недочет...
если ID мобов доходит до 90+ то вылетает ошибка как я понял связанная с этим
GetMinMaxX(MobsRAS);
if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
msg.Lines.Add('Мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
DelElArr(MaxID);
end;
при отключение этого.. доходит до 100 и начинает не видеть рядом стоящих мобов вплоть до тех которые его бьют, тестил в катакомбах!

Добавлено спустя 1 день 9 часов 1 минуту 39 секунд:
Re:
Цитата:
Сообщение от nezabudkin
Ну все, Господа... Выкладываю свой собственный ботоскрипт- локомотив :D

Прошу высказывать свои замечания и предложения.

Код:
{#############################################################################
Бот от Alexus
версия : 0.1 (бета)
дата: 12.03.08

Скрипт основан на всем том что я вычитал на этом форуме и моем опыте программирования.
Некоторые интересные идеи взяты из волкера.
Скрипт распространяется как есть. Используем его на свой страх и риск.
Любые изменения и дополнения только приветствуются!!!

Бот для кача в принципе любого война, но тестился на гноме.
Бот оптимизирован для кача в катах, лучше в квадратных комнатах (равносторонний четырехугольник).
Охотиться только на заданных мобов, а то излишняя самостоятельность бота немного пугает.


Пока что бот умеет следующее:

- запоминать центр и радиус кача
- запоминать список мобов на которых надо охотиться!
- управляется из окна чата в самом клиенте
- имеет окно для вывода всех параметров и статистики
- работает пока только под С4

Инструкция:
1. Запускаем игру, запускаем скрипт, добираемся до места кача
2. Пьем HP пробирку (надежный способ добывания своего ID-номера).
3. Выбираем в таргет моба на которого хотим охотится и пишем в общий чат->  1
4. Валим моба. Если все правильно сделали будет выдано сообщение в чате что моб добавлен.
5. Выбираем следующего моба пишем цифру 2, валим его и т.д. можно выбрать до 10 разных тварей.
6. Становимся в центр комнаты и пишем в чат-> pos , если все правильно то в чате будет выдано сообщение.
7. Бежим к выходу из комнаты, и пишем-> dist, в чате вылезет сообщение от системы
8. Валим всех мобов в комнате, становимся примерно в центр и пишем-> start , если все сделано верно,
   то будет выдано соответствующее сообщение.
9. если бот поймал моба в таргет и побежал его атаковать, то можно свернуть окно игры
   и смотреть на информационное окно скрипта.
#############################################################################}



const
 NickName = 'abc';   // Твой ник в игре
 maximumItems = 100;      // Размер базы мобов
 MobsListRazmer = 10;     // Размер списка мобов (не трогать!)

 Vertical = 1000;         // Вертикальный радиус кача

// HPMedium = 70;         // Пока не используется

 OX = 1; OY = 2; OZ= 3;   //  Служебные константы

var
 InitMode : boolean;
//-------------------------------------- БД мобов ------
 MobsID   : array [1..maximumItems] of integer;
 MobsDist : array [1..maximumItems] of integer;           // Расстояние от центра кача
 MobsXYZ  : array [1..maximumItems, 1..3] of integer;     // Координаты
 MobsAgression : array [1..maximumItems] of boolean;      // Моб атакует меня или стоит в сторонке...
 LastItem: integer;                                       // индекс последнего элемента базы

 MobsList : array [1..MobsListRazmer] of integer;          // Список мобов  (коды мобов)
 MobsListCount : integer;                                  // Текущий размер списка

 TargetID: integer;                                        // Текущая цель
 Povtor: integer;
 CenterX, CenterY, CenterZ : integer;                      // Центр кача
 Radius: integer;                                          // Радиус кача
//--------------------------------------------------------
 MyX, MyY, MyZ : integer;                                  // Мои статы
 MyID, MyHP, MyMaxHP: integer;
 MyMP, MyMaxMP, MyCP, MyMaxCP: integer;
//--------------------------------------------------------
 frm: TForm;                                               // переменные описания формы
 log, mainscreen: TMemo;
 panel: TPanel;
 frmParamIndex: byte;
 textX, textY, textZ, textMyID, textMyHP, textMyMaxHP: TEdit;
 textMyMP, textMyMaxMP, textMyCP, textMyMaxCP: TEdit;
 textCenterX, textCenterY, textCenterZ, textRadius : TEdit;
 textTargetID, textMobX, textMobY, textMobZ : TEdit;
 textAttackCycle, textLastItem: TEdit;
//----------------------------------------------------------
 TimerForm, TimerCombat: TTimer;

 AttackCycle: integer;                                      // Цикл атаки

procedure ClearDB;                                          // Очистка БД
 var                                                        // Надо все занулять, иначе там хрень всякая вылезает или старые данные
  i: word;
 begin
  LastItem:= 0;                                              // Очищаем переменные
  TargetID:= 0;
  Povtor:= 0;
  CenterX:= 0;
  CenterY:= 0;
  CenterZ:= 0;
  Radius:= 0;
  AttackCycle:= 0;
  for i:=1 to MobsListRazmer do MobsList[i]:= 0;
  MobsListCount:= 0;
  for i:=1 to maximumItems do                                // Очищаем базу
   begin
    MobsID[i]:= 0;
    MobsDist[i]:= 0;
    MobsXYZ[i, OX]:= 0;
    MobsXYZ[i, OY]:= 0;
    MobsXYZ[i, OZ]:= 0;
    MobsAgression[i]:= false;
   end;
 end;

function SearchFreeItemDB : integer;                          // Функция ищет первый свободный елемент в БД
 var
  i:integer;
 begin
  result:=0;
  for i:=1 to maximumItems do if MobsID[i] = 0 then
   begin
    result:=i;
    break;
   end;
  if result = 0 then result:=maximumItems;              // Если БД переполнена, то возвращаем индекс последнего элемента
  if result > LastItem then LastItem := result;         // если надо, увеличиваем текущий размер БД
 end;

function rastoyanie(NpcX, NpcY, NpcZ : integer) : integer; // вычисление растояния между 2 точками
 var
  dx,dy,dz, summa : integer;
 begin
  dx:= NpcX-CenterX;
  dy:= NpcY-CenterY;
  dz:= NpcZ-CenterZ;
  summa:= dx*dx+dy*dy;                                            // мне кажется, что так будет быстрее считаться
  if summa = 0 then result:= 0 else result:= Round(sqrt(summa));  // обход возможной ошибки, если моб стоит прямо в центре кача
  if abs(dz) > vertical then result := result + 5000;             // добавляем коррекцию по вертикали
end;

procedure AddtoDB (id, x,y,z : integer; agression : boolean);     // Процедура добавляет в БД нового моба
 var
  i:integer;
  dist: integer;
 begin
  dist:= rastoyanie (x,y,z);                                       // вычиляем расстояние от центра кача до моба
  if dist > (Radius + 1000) then exit;                             // если моб слишко далеко то ничего не делаем
  i:= SearchFreeItemDB;                                            // ищем свободный эл. БД
  log.Lines.Add('Моб добавлен, индекс в БД: '+ inttostr(i));
  if agression then log.Lines.Add('На нас напала какая-то вражина.');
  MobsID[i]:= id;                                                  // Записываем моба
  MobsDist[i]:= dist;
  MobsXYZ[i, OX]:= x;
  MobsXYZ[i, OY]:= y;
  MobsXYZ[i, OZ]:= z;
  MobsAgression[i]:= agression;
 end;

procedure UpdateDB (i:integer; id, x,y,z : integer; agression : boolean);   // Процедура обновляет данные в БД по мобу
 var
  dist: integer;
 begin
  if (MOBSXYZ[i, OX] = x) and (MOBSXYZ[i, OY] = y) and (MobsAgression[i] = agression) then exit;  // проверяем, а надо ли чего нить менят
  dist:= rastoyanie (x,y,z);
  if dist > (Radius + 1000) then DelDBItem(i) else          // перепроверяем расстояние до моба, если он вышел за границу кача, то удаляем его
   begin
    log.Lines.Add('Моб обновлен, индекс в БД: '+ inttostr(i));
    if agression then log.Lines.Add('На нас напала какая-то вражина.');
    MobsDist[i]:= dist;                                    // записываем данные
    MobsXYZ[i, OX]:= x;
    MobsXYZ[i, OY]:= y;
    MobsXYZ[i, OZ]:= z;
    MobsAgression[i]:= agression;
   end;
 end;

procedure DelDBItem (i: integer);                             // процедура удалаяет моба из БД
 begin
  log.Lines.Add('Моб удален, индекс в БД: '+ inttostr(i));
  MobsID[i]:= 0;
  MobsDist[i]:= 0;
  MobsXYZ[i, OX]:= 0;
  MobsXYZ[i, OY]:= 0;
  MobsXYZ[i, OZ]:= 0;
  MobsAgression[i]:= false;
  if i = LastItem then LastItem := LastItem -1;                // если надо, уменьшаем размер БД
 end;

function TestPovtor (id: integer) : integer;                   // функция проверяет наличие заданного моба в БД
 var
  i: integer;
 begin
  result:=0;
  for i:=1 to LastItem do if MobsID[i] = id then               // Ищем нужный ID в нашей БД
   begin
    result:=i;                                                  // И возвращаем его индекс по БД
    break;
   end;
 end;

function InMobsList (NpcTypeID: integer) : boolean;            // функция проверяет наличие заданного моба в списке на атаку
 var
  i: integer;
 begin
  result:= false;
  for i:=1 to MobsListCount do if MobsList[i] = NpcTypeID then result:= true;     // проверяем по списку
 end;

procedure SendMsg(msg:string);                                  // отправка системных сообщений клиенту
begin
  buf:=#$4A;
  WriteD(0);
  WriteD(10);
  WriteS('');
  WriteS(msg);
  SendToClientEx(NickName);
end;

function ValidateData : boolean;                                // функция проверки правильности задания всех параметров для начала кача
 procedure ValidateMobsList;                                    // подпроцедурка, перепроверяющая список мобов, и подсчитывающая количество записей в нем
  var                                                           // этот алгоритм мне не нравится, буду переделывать
   i: integer;
  begin
   for i:=1 to MobsListRazmer do if MobsList[i] = 0 then break;
   i:= i - 1;
   MobsListCount := i;
   log.Lines.Add('MobsListCount = '+ inttostr(MobsListCount));
  end;
 begin
  ValidateMobsList;
  if (MyX <> 0) and (MyY <> 0) and (MyZ <> 0) and (MyID <> 0) and (MyHP <> 0) and (MyMaxHP <> 0) and         // верификация всех данных, чтобы потом в боевом режиме
     (MyMP <> 0) and (MyMaxMP <> 0) and (MyCP <> 0) and (MyMaxCP <> 0) and                                   // не перепроверять все данные по 100 раз
     (CenterX <> 0) and (CenterY <> 0) and (CenterZ <> 0) and (Radius > 0) and (MobsListCount > 0) then
      begin
       SendMsg('Все начальные параметры заданы и проверены!');
       log.Lines.Add('Все начальные параметры заданы и проверены!');
       result:= true;
      end
     else
      begin
       SendMsg('Ошибка задания начальных параметров!');
       log.Lines.Add('Ошибка задания начальных параметров!');
       result:= false;
      end;
 end;

procedure UserCommandsInitMode;    // комманды пользователя для режима настройки бота
 begin                              // если комманда обработана удачно, то в чат сообщение не попадет, а будет выдано системное сообщение прямо в клиент
  case (ReadS(2)) of
   'pos' :   if MyX <> 0 then                        // центр кача
              begin
               CenterX:= MyX;
               CenterY:= MyY;
               CenterZ:= MyZ;
               SendMsg('Центр кача задан успешно!');
               log.Lines.Add('Центр кача задан успешно!');
               pck:='';
              end;
   'dist' :  if (CenterX <> 0) and (MyX <> 0) then                // радиус кача
              begin
               Radius:= rastoyanie (MyX,MyY,MyZ);
               SendMsg('Радиус кача задан успешно');
               SendMsg('R= '+ inttostr(Radius));
               log.Lines.Add('Радиус кача задан успешно, R = '+ inttostr(Radius));
               pck:='';
              end;
   'reset':  begin                                                // сброс параметров
              ClearDB;
              SendMsg('БД очищена, введите заново все параметры');
              log.Lines.Add('БД очищена!');
              pck:='';
             end;
   '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' :            // задаем мобов
              begin
               MobsListCount:= strtoint(ReadS(2));
               SendMsg('Добавляем моба № '+ ReadS(2));
               pck:='';
              end;
   'start':   begin                                               // собственно запуск бота
               if ValidateData and InitMode then
                begin
                 SendMsg('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
                 log.Lines.Add('ЗАПУСКАЕМ ИСУСТВЕННЫЙ ИНТЕЛЛЕКТ!');
                 TargetID:=0;
                 InitMode:= false;
                 TimerCombat.enabled:=true;                      // запускаем таймер
                end
                else
                 begin
                  SendMsg('Еще не все параметры заданы. Проверьте параметры...');
                  log.Lines.Add('Еще не все параметры заданы. Проверьте параметры...');
                 end;
               pck:='';
              end;
  end;
 end;

procedure UserCommandsCombatMode;     // комманды пользователя для боевого режима
 begin                                // команды говорят сами за себя)
  case (ReadS(2)) of
   'pause' : begin
              TimerCombat.enabled:= not(TimerCombat.enabled);
              pck:='';
              if TimerCombat.enabled then
               begin
                SendMsg('Искуственный интелект запущен!');
                log.Lines.Add('Искуственный интелект запущен!');
               end
               else
                begin
                 SendMsg('Искуственный интелект приостановлен.');
                 log.Lines.Add('Искуственный интелект приостановлен.');
                end
             end;
   'stop'  : begin
              pck:='';
              TimerCombat.enabled:= false;
              InitMode:= true;
              SendMsg('Искуственный интелект остановлен.');
              log.Lines.Add('Искуственный интелект остановлен.');
             end;

  end;
 end;

function GetMinDistID : integer;     // функция поиска ближайшего моба в БД
 var
  i, dist : integer;
 begin
  dist:=10000;                       // задаем заранее нереальную дистанцию
  for i:=1 to LastItem do if (MobsID[i] <> 0) and (MobsDist[i] < dist) then
   begin                            // фишка в том, что в базе хранятся расстояния не до меня, а до центра кача
    dist:= MobsDist[i];             // но в катах то расстояния небольшие
    result:= i;                      // если нашли хоть одного моба или несколько возращаем его индекс ближайшего к центру кача
   end;
  if dist = 10000 then result:= dist;   // иначе возвращаем 10000
 end;

function AgroTest : integer;        // функция проверяет, атакует ли меня кто-нибудь или нет
 var
  i: integer;
 begin
  result:=0;
  for i:=1 to LastItem do if MobsAgression[i] then  // ищем первого попавшегося моба, который нас атакует
   begin
    result:= i;                                      // возвращаем его индекс по БД
    break;
   end;
 end;

procedure PhisicalAttack;          // команда атаки
 begin
 buf:=#$04; //action
  WriteD(TargetID);
  WriteD(MyX);
  WriteD(MyY);
  WriteD(MyZ);
  WriteC(0);
  SendToServerEx(NickName);
 end;

procedure OnTimerCombat (Sender: TObject);         // боевой таймер, вся логика поведения бота находится именно здесь!!!
 var
  Agro, MinDistID: integer;
 begin
  if LastItem > 0 then                             // если есть мобы в базе то:
   begin
    if TargetID = 0 then                          // если нет текущей цели, то
     begin
      Agro:= AgroTest;                            // запускаем алгоритм выбора цели
      MinDistID:= GetMinDistID;
      if Agro > 0 then                            // если нас кто-то атакует, то его и выбираем
       begin
        TargetID:= MobsID[Agro];
        PhisicalAttack;                            // берем вражину в таргет
        AttackCycle:= 0;
       end
      else if MinDistID <= Radius then            // иначе ищем ближайшего
       begin
        TargetID:= MobsID[MinDistID];
        PhisicalAttack;                           // берем вражину в таргет
        AttackCycle:= 0;
       end;
     end;
    if TargetID > 0 then
     begin
      case AttackCycle of                          // валим вражину
       1, 5, 6 : PhisicalAttack;
       10 : ;
      end;
      inc(AttackCycle)
     end;
   end;
  if LastItem = 0 then ;                        // если нет мобов в базе, то по идее надо вернуться в центр кача, пока не разобрался с алгоритмом
 end;                                           // хочется точно сэмулировать клиент, как он работает


procedure OnTimerForm (Sender: TObject);           // таймер обновления данных в форме
 var
  i: integer;
 begin
  textMyID.text:= inttostr(MyID);                      // обновляем данные в окне
  textX.text:= inttostr(MyX);
  textY.text:= inttostr(MyY);
  textZ.text:= inttostr(MyZ);
  textMyHP.text:= inttostr(MyHP);
  textMyMaxHP.text:= inttostr(MyMaxHP);
  textMyMP.text:= inttostr(MyMP);
  textMyMaxMP.text:= inttostr(MyMaxMP);
  textMyCP.text:= inttostr(MyCP);
  textMyMaxCP.text:= inttostr(MyMaxCP);
  textCenterX.text:= inttostr(CenterX);
  textCenterY.text:= inttostr(CenterY);
  textCenterZ.text:= inttostr(CenterZ);
  textRadius.text:= inttostr(Radius);
  textTargetID.text:= inttostr(TargetID);
  textAttackCycle.text:= inttostr(AttackCycle);
  textLastItem.text:= inttostr(LastItem);

  mainscreen.lines.Clear;
  for i:=1 to LastItem do if MobsID[i] > 0 then        // выводим БД мобов
   begin                                               // алгоритм пока не доделан
    mainscreen.lines.add ('-- '+inttostr(i)+' МобID: '+inttostr(MobsID[i])+' дистанция '+inttostr(MobsDist[i]));
   end;

 end;

procedure CreateLabel (text: string);             // процедура автоматизирует создание текстовых меток в форме
 var
  l: TLabel;
 begin
  l:= TLabel.Create(panel);
  l.caption:=text;
  l.parent:=panel;
  l.left:=5;
  l.top:=15+20*frmParamIndex;
  inc(frmParamIndex);
 end;

function CreateTextBox (text:string) :TEdit;        // функция автоматизирует создание текстовых полей для вывода данных в форме
 var
  e: TEdit;
 begin
  e:= TEdit.Create(panel);
  e.text:=text;
  e.parent:=panel;
  e.left:=60;
  e.top:=10+20*frmParamIndex;
  result:= e;
 end;

procedure Init; //Вызывается при включении скрипта
 begin
  ClearDB;
  MyID:= 0;        // обнуляем ВСЕ данные
  MyX:= 0;
  MyY:= 0;
  MyZ:= 0;
  MyID:= 0;
  MyHP:= 0;
  MyMaxHP:= 0;
  MyMP:= 0;
  MyMaxMP:= 0;
  MyCP:= 0;
  MyMaxCP:= 0;

  InitMode:= true;

  TimerCombat:=TTimer.Create(nil);           // создаем таймеры
  TimerCombat.OnTimer:=@OnTimerCombat;
  TimerCombat.enabled:=false;
  TimerCombat.interval:=1000;
  TimerForm:=TTimer.Create(nil);
  TimerForm.OnTimer:=@OnTimerForm;
  TimerForm.enabled:=true;
  TimerForm.interval:=1000;

  frmParamIndex:=0;                          // создаем контролы в форме
  frm:= TForm.Create(nil);
  frm.Caption:= 'BOT info';
  frm.BorderStyle := bsSizeable;
  frm.Position := poScreenCenter;
  frm.Width:=650;
  frm.Height:=700;
  mainscreen:=TMemo.Create(frm);
  mainscreen.parent:=frm;
  mainscreen.align:=alLeft;
  mainscreen.ReadOnly:=true;
  mainscreen.ScrollBars:=2;
  mainscreen.Width:=470;
  mainscreen.Height:=370;
  mainscreen.Lines.Add('Инициализация');
  panel:=TPanel.Create(frm);
  panel.parent:=frm;
  panel.align:=alRight;
  log:=TMemo.Create(panel);
  log.parent:=frm;
  log.align:=alBottom;
  log.ReadOnly:=true;
  log.ScrollBars:=0;
  log.Width:=570;
  log.Height:=100;
  log.Lines.Add('...');

  textMyID:= CreateTextBox('textMyID');
  CreateLabel('Мой ID :');
  textX:= CreateTextBox('textX');
  CreateLabel('Мой X :');
  textY:= CreateTextBox('textY');
  CreateLabel('Мой Y :');
  textZ:= CreateTextBox('textZ');
  CreateLabel('Мой Z :');
  textMyHP:= CreateTextBox('textMyHP');
  CreateLabel('Мой HP :');
  textMyMaxHP:= CreateTextBox('textMyMaxHP');
  CreateLabel('Мой MaxHP :');
  textMyMP:= CreateTextBox('textMyMP');
  CreateLabel('Мой MP :');
  textMyMaxMP:= CreateTextBox('textMyMaxMP');
  CreateLabel('Мой MaxMP :');
  textMyCP:= CreateTextBox('textMyCP');
  CreateLabel('Мой CP :');
  textMyMaxCP:= CreateTextBox('textMyMaxCP');
  CreateLabel('Мой MaxCP :');
  inc(frmParamIndex);
  textCenterX:= CreateTextBox('textCenterX');
  CreateLabel('Ц. кач Х:');
  textCenterY:= CreateTextBox('textCenterY');
  CreateLabel('Ц. кач Y:');
  textCenterZ:= CreateTextBox('textCenterZ');
  CreateLabel('Ц. кач Z:');
  textRadius:= CreateTextBox('Radius');
  CreateLabel('Radius :');
  inc(frmParamIndex);
  textTargetID:= CreateTextBox('TargetID');
  CreateLabel('Цель ID :');
  textAttackCycle:= CreateTextBox('AttackCycle');
  CreateLabel('Цикл атаки:');
  textLastItem:= CreateTextBox('LastItem');
  CreateLabel('Элем. БД:');


  frm.Show;                // выводим форму на экран
end;

procedure Free; //Вызывается при выключении скрипта
begin
 mainscreen.free;
 log.free;
 frm.free;
 ClearDB;
 TimerForm.free;
 TimerCombat.free;
end;

procedure UserInfo;            // обновление донных о себе
 var                            // где-то тут что-то надо править чтобы в интерлюде работало
  i:word;
 begin
  if InitMode then MyID:=ReadD(18);
  MyX:=ReadD(2);
  MyY:=ReadD(6);
  MyZ:=ReadD(10);
  i:=22;
  ReadS(i);
  i:=i+44;
  MyMaxHP:=ReadD(i);
  MyHP:=ReadD(i);
  MyMaxMP:=ReadD(i);
  MyMP:=ReadD(i);
  i:=i+363;
  MyMaxCP:=ReadD(i);
  MyCP:=ReadD(i);
 end;

procedure StatusUpdate;       // обновление данных о себе
 var
  i:integer;
 begin
  for i:=0 to ReadD(6)-1 do
   case pck[i*8+10] of
    #$09: MyHP:=ReadD(i*8+14);
    #$0A: MyMaxHP:=ReadD(i*8+14);
    #$0B: MyMP:=ReadD(i*8+14);
    #$0C: MyMaxMP:=ReadD(i*8+14);
    #$21: MyCP:=ReadD(i*8+14);
    #$22: MyMaxCP:=ReadD(i*8+14);
   end;
 end;

begin
 if pck = '' then exit;
 if (ConnectName = NickName) and FromServer and (not InitMode) then  // разбор пакетов от сервера в Боевом режиме
   case pck[1] of
    #$01: begin                             //   MoveToLocation:h(ObjectID)d(CurX)d(CurY)d(CurZ)d(DestX)d(DestY)d(DestZ)
           povtor:= TestPovtor(ReadD(2));
           if Povtor > 0 then
            begin
             updateDB(Povtor, ReadD(2), ReadD(18), ReadD(22), ReadD(26), false);
            end;
          end;

    #$03: ;                             //   CharInfo:d(X)d(Y)d(Z)-(4)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)-(4)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PvPFlag)d(Carma)d(MSpeed)d(PSpeed)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(SiegeFlags)b(Sitting)b(Running)b(InCombat)b(AlikeDead)b(Invisible)b(MountType)b(PrivateStoreType)
    #$04: if ReadS(22) = NickName then UserInfo; //   UserInfo:d(X)d(Y)d(Z)d(Heading)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)d(Level)d(Exp)d(STR)d(DEX)d(CON)d(INT)d(WIT)d(MEN)d(MaxHP)d(CurrentHP)d(MaxMP)d(CurrentMP)d(SP)d(CurrentLoad)d(MaxLoad)d(Unknown)d(Under)d(REar)d(LEar)d(Neck)d(RFinger)d(LFinger)d(Head)d(RHand)d(LHand)d(Gloves)d(Chest)d(Legs)d(Feet)d(Back)d(LRHand)d(Hair)i(Under)i(REar)i(LEar)i(Neck)i(RFinger)i(LFinger)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accuracy)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateStoreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cubics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLeft)b()b(RecomHave)b()
    #$05{, #$48}: begin                     //   05= Attack:d(AttackerID)d(TargetID)d(Damage)b(Flags)d(X)d(Y)d(Z)h(Hits)
           if ReadD(6) = MyID then
            begin
             Povtor:= TestPovtor(ReadD(2));//   48= MagicSkillUse
             if Povtor = 0 then AddtoDB (ReadD(2), ReadD(15), ReadD(19), ReadD(23), true)
                           else UpdateDB(Povtor, ReadD(2), ReadD(15), ReadD(19), ReadD(23), true);
            end;
          end;

    #$06: begin                             //   Die:d(ChaID)
           povtor:= TestPovtor(ReadD(2));
           if Povtor > 0 then
            begin
             if MobsID[povtor] = TargetID then
              begin
               TargetID:= 0;
               // статистика тут должна считаться
               // и споил надо делать
              end;
             DelDBItem(povtor);
            end;
          end;

    #$0C: ;                             //   DropItem:h(PlayerID)h(ObjectID)i(ItemID)d(X)d(Y)d(Z)d(Stackable)d(Count)
    #$0E: if MyID=ReadD(2) then StatusUpdate; //   StatusUpdate:h(ObjectID)d(Attributes)
   { #$12: begin                        //   DeleteObject:h(ObjectID)
           povtor:= TestPovtor(ReadD(2));
           if Povtor > 0 then
            begin
             DelDBItem(povtor);
            end;
          end;}
    #$16: begin                         //   NpcInfo:h(ObjectID)d(NpcTypeID)d(IsAttackable)d(X)d(Y)d(Z)d(Heading)d(Unknown)d(MAtkSpd)d(PAtkSpd)d(RunSpd)d(WalkSpd)d(SwimRunSpd)d(SwimWalkSpd)d(FlRunSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(ProperMultiplier)f(PAtkSpd)f(CollisionRadius)f(CollisionHeight)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRunning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Name)s(Title)
           if InMobsList(ReadD(6)) and (ReadD(10)=1) and (pck[121]=#$00) then
            begin
             Povtor:= TestPovtor(ReadD(2));
             if Povtor = 0 then AddtoDB (ReadD(2), ReadD(14), ReadD(18), ReadD(22), false)
                           else UpdateDB(Povtor, ReadD(2), ReadD(14), ReadD(18), ReadD(22), false);

           end;
          end;
   end;

 if (ConnectName = NickName) and FromClient and (not InitMode) then   // разбор пакетов от клиента в боевом режиме
   case pck[1] of
   #$04: {TargetID:= ReadD(2)};            //  Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b(ActionID)
   #$38: UserCommandsCombatMode;         //  Say2:s(Text)d(Type)s(Target)
    #$48: begin                          //  ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
           MyX:= ReadD(2);
           MyY:= ReadD(6);
           MyZ:= ReadD(10);
          end;


   end;


 if (ConnectName = NickName) and FromServer and InitMode then   // разбор клиентов от сервера в режиме настройки бота
   case pck[1] of
    #$04: if ReadS(22) = NickName then UserInfo; //   UserInfo:d(X)d(Y)d(Z)d(Heading)h(ObjectID)s(Name)d(Race)d(Sex)d(ClassID)d(Level)d(Exp)d(STR)d(DEX)d(CON)d(INT)d(WIT)d(MEN)d(MaxHP)d(CurrentHP)d(MaxMP)d(CurrentMP)d(SP)d(CurrentLoad)d(MaxLoad)d(Unknown)d(Under)d(REar)d(LEar)d(Neck)d(RFinger)d(LFinger)d(Head)d(RHand)d(LHand)d(Gloves)d(Chest)d(Legs)d(Feet)d(Back)d(LRHand)d(Hair)i(Under)i(REar)i(LEar)i(Neck)i(RFinger)i(LFinger)i(Head)i(RHand)i(LHand)i(Gloves)i(Chest)i(Legs)i(Feet)i(Back)i(LRHand)i(Hair)d(PAtk)d(PAtkSpd)d(PDef)d(EvasionRate)d(Accuracy)d(CritikalHit)d(MAtk)d(MAtkSpd)d(PAtkSpd)d(MDef)d(PvpFlag)d(Karma)d(RunSpeed)d(WalkSpeed)d(SwimRunSpeed)d(SwimWalkSpeed)d(FlRunSpeed)d(FlWalkSpeed)d(FlyRunSpeed)d(FlyWalkSpeed)f(MovementSpeedMultiplier)f(AttackSpeedMultiplier)f(CollisionRadius)f(CollisionHeight)d(HairStyle)d(HairColor)d(Face)d(AccessLevel)s(Title)d(ClanId)d(ClanCrestId)d(AllyId)d(AllyCrestId)d(IsClanLeader)b(MountType)b(PrivateStoreType)b(DwarvenCraft)d(PkKills)d(PvpKills)b(Cubics)b(Cubics)b(FindPartyMembers)d(AbnormalEffect)b()d(ClanPrivileges)d()d()d()d()d()d()d()b(RecomLeft)b()b(RecomHave)b()
    #$06: if (ReadD(2) = TargetID) and (MobsListCount <> 0) then                              //   Die:d(ChaID)
           if (MobsList[MobsListCount] <> 0) then
            begin
             SendMsg('Моб №' + inttostr(MobsListCount) + ' добавлен в базу');
             log.Lines.Add('Моб №' + inttostr(MobsListCount) + ' добавлен в базу');
             MobsListCount:= 0;
             TargetID:= 0;
            end;
    #$16: if (ReadD(2) = TargetID) and (MobsListCount <> 0) then MobsList[MobsListCount]:= ReadD(6);//NpcInfo:h(ObjectID)d(NpcTypeID)d(IsAttackable)d(X)d(Y)d(Z)d(Heading)d(Unknown)d(MAtkSpd)d(PAtkSpd)d(RunSpd)d(WalkSpd)d(SwimRunSpd)d(SwimWalkSpd)d(FlRunSpd)d(FlWalkSpd)d(FlyRunSpd)d(FlyWalkSpd)f(ProperMultiplier)f(PAtkSpd)f(CollisionRadius)f(CollisionHeight)d(RHand)d(Unknown)d(LHand)b(Unknown)b(IsRunning)b(IsInCombat)b(IsALikeDead)b(IsSummoned)s(Name)s(Title)
   end;
 if (ConnectName = NickName) and FromClient and InitMode then      // разбор пакетов от клиента в режиме настройки бота
   case pck[1] of
    #$04: TargetID:= ReadD(2);       //  Action:h(ObjectID)d(OriginX)d(OriginY)d(OriginZ)b(ActionID)
    #$38: UserCommandsInitMode;      //  Say2:s(Text)d(Type)s(Target)
    #$48: begin                      //  ValidatePosition:d(X)d(Y)d(Z)d(Heading)d(Data)
           MyX:= ReadD(2);
           MyY:= ReadD(6);
           MyZ:= ReadD(10);
          end;
   end;

end.
Главный косяк в том что...
1. если тебя застанили то снова мы не атакуем моба..
2. если словили всеже моба за радиусом аггро то тоже не отвечаем ему.. хотя в лог пишет что НАС АТАКУЮТ, в ответ сдачи только не даем...
тестировал на интерлюде работает и забивает мобов в базу отлично...
еше минусы
- что не поднимает дроп :)
- не пьет бутылочки :)
хотя все это можно взять с других скриптов или совместить другие с этим.
DashKAaa вне форума   Ответить с цитированием
Старый 20.03.2008, 22:48   #304
Рыцарь
 
Аватар для Grinch
 
Регистрация: 29.02.2008
Сообщений: 928
Сказал Спасибо: 127
Имеет 130 спасибок в 93 сообщенях
Grinch пока неопределено
По умолчанию

Цитата:
Сообщение от VORON
ДРУЗЬЯ, частично перечитал топ.. и с ужасом обнаружил что нет нормальной реализации глотания банок ХП, ГХП, ГЦП... тот вариант что предложил МКС предполагает предварительную подготовку скрипта.. т.е. после запуска скрипта следуют самому ручками глотнуть банки в нужной последовательности..
спешу исправить етот пробел в наших знаниях.. хотя тут дело не в знаниях а просто лень было делать многим.. но!.. спешу представиить вышеупомянутый скрипт в более продвинутой модификации.. теперь если у вас даже и нет вовсе ПП ШЕ ЕЕ или БИША то и вы совсем один то всё равно скрипт вам будет полезен ибо он нетребует никаких настроек и будет пить банки ХП ГЦП ГХП при условии что они есть в инвенторе у вас.. скрипт также настроен на то что ети зелья будут пить ваши баферы- (если они у них есть..).. плиз неспрашивайте меня почему не работают елексиры- я пока не разбирался.. в сыром виде их реализовал но они не пашут.. незнаю почему но они никак не влеяют на работоспособность скрипта.. для подготовки скрипта к работе требуется лиш имена поменять на реальные.. в 4-х строчках (188-192), после етого скрипт щитается полностью рабочим и готовым к использованию.. но если вам хочется изменить уровни ХП и МП при которых срабатывает ХИЛ и ЗАЛИВКА МП и ХП то там просто значения исправте.. ну я думаю понятно что в конце скрипта написан код- какие бафы на ково класть там весде вбито АСИСТ ТАРГЕТ. т.е. если вас кто то просит: "БАФНИ ПЛЗ" то просто береш его в таргет и жмеш NO или UNWARE от кнопки будет зависеть буф мага или физика.. нужные бафы перечисляются в конце скрипта кому и что бафать.. вопщем.. отличие етого скрипта от того что я раньше дал в том что командир и баферы глотают банки ГЦП,ХП,ГХП сами- автоматом.. при етом ненужно никаких подготовок скрипта.. ето реализуется очень просто.. 1 умный человек в етом топе сказал что пакет ЮЗЕР ИНФО можно вызвать если отправиить запрос на открытие инвенторя.. я проверил- ето правда.. когда скрипт начинает свою работу на все аки отсылается запрос на открытие инвенторя (автоматически).. из попутного пакета ЮЗЕР ИНФО скрипт сам узнает ИДешники всех.. а из инвенторя скрипт сам ищет БАНКИ с ХП,ГХП и ГЦП.. запоминает их OID и потом когда надо использует..
ты прав :) влом это делать кстате поставь между банками цп 100 и поймай стан. хотя не проверял после разделения моего скрипта на 2 разных врод всё работает а что надо пить банки цп и хп что б запустить скрипт это не главная проблема у МСК в пати скрипт не работает т.е. если в пати у кого то начинает падать цп или хп вы начинаете жрать банки. если кто попросит выложу свои скрипты их 2. не довожу их до ума и не выкладываю только из-за лени вообще в лом ща всё весна что б её.
Grinch вне форума   Ответить с цитированием
Старый 22.03.2008, 03:59   #305
Рыцарь
 
Аватар для VORON
 
Регистрация: 06.08.2007
Сообщений: 209
Сказал Спасибо: 6
Имеет 67 спасибок в 34 сообщенях
VORON пока неопределено
По умолчанию

ДРУЗЬЯ, давайте подумаем как соло рейдов килить.. ну не соло а фулпати на скрипте, без клиентов.. думаю под ету задучу будет отдельный топ отведен.. но вапще хочется же??..
__________________
Цитата:
Сообщение от pybukon
прежде чета попросить я немнога раскажу чтоб вы понили как мне плоха
Цитата:
Сообщение от Byrger
А как сделать мой скрипт бесконечным?
Цитата:
Сообщение от XKOR
.. каждый день ионизированной ногой протирает больную)
Цитата:
Сообщение от PsyR
Вылоджите пожалуйста скрипт на рыбалку желательно что бы сам в ВХ клал адаптированый под шоки и так же скрипт на ТТ рец, тоже с диалогами
VORON вне форума   Ответить с цитированием
Старый 22.03.2008, 06:46   #306
Заблокирован
 
Регистрация: 10.03.2008
Адрес: Тула
Сообщений: 1,098
Сказал Спасибо: 188
Имеет 108 спасибок в 60 сообщенях
DashKAaa
По умолчанию

2 destra pod bd/sws/пофом от се или пп, валят рб 50-60 в лет далее аналогично до 70думаю только подольше
на интерлюде... в с4 все не так .. ибо маги решают
DashKAaa вне форума   Ответить с цитированием
Старый 25.03.2008, 03:15   #307
Местный
 
Аватар для PanAm
 
Регистрация: 18.01.2008
Сообщений: 286
Сказал Спасибо: 24
Имеет 133 спасибок в 80 сообщенях
PanAm
По умолчанию

Цитата:
Сообщение от aker
можноли взять в таргет моба но только чтобы он не аттакавал типо как командой "/target и имя моба" ?
buf:=hstr('04') + ObjectID + MyCoordX + MyCoordY + MyCoordZ + hstr('00');
PanAm вне форума   Ответить с цитированием
Старый 25.03.2008, 12:44   #308
Рыцарь
 
Аватар для QaK
 
Регистрация: 28.09.2007
Сообщений: 1,558
Сказал Спасибо: 71
Имеет 351 спасибок в 244 сообщенях
QaK пока неопределено
По умолчанию

Цитата:
Сообщение от aker
ну я же не знаю ObjectID !!
лови все пакеты NPCINFo и выдирай из них ОбджектИД.
QaK вне форума   Ответить с цитированием
Старый 25.03.2008, 12:58   #309
Гость
 
Сообщений: n/a
По умолчанию

а если моб стоит наместе то пакет NPCINFo не придет же!
  Ответить с цитированием
Старый 25.03.2008, 13:38   #310
Местный
 
Аватар для PanAm
 
Регистрация: 18.01.2008
Сообщений: 286
Сказал Спасибо: 24
Имеет 133 спасибок в 80 сообщенях
PanAm
По умолчанию

Обязательно придет! этот пакет всегда посылается при респауне или появлении в зоне видимости, а так же и просто так, с неопределенной переодичностью. иначи как клиент узнает что моб стоит? :)

Добавлено спустя 2 минуты 27 секунд:
посмотри еще эту тему
viewtopic.php?f=9&t=147
PanAm вне форума   Ответить с цитированием
Ответ

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



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

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


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

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

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