Универсальный скрипт для автоматической зарядки иконы для любых танков

Универсальный скрипт для авто зарядки иконы любым танкам. Может заряжаться как об пета, так и управлять двумя танками, чтобы те заряжались друг об друга. Выполнен в виде потока и легко встраиваем в уже существующие скрипты.

Скрипт может работать как для одного танка (заряжается об пета или от мобов) так и для двух (заряжают друг друга).

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

Код специально выполнен в виде одной процудеры, вызываемой в потоке, чтобы его можно было очень легко встроить в любой Ваш скрипт. Для настройки достаточно изменить значения констант внутри процедуры.

procedure IconAutouseThread();
const
// ----------------------     НАСТРОЙКИ     ---------------------- 
  ENABLE_INTERFACE = False;               // активировать ли обратно интерфейс после зарядки (True - да, False - нет)
  PET_ITEM_ID = 10426;                    // указываем ID предмета для сумона пета - Fenrir Necklace [id: 10426]  
  SECOND_TANK_NAME = 'Nickname';          // указываем ник второго танка, об которого нужно заряжаться
  CHARGE_WEAPON_ID = 256;                 // указываем ID оружия для зарядки - Cestus [id: 256]
  SWORD_ID = 14120;                       // указываем ID основного оружия 
  SHIELD_ID = 2498;                       // указываем ID щита
var   
  second_name: string;
  seed_id, icon_id, trigger_id: cardinal;
  seed, icon: TL2skill;
  trigger: TL2Buff;
  E, E2: TL2Control;
  player: TL2Char;
  target: TL2Live;
  item: TL2Item;
  point: TXYZ;
  
  // процедура настройки переменных в зависимости от профы
  procedure SetVars();
  begin    
    if (E.GetUser.ClassID = 91) then begin  // если мы - Hell Knight, то
      seed_id:= 761;                        // skill Seed of Revenge [id: 761]
      icon_id:= 762;                        // skill Insane Crusher [id: 762]
      trigger_id:= 5561;                    // buff Seed of Revenge [id: 5561]
    end; 
    if (E.GetUser.ClassID = 90) then begin  // если мы - Phoenix Knight, то
      seed_id:= 784;                        // skill Spirit of Phoenix [id: 784]
      icon_id:= 785;                        // skill Flame Icon [id: 785]
      trigger_id:= 5562;                    // buff Spirit of Phoenix [id: 5562]
    end; 
    if (E.GetUser.ClassID = 99) then begin  // если мы - Eva's Templar, то
      seed_id:= 786;                        // skill Eva's Will [id: 786]
      icon_id:= 787;                        // skill Touch of Eva [id: 787]
      trigger_id:= 5563;                    // buff Eva's Will [id: 5563]
    end;  
    if (E.GetUser.ClassID = 106) then begin // если мы - Shillien Templar, то
      seed_id:= 788;                        // skill Pain of Shilen [id: 788] 
      icon_id:= 789;                        // skill Spirit of Shilen [id: 789]
      trigger_id:= 5564;                    // buff Pain of Shillien [id: 5564]
    end;     
  end;
     
  // процедура, определяющая кто из танков будет первым использовать икону
  procedure Init();
  var skill: TL2Skill; cd: cardinal;
  begin
    if (LanguageID = 1) then
      Engine.Msg('AdrenalineBot.com', 'покупка ключей к боту, розыгрыши бесплатных ключей, бесплатные скрипты и многое другое!', $0045FF)
    else
      Engine.Msg('AdrenalineBot.com', 'selling bot keys, free keys lottery, free scripts and much more!', $0045FF);      
    if (GetControl(SECOND_TANK_NAME) = nil) then begin
      E:= Engine;
      second_name:= SECOND_TANK_NAME;
    end else begin  
      E:= Engine;  
      SetVars();    
      if E.GetSkillList.ByID(icon_id, skill) then cd:= skill.EndTime;
      E:= GetControl(SECOND_TANK_NAME);
      SetVars();  
      if E.GetSkillList.ByID(icon_id, skill) then begin
        if (cd > skill.EndTime) then begin 
          E:= GetControl(SECOND_TANK_NAME);
          second_name:= User.Name;
        end else begin
          E:= Engine;
          second_name:= SECOND_TANK_NAME; 
        end;
      end; 
    end; 
  end;
  
  // процедура, надевающая указанный итем по ID
  procedure EquipItem(item_id: integer; Control: TL2Control = nil);
  var item: TL2Item;
  begin
    if (Control = nil) then Control:= E;  
    {while (Control.GetInventory.User.ByID(item_id, item) and (not item.Equipped)) do begin
      if Control.UseItem(item) then Delay(1000);
    end;}        
    if Control.GetInventory.User.ByID(item_id, item) and (not item.Equipped) then
      if Control.UseItem(item) then Delay(1000);  
  end;

  // процедура, меняющая танков ролями
  procedure SwitchChars();
  begin                  
    if (E = Engine) then begin
      E:= GetControl(SECOND_TANK_NAME);
      second_name:= User.Name;
    end else begin
      E:= Engine;   
      second_name:= SECOND_TANK_NAME;
    end;
  end;

begin
  Init();
  while Delay(500) do begin                                                       // запускаем бесконечный цикл, чтобы поток работал постоянно
    SetVars();
    if (E.Status = lsOnline)                                                      // если мы в игре
    and (not (E.GetZoneType = ztPeace))                                           // и не в мирной зоне
    and ((not E.GetUser.Buffs.ByID(icon_id, icon)) or (icon.EndTime < 15000)) then begin   // и икона не бафнута или бафу осталось < 15 сек, то
      
      if E.GetSkillList.ByID(icon_id, icon) and (icon.EndTime < 15000)            // если скил иконы откатится < чем через 15 сек (или уже готов)
      and E.GetSkillList.ByID(seed_id, seed) and (seed.EndTime = 0) then begin    // и PoS не в откате, то 
      	if (not E.GetUser.Buffs.ByID(seed_id, trigger))                           // если на нас нет бафа зарядки
      	and (not E.GetUser.Buffs.ByID(trigger_id, trigger)) then begin 
      	  Engine.Msg('[IconAutouseThread]', E.GetUser.Name+': бафаю зарядку '+BaseSkillByID(seed_id, True), 0);  
      	  if E.UseSkill(seed) then Delay(E.GetUser.Cast.EndTime);                 // то бафаем его
        end;

        // 1 случай: когда указан никнейм 2го танка и этот танк а зоне видимости
      	if (second_name <> '') and E.GetCharList.ByName(second_name, player) then begin
          target:= E.GetUser;                                                     // определяем, кого нужно атаковать (в данном случае - наш персонаж)
          E2:= GetControl(second_name);                                           // определяем контроллер 2го танка 
          E2.FaceControl(0, False);                                               // выключаем интерфейс 2му танку
          EquipItem(CHARGE_WEAPON_ID, E2);                                        // если у 2го танка есть оружие для зарядки и оно не надето - то надеваем
          point:= CalcXYZ(E2.GetUser, target, -50, 0);                            // вычисляем точку рядом с целью
          if E2.DMoveTo(point.X, point.Y, point.Z) then Delay(500);               // бежим 2ым танком в эту точку
      	  while ( (E.GetUser.Buffs.ByID(seed_id, trigger))
      	  or (E.GetUser.Buffs.ByID(trigger_id, trigger) and (trigger.Level < 3)) )// пока на нас висит баф зарядки и его уровень < 3 
      	  and (target <> nil) and (not target.Dead) do begin                      // и целью существует и не мертва
      	    if (E2.GetUser.Dead) then break;                                      // если 2ой танк умер - выходим из цикла
      	    if (E2.GetUser.Target <> target) then                                 // если у 2го танка не выбрана цель (наш персонаж) 
              if E2.SetTarget(target) then Delay(500);                            // то говорим 2му танку взять нашего персонажа в таргет
            E2.Attack(true);                                                      // говорим 2му танку атаковать нашего персонажа
      	  end;  
      	  if (trigger.Level = 3) then begin                                       // если наш персонаж накопил уроень зарядки = 3
      	    while (icon.EndTime > 0) do Delay(500);                               // ждем, пока скил иконы точно откатится
      	    while (not E.GetUser.Buffs.ByID(icon_id, icon)) or (icon.EndTime < 50000) do begin        // пока на нас не обновится баф иконы
      	      if (not E.GetUser.Buffs.ByID(trigger_id, trigger)) or (trigger.Level < 3) then Break;   // если зарядка слетела - выходим из цикла
      	      if E.UseSkill(icon_id) then Delay(E.GetUser.Cast.EndTime);          // активируем икону и ждем окончания каста
      	      Delay(500);
      	    end;
      	    Engine.Msg('[IconAutouseThread]', E.GetUser.Name+': икона активирована '+BaseSkillByID(icon_id, True), 0);
      	    E2.DMoveTo(E2.GetUser.X+10, E2.GetUser.Y+10, E2.GetUser.Z+10);           // двигаемся 2ым танком в точку рядом с ним, чтобы прекатить атаку
      	    EquipItem(SWORD_ID, E2);                                              // говорим 2му танку надеть обратно меч, если нужно
      	    EquipItem(SHIELD_ID, E2);                                             // говорим 2му танку надеть обратно щит, если нужно  
      	    E2.FaceControl(0, ENABLE_INTERFACE);                                  // включаем интерфейс 2му танку (можно закоментировать если не нужно)
      	    Delay(5000);
      	    SwitchChars();                                                        // вызываем процедуру, которая меняет персонажей ролями
          end;
      	end
      	else  
        // 2 случай: когда у нас призван живой пет или есть предмет для его призыва
        if ((E.GetPetList.Count > 0) and (not E.GetPetList.Items(0).Dead))
        or (E.GetInventory.User.ByID(PET_ITEM_ID, item)) then begin    
          if (E.GetPetList.Count = 0) then begin                                  // проверяем, если пет не вызван, то
            if E.UseItem(PET_ITEM_ID) then Delay(E.GetUser.Cast.EndTime);         // используем предмет для призыва пета и ожидаем окончания каста
          end;                                                                           
          target:= E.GetPetList.Items(0);                                         // определяем, кого нужно атаковать (в данном случае - нашего пета) 
          E.FaceControl(0, False);                                                // выключаем интерфейс
          EquipItem(CHARGE_WEAPON_ID);                                            // если у нас есть оружие для зарядки и оно не надето - то надеваем  
          point:= CalcXYZ(E.GetUser, target, -50, 0);                             // вычисляем точку рядом с целью
          if E.DMoveTo(point.X, point.Y, point.Z) then Delay(500);                // бежим в эту точку
      	  while ( (E.GetUser.Buffs.ByID(seed_id, trigger))
      	  or (E.GetUser.Buffs.ByID(trigger_id, trigger) and (trigger.Level < 3)) )// пока на нас висит баф зарядки и его уровень < 3 
      	  and (target <> nil) and (not target.Dead) do begin  
      	    if (E.GetUser.Dead) then break;                                       // если мы умерли - выходим из цикла
      	    if (E.GetUser.Target <> target) then                                  // если пет не в таргете
              if E.SetTarget(target) then Delay(500);                             // то берем его в таргет                                   
            E.Attack(true);                                                       // атакуем пета в ожидании зарядки
      	  end; 
      	  if (trigger.Level = 3) then begin                                       // если мы накопили уровень зарядки = 3   
      	    while (icon.EndTime > 0) do Delay(500);                               // ждем, пока скил иконы точно откатится 
      	    while (not E.GetUser.Buffs.ByID(icon_id, icon)) or (icon.EndTime < 50000) do begin        // пока на нас не обновится баф иконы
      	      if (not E.GetUser.Buffs.ByID(trigger_id, trigger)) or (trigger.Level < 3) then Break;   // если зарядка слетела - выходим из цикла
      	      if E.UseSkill(icon_id) then Delay(E.GetUser.Cast.EndTime);          // активируем икону и ждем окончания каста
      	      Delay(500);
      	    end; 
      	    Engine.Msg('[IconAutouseThread]', E.GetUser.Name+': икона активирована '+BaseSkillByID(icon_id, True), 0);
      	    E.DMoveTo(E.GetUser.X+10, E.GetUser.Y+10, E.GetUser.Z);               // прекращаем атаку пета 
      	    EquipItem(SWORD_ID);                                                  // надеваем обратно меч, если нужно
      	    EquipItem(SHIELD_ID);                                                 // надеваем обратно щит, если нужно   
      	    E.FaceControl(0, ENABLE_INTERFACE);                                   // включаем интерфейс обратно (можно закоментировать если не нужно)
          end;
      	end
      	else
      	// 3 случай: просто ждем пока зарядка набьется сама
      	begin
      	  if (trigger.Level = 3) then begin                                       // если мы накопили уровень зарядки = 3   
      	    if E.UseSkill(icon) then Delay(E.GetUser.Cast.EndTime);               // активируем икону
      	  end; 
      	end;
      end;
    end;
  end;
end;


begin
  Script.NewThread(@IconAutouseThread);   // запускаем поток на автозарядку иконы
  // code...
  
  Delay(-1);
end.