Jump to content

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


Glassman

Recommended Posts

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

Так же следит за мп у критически важных персов (хилы, заливки, маги). Если мп мало (<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
Link to comment
Share on other sites

За труд лайк =) Есть такой еще скрипт 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 подставить контроллер бота.

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

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

Link to comment
Share on other sites

Понятно, кстати я проверил на обычных мобах 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.

 

 

 

Edited by nixer
Link to comment
Share on other sites

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

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...