Universal script for auto charging icons for any tanks

A universal script for automated activation of tanks' buffs. The medium of charging can be either a pet or a character; in which case two tanks can charge off each other by controlling both of them.

The script can work for both, one tank (charge off a pet or off a mob) and two (charge off each other).

How it works: turns off the bot interface, puts on specific weapon used for charging (if any), starts hitting a pet (damage reflection is needed) or attacks itself with the second tank until it charges completely, puts on the sword + shield back (if any) and turns the bot interface back on (if necessary). Works with any tanks. Also, in the case of two tanks, at the beginning, it determines which one has lower cooldown as to charge this one first (Optimizing the whole process in case the script is restarted).

The code runs inside its own thread, making it easier to integrate in existing scripts. To configure it, just change the values of constants inside the procedure.

procedure IconAutouseThread();
const
// ----------------------     SETTINGS     ---------------------- 
  ENABLE_INTERFACE = False;               // whether to reactivate the interface after charging (True - yes, False - no)
  PET_ITEM_ID = 10426;                    // specify the item ID for the summon pet - Fenrir Necklace [id: 10426]  
  SECOND_TANK_NAME = 'Nickname';          // specify the nickname of the second tank to be charged about
  CHARGE_WEAPON_ID = 256;                 // specify the weapon ID to charge - Cestus [id: 256]
  SWORD_ID = 14120;                       // specify the main weapon ID 
  SHIELD_ID = 2498;                       // specify the shield 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 for setting variables depending on the class
  procedure SetVars();
  begin    
    if (E.GetUser.ClassID = 91) then begin  // if we are - Hell Knight, then
      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  // if we are - Phoenix Knight, then
      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  // if we are - Eva's Templar, then
      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 // if we are - Shillien Templar, then
      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 that determines which tank will use the icon first
  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;
  
  // procedure putting on the specified item by 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;

  // role-changing procedure for tanks
  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                                                       // run an endless loop so that the thread runs continuously
    SetVars();
    if (E.Status = lsOnline)                                                      // if we are in the game
    and (not (E.GetZoneType = ztPeace))                                           // and not in a peaceful zone
    and ((not E.GetUser.Buffs.ByID(icon_id, icon)) or (icon.EndTime < 15000)) then begin   // and the icon is not buffed or buff left < 15 sec, then
      
      if E.GetSkillList.ByID(icon_id, icon) and (icon.EndTime < 15000)            // if Icon cooldowns back after < 15 seconds (or is already ready)
      and E.GetSkillList.ByID(seed_id, seed) and (seed.EndTime = 0) then begin    // and seed isn't in cooldown, then 
      	if (not E.GetUser.Buffs.ByID(seed_id, trigger))                           // if we don’t have a charging buff
      	and (not E.GetUser.Buffs.ByID(trigger_id, trigger)) then begin 
      	  Engine.Msg('[IconAutouseThread]', E.GetUser.Name+': using a charging buff '+BaseSkillByID(seed_id, True), 0);  
      	  if E.UseSkill(seed) then Delay(E.GetUser.Cast.EndTime);                 // use a charging buff
        end;

        // 1st case: when the nickname of the 2nd tank was set and this tank in the line of sight are indicated
      	if (second_name <> '') and E.GetCharList.ByName(second_name, player) then begin
          target:= E.GetUser;                                                     // determine who needs to be attacked (in this case, our character)
          E2:= GetControl(second_name);                                           // determine the controller of the 2nd tank
          E2.FaceControl(0, False);                                               // turn off the interface to the 2nd tank
          EquipItem(CHARGE_WEAPON_ID, E2);                                        // if the 2nd tank has a weapon for charging and it is not worn, then we put on
          point:= CalcXYZ(E2.GetUser, target, -50, 0);                            // calculate the point next to the target
          if E2.DMoveTo(point.X, point.Y, point.Z) then Delay(500);               // run the 2nd tank to this point
      	  while ( (E.GetUser.Buffs.ByID(seed_id, trigger))
      	  or (E.GetUser.Buffs.ByID(trigger_id, trigger) and (trigger.Level < 3)) )// while the charging buff is hanging on us and its level is < 3
      	  and (target <> nil) and (not target.Dead) do begin                      // and the target exists and is not dead
      	    if (E2.GetUser.Dead) then break;                                      // if the 2nd tank is dead, we exit the cycle
      	    if (E2.GetUser.Target <> target) then                                 // if the 2nd tank has no target selected (our character)
              if E2.SetTarget(target) then Delay(500);                            // then we tell the 2nd tank to take our character to the target
            E2.Attack(true);                                                      // tell the second tank to attack our character
      	  end;  
      	  if (trigger.Level = 3) then begin                                       // if our character has accumulated charge level = 3
      	    while (icon.EndTime > 0) do Delay(500);                               // we wait until the icon exactly cooldowns back
      	    while (not E.GetUser.Buffs.ByID(icon_id, icon)) or (icon.EndTime < 50000) do begin        // until the icon buff is updated on us
      	      if (not E.GetUser.Buffs.ByID(trigger_id, trigger)) or (trigger.Level < 3) then Break;   // if the charge has flown - we exit the cycle
      	      if E.UseSkill(icon_id) then Delay(E.GetUser.Cast.EndTime);          // activate the icon and wait for the end of the cast
      	      Delay(500);
      	    end;
      	    Engine.Msg('[IconAutouseThread]', E.GetUser.Name+': icon activated '+BaseSkillByID(icon_id, True), 0);
      	    E2.DMoveTo(E2.GetUser.X+10, E2.GetUser.Y+10, E2.GetUser.Z+10);           // move the 2nd tank to the point next to it to cancel the attack
      	    EquipItem(SWORD_ID, E2);                                              // we tell the 2nd tank to put back the sword if necessary
      	    EquipItem(SHIELD_ID, E2);                                             // we tell the 2nd tank to put back the shield, if necessary
      	    E2.FaceControl(0, ENABLE_INTERFACE);                                  // turns on the interface of the 2nd tank (you can comment if you don't need it)
      	    Delay(5000);
      	    SwitchChars();                                                        // we call a procedure that changes characters in roles
          end;
      	end
      	else  
        // 2nd case: when we have a living pet called up or have an item to summon him
        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                                  // check if the pet is not called, then
            if E.UseItem(PET_ITEM_ID) then Delay(E.GetUser.Cast.EndTime);         // use the item to summon the pet and expect the end of the cast
          end;                                                                           
          target:= E.GetPetList.Items(0);                                         // determine who needs to be attacked (in this case, our pet)
          E.FaceControl(0, False);                                                // turns off the interface
          EquipItem(CHARGE_WEAPON_ID);                                            // if we have a weapon for charging and it is not worn, then we put on
          point:= CalcXYZ(E.GetUser, target, -50, 0);                             // calculate the point next to the target
          if E.DMoveTo(point.X, point.Y, point.Z) then Delay(500);                // run to this point
      	  while ( (E.GetUser.Buffs.ByID(seed_id, trigger))
      	  or (E.GetUser.Buffs.ByID(trigger_id, trigger) and (trigger.Level < 3)) )// while the charging buff is hanging on us and its level is <3
      	  and (target <> nil) and (not target.Dead) do begin  
      	    if (E.GetUser.Dead) then break;                                       // if we are dead we exit the cycle
      	    if (E.GetUser.Target <> target) then                                  // if pet is not in target
              if E.SetTarget(target) then Delay(500);                             // then take it to target                                   
            E.Attack(true);                                                       // attack pet while waiting for charging
      	  end; 
      	  if (trigger.Level = 3) then begin                                       // if we have accumulated charge level = 3
      	    while (icon.EndTime > 0) do Delay(500);                               // we wait until the icon exactly cooldowns back
      	    while (not E.GetUser.Buffs.ByID(icon_id, icon)) or (icon.EndTime < 50000) do begin        // until the icon buff is updated on us
      	      if (not E.GetUser.Buffs.ByID(trigger_id, trigger)) or (trigger.Level < 3) then Break;   // if the charge has flown - we exit the cycle
      	      if E.UseSkill(icon_id) then Delay(E.GetUser.Cast.EndTime);          // activate the icon and wait for the end of the cast
      	      Delay(500);
      	    end; 
      	    Engine.Msg('[IconAutouseThread]', E.GetUser.Name+': icon activated '+BaseSkillByID(icon_id, True), 0);
      	    E.DMoveTo(E.GetUser.X+10, E.GetUser.Y+10, E.GetUser.Z);               // cancel attack pet
      	    EquipItem(SWORD_ID);                                                  // put the sword back if necessary
      	    EquipItem(SHIELD_ID);                                                 // put the shield back if necessary
      	    E.FaceControl(0, ENABLE_INTERFACE);                                   // turn the interface back on (you can comment if you don't need it)
          end;
      	end
      	else
      	// 3rd case: just wait until the charge is full
      	begin
      	  if (trigger.Level = 3) then begin                                       // if we have accumulated charge level = 3
      	    if E.UseSkill(icon) then Delay(E.GetUser.Cast.EndTime);               // activate the icon
      	  end; 
      	end;
      end;
    end;
  end;
end;


begin
  Script.NewThread(@IconAutouseThread);   // start the thread for auto-charging icons
  // code...
  
  Delay(-1);
end.