package com.script;
 
	import com.script.data.Food; 
	import com.script.util.Stopwatch; 
	import com.script.util.XPTracker; 
	import java.awt.Graphics2D; 
	import java.util.Iterator; 
	import java.util.List; 
	import java.util.concurrent.TimeUnit; 
	import org.osbot.rs07.api.Camera; 
	import org.osbot.rs07.api.Combat; 
	import org.osbot.rs07.api.Dialogues; 
	import org.osbot.rs07.api.Equipment; 
	import org.osbot.rs07.api.Inventory; 
	import org.osbot.rs07.api.Mouse; 
	import org.osbot.rs07.api.Prayer; 
	import org.osbot.rs07.api.Skills; 
	import org.osbot.rs07.api.Tabs; 
	import org.osbot.rs07.api.Walking; 
	import org.osbot.rs07.api.def.ItemDefinition; 
	import org.osbot.rs07.api.map.Position; 
	import org.osbot.rs07.api.model.GroundItem; 
	import org.osbot.rs07.api.model.Item; 
	import org.osbot.rs07.api.model.NPC; 
	import org.osbot.rs07.api.model.Player; 
	import org.osbot.rs07.api.model.RS2Object; 
	import org.osbot.rs07.api.ui.EquipmentSlot; 
	import org.osbot.rs07.api.ui.Message; 
	import org.osbot.rs07.api.ui.PrayerButton; 
	import org.osbot.rs07.api.ui.Skill; 
	import org.osbot.rs07.api.ui.Tab; 
	import org.osbot.rs07.event.WalkingEvent;
 
	@org.osbot.rs07.script.ScriptManifest(author="SwiffyP", info="Dwarf cannon support. Kills specified targets. Great antiban.", name="AIOCannonKiller", version=0.3D, logo="https://i.gyazo.com/18548983784d507f8954aa270646fb08.jpg") 
	public class AIOCannonKiller extends org.osbot.rs07.script.Script 
	{ 
	  private Preferences preferences = new Preferences(); 
	  private XPTracker xpTrack; 
	   
	  public Preferences getPreferences() { return preferences; } 
	  
 
	  private NPC target; 
	   
	  private ScriptStatus status; 
	   
	  private com.script.gui.Gui gui; 
	  private java.awt.Font font; 
	  private long run_time; 
	  public boolean start; 
	  private Stopwatch talk_timer; 
	  private Stopwatch cannon_timer; 
	  private int ammunition_id; 
	  private GroundItem item_pickup; 
	  private String status_string = ""; 
	   
	  private Position start_pos; 
	  private int targetFindCounter; 
	  private boolean specialAttack; 
	  private static final Skill[] melee_combat_stats = { Skill.STRENGTH, Skill.ATTACK, Skill.DEFENCE }; 
	  private Position cannonPosition; 
	  private boolean fire_cannon; 
	  private boolean repair_cannon; 
	   
	  public AIOCannonKiller() 
	    throws InterruptedException 
	  { 
	    gui = new com.script.gui.Gui(this); 
	    gui.setVisible(true); 
	  } 
	   
	  public void onStart() 
	  { 
	    run_time = System.currentTimeMillis(); 
	    status = ScriptStatus.AWAIT_GUI_INPUT; 
	    font = new java.awt.Font("Serif", 1, 12); 
	    talk_timer = new Stopwatch().reset(); 
	    cannon_timer = new Stopwatch().reset(); 
	    xpTrack = new XPTracker(this, Skill.values()); 
	    xpTrack.start(); 
	    start_pos = myPlayer().getPosition(); 
	  } 
	  
 
	 
	  public void pause() 
	  { 
	    if ((getBot().getRandomExecutor().getTimeUntilBreak() <= 1) &&  
	      (pickupCannon())) { 
	      try { 
	        sleep(500L); 
	        while (myPlayer().isMoving()) { 
	          sleep(500L); 
	        } 
	        sleep(100L); 
	      } catch (InterruptedException e) { 
	        e.printStackTrace(); 
	      } 
	    } 
	  } 
	   
	  public void onMessage(Message m) 
	    throws InterruptedException 
	  { 
	    String msg = m.getMessage().toLowerCase(); 
	     
	    if (m.getType() == org.osbot.rs07.api.ui.Message.MessageType.PLAYER) 
	    { 
	      if ((msg.contains("bot")) &&  
	        (talk_timer.elapsed(60000L))) 
	      { 
	        String response = "Can't chat atm"; 
	        if (random(5) == 1) { 
	          response = "Can't talk atm"; 
	        } 
	        keyboard.typeString(response, true); 
	        talk_timer.reset(); 
	      } 
	       
	    } 
	    else if (m.getType() == org.osbot.rs07.api.ui.Message.MessageType.GAME) 
	    {
 
	      if (msg.equals("there is no ammo left in your quiver.")) { 
	        stop(); 
	        return; 
	      } 
	      
 
	      if (msg.equals("i can't reach that!")) { 
	        target = null; 
	        return; 
	      } 
	      
 
	      if (preferences.useDwarfCannon()) 
	      {
 
	        if (msg.equals("there isn't enough space to set up here.")) { 
	          preferences.setUseDwarfCannon(false); 
	          logger.debug("Could not setup cannon because the script was started in a bad place!"); 
	          walking.walk(start_pos); 
	          sleep(3000L); 
	          return; 
	        } 
	        
 
	        if (msg.equals("your cannon is out of ammo!")) { 
	          fire_cannon = true; 
	          return; 
	        } 
	        
 
	        if (msg.contains("you load the cannon")) { 
	          fire_cannon = false; 
	          return; 
	        } 
	        
 
	        if (msg.contains("cannon is already firing")) { 
	          fire_cannon = false; 
	          return; 
	        } 
	        
 
	        if (msg.contains("cannon has broken")) { 
	          repair_cannon = true; 
	          return; 
	        } 
	        
 
	        if (msg.contains("you repair your cannon")) { 
	          repair_cannon = false; 
	          return; 
	        } 
	        
 
	        if (msg.contains("you pick up the cannon")) { 
	          cannonPosition = null; 
	          return; 
	        } 
	      } 
	      
 
	      if (preferences.isNightmareZone()) { 
	        if (msg.contains("a surge of special attack power")) { 
	          specialAttack = true; 
	          return; 
	        } 
	         
	        if (msg.contains("surge of special attack power has ended")) { 
	          specialAttack = false; 
	          return; 
	        } 
	      } 
	    } 
	  } 
	   
	  public int onLoop() 
	    throws InterruptedException 
	  { 
	    if (!start) { 
	      status_string = "Waiting for GUI Input"; 
	      return 400; 
	    } 
	     
	    try 
	    { 
	      status = getStatus(); 
	      
 
	      if ((!settings.isRunning()) && (random(20) == 5) &&  
	        (settings.getRunEnergy() >= 40 + random(20))) { 
	        status_string = "Toggle Run"; 
	        settings.setRunning(true); 
	        sleep(random(100, 200)); 
	      } 
	      
 
	 
	      eat(false); 
	      
 
	      handlePrayer(); 
	      
 
	      if (!combat.isAutoRetaliateOn()) { 
	        status_string = "Activate Auto Retaliate"; 
	        combat.toggleAutoRetaliate(true); 
	      } 
	      
 
	      if (equipment.isWearingItem(EquipmentSlot.ARROWS)) { 
	        Item arrow = equipment.getItemInSlot(ARROWSslot); 
	        if (preferences.pickupAmmunition()) { 
	          ammunition_id = arrow.getId(); 
	          if (!preferences.getLoot().contains(arrow.getName())) { 
	            preferences.getLoot().add(arrow.getName()); 
	          } 
	        } 
	        if ((inventory.contains(new int[] { arrow.getId() })) &&  
	          (random(10) <= 2)) { 
	          status_string = "Equip Ammunition"; 
	          inventory.interact("Wield", new int[] { arrow.getId() }); 
	          sleep(random(500, 800)); 
	        } 
	      } 
	      
 
	 
	      if (preferences.lootAndBuryBones()) { 
	        if (!preferences.getLoot().contains("Bones")) { 
	          preferences.getLoot().add("Bones"); 
	        } 
	        if ((inventory.contains(new String[] { "Bones" })) &&  
	          (random(10) <= 2)) { 
	          status_string = "Bury Bones"; 
	          inventory.interact("Bury", new String[] { "Bones" }); 
	          sleep(random(500, 800)); 
	        } 
	      } 
	      
 
	 
	      if (preferences.isNightmareZone()) { 
	        handleBoosts(); 
	        
 
	        if (statBoostNeeded()) { 
	          status_string = "Drink Overload"; 
	          potionHandler("Overload ", "Drink"); 
	          sleep(350L); 
	        } 
	      } 
	       
	      if ((preferences.isCombatPotions()) && ( 
	        (getSkills().getDynamic(Skill.ATTACK) == getSkills().getStatic(Skill.ATTACK)) ||  
	        (getSkills().getDynamic(Skill.STRENGTH) == getSkills().getStatic(Skill.STRENGTH)))) { 
	        potionHandler("Combat potion", "Drink"); 
	        sleep(450L); 
	      } 
	      
 
	      if ((preferences.isSuperDefencePotions()) &&  
	        (getSkills().getDynamic(Skill.DEFENCE) == getSkills().getStatic(Skill.DEFENCE))) { 
	        potionHandler("Super defence", "Drink"); 
	        sleep(450L); 
	      } 
	       
	      String name; 
	      if (combat.isPoisoned()) { 
	        for (Item item : inventory.getItems()) 
	          if (item != null) 
	          { 
	            name = item.getName().toLowerCase(); 
	            if ((name.contains("poison")) || (name.contains("antidote"))) { 
	              String potionName = name.substring(0, name.length() - 3); 
	              potionHandler(potionName, "Drink"); 
	              break; 
	            } 
	          } 
	        sleep(450L); 
	      } 
	      
 
	      boolean hasEnergy = false; 
	       
	      String specWeapon = preferences.getSpecialWeapon(); 
	      if (specWeapon != null) { 
	        if ((specWeapon.equals("Magic shortbow")) || (specWeapon.equals("Magic shortbow (i)"))) { 
	          hasEnergy = combat.getSpecialPercentage() >= 55; 
	        } else if (specWeapon.equals("Toxic blowpipe")) { 
	          hasEnergy = combat.getSpecialPercentage() >= 50; 
	        } else if (specWeapon.equals("Dragon scimitar")) { 
	          hasEnergy = combat.getSpecialPercentage() >= 55; 
	        } else if (specWeapon.equals("Dragon dagger(p++)")) { 
	          hasEnergy = combat.getSpecialPercentage() >= 25; 
	        } else if (specWeapon.equals("Granite maul")) { 
	          hasEnergy = combat.getSpecialPercentage() >= 50; 
	        } else if (specWeapon.equals("Saradomin sword")) { 
	          hasEnergy = combat.getSpecialPercentage() >= 100; 
	        } else if (specWeapon.equals("Abyssal whip")) { 
	          hasEnergy = combat.getSpecialPercentage() >= 55; 
	        } 
	         
	        if (hasEnergy) if (!inventory.contains(new String[] { specWeapon })) { if (!equipment.contains(new String[] { specWeapon })) {} 
	          } else { if (random(5) != 1) break label965; 
	            specialAttack = true; 
	            break label965; 
	          } 
	        specialAttack = false; 
	         
	        label965: 
	        if (specialAttack) 
	        { 
	          status_string = "Special Attacks"; 
	           
	          if (equipment.isWearingItem(EquipmentSlot.WEAPON, preferences.getOrdinaryWeapon())) { 
	            if (inventory.contains(new String[] { specWeapon })) { 
	              inventory.interact("Wield", new String[] { specWeapon }); 
	              sleep(100 + random(80)); 
	            } 
	          } 
	          if (getTabs().getOpen() != Tab.ATTACK) { 
	            getTabs().open(Tab.ATTACK); 
	          } 
	           
	          if (!combat.isSpecialActivated()) { 
	            combat.toggleSpecialAttack(true); 
	            sleep(150 + random(100)); 
	          } 
	          
 
	        } 
	        else if (equipment.isWearingItem(EquipmentSlot.WEAPON, specWeapon)) { 
	          inventory.interact("Wield", new String[] { preferences.getOrdinaryWeapon() }); 
	          sleep(50 + random(80)); 
	        } 
	      } 
	      
 
	      switch (status) { 
	      case FIRE_CANNON:  
	        if (item_pickup.exists()) { 
	          status_string = "Pickup Item"; 
	          item_pickup.interact(new String[] { "Take" }); 
	          sleep(420 + random(80)); 
	          while (myPlayer().isMoving()) { 
	            sleep(450L); 
	          } 
	        } 
	        break; 
	       
	      case ANTIBAN:  
	        status_string = "Waiting for GUI Input"; 
	        break; 
	      case ATTACK_TARGET:  
	        status_string = "Closing Dialogue.."; 
	        if (dialogues.isPendingOption()) { 
	          dialogues.selectOption(random(2)); 
	        } else { 
	          dialogues.clickContinue(); 
	        } 
	        break; 
	       
	      case FIGHTING:  
	        status_string = "Attacking Target.."; 
	         
	        if (!validTarget(target)) { 
	          resetTarget();
 
	 
	        } 
	        else if (!myPlayer().isInteracting(target)) 
	        { 
	          if (random(5) == 1) { 
	            camera.toEntity(target); 
	          } else if (random(10) == 2) { 
	            camera.moveYaw(random(180)); 
	          } 
	           
	          target.interact(new String[] { "Attack" }); 
	           
	          int random = random(21); 
	          if (random <= 3) { 
	            mouse.moveOutsideScreen(); 
	          } else if (random <= 6) { 
	            mouse.move(random(300), random(300)); 
	          } else if (random <= 15) { 
	            mouse.move(random(30), random(30)); 
	          } 
	           
	          sleep(300L); 
	          while (myPlayer().isMoving()) { 
	            sleep(500L); 
	          } 
	           
	          handleSafeSpot(); 
	        } 
	        
 
	        break; 
	      case CLOSE_DIALOGUE:  
	        if (preferences.getTargets().size() > 0) { 
	          status_string = "Finding Target.."; 
	           
	          boolean flag = false; 
	          
 
	          if (myPlayer().isUnderAttack()) { 
	            for (NPC npc : npcs.getAll()) { 
	              if ((npc.isInteracting(myPlayer())) && (validTarget(npc))) { 
	                target = npc; 
	                flag = true; 
	                break; 
	              } 
	            } 
	          } 
	           
	          if (!flag) 
	          { 
	            NPC closest = null; 
	            int lowest = Integer.MAX_VALUE; 
	             
	            for (NPC npc : getNpcs().getAll()) { 
	              int distance = npc.getPosition().distance(myPosition()); 
	               
	              if (validTarget(npc)) 
	              {
 
	 
	                if (distance < lowest) { 
	                  closest = npc; 
	                  lowest = distance; 
	                } 
	              } 
	            } 
	            target = closest; 
	             
	            if (target != null) 
	            {
 
	              if (target.getDefinition().getName().toLowerCase().equals("sandy rocks")) 
	              { 
	                status_string = "Walking to crab.."; 
	                 
	                WalkingEvent walk = new WalkingEvent(target.getPosition()); 
	                walk.setMinDistanceThreshold(0); 
	                walk.setBreakCondition(new org.osbot.rs07.utility.Condition() 
	                { 
	                  public boolean evaluate() { 
	                    return myPosition().distance(target.getPosition()) <= 1; 
	                  } 
	                }); 
	                execute(walk); 
	                 
	                sleep(300L); 
	                while (myPlayer().isMoving()) { 
	                  sleep(500L); 
	                } 
	                 
	                sleep(random(1500, 2000)); 
	                 
	                if (!myPlayer().isUnderAttack()) { 
	                  status_string = "Aggression reset!"; 
	                  walking.webWalk(new Position[] { new Position(myPosition().getX() - 25 - random(5), myPosition().getY() + 25 + random(5), myPosition().getZ()) }); 
	                  while (myPlayer().isMoving()) { 
	                    sleep(500L); 
	                  } 
	                   
	                  walking.webWalk(new Position[] { start_pos }); 
	                  while (myPlayer().isMoving()) { 
	                    sleep(500L); 
	                  } 
	                } 
	                
 
	                target = null; 
	              } 
	               
	              targetFindCounter = 0; 
	            } 
	            else 
	            { 
	              if (targetFindCounter >= 5) { 
	                walking.webWalk(new Position[] { start_pos }); 
	                sleep(4000L); 
	                targetFindCounter = 0; 
	                getCamera().moveYaw(random(360)); 
	              } 
	               
	              targetFindCounter += 1; 
	            } 
	          } 
	        } 
	        else { 
	          status_string = "No targets specified in GUI. Auto-retaliate and/or Cannon dependant!"; 
	        } 
	         
	        break; 
	       
	      case FIND_TARGET:  
	        status_string = "Fighting.."; 
	         
	        handleSafeSpot(); 
	         
	        break; 
	      
 
	      case PICKUP_CANNON:  
	      case SETUP_CANNON:  
	        sleep(random(200)); 
	         
	        String action = ""; 
	         
	        if (status == ScriptStatus.FIRE_CANNON) { 
	          action = "Fire"; 
	          interactCannon(action, false); 
	        } else if (status == ScriptStatus.REPAIR_CANNON) { 
	          action = "Repair"; 
	          interactCannon(action, true); 
	        } 
	         
	        status_string = (action + " Cannon"); 
	         
	        sleep(300L); 
	        while (myPlayer().isMoving()) { 
	          sleep(500L); 
	        } 
	        sleep(700L); 
	         
	        break; 
	       
	      case PICKING_UP_LOOT:  
	        Item cannon_base = inventory.getItem(new int[] { 6 }); 
	        if (cannon_base != null) { 
	          status_string = "Set-up Cannon"; 
	          cannon_base.interact(new String[] { "Set-up" }); 
	          sleep(random(9000, 10000)); 
	           
	          interactCannon("Fire", false); 
	        } 
	         
	        break; 
	       
	      case REPAIR_CANNON:  
	        status_string = "Pick-up Cannon"; 
	         
	        if (inventory.getEmptySlots() >= 4) 
	        { 
	          if (pickupCannon()) 
	          { 
	            sleep(250L); 
	            while (myPlayer().isMoving()) { 
	              sleep(500L); 
	            } 
	            sleep(100L); 
	            preferences.setUseDwarfCannon(false); 
	            cannonPosition = null; 
	          } 
	          
 
	        } 
	        else if (preferences.getFood() != Food.NONE) { 
	          eat(true); 
	        } 
	        
 
	        break; 
	       
	      case AWAIT_GUI_INPUT:  
	        int s = random(0, 7); 
	        status_string = ("Performing Antiban number " + s); 
	        switch (s) { 
	        case 1:  
	          if (random(5) <= 2) { 
	            mouse.moveOutsideScreen(); 
	          } 
	          sleep(random(5500, 6000)); 
	          break; 
	        case 2:  
	          getCamera().moveYaw(random(360)); 
	          break; 
	        case 3:  
	          if (random(3) == 1) { 
	            StringBuilder sb = new StringBuilder(); 
	            for (int i = 0; i < random(15); i++) { 
	              char c = Static.CHARACTERS[random(Static.CHARACTERS.length - 1)]; 
	              sb.append(c); 
	            } 
	            getKeyboard().typeString(sb.toString(), false); 
	          } 
	          break; 
	        case 4:  
	          if (random(5) <= 2) { 
	            mouse.move(random(100), random(100)); 
	          } 
	          break; 
	        case 5:  
	          getTabs().open(Tab.ATTACK); 
	          break; 
	        case 6:  
	          getSkills().hoverSkill(Skill.forId(random(0, Skill.values().length - 1))); 
	          break; 
	        case 7:  
	          getTabs().open(Tab.forId(random(0, Tab.values().length - 1))); 
	        } 
	         
	         
	        sleep(random(500, 900)); 
	      } 
	    } 
	    catch (Exception e) { 
	      e.printStackTrace(); 
	    } 
	     
	    return 400 + random(80); 
	  } 
	  
 
	  public boolean validTarget(NPC npc) 
	  { 
	    boolean properTarget = false; 
	    for (String t : preferences.getTargets()) { 
	      if ((preferences.getTargets().contains("rock crab")) || (preferences.getTargets().contains("sand crab"))) { 
	        if ((npc.getDefinition().getName().toLowerCase().equals("sandy rocks")) || (npc.getDefinition().getName().toLowerCase().equals("sand crab"))) { 
	          properTarget = true; 
	        } 
	      } 
	      else if (npc.getDefinition().getName().toLowerCase().contains(t)) { 
	        properTarget = true; 
	        break; 
	      } 
	    } 
	    
 
	 
	    if (!properTarget) { 
	      return false; 
	    } 
	    
 
	    if (npc.getHealthPercent() <= 0) { 
	      return false; 
	    } 
	    
 
	    if (!npc.exists()) { 
	      return false; 
	    } 
	    
 
	    if (!npc.isOnScreen()) { 
	      return false; 
	    } 
	    
 
	    if (!map.canReach(npc)) { 
	      return false; 
	    } 
	    
 
	    if ((npc.getInteracting() != null) && (npc.getInteracting() != myPlayer())) { 
	      return false; 
	    } 
	     
	    return true; 
	  } 
	   
	  public void resetTarget() { 
	    target = null; 
	  } 
	   
	  public void eat(boolean force) throws InterruptedException 
	  { 
	    boolean flag = false; 
	    if (preferences.getFood() != Food.NONE) 
	    { 
	      if ((myPlayer().getHealthPercent() <= 50) || (force)) 
	      { 
	        if (inventory.contains(new int[] { preferences.getFood().item })) 
	        { 
	          status_string = "Eat"; 
	          inventory.interact("Eat", new int[] { preferences.getFood().item }); 
	          sleep(random(700, 900)); 
	           
	          flag = true; 
	        } 
	      } 
	    } 
	    
 
	 
	    if ((inventory.contains(new String[] { "Edible seaweed" })) &&  
	      (myPlayer().getHealthPercent() <= 80) && (random(20) <= 8)) 
	    { 
	      status_string = "Eat Seaweed"; 
	      inventory.interact("Eat", new String[] { "Edible seaweed" }); 
	      sleep(random(700, 900)); 
	       
	      flag = true; 
	    } 
	    
 
	 
	    if (!flag) 
	    {
 
	      if ((preferences.getOverheads() != com.script.data.Overheads.NONE) &&  
	        (preferences.usePrayerPots()) && (skills.getDynamic(Skill.PRAYER) > 0)) { 
	        return; 
	      } 
	      
 
	      if (myPlayer().getHealthPercent() <= 50) 
	      {
 
	        if (preferences.getTeleport() != com.script.data.SafetyTeleport.NONE) { if (inventory.contains(new int[] { preferences.getTeleport().getId() })) 
	          { 
	            status_string = "Teleport"; 
	             
	            if (pickupCannon()) { 
	              sleep(500L); 
	              while (myPlayer().isMoving()) { 
	                sleep(500L); 
	              } 
	              sleep(100L); 
	            } 
	             
	            inventory.interact("Break", new int[] { preferences.getTeleport().getId() }); 
	            sleep(8000L); 
	            stop(); 
	             
	            return; 
	          } 
	        } 
	        if (pickupCannon()) { 
	          sleep(500L); 
	          while (myPlayer().isMoving()) { 
	            sleep(500L); 
	          } 
	          sleep(100L); 
	        } 
	         
	        stop(); 
	      } 
	    } 
	  } 
	   
	  public void handlePrayer() 
	    throws InterruptedException 
	  { 
	    if ((preferences.usePrayerPots()) && (skills.getDynamic(Skill.PRAYER) <= 15 + random(5))) { 
	      status_string = "Drink Prayer Pot"; 
	      potionHandler("Prayer potion", "Drink"); 
	      sleep(200L); 
	    } 
	     
	    if ((preferences.getOverheads() != com.script.data.Overheads.NONE) &&  
	      (skills.getDynamic(Skill.PRAYER) > 0)) { 
	      status_string = "Activate Overhead Prayer"; 
	      switch (preferences.getOverheads()) { 
	      case PROTECT_FROM_MELEE:  
	        if ((!prayer.isActivated(PrayerButton.PROTECT_FROM_MAGIC)) && (prayer.hasLevelFor(PrayerButton.PROTECT_FROM_MAGIC))) { 
	          prayer.set(PrayerButton.PROTECT_FROM_MAGIC, true); 
	        } 
	        break; 
	      case PROTECT_FROM_MISSILES:  
	        if ((!prayer.isActivated(PrayerButton.PROTECT_FROM_MELEE)) && (prayer.hasLevelFor(PrayerButton.PROTECT_FROM_MELEE))) { 
	          prayer.set(PrayerButton.PROTECT_FROM_MELEE, true); 
	        } 
	        break; 
	      case PROTECT_FROM_MAGIC:  
	        if ((!prayer.isActivated(PrayerButton.PROTECT_FROM_MISSILES)) && (prayer.hasLevelFor(PrayerButton.PROTECT_FROM_MISSILES))) { 
	          prayer.set(PrayerButton.PROTECT_FROM_MISSILES, true); 
	        } 
	        break; 
	      } 
	       
	    } 
	  } 
	  
 
	  public void potionHandler(String potionName, String potionInteraction) 
	  { 
	    for (int i = 1; i <= 4; i++) { 
	      if (inventory.contains(new String[] { potionName + "(" + i + ")" })) { 
	        inventory.interact(inventory.getSlot(new String[] { potionName + "(" + i + ")" }), new String[] { potionInteraction }); 
	        break; 
	      } 
	    } 
	  } 
	   
	  public boolean pickupCannon() { 
	    if (preferences.useDwarfCannon()) { if (inventory.contains(new int[] { 12 })) if (inventory.contains(new int[] { 6 })) if (inventory.contains(new int[] { 8 })) if (inventory.contains(new int[] { 10 })) break label100; 
	      interactCannon("Pick-up", repair_cannon); 
	      cannonPosition = null; 
	      return true; } 
	    label100: 
	    return false; 
	  } 
	  
 
	  public void onPaint(Graphics2D g) 
	  { 
	    try 
	    { 
	      g.setFont(font); 
	      g.setColor(java.awt.Color.CYAN); 
	      
 
	      g.drawString("Version: " + getVersion(), 7, 42); 
	      g.drawString("Status: " + status_string, 7, 60); 
	      g.drawString("Runtime: " + getRuntimeFormat(System.currentTimeMillis() - run_time), 7, 80); 
	      
 
	      xpTrack.refresh(); 
	      int y = 110; 
	      for (Skill skill : Skill.values()) { 
	        if (xpTrack.getGainedExperience(skill) > 0) { 
	          int current = xpTrack.getSkillLevel(skill); 
	          int gained = xpTrack.getGainedLevels(skill); 
	           
	          y += 30; 
	          g.drawString(skill.name(), 4, y); 
	           
	          y += 20; 
	          g.drawString("Level: " + current + " (+" + gained + ")", 4, y); 
	           
	          y += 20; 
	          g.drawString("Remaining XP: " + insertCommasToNumber(new StringBuilder().append(xpTrack.getExperienceLeft(skill)).toString()) + " (" + timeTolevel(xpTrack.getTimeLeft(skill)) + ")", 4, y); 
	           
	          y += 20; 
	          g.drawString("Gained XP: " + insertCommasToNumber(new StringBuilder().append(xpTrack.getGainedExperience(skill)).toString()) + " (" + insertCommasToNumber(new StringBuilder().append((int)xpTrack.getExperiencePerHour(skill)).toString()) + " per hour)", 4, y); 
	        } 
	      } 
	    } 
	    catch (Exception e) 
	    { 
	      e.printStackTrace(); 
	    } 
	  } 
	   
	  private void interactCannon(String action, boolean broken_cannon) { 
	    RS2Object cannon = getCannonObject(broken_cannon); 
	    if (cannon != null) { 
	      cannon.interact(new String[] { action }); 
	    } 
	  } 
	   
	  private boolean repairCannon() 
	  { 
	    if (repair_cannon) { 
	      return true; 
	    } 
	     
	    RS2Object cannon = getCannonObject(true); 
	    if (cannon != null) { 
	      return cannon.hasAction(new String[] { "Repair" }); 
	    } 
	     
	    return false; 
	  } 
	   
	  private RS2Object getCannonObject(boolean broken_cannon) 
	  { 
	    if (cannonPosition == null) 
	    { 
	      RS2Object cannon = (RS2Object)objects.closest(new int[] { broken_cannon ? '㩄' : 6 }); 
	       
	      if (cannon != null) { 
	        cannonPosition = cannon.getPosition(); 
	      } 
	       
	      return cannon; 
	    } 
	    
 
	    for (RS2Object obj : objects.get(cannonPosition.getX(), cannonPosition.getY())) { 
	      if (broken_cannon) { 
	        if (obj.getId() == 14916) { 
	          return obj; 
	        } 
	      } 
	      else if (obj.getId() == 6) { 
	        return obj; 
	      } 
	    } 
	    
 
	 
	    return null; 
	  } 
	   
	  private void handleBoosts() throws InterruptedException 
	  { 
	    for (RS2Object obj : objects.getAll()) { 
	      if (obj != null) 
	      {
 
	 
	        if (obj.hasAction(new String[] { "Activate" })) { 
	          String name = obj.getName().toLowerCase(); 
	          if ((name.contains("zapper")) || (name.contains("recurrent")) || (name.contains("power"))) 
	          { 
	            status_string = "Activate Nightmare Zone Boost"; 
	             
	            if (random(5) == 1) { 
	              camera.toEntity(obj); 
	            } else if (random(10) == 2) { 
	              camera.moveYaw(random(180)); 
	            } 
	             
	            obj.interact(new String[] { "Activate" }); 
	             
	            sleep(200L); 
	            while (myPlayer().isMoving()) { 
	              sleep(500L); 
	            } 
	          } 
	        } 
	      } 
	    } 
	  } 
	   
	  private boolean statBoostNeeded() { 
	    for (Skill skill : melee_combat_stats) { 
	      if (getSkills().getDynamic(skill) == getSkills().getStatic(skill)) { 
	        return true; 
	      } 
	    } 
	    return false; 
	  } 
	   
	  private void handleSafeSpot() 
	  { 
	    if ((preferences.getSafeSpotPosition() != null) &&  
	      (!myPlayer().getPosition().equals(preferences.getSafeSpotPosition())) &&  
	      (myPlayer().isHitBarVisible())) { 
	      status_string = "Safe-spot setup.."; 
	       
	      WalkingEvent ev = new WalkingEvent(preferences.getSafeSpotPosition()); 
	      ev.setMinDistanceThreshold(1); 
	      ev.setBreakCondition(new org.osbot.rs07.utility.Condition() 
	      { 
	        public boolean evaluate() { 
	          return !myPlayer().isHitBarVisible(); 
	        } 
	      }); 
	      execute(ev); 
	    } 
	  } 
	  
 
	 
	  private ScriptStatus getStatus() 
	  { 
	    if ((dialogues.isPendingContinuation()) || (dialogues.isPendingOption())) { 
	      return ScriptStatus.CLOSE_DIALOGUE; 
	    } 
	    
 
	    if (random(45) == 5) { 
	      return ScriptStatus.ANTIBAN; 
	    } 
	     
	    if (preferences.useDwarfCannon()) 
	    { 
	      if (inventory.contains(new int[] { 12 })) if (inventory.contains(new int[] { 6 })) if (inventory.contains(new int[] { 8 })) { if (inventory.contains(new int[] { 10 })) { 
	              return ScriptStatus.SETUP_CANNON; 
	            } 
	          } 
	      if (repairCannon()) { 
	        return ScriptStatus.REPAIR_CANNON; 
	      } 
	      
 
	      if ((!fire_cannon) && (cannon_timer.elapsed(15000L)) &&  
	        (random(30) == 1)) 
	      { 
	        cannon_timer.reset(); 
	      } 
	      
 
	      if (fire_cannon) 
	      { 
	        if (inventory.getAmount(new int[] { 2 }) <= 0L) { 
	          return ScriptStatus.PICKUP_CANNON; 
	        } 
	         
	        return ScriptStatus.FIRE_CANNON; 
	      } 
	    } 
	    
 
	    if ((myPlayer().isInteracting(target)) || (myPlayer().isUnderAttack())) { 
	      return ScriptStatus.FIGHTING; 
	    } 
	    Iterator localIterator2; 
	    label481: 
	    for (Iterator localIterator1 = groundItems.getAll().iterator(); localIterator1.hasNext();  
	        
 
	        localIterator2.hasNext()) 
	    { 
	      GroundItem d = (GroundItem)localIterator1.next(); 
	      if ((!d.exists()) || (!d.isOnScreen()) || (!d.isVisible()) || (!map.canReach(d))) { 
	        break label481; 
	      } 
	       
	      localIterator2 = preferences.getLoot().iterator(); continue;String itemName = (String)localIterator2.next(); 
	      if (d.getName().equalsIgnoreCase(itemName)) { 
	        if (inventory.isFull()) { if (stackable(d.getDefinition())) { if (!inventory.contains(new int[] { d.getId() })) {} 
	          } 
	          
 
	        } 
	        else if ((!preferences.pickupAmmunition()) ||  
	          (d.getId() != ammunition_id) ||  
	          (d.getAmount() >= 3)) 
	        {
 
	          if ((!preferences.lootAndBuryBones()) ||  
	            (d.getId() != 526) ||  
	            (d.getPosition().distance(myPosition()) <= 1)) 
	          {
 
	 
	            if (d.getPosition().distance(myPosition()) <= 4) { 
	              item_pickup = d; 
	              return ScriptStatus.PICKING_UP_LOOT; 
	            } 
	          } 
	        } 
	      } 
	    } 
	     
	    if ((target == null) || (target.getHealthPercent() <= 0)) { 
	      return ScriptStatus.FIND_TARGET; 
	    } 
	    
 
	    return ScriptStatus.ATTACK_TARGET; 
	  } 
	   
	  private static enum ScriptStatus { 
	    AWAIT_GUI_INPUT,  
	    CLOSE_DIALOGUE,  
	    ANTIBAN,  
	    FIND_TARGET,  
	    ATTACK_TARGET,  
	    FIGHTING,  
	    PICKING_UP_LOOT,  
	    SETUP_CANNON,  
	    FIRE_CANNON,  
	    PICKUP_CANNON,  
	    REPAIR_CANNON; 
	  } 
	   
	  private final String insertCommasToNumber(String number) { 
	    return  
	    
 
	      insertCommasToNumber(number.substring(0, number.length() - 3)) + "," + number.substring(number.length() - 3, number.length()); 
	  } 
	   
	  private final String getRuntimeFormat(long totalPlayTime) { 
	    int sec = (int)(totalPlayTime / 1000L);int h = sec / 3600;int m = sec / 60 % 60;int s = sec % 60; 
	    return (h < 10 ? "0" + h : Integer.valueOf(h)) + ":" + (m < 10 ? "0" + m : Integer.valueOf(m)) + ":" + (s < 10 ? "0" + s : Integer.valueOf(s)); 
	  } 
	   
	  private final String timeTolevel(long duration) 
	  { 
	    String res = ""; 
	    long days = TimeUnit.MILLISECONDS.toDays(duration); 
	    long hours = TimeUnit.MILLISECONDS.toHours(duration) -  
	      TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration)); 
	    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) -  
	      TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS 
	      .toHours(duration)); 
	    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) -  
	      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS 
	      .toMinutes(duration)); 
	    if (days == 0L) { 
	      res = hours + ":" + minutes + ":" + seconds; 
	    } else { 
	      res = days + ":" + hours + ":" + minutes + ":" + seconds; 
	    } 
	    return res; 
	  } 
	   
	  public boolean stackable(ItemDefinition def) { 
	    String name = def.getName().toLowerCase(); 
	    if ((name.endsWith(" arrow")) || (name.endsWith(" bolts")) || (name.endsWith(" rune"))) { 
	      return true; 
	    } 
	    if (def.isNoted()) { 
	      return true; 
	    } 
	    return false; 
	  } 
	}