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

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

Код:
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!

{Бот для кача ТК 64+ лвл
Достоинства:
- миникарта;
- панель с инфой;
- бафает себя:
- юзает кубики;
- юзает пошин алакрити;
- лечит себя хил пошинами и элементал хилом;
- при желании можно отключить клиент

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

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

  max=100; //максимальное значение массива

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

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

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

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

  heal, kill : string;
  MaxHP, MyZpos, cvaZ, CurHP, ObjID, ID, xpos, ypos, skill, MyID, PercentHP, MEsit: integer;
  MEup, but, sud, bst, Radius, cvaX, attackIDMinID, attackID, cvaY, zpos: integer;
  Hpotion, Apotion, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
  sit, povtor, tame, gdo, npc : Boolean;
  attackk, bfi, atck, hpi, i, ii: integer; //индексы различных циклов
  last : integer; //последняя запись в массиве, для ускорения скрипта
  //массив мобов
  MobsObjID: array[1..max] of integer;
  MobsID: array[1..max] of integer;
  MobsName: array[1..max] of string;
  MobsRAS: array[1..max] of integer;
  MobsX: array[1..max] of integer;
  MobsY: array[1..max] of integer;
  MobsZ: array[1..max] of integer;
  NPCid: array[1..max] of integer;
  Aggro: array[1..max] of Boolean;

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

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

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

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

  StartTime:=time;
  underattack:=false; //атакован?

  atck:=0; //кол-во неуспешных атак после которых пробуем сменить таргет, здесь инициализация =0
  hpi:=0;
  bfi:=60; //60 сек
  ii:=1;
  last:=1; //начальное значение
  Radius:=1500; // радиус круга кача!
  PercentHP:=70;   // при каком количестве хп в % юзать бутылку лечения
  MEsit:=55;   // при каком количестве хп в % надо сесть и подкопить хп
  MEup:=90;   // при каком количестве хп в % надо встать после отдыха
  frm := TForm.Create(nil);
  frm.Caption := 'BOT '+name;
  frm.BorderStyle := bsSizeable;
  frm.Position := poScreenCenter;
  frm.Width:=520;
  frm.Height:=700;

  info:=TMemo.Create(frm);
  info.parent:=frm;
  info.align:=alLeft;
  info.ReadOnly:=true;
  info.ScrollBars:=0;
  info.Width:=370;
  info.Height:=370;
//  info.Lines.Add('БОТ НЕ ПОДКЛЮЧЁН К СЕРВЕРУ!');

  stats:=TMemo.Create(frm);
  stats.parent:=frm;
  stats.align:=alClient;
  stats.ReadOnly:=true;
  stats.ScrollBars:=0;
  stats.Width:=240;
  stats.Height:=100;

  msg:=TMemo.Create(frm);
  msg.parent:=frm;
  msg.align:=alBottom;
  msg.ReadOnly:=true;
  msg.ScrollBars:=2;
  msg.Width:=520;
  msg.Height:=100;
  msg.Lines.Add('...');

  splitter1:=Tsplitter.Create(frm);
  splitter1.parent:=frm;
  splitter1.Top:=0;
  splitter1.Width:=3;
  splitter1.Left:=470;
  splitter1.align:=alLeft;

  splitter2:=Tsplitter.Create(frm);
  splitter2.parent:=frm;
  splitter2.Left:=0;
  splitter2.Height:=3;
  splitter2.align:=alBottom;

  frm.Show;

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

  heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); //  СИДЕТЬ!!!
  //атака и прочее
  timer1:=TTimer.Create(nil);
  timer1.OnTimer:=@OnTimer1; //
  timer1.enabled:=false; // таймер по умолчанию выключен
  timer1.interval:=1000; // через каждые 1сек будем обновлять

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

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

  for i:= 1 to max do begin
    Aggro[i]:=false;

    TTShape[i]:=Tshape.create(nil); //для мобов
    TTShape[i].parent:=map;
    TTShape[i].Brush.Color:=clBlue; //(clBlack, clRed, clGreen, clYellow, clBlue, clPurple)
    TTShape[i].shape:=stCircle;
    TTShape[i].left:=-70; //координаты
    TTShape[i].top:=-70;
    TTShape[i].width:=7; //размеры
    TTShape[i].height:=7;

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

  TTlabel[0]:=Tlabel.create(nil); //для моего чара
  TTlabel[0].parent:=map;
  TTlabel[0].left:=TTShape[0].left+4; //координаты
  TTlabel[0].top:=TTShape[0].top+4;
  TTlabel[0].caption:=name;
  TTlabel[0].font.size:=7;
  TTlabel[0].font.color:=clBlack;
end;

//***************************************************************
procedure GameToMap(x, y : integer);
//преобразуем игровые координаты в координаты карты
var
  masshtabx, masshtaby : extended;
begin
//  masshtabx:=radius*2  div map.Width;
//  masshtaby:=radius*2 div map.Height;
  xm:=Round(((X-myXpos)*map.Width/6000)+(map.Width/2));
  ym:=Round(((Y-myYpos)*map.Height/6000)+(map.Width/2)*0.9);
//  xm:=Round(((X-cvaX)*map.Width/5000)+(map.Width/2));
//  ym:=Round(((Y-cvaY)*map.Height/5000)+(map.Width/2));
end;

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

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

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

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

//***************************************************************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
  //01=MoveBackwardToLocation:d(targetX)d(targetY)d(targetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
  buf:=#$01;
  WriteD(targetx); //куда
  WriteD(targety);
  WriteD(targetz);
  WriteD(MyXpos); //откуда
  WriteD(MyYpos);
  WriteD(MyZpos);
  WriteD(1); //используем 1-мышь 0-клавиатура
  SendToServerEx(Name);
  msg.Lines.Add('MoveTo('+inttostr(targetx)+','+inttostr(targety)+','+inttostr(targetz)+')');
end;

//***************************************************************
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:extended):boolean;
begin
     if delta(targetx, targety, MyXpos, MyYpos)<=distanciya
     then result:=true else result:=false;
end;

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

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

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

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

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

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

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

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

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

//***************************************************************
procedure OnTimer2(Sender: TObject); //
begin

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

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

  GetMinMaxX(MobsRAS);
  if (Summ(MobsRAS)>=round(max*0.9)) or (MaxX>5000) then begin
    //если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
    msg.Lines.Add('мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(Summ(MobsRAS))+'-');
    DelElArr(MaxID);
  end;
  //идем в центр если нет мобов
//  if (Summ(MobsRAS)=0) and (timer1.enabled=true) and (cvax<>0) then begin
    //if not PosInRange(cvaX,cvaY,cvaZ,50) then MoveTo(cvaX,cvaY,cvaZ);
//  end;

  if (CurHP<but) and (Summ(Aggro)=0) and (sit=false) then begin
    msg.Lines.Add('Баффаюсь elemental heal!');
    MagicSkillUse(elementalheal);
  end;

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

end;

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

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

        GameToMap(posx,posy);
        TTshape[i].left:=xm; //координаты моего чара
        TTshape[i].top:=ym;
        TTlabel[i].left:=TTShape[i].left+4; //координаты
        TTlabel[i].top:=TTShape[i].top+4;
        TTlabel[i].caption:=inttostr(i);

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

        GameToMap(posx,posy);
        TTshape[i].left:=xm; //координаты моего чара
        TTshape[i].top:=ym;
        TTlabel[i].left:=TTShape[i].left+4; //координаты
        TTlabel[i].top:=TTShape[i].top+4;
        TTlabel[i].caption:=inttostr(i);

        break;
      end;
    end;
  end;
end;

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

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

//***************************************************************
//2F=RequestMagicSkillUse:dMagicID)d(CtrlPressed)b(ShiftPressed)
procedure MagicSkillUse(MagicID:integer);
begin
  buf:=#$2F;
  WriteD(MagicID);
  WriteD(00);
  WriteC(00);
  SendToServerEx(Name);
end;

//******************************************************************************
// вызывается при приходе каждого пакета, если скрипт включен
//******************************************************************************
begin
  //****************************************************************************
  //не обрабатываем пустые пакеты
  if pck='' then exit;

  //****************************************************************************
  if (ConnectName=Name) and FromServer then begin
    case pck[1] of
{      #$76: begin
          msg.Lines.Add('S>C $76');
          if (ReadD(2)=MyID) then begin //я юзнул какой то скилл
            msg.Lines.Add(' юзнул скилл!');
            skill:=1;
          end;
      end;
}      #$0E: begin
          msg.Lines.Add('S>C $0E StatsUpdate');
          if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
      end;
      //MagicSkillUse 48, Attack 05
      #$05: begin
          msg.Lines.Add('S>C $05 Attack');
           if (ReadD(6)=MyID) then begin
           //меня ударили
             sit:=false;
             if (ETOpovtor(ReadD(2),MobsObjID)=false) then AddBD(ReadD(2),ReadD(15),ReadD(19),ReadD(23));
             for i:=1 to last do begin
               if (MobsObjID[i]=ReadD(2)) then begin  //если моб записан в базе данных
                 msg.Lines.Add('На нас напали враги!!!'+IntToStr(i)+'-'+IntToStr(MobsObjID[i]));
                 MobsRAS[i]:=1;
                 Aggro[i]:=true;  // стал агрессор
                 if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
                   attackIDMinID:=i;
                   timer1.enabled:=true;
                 end;
                 if (attackIDMinID<>0) and (Aggro[attackIDMinID]=false) then attackIDMinID:=i;
                 break;
               end;
             end;
           end;
      end;
      #$0C: begin
          msg.Lines.Add('S>C $0C DropItem');
          if (MyXpos<>0) then begin
            if (delta(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
              msg.Lines.Add('Выпала вещь!!!');
              timer1.enabled:=false;
              buf:=#$04;
              WriteD(ReadD(6));
              WriteD(ReadD(14));
              WriteD(ReadD(18));
              WriteD(ReadD(22));
              WriteC(0);
              SendToServerEx(Name);
              msg.Lines.Add(' Пробую поднять!!!');
              delay(1000);
              timer1.enabled:=true;
            end;
          end;
      end;
      #$04: begin
          msg.Lines.Add('S>C $04 CharInfo');
          //пакет с инфой о моём чаре
          i:=2;
          MyXpos:=ReadD(i); //получаю координату х моего чара
          MyYpos:=ReadD(i); //получаю координату у моего чара
          MyZpos:=ReadD(i); //получаю координату z моего чара
          //Запоминаем ИД
          i:=18;
          MyID:=ReadD(i); //получаю ид моего чара
          //смещение переменное, зависит от имени (LenName*2+2)
          i:=i+(Length(Name)*2+2)+offs1; //44 для С4, 48 для IL
          MaxHP:=ReadD(i);
          CurHP:=ReadD(i);
          if (gdo=false) then begin //задаем центр окружности кача
            cvaX:=MyXpos;
            cvaY:=MyYpos;
            gdo:=true;
          end;
          GameToMap(MyXpos,MyYpos);
          TTshape[0].left:=xm; //координаты моего чара
          TTshape[0].top:=ym;
          TTlabel[0].left:=TTShape[0].left+4; //координаты
          TTlabel[0].top:=TTShape[0].top+4;
      end;
      #$01: begin
          msg.Lines.Add('S>C $01 Move');
          if (MyID<>0) and (ReadD(2)<>MyID) then begin //если кто-то перемещается
            i:=2;
            ObjID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
            ID:=0; //кто-то рыпнулся с места надо это записать...
            xpos:=ReadD(i);
            ypos:=ReadD(i);
            zpos:=ReadD(i);
            if not ISnpc(ObjID) {and (delta(cvaX,cvaY,xpos,ypos)<=Radius)} then AddBD(ObjID,xpos,ypos,zpos);
          end;
      end;
      //принят пакет Die
      #$06: begin
          msg.Lines.Add('S>C $06 Die');
          //нас убили
          if (myID=ReadD(2)) then begin
            info.Lines.Add('Нас убили в '+TimeToStr(time));
            inc(death1);
            RequestRestartPoint; //оживаем после смерти
//            mov:=1;
            //TODO сделать проверки на место появления
//            moveto1.enabled:=true;
            info.Lines.Add('Бежим после смерти на берег...');
            underattack:=false;
            for i:= 1 to max do begin
              Aggro[i]:=false;
              TTShape[i].Brush.Color:=clBlue;
              TTlabel[i].font.color:=clBlue;
            end;
          end;
          //моб сдох! выкидываем его из базы and (attackID=ReadD(2))
          for i:=1 to last do begin
            if (MobsObjID[i]=ReadD(2)) then begin
              inc(mob1);
              DelElArr(i);
              attackk:=0;
              atck:=0;
              msg.Lines.Add('БОБИК СДОХ!! :'+IntToStr(i));
              if (i=last) and (last<>1) then dec(last);
              break;
            end;
          end;
      end;
      //принят пакет DeleteObject
      #$12: begin
          msg.Lines.Add('S>C $12 DeleteObject');
          //выкидываем из базы
          for i:=1 to last do begin
            if (MobsObjID[i]=ReadD(2)) then begin
              DelElArr(i);
              msg.Lines.Add('Удаляю из базы!! :'+IntToStr(i));
              if (i=last) and (last<>1) then dec(last);
              break;
            end;
          end;
      end;
      #$03: begin
          msg.Lines.Add('S>C $03 Char');
          if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
            for i:=last to max do begin
              if (NPCid[i]=0) then begin
                if (ETOpovtor(ReadD(18),NPCid)=false) then begin
                  NPCid[i]:=ReadD(18);
                  msg.Lines.Add('ДОБАВЛЕН ИГРОК:'+ReadS(22)+'-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
                  break;
                end;
              end;
            end;
          end;
      end;
      #$16: begin
          msg.Lines.Add('S>C $16 NPC');
          if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
            msg.Lines.Add('Вижу NPC!');
            if (ReadD(10)=0) then begin  //если нельзя атаковать
              for i:=last to max do begin
                 if (NPCid[i]=0) then begin
                   if (ETOpovtor(ReadD(2), NPCid)=false) then begin
                     NPCid[i]:=ReadD(2);
                     msg.Lines.Add('Запомнили, NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
                     break;
                   end;
                 end;
              end;
            end;
            if (ReadD(10)=1) and (pck[120]=#$00) then begin  //если можно атаковать
//              if (delta(cvaX, cvaY, ReadD(14), ReadD(18))<=Radius) then begin
                id:=ReadD(6);
                AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
                msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
//              end
//              else msg.Lines.Add('NPCid='+IntToStr(ReadD(2))+' вне радиуса действия!');
            end;
          end;
      end;
      //InventoryUpdate
      #$27: begin
          msg.Lines.Add('S>C $27 InventoryUpdate');
          if ((ReadD(12)=1060) or (ReadD(12)=1061)) then begin //Healing Potion, Lesser Healing Potion
            Hpotion:=ReadD(8);
            msg.Lines.Add('ID бутылок Hpotion:'+inttostr(Hpotion));
          end;
          if ReadD(12)=735 then begin //Potion of Alacrity
            Apotion:=ReadD(8);
            msg.Lines.Add('ID бутылок Apotion:'+inttostr(Apotion));
          end;
      end;
  end;
  end;

  //****************************************************************************
  if (ConnectName=Name) and FromClient then begin
    case pck[1] of
      #$1B: begin
        msg.Lines.Add('C>S $1B ');
        case ReadD(2) of
          //социальное действие Yes для начала
          $06: begin
            cvaX:=MyXpos;
            cvaY:=MyYpos;
            cvaZ:=MyZpos;

            GameToMap(MyXpos,MyYpos);
            TTshape[0].left:=xm; //координаты моего чара
            TTshape[0].top:=ym;
            TTlabel[0].left:=TTShape[0].left+4; //координаты
            TTlabel[0].top:=TTShape[0].top+4;

            attackk:=0;
            atck:=0;
            msg.Lines.Add('БОТ ВКЛЮЧЕН, координаты ОБНОВЛЕНЫ!!');
//            GetMinMaxX(MobsRAS);
            timer1.enabled:=true;
            timer3.enabled:=true;
          end;
          //социальное действие No для окончания
          $05: begin
            timer1.enabled:=false;
            timer3.enabled:=false;
            msg.Lines.Add('БОТ ВЫКЛЮЧЕН!!!');
          end;
{          //социальное действие Applaud
          $0B: begin
            if timer2.enabled=false
              then timer2.enabled:=true
              else timer2.enabled:=false;
            attackk:=0;
            atck:=0;
            msg.Lines.Add('! ВКЛ/ВЫКЛ!!!');
          end;
}          //социальное действие Sorrow - удаляем текущую запись в базе
          $0D: begin
            ObjID:=MobsObjID[attackIDMinID];
            DelElArr(attackIDMinID);
            attackk:=0;
            atck:=0;
            msg.Lines.Add('Удаляем текущую запись в базе!!!');
            for i:= last to max do begin
              if (NPCid[i]=0) then begin
                NPCid[i]:=ObjID;
                msg.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
                break;
              end;
            end;
          end;
        end;
      end;
      //ValidatePosition пакет от клиента с моими кординатами
      #$48: begin
        msg.Lines.Add('C>S $48 ValidatePosition');
          //обновляем ВСЕ растояния в BD если мы сошли с места
          MyXpos:=ReadD(2); //получаю координату х моего чара
          MyYpos:=ReadD(6); //получаю координату у моего чара
          MyZpos:=ReadD(10); //получаю координату z моего чара

          GameToMap(MyXpos,MyYpos);
          TTshape[0].left:=xm; //координаты моего чара
          TTshape[0].top:=ym;
          TTlabel[0].left:=TTShape[0].left+4; //координаты
          TTlabel[0].top:=TTShape[0].top+4;

          for i:=1 to last do begin
            if (MobsObjID[i]<>0) then begin
              if (true<>Aggro[i]) then begin
                MobsRAS[i]:=delta(MyXpos,MyYpos,MobsX[i],MobsY[i]);
              end;
            end;
          end;
      end;
    end;
  end;
end.
Добавлено спустя 21 минуту 31 секунду:
Цитата:
Сообщение от Юзер
Отличный скрипт, спасибо.
Но при каче в катах бот может взять в таргет цель, которая на поверхности. Можно ли сделать ограничение по Z в скрипте? Еще не понял вот этот момент: atck:=0; //кол-во неуспешных атак после которых пробуем сместиться. Какое значение лучше оставить и на что влияет? Бот возьмет другой таргет при неудачной атаке (если поставить значение "1") или вернется в центр зоны?
Спасибо.
В катах можно попробовать сильно уменьшить RADIUS - радиус кача.
Ограничение по Z можно сделать, например типа такого
Код:
const  DeltaZ=200;  
...
  //NPCInfo, запоминаем мобов
  if FromServer and (ConnectName=Name) and (pck[1]=#$16) then begin
  ...
    //проверям, не под землей ли моб(в катакомбах)
    tempZ:=BotCoordZ-ReadD(22);
    if abs(tempZ)<=DeltaZ then begin
        for i:=1 to max do begin
...
Переменная atck и attackk используются в процедуре OnTimer1.
attackk - нужна для контроля атаки
atck - если вдруг застряли - пытаемся изменить цель (через время atck(5) * attackk(7) = 35 сек)
цель меняется даже если не застряли но вреемя вышло, можно подкорректировать время в нужную сторону
__________________
| Для самых ленивый | Телепаты в отпуске |Мы работаем над этим |
Не умеешь - учись, не хочешь учиться - плати © Суровый Закон Жизни


NLObP вне форума   Ответить с цитированием