Перейти к содержанию

Отдых в безопасной зоне на время рестарта и нехватки маны.


Рекомендуемые сообщения

Скрипт отходит на время рестарта в безопасную зону и после рестарта возвращается на спот. 

Так же следит за мп у критически важных персов (хилы, заливки, маги). Если мп мало (<20% у всех), то идет нв безопасную зону, где ждет регена.

Пока стоит в безопасной зоне - отбивается от агро-мобов, которые повисли на пати.

Поддерживает офф-пати сапорт. Как в случае защиты от агро-мобов на ресте, так и при контроле мп.

Скрипт должен запускаться на персе, по которому настроен ассист и фоллоу.

 

Настройка скрипта под себя:

1. Время рестарта. Задать в константе str_restart_time время, когда отходить на отдых перед рестартом с учетом своего часового пояса.

2. Запуск после рестарта. Задать в константа str_start_time время, когда возвращаться на спот после рестарта с учетом своего часового пояса.

3. Офф-пати персы. В массиве off_party_chars указать перечень персов, которые у вас вне пати. Если таких нет, то оставить массив пустым (const off_party_chars: array of string =   [];)

4. Критически важные персонажи, у которых мониторить уровень мп. Указать в массиве mp_critical список таких персонажей. 

5. Пусть на место отдыха. В процедуре MoveToSafeSpot() записать свои команды передвижения со спота в зону отдыха.

6. Возврат на спот. В процедуре MoveFromSafeSpot() записать свои команды возврата на спот из зоны отдыха.

 

P.S. В примере скрипта зона кача - круглая комната перед первым мостом в ЛОА. Отдых - в кишке наверх к хавлерам.

P.P.S. Процедура убивания агро-мобов плохо работает с магическими атаками мобов. Пока моб не подойдет и руками не стукнет свою цель, его не будут убивать. Особых проблем это не создает, но стоит иметь в виду.

 

uses SysUtils;

const str_restart_time: string = '16:55:00';
const str_start_time: string = '17:15:00';
const off_party_chars: array of string =   ['OffPartyEE', 'OffPartySE'];

const mp_critical: array of string =   ['OffPartyEE',
                                        'OffPartySE',
                                        'EE',
                                        'Mage1',
                                        'Mage2',
                                        'Mage3'];

var ct, restart_time, start_time: tDateTime;
  is_restarting, is_resting: boolean;
  cntr: TL2Control;
  normal_mana, i: integer;
  
//route from safe spot to combat zone
procedure MoveFromSafeSpot();
begin
  Engine.MoveTo(147080, 119400, -4304);
  Engine.MoveTo(147048, 119944, -4464);
  Engine.MoveTo(147240, 120536, -4640);
  Engine.MoveTo(147656, 121240, -4792);
end;

//route from combat zone to safe spot
procedure MoveToSafeSpot();
begin
  Engine.MoveTo(147624, 121240, -4792);
  Engine.MoveTo(147304, 120904, -4704);
  Engine.MoveTo(147032, 120248, -4536);
  Engine.MoveTo(147000, 119608, -4368);
  Engine.MoveTo(147016, 119224, -4248);
end;

//true if time d1 > d2
function compare_time(d1: TDateTime; d2: TDateTime): boolean;
var
  hour, minute, second, ms: word;
  c1, c2: tDateTime;
begin
  decodetime(d1, hour, minute, second, ms);
  c1 := encodeTime(hour, minute, second, ms);
  decodetime(d2, hour, minute, second, ms);
  c2 := encodeTime(hour, minute, second, ms);

  result := (c1 - c2) > 0;
  
end;

procedure Kill(Enemy: TL2Live);
begin
  if Enemy.dead then exit;
  Engine.SetTarget(Enemy);
  delay(300);
  while not Enemy.dead do begin
    //Engine.Attack();
    delay(500);
  end;
end;

function IsAgr(E:TL2Control; Mob: TL2Npc): boolean;
begin
  result := (Mob.AtkOID = E.GetUser().OID) and (not Mob.Dead);
end;

function AttackedBy(E:TL2Control): TL2Npc;
var
  moblist: TNpcList;
  cnt: integer;
begin
  result := nil;
  moblist := E.GetNpcList();
  
  for cnt:= 0 to moblist.Count-1 do begin
    if IsAgr(E, moblist(cnt)) then begin
      result:= moblist(cnt);
      break;
    end;
  end;
end;

procedure BeatOff();
var
  Enemy: TL2Live;
  i: integer;
  E: TL2Control;
  HaveMobsOnParty: boolean;
begin
  HaveMobsOnParty := true;
  while HaveMobsOnParty do begin
    HaveMobsOnParty := false;

    Enemy := AttackedBy(Engine);
    if (Enemy <> nil) then begin
      Kill(Enemy);
      HaveMobsOnParty := true;
    end;
    
    for i := 0 to Engine.GetParty().chars.count - 1 do begin
      E := GetControl(Engine.GetParty().chars.items(i).name);
      if Assigned(E) and (E.status = lsOnline) then begin
        Enemy := AttackedBy(E);
        if (Enemy <> nil) then begin
          Kill(Enemy);
          HaveMobsOnParty := true;
        end;
      end;
    end;

    for i := 0 to Length(off_party_chars) - 1 do begin
      E := GetControl(off_party_chars[i]);
      if Assigned(E) and (E.status = lsOnline) then begin
        Enemy := AttackedBy(E);
        if (Enemy <> nil) then begin
          Kill(Enemy);
          HaveMobsOnParty := true;
        end;
      end;
    end;
    
    delay(500);
  end;
end;

begin
  restart_time := strtotime(str_restart_time);
  start_time := strtotime(str_start_time);
  is_restarting:= false;
  is_resting := false;
  
  while true do begin
    ct := Now;
    
    if is_restarting and (engine.status = lsOnline) then begin
      if compare_time(ct, start_time) then begin
        is_restarting := false;
        MoveFromSafeSpot();
        Engine.FaceControl(0, true);
      end;
      if not compare_time(ct, start_time) then begin
        BeatOff();
      end;
    end;

    if not is_restarting then begin
      if compare_time(ct, restart_time) and
        not compare_time(ct, start_time) and
        (engine.status = lsOnline) then begin
        is_restarting := true;
        Engine.FaceControl(0, false);
        MoveToSafeSpot();
      end;
    end;

    if not is_resting and (Length(mp_critical) > 0) then begin
      normal_mana := Length(mp_critical);
      for i := 0 to Length(mp_critical) - 1 do begin
        cntr := GetControl(mp_critical[i]);
        if Assigned(cntr) and (cntr.status = lsOnline) then begin
          if (cntr.GetUser().MP < 20) then normal_mana := normal_mana - 1;
        end;
      end;

      if (normal_mana = 0) then begin
        Engine.EnterText('#mp low. resting.');
        is_resting := true;
        Engine.FaceControl(0, false);
        MoveToSafeSpot();
      end;
    end;

    if is_resting and (Length(mp_critical) > 0) and not is_restarting then begin
      BeatOff();
      normal_mana := 0;
      for i := 0 to Length(mp_critical) - 1 do begin
        cntr := GetControl(mp_critical[i]);
        if Assigned(cntr) and (cntr.status = lsOnline) then begin
          if (cntr.GetUser().MP > 80) then normal_mana := normal_mana + 1;
        end;
      end;
      if (normal_mana = Length(mp_critical)) then begin
        is_resting := false;
        MoveFromSafeSpot();
        Engine.FaceControl(0, true);
      end;
    end;
    delay(1000);
  end;
end.

 

  • Like 1
  • Thanks 1
Ссылка на сообщение
Поделиться на другие сайты

За труд лайк =) Есть такой еще скрипт https://adrenalinebot.com/ru/api/example/stop-farming-on-detecting-strangers-and-retreat-to-a-secluded-place. Там используют немного другую функцию на проверку агро:

function IsAgr(Mob: TL2Npc): boolean;
begin
  result:= (Mob.Target = User) and (not Mob.Dead);
end;

> Пока моб не подойдет и руками не стукнет свою цель, его не будут убивать
Возможно решает эту проблему, т.к. просто использует таргет вместо детектора атаки (но я не проверял) .

Вместо User подставить контроллер бота.

Я сам планирую написать похожий скрипт, как пример будет полезно, но я наверное буду делать на основе примера из адрика + на платном боте (с нормальным поиском путей).

Оффтоп: Есть еще у меня скрипт на автологин + детектор оффлайна (обычный метод не всегда работает) + простейший парсер текстовика с логинами и паролями, вроде работает пока +- нормально (пока тестирую его). Может выложу как доделаю.

Ссылка на сообщение
Поделиться на другие сайты

Проблема в том, что на этом сервере ты не можешь взять ассист с моба и его Mob.Target всегда пустой. Поэтому через айдишники сделано.

Ссылка на сообщение
Поделиться на другие сайты

Понятно, кстати я проверил на обычных мобах Wyrm в Dragon Valey, как только он кастует blaze, OID совпадает с моим, когда начинает бежать на меня не совпадает, когда бьет совпадает. 

Тестил вот так:

  while true do begin
    print(User.Target.name);
    print(User.Target.Cast.name);
    print(User.Target.AtkOID = User.OID);
    engine.delay(1000);
  end;

Атакует, не разу не бил
[3:53:22 PM] Wyrm
[3:53:22 PM] Blaze
[3:53:22 PM] true

Бежит на нас
[3:53:23 PM] Wyrm
[3:53:23 PM] Blessed Spiritshot (No-grade)
[3:53:23 PM] false
[3:53:24 PM] Wyrm
[3:53:24 PM] Blessed Spiritshot (No-grade)
[3:53:24 PM] false
[3:53:25 PM] Wyrm
[3:53:25 PM] Blessed Spiritshot (No-grade)
[3:53:25 PM] false
[3:53:26 PM] Wyrm
[3:53:26 PM] Blessed Spiritshot (No-grade)
[3:53:26 PM] false

Добежал и ударил
[3:53:27 PM] Wyrm
[3:53:27 PM] Blessed Spiritshot (No-grade)
[3:53:27 PM] true

Получается OID сбивается во время того как он бежит.

Возможно проблему можно решить, просто записывать в массив (допустим 100 элементов) OID мобов которые кастанули что-то на нас хотя-бы раз (если нет проблем с OID и он почти всегда уникальный) и сбрасывать его как только он заполнился или по таймеру. Ну соответственно включить проверку массива в IsAgr.

 

 

 

Изменено пользователем nixer
Ссылка на сообщение
Поделиться на другие сайты

Можно и так, да. Обычно мобы не кастуют больше 2-3 кастов. Бегут рукой бить. ))) так что обычно все ок работает и так. Ни разу не видел, чтоб пати упала. Если даже 1-2 нюка пропускают, то биш отхилит.

Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
×
×
  • Создать...