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

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

Чат (Новых сообщений с момента вашего последнего визита нет)
Загрузка...
Задавайте ваши вопросы на форуме. Чат предназначен для небольших разговоров.
 
Ответ
 
Опции темы Опции просмотра
Старый 05.03.2008, 08:44   #281
Рыцарь
 
Аватар для Grinch
 
Регистрация: 29.02.2008
Сообщений: 928
Сказал Спасибо: 127
Имеет 130 спасибок в 93 сообщенях
Grinch пока неопределено
По умолчанию

NLObP, в катах там вообще жесть если моб в соседней комнате встанет у стеночки то бот затупит у стенки
Grinch вне форума   Ответить с цитированием
Старый 06.03.2008, 00:10   #282
Пользователь
 
Аватар для ASSA
 
Регистрация: 09.02.2008
Сообщений: 38
Сказал Спасибо: 1
Имеет 1 спасибку в 1 сообщении
ASSA
По умолчанию

СУПЕР СКРИПТЯРИЩЩЩЕЕ!!!! Я фигею как ты его написал то, я его даже прокручивать устал=)))
А в катах ка4 в 1 перс - лажа=)))

Добавлено спустя 35 минут 43 секунды:
Люди! Вот такие пакеты бутылей и они не пьютца!
Может знаете как расшифровать, или как заюзать энто???
Заранее спасибо - это Эльмор.ру
хрень1 - 0 14 ee
хрень2 - 252
время- 23 03 35 609
ИД- 408B7B96
14 96 7B 8B 40 00 00 00 00 E6 58 A5 52 E8 CE 6F 56 48 6D 90 ED 0D C8 46 2D
14 96 7B 8B 40 00 00 00 00 F5 13 52 66 E6 4D F9 72 5E 6D 05 59 25 34 13 A2
14 96 7B 8B 40 00 00 00 00 BE 42 64 63 38 C3 C5 18 79 F6 80 B2 B6 D4 DF 7F
14 96 7B 8B 40 00 00 00 00 9F 0D D3 0E FD F1 26 F5 D0 D9 04 D1 5A 34 B7 ED
14 96 7B 8B 40 00 00 00 00 8A 38 27 0E A1 28 DA F2 CE 66 98 BC B8 FF EC 82
14 96 7B 8B 40 00 00 00 00 1B 64 EF 77 3C 67 33 0A E5 4A C5 5D 71 DB A2 E2
14 96 7B 8B 40 00 00 00 00 B8 7C 53 68 27 DD 47 0A 8F BB 1E 82 C5 7E 59 60
14 96 7B 8B 40 00 00 00 00 68 6F E1 1E 4E ED DB AA 64 29 D1 E2 99 F5 DE 38
14 96 7B 8B 40 00 00 00 00 72 3A 58 67 6D 52 70 C6 EE 82 35 19 1B CE 02 65
14 96 7B 8B 40 00 00 00 00 14 60 D5 7D 9A C7 93 E8 D8 77 B5 C8 C6 40 D9 C1
14 96 7B 8B 40 00 00 00 00 CD 33 37 73 72 A9 6F A9 3A BA 4D 24 7C 09 4C 5A
14 96 7B 8B 40 00 00 00 00 0D 7F 7D 5A BD 6C 8D DA 1A 14 15 AC 61 BC EB 96
14 96 7B 8B 40 00 00 00 00 44 20 5E 79 67 04 71 9B 24 07 B3 1D 55 5B 11 E0
14 96 7B 8B 40 00 00 00 00 B4 1F 94 65 48 A5 5D AC 6D 92 A3 20 E9 28 2A CF
14 96 7B 8B 40 00 00 00 00 66 4F 08 6E D3 77 AA 3A 5B E7 5B 3B C2 6A 13 A2
14 96 7B 8B 40 00 00 00 00 33 78 FD 0C FA C1 0D 81 E1 9A CD DC 02 7F 35 59
14 96 7B 8B 40 00 00 00 00 CB 63 A5 64 68 96 66 56 CC 42 DC 70 40 FC F7 C2
14 96 7B 8B 40 00 00 00 00 10 54 0F 2F C2 CA C0 10 28 10 2A 27 40 29 39 A0
14 96 7B 8B 40 00 00 00 00 4C 3A F0 09 EF 2C A2 AE 10 58 62 D1 74 73 B4 84
14 96 7B 8B 40 00 00 00 00 03 55 42 08 4A A1 10 17 97 6E 77 3C B2 F9 A4 75
14 96 7B 8B 40 00 00 00 00 73 51 E2 6E DB F0 48 89 4C 0A 83 BD 96 CE 7A DB
14 96 7B 8B 40 00 00 00 00 05 36 48 35 54 38 02 B1 D5 2A D3 84 EF 7F AF 88
14 96 7B 8B 40 00 00 00 00 31 45 1A 05 35 A4 E9 34 83 BF F7 E1 E6 11 5F E0
14 96 7B 8B 40 00 00 00 00 AA 44 A0 37 E7 3D 13 B5 31 D5 C2 57 91 F1 6E AB
14 96 7B 8B 40 00 00 00 00 CF 32 03 5D 89 08 78 B3 AF B3 0F 4D E0 82 22 B7
14 96 7B 8B 40 00 00 00 00 B0 04 7B 51 0B 1E E4 00 6E 51 49 F9 E9 F3 FF 3B
14 96 7B 8B 40 00 00 00 00 27 19 64 18 B4 F2 1E 20 6E A3 32 81 3A 01 23 CD
14 96 7B 8B 40 00 00 00 00 D8 31 51 75 A9 09 E8 B0 CF 8D A6 9C C1 CA C2 4C
14 96 7B 8B 40 00 00 00 00 14 09 33 36 03 B0 9E D1 5F FA 8F C3 9F AE 8B 56
14 96 7B 8B 40 00 00 00 00 F4 13 E3 64 25 65 CE 2A AE 0F 35 46 90 09 9A 2A
14 96 7B 8B 40 00 00 00 00 27 3A D7 2F B0 0F AD 0B C5 B0 FE 74 14 63 D7 36
14 96 7B 8B 40 00 00 00 00 42 59 F7 30 CC 88 54 C5 95 F8 65 1B 47 A2 BD 33
14 96 7B 8B 40 00 00 00 00 9C 57 D2 45 10 5F BF 9B F1 9E 74 CA F3 92 3B 83
14 96 7B 8B 40 00 00 00 00 F8 6A 6F 4F C7 5E 7A 82 3C E8 18 A8 30 46 8B A9
14 96 7B 8B 40 00 00 00 00 8C 19 63 36 B2 00 A2 31 20 0C 68 2E 5B EA D8 F4
14 96 7B 8B 40 00 00 00 00 20 70 29 04 94 87 E9 F9 CE F8 1F 87 27 AA 60 E4
14 96 7B 8B 40 00 00 00 00 64 7E 8D 4F 50 31 37 69 0A 01 46 C0 A1 BE C2 CF
__________________
Пишите в асю если чего. 446-693-955
ASSA вне форума   Ответить с цитированием
Старый 06.03.2008, 07:10   #283
Рыцарь
 
Аватар для Grinch
 
Регистрация: 29.02.2008
Сообщений: 928
Сказал Спасибо: 127
Имеет 130 спасибок в 93 сообщенях
Grinch пока неопределено
По умолчанию

Цитата:
Сообщение от ASSA
А в катах ка4 в 1 перс - лажа=)))
ну смотря какой перс и как играть :) тёмным сумонером ПП нужен 74 лвл, если котоводом то ПП и ШЕ в пати и комнаты где 8 мобов ну понятно без резистов к физике умирают если БД воткнуть до 60лвла даже то кошка и тень простаивают долго, тенью и кошкой это по раздельности.
Grinch вне форума   Ответить с цитированием
Старый 07.03.2008, 11:13   #284
Новичок
 
Регистрация: 22.11.2007
Сообщений: 17
Сказал Спасибо: 0
Имеет 0 спасибок в 0 сообщенях
Rubec
По умолчанию

Гринч ты не внимательно прочитал там же написано в одного перса т.е. без ШЕ ПП БД БИШОПА и прочих :)
Rubec вне форума   Ответить с цитированием
Старый 07.03.2008, 21:07   #285
Гость
 
Сообщений: n/a
По умолчанию АвтоСвип

Всем привет. Вот наконец доделал и протестил АвтоСвип.
Зацените мой первый скриптец. Если какие ошибки найдете, пишите.
Код:
//Автоматизация sweep'а by APXAHGEJI
//Свип производится тока при условии что моб был ,хоть один раз, ударен ВАМИ и
//находится в списке нужных мобов.
//Возможность работы нескольких одновременных скриптов
//Социальное действие YES - запусстить/приостановить запись/АвтоСвип мобов
//Социальное действие NO остановиться - завершить запись мобов и перейтии к АвтоСвип
//После того как скрипт запущен нажимаете Yes и атакуете по одному мобу каждого
//вида которых собираетесь спойлить. Атакуете до тех пор пока не появилась запись
//что моб записан. Для удобства процесс записи можно приостановить нажатие той же
//клавиши Yes. После того как все нужные мобы записаны жмакаете NO, запись мобов
//завершается, АвтоСвип запускается, можете приступать к спойлу. АвтоСвип можно
//приостановить нажав всю туже клавишу соцдействия Yes, но запись мобов под АвтоСвип
//не остановится, и снова активировав, все нужные мобы просвипятся.

Const
  Name='Yes';
  Sweep='2F 2A 00 00 00 00 00 00 00 00';
Var
  Timer: TTimer;
  N,M,i,NpcNum: Byte;
  X,Y,Z,CharID: Integer;
  NpcTypeID,TargetID: array of Integer;
  NeedSweep,Dead: array of Boolean;
  Switch,SaveID,HaveNpc,OffSweeper: Boolean;
//******************************************************************************
//                      Вызывается при включении скрипта
//******************************************************************************
Procedure Init;
begin
  N:= 1;
  M:= 0;
  Switch:= False;
  SaveID:= True;
  SetLength( NpcTypeID, N );
  SetLength( TargetID, N );
  Timer:=TTimer.Create(nil);
  Timer.OnTimer:=@Sweeper;
  Timer.Enabled:= False;
  Timer.Interval:= 500;//время задержки свипа
  Say('Введите 1 в чат, чтобы начать/приостановить');
  Say('запись мобов или АвтоСвип.');
  Say('Введите 2 в чат, чтобы завершить запись мобов');
  Say('и приступить к сполйу.');
end;
//******************************************************************************

//******************************************************************************
//                        Вызывается при выключении скрипта
//******************************************************************************
Procedure Free;
begin
  Timer.Free;
end;
//******************************************************************************

//******************************************************************************
//             Посылаем сообщение, которое видно только в окне бота
//******************************************************************************
Procedure Say(msg:string);
begin
  buf:=hstr('4A 00 00 00 00');
  WriteD(2);
  WriteS(Name);
  WriteS(msg);
  SendToClientEx(Name);
end;
//******************************************************************************

//******************************************************************************
//                     Проверка наличия ИД моба в массиве
//******************************************************************************
Procedure FindMob(ObjectID: Integer);
begin
  HaveNpc:= False;
  NpcNum:= M;
  For i:=0 to (M-1) do
   If (ObjectID=TargetID[i]) then begin
     NpcNum:= i;
     HaveNpc:= True;
     break;
   end Else
     If (TargetID[i]= 0) and (NpcNum = M) then NpcNum:= i;
end;
//******************************************************************************

//******************************************************************************
// Запуск свипа каждые n секунд (n= Timer.Interval)
//******************************************************************************
Procedure Sweeper(Sender: TObject);
begin
  OffSweeper:= True;
  For i:=0 to (M-1) do begin
    If NeedSweep[i] and Dead[i] then begin
      If Switch then begin
        buf:= #$04;
        WriteD(TargetID[i]);
        WriteD(X);
        WriteD(Y);
        WriteD(Z);
        WriteC(00);
        SendToServerEx(Name);
        buf:=HStr(Sweep);
        SendToServerEx(Name);
      end;
      exit;
    end;
    If (TargetID[i]<>0) then OffSweeper:= False;
  end;
  If OffSweeper then begin
    M:= 0;
    SetLength(TargetID, M);
    SetLength(NeedSweep, M);
    SetLength(Dead, M);
    Timer.Enabled:= False;
    exit;
  end;
end;
//******************************************************************************

//******************************************************************************
//     Вызывается при приходе каждого пакета, если скрипт включен
//******************************************************************************
Begin

  //****************************************************************************
  //Не обрабатываем пустые пакеты
  If pck='' then exit;
  //****************************************************************************

  //****************************************************************************
  //Если от сервака принят пакет UserInfo. Запоминаем собственный ИД.
  If FromServer and (ConnectName=Name) and (pck[1]=#$04) then CharID:= ReadD(18);
  //****************************************************************************

  //****************************************************************************
  //Переключение между записью ИД и АвтоСвипом
  If SaveID then begin
    //**************************************************************************
    //Делаем выборку нужных для свипа видов мобов
    //**************************************************************************
    if Switch then
      if FromServer and (ConnectName=Name) then
        if (pck[1]=#$05) and (ReadD(2)=CharID) then
          if (ReadD(6)<>TargetID[N-1]) then TargetID[N-1]:= ReadD(6);
        if (pck[1]=#$16) and (ReadD(2)=TargetID[N-1]) then
          if (ReadD(6)<> NpcTypeID[N-1]) then begin
            NpcTypeID[N-1]:= ReadD(6);
            Inc(N);
            SetLength( NpcTypeID, N );
            SetLength( TargetID, N );
            TargetID[N-1]:= TargetID[N-2];
            NpcTypeID[N-1]:= NpcTypeID[N-2];
            Say('Моб записан');
          end;
    //**************************************************************************
    //Управление записью мобов
    //**************************************************************************
    If FromClient and (ConnectName=Name) and (pck[1]=#$1B) then begin
      If (ReadD(2)=6) then
        if Switch then begin
          pck:='';
          Switch:= False;
          Say('Запись мобов приостановлена');
        end
        else begin
          pck:='';
          Switch:= True;
          Say('Начата запись мобов, атакуйте нужных мобов');
        end;
      If (ReadD(2)=5) then begin
        pck:='';
        Dec(N);
        SetLength(NpcTypeID, N);
        SetLength(TargetID, M);
        SetLength(NeedSweep, M);
        SetLength(Dead, M);
        SaveID:= False;
        Switch:= True;
        Say('Запись мобов завершена, АвтоСвип активирован');
        Say('Удачного спойла');
      end;
    end;
    //**************************************************************************
  end
  //****************************************************************************

  //****************************************************************************
  //Переходим от записи нужных мобов к АвтоСвипу
  Else begin
  //****************************************************************************

    //**************************************************************************
    //Записываем текущие координаты
    if FromClient and (ConnectName=Name) and (pck[1]=#$48) then begin
      X:= ReadD(2);
      Y:= ReadD(6);
      Z:= ReadD(10);
    end;
    //**************************************************************************

     //**************************************************************************
    //Анализ мобов :=))
    If FromServer and (ConnectName=Name) then begin
      //************************************************************************
      //Записываем всех атакованых нами мобов (пакет Attack, причем Attacker=CharID)
      If ((pck[1]= #$05) and (ReadD(2)= CharID)) then begin
        FindMob(ReadD(6));
        If not HaveNpc then
          If (NpcNum <> M) then begin
            TargetID[NpcNum]:= ReadD(6);
            NeedSweep[NpcNum]:= False;
            Dead[NpcNum]:= False
          end Else begin
            Inc(M);
            SetLength(TargetID, M);
            SetLength(NeedSweep, M);
            SetLength(Dead, M);
            TargetID[M-1]:= ReadD(6);
            NeedSweep[M-1]:= False;
            Dead[M-1]:= False;
            Timer.enabled:= True;
          end;
      end;
      //************************************************************************
      //Проверяем есть ли в списке мобы
      if (M <> 0) then begin
        //**********************************************************************
        //Проверяем тот ли вид моба атакован (пакет NpcInfo)
        If (pck[1]= #$16) then begin
          FindMob(ReadD(2));
          If HaveNpc and (not NeedSweep[NpcNum]) then begin
            For i:=0 to (N-1) do
              If (ReadD(6)= NpcTypeID[i]) then begin
                HaveNpc:= False;
                Break;
              end;
            If not HaveNpc then NeedSweep[NpcNum]:= True;
          end;
        end;
        //**********************************************************************
        //Записываем что атакованый моб умер (пакет Die, причем Sweepable=1)
        If (pck[1]= #$06) and (pck[22]= #$01) then begin
          FindMob(ReadD(2));
          If HaveNpc then Dead[NpcNum]:= True;
        end;
        //**********************************************************************
        //Удаляем записи об атакованом мобе (пакет DeleteObject)
        If (pck[1]= #$12) then  begin
          FindMob(ReadD(2));
          If HaveNpc then begin
            TargetID[NpcNum]:= 0;
            NeedSweep[NpcNum]:= False;
            Dead[NpcNum]:= False;
          end;
        end;
        //**********************************************************************
      end;
      //************************************************************************
    end;
    //**************************************************************************

    //**************************************************************************
    //Запускаем/приостанавливаем АвтоСвип
    //**************************************************************************
    If FromClient and (ConnectName=Name) and (pck[1]=#$1B) and (ReadD(2)=6) then
      if Switch then begin
        pck:='';
        Switch:= False;
        Say('АвтоСвип приостановлен');
      end
      else begin
        pck:='';
        Switch:= True;
        Say('АвтоСвип запущен');
      end;
    //**************************************************************************
  end;
  //****************************************************************************
End.
//******************************************************************************
  Ответить с цитированием
Старый 08.03.2008, 00:02   #286
Пользователь
 
Аватар для ASSA
 
Регистрация: 09.02.2008
Сообщений: 38
Сказал Спасибо: 1
Имеет 1 спасибку в 1 сообщении
ASSA
По умолчанию

Я оценил! ошибок вроде нет, все автоматизировано. Кстати я ничего не смыслю в програмировании=))) но скрипт правда качаственный :)
__________________
Пишите в асю если чего. 446-693-955
ASSA вне форума   Ответить с цитированием
Старый 11.03.2008, 05:13   #287
Рыцарь
 
Аватар для NLObP
 
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
NLObP пока неопределено
По умолчанию Re: ДА БУДЕТ БОТ!

Новая версия бота. Проверяет координату Z. Подрихтовал миникарту.
Код:
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

//***************************************************************
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
  //01=MoveBackwardToLocation:d(targetX)d(targetY)d(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.
__________________
| Для самых ленивый | Телепаты в отпуске |Мы работаем над этим |
Не умеешь - учись, не хочешь учиться - плати © Суровый Закон Жизни


NLObP вне форума   Ответить с цитированием
Старый 13.03.2008, 18:43   #288
Местный
 
Аватар для nezabudkin
 
Регистрация: 06.03.2008
Сообщений: 154
Сказал Спасибо: 46
Имеет 130 спасибок в 38 сообщенях
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.
nezabudkin вне форума   Ответить с цитированием
Старый 13.03.2008, 19:04   #289
Рыцарь
 
Аватар для NLObP
 
Регистрация: 25.02.2008
Адрес: г.Волгоград
Сообщений: 2,009
Сказал Спасибо: 1,285
Имеет 1,458 спасибок в 793 сообщенях
NLObP пока неопределено
По умолчанию Re:

Цитата:
Сообщение от nezabudkin
Ну все, Господа... Выкладываю свой собственный ботоскрипт- локомотив :D

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

Константы для ИЛ и С4

установить константы в зависимости от типа игры (С4 или Интерлюд)
//CreateItemBase
offs1=24; //16 для С4, 24 для IL
//InventoryUpdate
offs2=22; //14 для С4, 22 для IL
//UserInfo, основной цикл
offs3=48; //44 для С4, 48 для IL
//InventoryUpdate, основной цикл
offs4=41; //32 для С4, 41 для IL
//StatsUpdate
offs5=14; //одинаково для C4 и IL

Например в твоем случае
Код:
procedure UserInfo;            // обновление донных о себе
var                            // где-то тут что-то надо править чтобы в интерлюде работало
  i:word;
begin
  if InitMode then MyID:=ReadD(18);
  MyX:=ReadD(2);
  MyY:=ReadD(6);
  MyZ:=ReadD(10);
  i:=22;
  ReadS(i);
  i:=i+48; //<----------- 44 для С4, 48 для IL
  MyMaxHP:=ReadD(i);
  MyHP:=ReadD(i);
  MyMaxMP:=ReadD(i);
  MyMP:=ReadD(i);
  i:=515                  //<-------i+363;
  MyMaxCP:=ReadD(i);
  MyCP:=ReadD(i);
end;
Так и не смог моба в базу добавить (на интерлюде).
__________________
| Для самых ленивый | Телепаты в отпуске |Мы работаем над этим |
Не умеешь - учись, не хочешь учиться - плати © Суровый Закон Жизни


NLObP вне форума   Ответить с цитированием
Старый 13.03.2008, 21:48   #290
Пользователь
 
Аватар для ASSA
 
Регистрация: 09.02.2008
Сообщений: 38
Сказал Спасибо: 1
Имеет 1 спасибку в 1 сообщении
ASSA
По умолчанию

НАрод а можно ли сымитировать нажатие клавиш в л2пкх?
Например каждые 30 сек F2?
%)
__________________
Пишите в асю если чего. 446-693-955
ASSA вне форума   Ответить с цитированием
Ответ

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


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

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

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


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

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

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