Показать сообщение отдельно
Старый 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") или вернется в центр зоны?
  Ответить с цитированием