From b7b87335f8e923f38ab25681ffba121bbe82b286 Mon Sep 17 00:00:00 2001 From: See1Duck <61428716+see1duck@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:29:43 +0200 Subject: [PATCH 1/5] microbot: feat(LootingParameters): add eatFoodForSpace option and improve item looting logic --- .../util/grounditem/LootingParameters.java | 56 +---- .../util/grounditem/Rs2GroundItem.java | 208 ++++++++++-------- 2 files changed, 127 insertions(+), 137 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/LootingParameters.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/LootingParameters.java index 4314284409b..6884d96d363 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/LootingParameters.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/LootingParameters.java @@ -1,9 +1,14 @@ package net.runelite.client.plugins.microbot.util.grounditem; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter public class LootingParameters { private int minValue, maxValue, range, minItems, minQuantity, minInvSlots; - private boolean delayedLooting, antiLureProtection; + private boolean delayedLooting, antiLureProtection, eatFoodForSpace; private String[] names; private String[] ignoredNames; @@ -20,7 +25,7 @@ public class LootingParameters { * @param antiLureProtection A boolean indicating whether anti-lure protection should be enabled. */ public LootingParameters(int minValue, int maxValue, int range, int minItems, int minInvSlots, boolean delayedLooting, boolean antiLureProtection) { - setValues(minValue, maxValue, range, minItems, 1, minInvSlots, delayedLooting, antiLureProtection, null, null); + setValues(minValue, maxValue, range, minItems, 1, minInvSlots, delayedLooting, antiLureProtection,false, null, null); } /** @@ -36,7 +41,7 @@ public LootingParameters(int minValue, int maxValue, int range, int minItems, in * @param names The names of the items to be looted. */ public LootingParameters(int range, int minItems, int minQuantity, int minInvSlots, boolean delayedLooting, boolean antiLureProtection, String... names) { - setValues(0, 0, range, minItems, minQuantity, minInvSlots, delayedLooting, antiLureProtection, null, names); + setValues(0, 0, range, minItems, minQuantity, minInvSlots, delayedLooting, antiLureProtection,false, null, names); } /** @@ -54,10 +59,10 @@ public LootingParameters(int range, int minItems, int minQuantity, int minInvSlo */ public LootingParameters(int minValue, int maxValue, int range, int minItems, int minInvSlots, boolean delayedLooting, boolean antiLureProtection, String[] ignoredNames) { - setValues(minValue, maxValue, range, minItems, 1, minInvSlots, delayedLooting, antiLureProtection, ignoredNames, null); + setValues(minValue, maxValue, range, minItems, 1, minInvSlots, delayedLooting, antiLureProtection,false, ignoredNames, null); } - private void setValues(int minValue, int maxValue, int range, int minItems, int minQuantity, int minInvSlots, boolean delayedLooting, boolean antiLureProtection, String[] ignoredNames, String[] names) { + private void setValues(int minValue, int maxValue, int range, int minItems, int minQuantity, int minInvSlots, boolean delayedLooting, boolean antiLureProtection,boolean eatFoodForSpace, String[] ignoredNames, String[] names) { this.minValue = minValue; this.maxValue = maxValue; this.range = range; @@ -66,50 +71,11 @@ private void setValues(int minValue, int maxValue, int range, int minItems, int this.minInvSlots = minInvSlots; this.delayedLooting = delayedLooting; this.antiLureProtection = antiLureProtection; + this.eatFoodForSpace = eatFoodForSpace; this.ignoredNames = ignoredNames; this.names = names; } - // Getters - public int getMinValue() { - return minValue; - } - - public int getMaxValue() { - return maxValue; - } - - public int getRange() { - return range; - } - - public int getMinItems() { - return minItems; - } - - public int getMinQuantity() { - return minQuantity; - } - - public int getMinInvSlots() { - return minInvSlots; - } - - public boolean isDelayedLooting() { - return delayedLooting; - } - - public boolean isAntiLureProtection() { - return antiLureProtection; - } - - public String[] getIgnoredNames() { - return ignoredNames; - } - - public String[] getNames() { - return names; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/Rs2GroundItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/Rs2GroundItem.java index 2f804e4200d..436f22b4f24 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/Rs2GroundItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/grounditem/Rs2GroundItem.java @@ -32,6 +32,8 @@ */ @Slf4j public class Rs2GroundItem { + private static final int DESPAWN_DELAY_THRESHOLD_TICKS = 150; + private static boolean runWhilePaused(BooleanSupplier booleanSupplier) { final boolean paused = Microbot.pauseAllScripts.getAndSet(true); final boolean success = booleanSupplier.getAsBoolean(); @@ -173,7 +175,7 @@ public static RS2Item[] getAll(int range) { /** * Retrieves all RS2Item objects within a specified range of a WorldPoint, sorted by distance. - * + * * @param range The radius in tiles to search around the given world point * @param worldPoint The center WorldPoint to search around * @return An array of RS2Item objects found within the specified range, sorted by proximity @@ -288,131 +290,140 @@ private static boolean validateLoot(Predicate filter) { } - public static boolean lootItemBasedOnValue(LootingParameters params) { - final Predicate filter = groundItem -> groundItem.getGePrice() > params.getMinValue() && (groundItem.getGePrice() / groundItem.getQuantity()) < params.getMaxValue() && - groundItem.getLocation().distanceTo(Microbot.getClient().getLocalPlayer().getWorldLocation()) < params.getRange() && - (!params.isAntiLureProtection() || (params.isAntiLureProtection() && groundItem.getOwnership() == OWNERSHIP_SELF)); - List groundItems = getGroundItems().values().stream() - .filter(filter) - .collect(Collectors.toList()); - if (groundItems.size() < params.getMinItems()) return false; - if (params.isDelayedLooting()) { - // Get the ground item with the lowest despawn time - GroundItem item = groundItems.stream().min(Comparator.comparingInt(Rs2GroundItem::calculateDespawnTime)).orElse(null); - assert item != null; - if (calculateDespawnTime(item) > 150) return false; + + private static Predicate baseRangeAndOwnershipFilter(LootingParameters params) { + final WorldPoint me = Microbot.getClient().getLocalPlayer().getWorldLocation(); + final boolean anti = params.isAntiLureProtection(); + return gi -> + gi.getLocation().distanceTo(me) < params.getRange() && + (!anti || gi.getOwnership() == OWNERSHIP_SELF); + } + + private static boolean passesIgnoredNames(GroundItem gi, Set ignoredLower) { + if (ignoredLower == null || ignoredLower.isEmpty()) return true; + final String name = gi.getName() == null ? "" : gi.getName().trim().toLowerCase(); + for (String needle : ignoredLower) { + if (name.contains(needle)) return false; + } + return true; + } + + private static boolean ensureSpaceFor(GroundItem gi, LootingParameters params) { + if (Rs2Inventory.emptySlotCount() > params.getMinInvSlots()) { + return true; } - return runWhilePaused(() -> { - for (GroundItem groundItem : groundItems) { - if (groundItem.getQuantity() < params.getMinItems()) continue; - if (params.getIgnoredNames() != null && Arrays.stream(params.getIgnoredNames()).anyMatch(name -> groundItem.getName().trim().toLowerCase().contains(name.trim().toLowerCase()))) continue; - if (Rs2Inventory.emptySlotCount() < params.getMinInvSlots()) return true; - coreLoot(groundItem); + if (params.isEatFoodForSpace() && !canTakeGroundItem(gi) && !Rs2Inventory.getInventoryFood().isEmpty()) { + if (Rs2Player.eatAt(100)) { + Rs2Player.waitForAnimation(); } - return validateLoot(filter); - }); + } + return canTakeGroundItem(gi); } - public static boolean lootItemsBasedOnNames(LootingParameters params) { - final Predicate filter = groundItem -> - groundItem.getLocation().distanceTo(Microbot.getClient().getLocalPlayer().getWorldLocation()) < params.getRange() && - (!params.isAntiLureProtection() || (params.isAntiLureProtection() && groundItem.getOwnership() == OWNERSHIP_SELF)) && - Arrays.stream(params.getNames()).anyMatch(name -> groundItem.getName().trim().toLowerCase().contains(name.trim().toLowerCase())); - List groundItems = getGroundItems().values().stream() - .filter(filter) + private static boolean lootWithFilter( + LootingParameters params, + Predicate itemPredicate, + Set ignoredLower + ) { + final Predicate base = baseRangeAndOwnershipFilter(params); + final Predicate combined = base.and(itemPredicate); + + final List groundItems = getGroundItems().values().stream() + .filter(combined) .collect(Collectors.toList()); + if (groundItems.size() < params.getMinItems()) return false; + if (params.isDelayedLooting()) { - // Get the ground item with the lowest despawn time - GroundItem item = groundItems.stream().min(Comparator.comparingInt(Rs2GroundItem::calculateDespawnTime)).orElse(null); - assert item != null; - if (calculateDespawnTime(item) > 150) return false; + final GroundItem soonest = groundItems.stream() + .min(Comparator.comparingInt(Rs2GroundItem::calculateDespawnTime)) + .orElse(null); + if (soonest == null) return false; + if (calculateDespawnTime(soonest) > DESPAWN_DELAY_THRESHOLD_TICKS) return false; } return runWhilePaused(() -> { - for (GroundItem groundItem : groundItems) { - if (groundItem.getQuantity() < params.getMinQuantity()) continue; - if (Rs2Inventory.emptySlotCount() <= params.getMinInvSlots()) return true; - coreLoot(groundItem); + for (GroundItem gi : groundItems) { + if (gi.getQuantity() < params.getMinQuantity()) continue; + if (!passesIgnoredNames(gi, ignoredLower)) continue; + if (!ensureSpaceFor(gi, params)) continue; + coreLoot(gi); } - return validateLoot(filter); + return validateLoot(combined); }); } - /** - * Loots items based on their location and item ID. - * @param location - * @param itemId - * @return - */ - public static boolean lootItemsBasedOnLocation(WorldPoint location, int itemId) { - final Predicate filter = groundItem -> - groundItem.getLocation().equals(location) && groundItem.getItemId() == itemId; + private static Set toLowerTrimmedSet(String[] arr) { + if (arr == null || arr.length == 0) return Collections.emptySet(); + Set out = new HashSet<>(arr.length); + for (String s : arr) { + if (s != null) { + final String t = s.trim().toLowerCase(); + if (!t.isEmpty()) out.add(t); + } + } + return out; + } - List groundItems = getGroundItems().values().stream() - .filter(filter) - .collect(Collectors.toList()); - return runWhilePaused(() -> { - for (GroundItem groundItem : groundItems) { - coreLoot(groundItem); + public static boolean lootItemBasedOnValue(LootingParameters params) { + Predicate byValue = gi -> { + final int qty = Math.max(1, gi.getQuantity()); + final int price = gi.getGePrice(); + return price > params.getMinValue() && (price / qty) < params.getMaxValue(); + }; + + final Set ignoredLower = toLowerTrimmedSet(params.getIgnoredNames()); + return lootWithFilter(params, byValue, ignoredLower); + } + + public static boolean lootItemsBasedOnNames(LootingParameters params) { + final Set needles = toLowerTrimmedSet(params.getNames()); + if (needles.isEmpty()) return false; + + Predicate byNames = gi -> { + final String n = gi.getName() == null ? "" : gi.getName().trim().toLowerCase(); + for (String needle : needles) { + if (n.contains(needle)) return true; } - return validateLoot(filter); - }); + return false; + }; + + return lootWithFilter(params, byNames, /*ignoredLower*/ null); } - // Loot untradables public static boolean lootUntradables(LootingParameters params) { - final Predicate filter = groundItem -> - groundItem.getLocation().distanceTo(Microbot.getClient().getLocalPlayer().getWorldLocation()) < params.getRange() && - (!params.isAntiLureProtection() || (params.isAntiLureProtection() && groundItem.getOwnership() == OWNERSHIP_SELF)) && - !groundItem.isTradeable() && - groundItem.getId() != ItemID.COINS_995; - List groundItems = getGroundItems().values().stream() - .filter(filter) - .collect(Collectors.toList()); - if (groundItems.size() < params.getMinItems()) return false; - if (params.isDelayedLooting()) { - // Get the ground item with the lowest despawn time - GroundItem item = groundItems.stream().min(Comparator.comparingInt(Rs2GroundItem::calculateDespawnTime)).orElse(null); - assert item != null; - if (calculateDespawnTime(item) > 150) return false; - } + Predicate untradables = gi -> + !gi.isTradeable() && gi.getId() != ItemID.COINS_995; - return runWhilePaused(() -> { - for (GroundItem groundItem : groundItems) { - if (groundItem.getQuantity() < params.getMinQuantity()) continue; - if (Rs2Inventory.emptySlotCount() <= params.getMinInvSlots()) return true; - coreLoot(groundItem); - } - return validateLoot(filter); - }); + return lootWithFilter(params, untradables, /*ignoredLower*/ null); } - // Loot coins public static boolean lootCoins(LootingParameters params) { + Predicate coins = gi -> gi.getId() == ItemID.COINS_995; + return lootWithFilter(params, coins, /*ignoredLower*/ null); + } + + + /** + * Loots items based on their location and item ID. + * @param location + * @param itemId + * @return + */ + public static boolean lootItemsBasedOnLocation(WorldPoint location, int itemId) { final Predicate filter = groundItem -> - groundItem.getLocation().distanceTo(Microbot.getClient().getLocalPlayer().getWorldLocation()) < params.getRange() && - (!params.isAntiLureProtection() || (params.isAntiLureProtection() && groundItem.getOwnership() == OWNERSHIP_SELF)) && - groundItem.getId() == ItemID.COINS_995; + groundItem.getLocation().equals(location) && groundItem.getItemId() == itemId; + List groundItems = getGroundItems().values().stream() .filter(filter) .collect(Collectors.toList()); - if (groundItems.size() < params.getMinItems()) return false; - if (params.isDelayedLooting()) { - // Get the ground item with the lowest despawn time - GroundItem item = groundItems.stream().min(Comparator.comparingInt(Rs2GroundItem::calculateDespawnTime)).orElse(null); - assert item != null; - if (calculateDespawnTime(item) > 150) return false; - } return runWhilePaused(() -> { for (GroundItem groundItem : groundItems) { - if (groundItem.getQuantity() < params.getMinQuantity()) continue; - if (Rs2Inventory.emptySlotCount() <= params.getMinInvSlots()) return true; coreLoot(groundItem); } return validateLoot(filter); @@ -420,6 +431,7 @@ public static boolean lootCoins(LootingParameters params) { } + private static boolean hasLootableItems(Predicate filter) { List groundItems = getGroundItems().values().stream() .filter(filter) @@ -539,4 +551,16 @@ public static boolean loot(final WorldPoint worldPoint, final int itemId) public static Table getGroundItems() { return GroundItemsPlugin.getCollectedGroundItems(); } + + private static boolean canTakeGroundItem(GroundItem groundItem) { + int maxQuantity = groundItem.isStackable() ? 1 : groundItem.getQuantity(); + int availableSlots = Rs2Inventory.emptySlotCount(); + int quantity = Math.min(maxQuantity, availableSlots); + + if (quantity == 0 && groundItem.isStackable()) { + return Rs2Inventory.hasItem(groundItem.getId()); + } + + return quantity > 0; + } } From 8326671a5f920dddb554b5762baf892993cac3e2 Mon Sep 17 00:00:00 2001 From: See1Duck <61428716+see1duck@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:31:01 +0200 Subject: [PATCH 2/5] ShortestPathPlugin: fix(getClosestLocation): restore original bank item usage after pathfinding --- .../client/plugins/microbot/util/npc/Rs2NpcManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/npc/Rs2NpcManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/npc/Rs2NpcManager.java index 984407bdd07..134bbd3bc56 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/npc/Rs2NpcManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/npc/Rs2NpcManager.java @@ -291,6 +291,7 @@ public static List getNpcLocations(String npcName) * @param avoidWilderness Whether to avoid locations in the Wilderness. */ public static MonsterLocation getClosestLocation(String npcName, int minClustering, boolean avoidWilderness) { + boolean originalUseBankItems = ShortestPathPlugin.getPathfinderConfig().isUseBankItems(); ShortestPathPlugin.getPathfinderConfig().setUseBankItems(true); Microbot.log(Level.INFO,"Finding closest location for: " + npcName); @@ -332,6 +333,7 @@ public static MonsterLocation getClosestLocation(String npcName, int minClusteri } Microbot.log(Level.INFO,"Closest location for " + npcName + ": " + closest.getLocationName()); + ShortestPathPlugin.getPathfinderConfig().setUseBankItems(originalUseBankItems); return closest; } From 3e5467f060ad6c7803b72030bf47fe386074185f Mon Sep 17 00:00:00 2001 From: See1Duck <61428716+see1duck@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:31:31 +0200 Subject: [PATCH 3/5] microbot: fix(AttackNpcScript): improve antiban logic for combat state handling --- .../aiofighter/combat/AttackNpcScript.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/AttackNpcScript.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/AttackNpcScript.java index 85e8f4e964a..183c63ab82e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/AttackNpcScript.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/AttackNpcScript.java @@ -4,7 +4,6 @@ import net.runelite.api.Actor; import net.runelite.api.coords.WorldPoint; import net.runelite.api.gameval.ItemID; -import net.runelite.api.gameval.VarPlayerID; import net.runelite.client.plugins.microbot.Microbot; import net.runelite.client.plugins.microbot.Script; import net.runelite.client.plugins.microbot.aiofighter.AIOFighterConfig; @@ -18,6 +17,7 @@ import net.runelite.client.plugins.microbot.util.antiban.Rs2AntibanSettings; import net.runelite.client.plugins.microbot.util.antiban.enums.ActivityIntensity; import net.runelite.client.plugins.microbot.util.camera.Rs2Camera; +import net.runelite.client.plugins.microbot.util.combat.Rs2Combat; import net.runelite.client.plugins.microbot.util.coords.Rs2WorldArea; import net.runelite.client.plugins.microbot.util.inventory.Rs2Inventory; import net.runelite.client.plugins.microbot.util.npc.Rs2Npc; @@ -114,11 +114,19 @@ public void run(AIOFighterConfig config) { } messageShown = false; - - if (Rs2AntibanSettings.actionCooldownActive) { - AIOFighterPlugin.setState(State.COMBAT); - handleItemOnNpcToKill(config); - return; + if(Rs2AntibanSettings.antibanEnabled && Rs2AntibanSettings.actionCooldownChance > 0){ + if (Rs2AntibanSettings.actionCooldownActive) { + AIOFighterPlugin.setState(State.COMBAT); + handleItemOnNpcToKill(config); + return; + } + } + else { + if (Rs2Combat.inCombat()) { + AIOFighterPlugin.setState(State.COMBAT); + handleItemOnNpcToKill(config); + return; + } } if (!attackableNpcs.isEmpty()) { From 35fe1b179a7d3ab74b5dc5f63b6dc3666558fa7b Mon Sep 17 00:00:00 2001 From: See1Duck <61428716+see1duck@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:32:00 +0200 Subject: [PATCH 4/5] FlickerScript: fix(lastAttack): include NPC animation check for force reset condition --- .../plugins/microbot/aiofighter/combat/FlickerScript.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/FlickerScript.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/FlickerScript.java index 21310b3ba70..f468f0e2501 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/FlickerScript.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/combat/FlickerScript.java @@ -173,7 +173,7 @@ public void resetLastAttack(boolean forceReset) { AttackStyle attackStyle = AttackStyleMapper.mapToAttackStyle(style); if (m != null) { - if (forceReset && m.lastAttack <= 0) { + if (forceReset && (m.lastAttack <= 0 || npc.getAnimation() != -1)) { m.lastAttack = m.rs2NpcStats.getAttackSpeed(); } if ((!npc.isDead() && m.lastAttack <= 0) || From 89487b6604ecd1036b604319983f609ecede89ae Mon Sep 17 00:00:00 2001 From: See1Duck <61428716+see1duck@users.noreply.github.com> Date: Sat, 30 Aug 2025 05:34:27 +0200 Subject: [PATCH 5/5] LootScript: refactor: rollback all the unnecessary changes that broke the looting add: looting will now check the eat for space setting --- .../microbot/aiofighter/loot/LootScript.java | 232 +++++++++++------- 1 file changed, 149 insertions(+), 83 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/loot/LootScript.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/loot/LootScript.java index f3e4a0ce511..7f73dc7e2b7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/loot/LootScript.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/aiofighter/loot/LootScript.java @@ -1,84 +1,57 @@ package net.runelite.client.plugins.microbot.aiofighter.loot; import lombok.extern.slf4j.Slf4j; -import net.runelite.client.plugins.grounditems.GroundItem; import net.runelite.client.plugins.microbot.Microbot; import net.runelite.client.plugins.microbot.Script; import net.runelite.client.plugins.microbot.aiofighter.AIOFighterConfig; import net.runelite.client.plugins.microbot.aiofighter.AIOFighterPlugin; import net.runelite.client.plugins.microbot.aiofighter.enums.DefaultLooterStyle; import net.runelite.client.plugins.microbot.aiofighter.enums.State; -import net.runelite.client.plugins.microbot.util.antiban.Rs2AntibanSettings; +import net.runelite.client.plugins.microbot.util.grounditem.LootingParameters; import net.runelite.client.plugins.microbot.util.grounditem.Rs2GroundItem; import net.runelite.client.plugins.microbot.util.inventory.Rs2Inventory; -import net.runelite.client.plugins.microbot.util.inventory.Rs2RunePouch; -import net.runelite.client.plugins.microbot.util.magic.Runes; import net.runelite.client.plugins.microbot.util.player.Rs2Player; -import java.util.*; import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static net.runelite.api.TileItem.OWNERSHIP_SELF; -import static net.runelite.client.plugins.microbot.util.grounditem.Rs2GroundItem.*; @Slf4j public class LootScript extends Script { int minFreeSlots = 0; + public LootScript() { + + } + + public boolean run(AIOFighterConfig config) { + mainScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> { try { minFreeSlots = config.bank() ? config.minFreeSlots() : 0; if (!super.run()) return; if (!Microbot.isLoggedIn()) return; if (!config.toggleLootItems()) return; - if (Rs2AntibanSettings.actionCooldownActive) return; - if (AIOFighterPlugin.getState().equals(State.BANKING) || AIOFighterPlugin.getState().equals(State.WALKING)) { + if (AIOFighterPlugin.getState().equals(State.BANKING) || AIOFighterPlugin.getState().equals(State.WALKING)) return; + if (((Rs2Inventory.isFull() || Rs2Inventory.getEmptySlots() <= minFreeSlots) && !config.eatFoodForSpace()) || (Rs2Player.isInCombat() && !config.toggleForceLoot())) { return; } - if (Rs2Player.isInCombat() && !config.toggleForceLoot()) { - return; - } - - String[] itemNamesToLoot = lootItemNames(config); - final Predicate filter = groundItem -> - groundItem.getLocation().distanceTo(Microbot.getClient().getLocalPlayer().getWorldLocation()) < config.attackRadius() && - (!config.toggleOnlyLootMyItems() || groundItem.getOwnership() == OWNERSHIP_SELF) && - (shouldLootBasedOnName(groundItem, itemNamesToLoot) || shouldLootBasedOnValue(groundItem, config)); - List groundItems = getGroundItems().values().stream() - .filter(filter) - .collect(Collectors.toList()); - if (groundItems.isEmpty()) { - return; - } - if (config.toggleDelayedLooting()) { - groundItems.sort(Comparator.comparingInt(Rs2GroundItem::calculateDespawnTime)); + if (config.looterStyle().equals(DefaultLooterStyle.MIXED) || config.looterStyle().equals(DefaultLooterStyle.ITEM_LIST)) { + lootItemsOnName(config); } - //Pause other scripts before looting - Microbot.pauseAllScripts.getAndSet(true); - for (GroundItem groundItem : groundItems) { - if (Rs2Inventory.emptySlotCount() <= minFreeSlots && !canStackItem(groundItem)) { - Microbot.log("Unable to pick loot: " + groundItem.getName() + " making space"); - if (!config.eatFoodForSpace()) { - continue; - } - int emptySlots = Rs2Inventory.emptySlotCount(); - if (Rs2Player.eatAt(100)) { - sleepUntil(() -> emptySlots < Rs2Inventory.emptySlotCount(), 1200); - } - } - Microbot.log("Picking up loot: " + groundItem.getName()); - if (!waitForGroundItemDespawn(() -> interact(groundItem), groundItem)) { - return; - } + + if (config.looterStyle().equals(DefaultLooterStyle.GE_PRICE_RANGE) || config.looterStyle().equals(DefaultLooterStyle.MIXED)) { + lootItemsByValue(config); } - Microbot.log("Looting complete"); - Microbot.pauseAllScripts.compareAndSet(true, false); - } catch (Exception ex) { + lootBones(config); + lootAshes(config); + lootRunes(config); + lootCoins(config); + lootUntradeableItems(config); + lootArrows(config); + + } catch(Exception ex) { Microbot.log("Looterscript: " + ex.getMessage()); } @@ -86,54 +59,147 @@ public boolean run(AIOFighterConfig config) { return true; } - private boolean canStackItem(GroundItem groundItem) { - if (!groundItem.isStackable()) { - return false; - } - int runePouchRunes = Rs2RunePouch.getQuantity(groundItem.getItemId()); - if (runePouchRunes > 0 && runePouchRunes <= 16000 - groundItem.getQuantity()) { - return true; + private void lootArrows(AIOFighterConfig config) { + if (config.toggleLootArrows()) { + LootingParameters arrowParams = new LootingParameters( + config.attackRadius(), + 1, + 10, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + "arrow" + ); + arrowParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootItemsBasedOnNames(arrowParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } } - //TODO("Coal bag, Herb Sack, Seed pack") - return Rs2Inventory.contains(groundItem.getItemId()); } - private boolean shouldLootBasedOnValue(GroundItem groundItem, AIOFighterConfig config) { - if (config.looterStyle() != DefaultLooterStyle.GE_PRICE_RANGE && config.looterStyle() != DefaultLooterStyle.MIXED) - return false; - int price = groundItem.getGePrice(); - return config.minPriceOfItemsToLoot() <= price && price / groundItem.getQuantity() <= config.maxPriceOfItemsToLoot(); - } - - private boolean shouldLootBasedOnName(GroundItem groundItem, String[] itemNamesToLoot) { - return Arrays.stream(itemNamesToLoot).anyMatch(name -> groundItem.getName().trim().toLowerCase().contains(name.trim().toLowerCase())); - } - - private String[] lootItemNames(AIOFighterConfig config) { - ArrayList itemNamesToLoot = new ArrayList<>(); - if (config.toggleLootArrows()) { - itemNamesToLoot.add("arrow"); - } + private void lootBones(AIOFighterConfig config) { if (config.toggleBuryBones()) { - itemNamesToLoot.add("bones"); + LootingParameters bonesParams = new LootingParameters( + config.attackRadius(), + 1, + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + "bones" + ); + bonesParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootItemsBasedOnNames(bonesParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } } + } + + private void lootAshes(AIOFighterConfig config) { if (config.toggleScatter()) { - itemNamesToLoot.add(" ashes"); + LootingParameters ashesParams = new LootingParameters( + config.attackRadius(), + 1, + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + " ashes" + ); + ashesParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootItemsBasedOnNames(ashesParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } } + } + + // loot runes + private void lootRunes(AIOFighterConfig config) { if (config.toggleLootRunes()) { - itemNamesToLoot.add(" rune"); + LootingParameters runesParams = new LootingParameters( + config.attackRadius(), + 1, + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + " rune" + ); + runesParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootItemsBasedOnNames(runesParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } } + } + + // loot coins + private void lootCoins(AIOFighterConfig config) { if (config.toggleLootCoins()) { - itemNamesToLoot.add("coins"); + LootingParameters coinsParams = new LootingParameters( + config.attackRadius(), + 1, + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + "coins" + ); + coinsParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootCoins(coinsParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } } + } + + // loot untradeable items + private void lootUntradeableItems(AIOFighterConfig config) { if (config.toggleLootUntradables()) { - itemNamesToLoot.add("untradeable"); - itemNamesToLoot.add("scroll box"); + LootingParameters untradeableItemsParams = new LootingParameters( + config.attackRadius(), + 1, + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + "untradeable" + ); + untradeableItemsParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootUntradables(untradeableItemsParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } } - if (config.looterStyle().equals(DefaultLooterStyle.MIXED) || config.looterStyle().equals(DefaultLooterStyle.ITEM_LIST)) { - itemNamesToLoot.addAll(Arrays.asList(config.listOfItemsToLoot().trim().split(","))); + } + + private void lootItemsByValue(AIOFighterConfig config) { + LootingParameters valueParams = new LootingParameters( + config.minPriceOfItemsToLoot(), + config.maxPriceOfItemsToLoot(), + config.attackRadius(), + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems() + ); + valueParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootItemBasedOnValue(valueParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); + } + } + + private void lootItemsOnName(AIOFighterConfig config) { + LootingParameters valueParams = new LootingParameters( + config.attackRadius(), + 1, + 1, + minFreeSlots, + config.toggleDelayedLooting(), + config.toggleOnlyLootMyItems(), + config.listOfItemsToLoot().trim().split(",") + ); + valueParams.setEatFoodForSpace(config.eatFoodForSpace()); + if (Rs2GroundItem.lootItemsBasedOnNames(valueParams)) { + Microbot.pauseAllScripts.compareAndSet(true, false); } - return itemNamesToLoot.toArray(new String[0]); } public void shutdown() {