From f39633b9acf4f9442797cba06a05f6c3b385c76c Mon Sep 17 00:00:00 2001 From: infuse21 Date: Sun, 5 Jul 2026 17:14:20 +0100 Subject: [PATCH 1/2] Clean up config descriptions to be clearer and reorganized Consolidate potion config by potion type instead of separate dose entries. Withdraw higher-dose potions first and drink lower-dose potions first. Add optional potion drinking at configured run energy some other stuff should be better --- .../microbot/agility/AgilityScript.java | 8 +- .../agility/AgilitySupplyManager.java | 239 +++++++++++++++--- .../microbot/agility/MicroAgilityConfig.java | 165 +++++++----- .../microbot/agility/MicroAgilityPlugin.java | 29 ++- .../agility/enums/AgilityPotionOption.java | 67 ++++- 5 files changed, 399 insertions(+), 109 deletions(-) diff --git a/src/main/java/net/runelite/client/plugins/microbot/agility/AgilityScript.java b/src/main/java/net/runelite/client/plugins/microbot/agility/AgilityScript.java index 30d55260e8..4c507e6966 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/agility/AgilityScript.java +++ b/src/main/java/net/runelite/client/plugins/microbot/agility/AgilityScript.java @@ -177,9 +177,13 @@ public boolean run() if (!hasRequiredLevel) { + if (supplyManager.shouldWalkToCourseStartForSummerPie(courseHandler, playerWorldLocation, currentObstacleIndex) + && courseHandler.handleCourseActions(playerWorldLocation)) + { + return; + } Microbot.log("Early return: Required level not met"); - Microbot.showMessage("You do not have the required level for this course."); - Rs2Player.logout(); + plugin.notifyUser("Your Agility level is too low for " + config.agilityCourse().getTooltip() + ". Select another course, or enable summer pies if a +5 boost is enough."); shutdown(); return; } diff --git a/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java b/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java index f1dfb06326..8f8709bea9 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java +++ b/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java @@ -51,13 +51,6 @@ public class AgilitySupplyManager GRACEFUL_GLOVES, GRACEFUL_BOOTS }; - private static final int[] STAMINA_POTION_IDS = { - ItemID._4DOSESTAMINA, - ItemID._3DOSESTAMINA, - ItemID._2DOSESTAMINA, - ItemID._1DOSESTAMINA - }; - private final MicroAgilityPlugin plugin; private final MicroAgilityConfig config; private final BooleanSupplier shuttingDown; @@ -66,6 +59,9 @@ public class AgilitySupplyManager private long lastBankFailureAt = 0; private long lastFoodBankUnavailableAt = 0; private boolean summerPieBankUnavailable = false; + private boolean pendingSupplyStop = false; + private boolean pendingSupplyLogout = false; + private String pendingSupplyStopMessage = null; public AgilitySupplyManager(MicroAgilityPlugin plugin, MicroAgilityConfig config, BooleanSupplier shuttingDown, Runnable shutdown) { @@ -80,20 +76,21 @@ public void reset() lastBankFailureAt = 0; lastFoodBankUnavailableAt = 0; summerPieBankUnavailable = false; + clearPendingSupplyStop(); } public InventorySnapshot createInventorySnapshot() { - return new InventorySnapshot(plugin.getInventoryFood(), plugin.getSummerPies(), getStaminaPotionCount()); + return new InventorySnapshot(plugin.getInventoryFood(), plugin.getSummerPies(), getConfiguredPotionCount()); } public boolean handleSummerPies(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, InventorySnapshot inventorySnapshot) { - if (!courseHandler.canBeBoosted()) + if (!shouldUseSummerPies(courseHandler)) { return false; } - if (!isAtCourseStart(courseHandler, playerWorldLocation, currentObstacleIndex)) + if (!shouldEatSummerPie(courseHandler, playerWorldLocation, currentObstacleIndex)) { return false; } @@ -121,30 +118,38 @@ public boolean handleSummerPies(AgilityCourseHandler courseHandler, WorldPoint p public boolean handlePreLevelCheck(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, boolean hasRequiredLevel, InventorySnapshot inventorySnapshot) { - boolean requiresBoost = courseHandler.canBeBoosted() && !plugin.hasRealRequiredLevel(courseHandler); + boolean requiresBoost = !plugin.hasRealRequiredLevel(courseHandler); if (!requiresBoost) { return false; } + if (!shouldUseSummerPies(courseHandler)) + { + return false; + } if (!isAtCourseStart(courseHandler, playerWorldLocation, currentObstacleIndex)) { if (!hasRequiredLevel) { - stopAndLogout("You do not have the required agility level for this course."); + if (isOnCourse(currentObstacleIndex) && !inventorySnapshot.getSummerPies().isEmpty()) + { + return false; + } + stopScript("Your Agility boost has dropped below the requirement and no summer pie was available.", shouldLogoutForSummerPieFailure()); return true; } return false; } if (hasRequiredLevel && inventorySnapshot.getSummerPies().isEmpty() && config.summerPieWithdrawAmount() <= 0) { - stopAndLogout("You need summer pies in inventory before starting this boosted course."); + stopScript("This boosted course needs summer pies. Add pies or select another course.", false); return true; } if (!needsSummerPieBanking(courseHandler, inventorySnapshot)) { if (!hasRequiredLevel) { - stopAndLogout("You do not have enough summer pies configured to start this course."); + stopScript("You do not have enough summer pies configured to start this course.", shouldLogoutForSummerPieFailure()); return true; } return false; @@ -155,14 +160,14 @@ public boolean handlePreLevelCheck(AgilityCourseHandler courseHandler, WorldPoin { if (!hasRequiredLevel) { - stopAndLogout("You do not have enough summer pies configured to start this course."); + stopScript("You do not have enough summer pies configured to start this course.", shouldLogoutForSummerPieFailure()); return true; } return false; } if (summerPieBankUnavailable && plugin.getSummerPies().size() < config.summerPieWithdrawAmount()) { - stopAndLogout("No summer pies were available for the selected boosted course."); + stopScript("No summer pies were available for the selected boosted course.", shouldLogoutForSummerPieFailure()); return true; } return true; @@ -180,10 +185,21 @@ public boolean handleBeforeObstacle(AgilityCourseHandler courseHandler, WorldPoi { return true; } + if (drinkConfiguredPotion(inventorySnapshot)) + { + return true; + } return handleBanking(courseHandler, playerWorldLocation, currentObstacleIndex, inventorySnapshot) || handleHealthSafety(inventorySnapshot); } + public boolean shouldWalkToCourseStartForSummerPie(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex) + { + return shouldUseSummerPies(courseHandler) + && !isOnCourse(currentObstacleIndex) + && !isAtCourseStart(courseHandler, playerWorldLocation, currentObstacleIndex); + } + private boolean handleFood(InventorySnapshot inventorySnapshot) { if (config.hitpoints() <= 0) @@ -203,8 +219,7 @@ private boolean handleFood(InventorySnapshot inventorySnapshot) { return false; } - Microbot.showMessage("Hitpoints are below the configured threshold and no food was found. Stopping agility."); - shutdown.run(); + stopScript("Hitpoints are below the configured threshold and no food was found. Stopping agility.", shouldLogoutForFoodFailure()); return true; } Rs2ItemModel foodItem = foodItems.get(0); @@ -288,8 +303,14 @@ private boolean handleBanking(AgilityCourseHandler courseHandler, WorldPoint pla return true; } + clearPendingSupplyStop(); boolean success = withdrawConfiguredSupplies(courseHandler); Rs2Bank.closeBank(); + if (!success && completePendingSupplyStop()) + { + lastBankFailureAt = 0; + return true; + } lastBankFailureAt = success ? 0 : System.currentTimeMillis(); return true; } @@ -349,6 +370,7 @@ private boolean withdrawConfiguredFood() { markFoodBankUnavailable(); Microbot.showMessage("No " + food.getName() + " found in the bank."); + requestFoodSupplyStop("No " + food.getName() + " was found in the bank."); return false; } @@ -408,6 +430,7 @@ private boolean withdrawAutoFood(int amountToWithdraw, int currentFood) { markFoodBankUnavailable(); Microbot.showMessage("Not enough configured food was found in the bank."); + requestFoodSupplyStop("No usable agility food was found in the bank."); return false; } clearFoodBankUnavailable(); @@ -418,7 +441,7 @@ private boolean withdrawConfiguredPotion() { AgilityPotionOption option = config.bankPotion(); int targetAmount = config.potionWithdrawAmount(); - int currentPotions = getStaminaPotionCount(); + int currentPotions = getConfiguredPotionCount(); int missingPotions = targetAmount - currentPotions; if (missingPotions <= 0) { @@ -431,21 +454,21 @@ private boolean withdrawConfiguredPotion() } int amountToWithdraw = Math.min(missingPotions, Rs2Inventory.emptySlotCount()); - if (option.isNone() || option.getItemId() <= 0) + if (option.isNone()) { return false; } - if (!Rs2Bank.hasBankItem(option.getItemId(), amountToWithdraw)) + if (getBankPotionCount(option) < amountToWithdraw) { Microbot.showMessage("No " + option + " found in the bank."); return false; } - if (!Rs2Bank.withdrawX(option.getItemId(), amountToWithdraw)) + if (!withdrawPotionFamily(option, amountToWithdraw)) { return false; } - return Global.sleepUntil(() -> getStaminaPotionCount() >= currentPotions + amountToWithdraw, 2400); + return Global.sleepUntil(() -> getConfiguredPotionCount() >= currentPotions + amountToWithdraw, 2400); } private boolean withdrawSummerPies() @@ -469,6 +492,7 @@ private boolean withdrawSummerPies() { summerPieBankUnavailable = true; Microbot.showMessage("No summer pies found in the bank."); + requestSupplyStop("No summer pies were found in the bank.", shouldLogoutForSummerPieFailure()); return false; } if (!Rs2Bank.withdrawX(SUMMER_PIE_ID, amountToWithdraw)) @@ -571,20 +595,94 @@ private boolean needsPotionBanking(InventorySnapshot inventorySnapshot) AgilityPotionOption potion = config.bankPotion(); return !potion.isNone() && config.potionWithdrawAmount() > 0 - && inventorySnapshot.getStaminaPotionCount() < config.potionWithdrawAmount(); + && inventorySnapshot.getPotionCount() < config.potionWithdrawAmount(); } private boolean needsSummerPieBanking(AgilityCourseHandler courseHandler, InventorySnapshot inventorySnapshot) { return courseHandler != null - && courseHandler.canBeBoosted() + && shouldUseSummerPies(courseHandler) && config.summerPieWithdrawAmount() > 0 && inventorySnapshot.getSummerPieCount() < config.summerPieWithdrawAmount(); } - private int getStaminaPotionCount() + private boolean drinkConfiguredPotion(InventorySnapshot inventorySnapshot) { - return Rs2Inventory.count(item -> item != null && Arrays.stream(STAMINA_POTION_IDS).anyMatch(id -> id == item.getId())); + AgilityPotionOption potion = config.bankPotion(); + if (potion.isNone() || config.potionDrinkAt() <= 0 || inventorySnapshot.getPotionCount() <= 0) + { + return false; + } + if (Rs2Player.getRunEnergy() > config.potionDrinkAt()) + { + return false; + } + if (potion.isStaminaEffect() && Rs2Player.hasStaminaActive()) + { + return false; + } + + for (int itemId : potion.getItemIdsLowToHigh()) + { + if (!Rs2Inventory.contains(itemId)) + { + continue; + } + + int potionCount = getConfiguredPotionCount(); + if (!Rs2Inventory.interact(itemId, "Drink")) + { + return false; + } + Global.sleepUntil(() -> getConfiguredPotionCount() < potionCount + || Rs2Player.getRunEnergy() > config.potionDrinkAt() + || (potion.isStaminaEffect() && Rs2Player.hasStaminaActive()), 1800); + return true; + } + return false; + } + + private int getConfiguredPotionCount() + { + AgilityPotionOption potion = config.bankPotion(); + if (potion.isNone()) + { + return 0; + } + return Rs2Inventory.count(item -> item != null && potion.matches(item.getId())); + } + + private int getBankPotionCount(AgilityPotionOption potion) + { + return Arrays.stream(potion.getItemIdsHighToLow()) + .map(Rs2Bank::count) + .sum(); + } + + private boolean withdrawPotionFamily(AgilityPotionOption potion, int amount) + { + int remaining = amount; + for (int itemId : potion.getItemIdsHighToLow()) + { + if (remaining <= 0 || Rs2Inventory.emptySlotCount() <= 0) + { + break; + } + + int available = Rs2Bank.count(itemId); + if (available <= 0) + { + continue; + } + + int withdrawAmount = Math.min(Math.min(remaining, available), Rs2Inventory.emptySlotCount()); + if (!Rs2Bank.withdrawX(itemId, withdrawAmount)) + { + return false; + } + remaining -= withdrawAmount; + } + return remaining <= 0; } private boolean shouldWaitForHealthInsteadOfBanking(InventorySnapshot inventorySnapshot) @@ -605,10 +703,6 @@ && isFoodBankingConfigured() private boolean canAttemptBanking(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex) { - if (!config.bankOnlyAtCourseStart()) - { - return true; - } if (courseHandler == null || playerWorldLocation == null || courseHandler.getStartPoint() == null) { return false; @@ -628,6 +722,27 @@ private boolean isAtCourseStart(AgilityCourseHandler courseHandler, WorldPoint p && playerWorldLocation.distanceTo(courseHandler.getStartPoint()) <= 12; } + private boolean shouldEatSummerPie(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex) + { + if (isAtCourseStart(courseHandler, playerWorldLocation, currentObstacleIndex)) + { + return true; + } + return isOnCourse(currentObstacleIndex); + } + + private boolean isOnCourse(int currentObstacleIndex) + { + return currentObstacleIndex > 0; + } + + private boolean shouldUseSummerPies(AgilityCourseHandler courseHandler) + { + return config.useSummerPies() + && courseHandler != null + && plugin.canSummerPieMeetRequirement(courseHandler); + } + private int getBankItemQuantity(int itemId) { return Rs2Bank.bankItems().stream() @@ -652,11 +767,57 @@ private boolean isFoodBankUnavailable() && System.currentTimeMillis() - lastFoodBankUnavailableAt < FOOD_BANK_UNAVAILABLE_RETRY_MS; } - private void stopAndLogout(String message) + private void requestFoodSupplyStop(String message) + { + if (plugin.getInventoryFood().isEmpty() && !config.hpSafetyWait()) + { + requestSupplyStop(message, shouldLogoutForFoodFailure()); + } + } + + private void requestSupplyStop(String message, boolean logout) + { + pendingSupplyStop = true; + pendingSupplyLogout = logout; + pendingSupplyStopMessage = message; + } + + private boolean completePendingSupplyStop() + { + if (!pendingSupplyStop) + { + return false; + } + + String message = pendingSupplyStopMessage; + boolean logout = pendingSupplyLogout; + clearPendingSupplyStop(); + stopScript(message, logout); + return true; + } + + private void clearPendingSupplyStop() + { + pendingSupplyStop = false; + pendingSupplyLogout = false; + pendingSupplyStopMessage = null; + } + + private boolean shouldLogoutForFoodFailure() + { + return config.logoutWhenOutOfSupplies() && !config.hpSafetyWait(); + } + + private boolean shouldLogoutForSummerPieFailure() + { + return config.logoutWhenOutOfSupplies() && config.summerPieWithdrawAmount() > 0 && plugin.getSummerPies().isEmpty(); + } + + private void stopScript(String message, boolean logout) { - Microbot.showMessage(message); + plugin.notifyUser(message); Microbot.status = "Stopping agility"; - if (Microbot.isLoggedIn()) + if (logout && Microbot.isLoggedIn()) { Rs2Player.logout(); } @@ -667,13 +828,13 @@ static final class InventorySnapshot { private final List foodItems; private final List summerPies; - private final int staminaPotionCount; + private final int potionCount; - private InventorySnapshot(List foodItems, List summerPies, int staminaPotionCount) + private InventorySnapshot(List foodItems, List summerPies, int potionCount) { this.foodItems = Collections.unmodifiableList(foodItems); this.summerPies = Collections.unmodifiableList(summerPies); - this.staminaPotionCount = staminaPotionCount; + this.potionCount = potionCount; } List getFoodItems() @@ -696,9 +857,9 @@ int getSummerPieCount() return summerPies.size(); } - int getStaminaPotionCount() + int getPotionCount() { - return staminaPotionCount; + return potionCount; } } } diff --git a/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityConfig.java b/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityConfig.java index 0453628c7d..9682e7d8b3 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityConfig.java +++ b/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityConfig.java @@ -22,35 +22,59 @@ public interface MicroAgilityConfig extends Config String itemsToAlch = "itemsToAlch"; @ConfigSection( - name = "General", - description = "General", + name = "Course", + description = "Choose which agility course to run.", position = 0, closedByDefault = false ) - String generalSection = "general"; + String courseSection = "courseSection"; @ConfigSection( - name = "Banking", - description = "Banking", + name = "Alching", + description = "Optional alching while running the course.", position = 1, closedByDefault = true ) + String alchingSection = "alching"; + + @ConfigSection( + name = "Banking", + description = "Optional equipment and boosted-course banking.", + position = 2, + closedByDefault = true + ) String bankingSection = "banking"; + @ConfigSection( + name = "Food", + description = "Food, eating, and food banking options.", + position = 3, + closedByDefault = true + ) + String foodSection = "food"; + @ConfigSection( name = "Safety", - description = "Safety", - position = 2, + description = "Extra protection for low health and empty supplies.", + position = 4, closedByDefault = true ) String safetySection = "safety"; + @ConfigSection( + name = "Potions", + description = "Run energy potion banking and drinking options.", + position = 5, + closedByDefault = true + ) + String potionsSection = "potions"; + @ConfigItem( keyName = selectedCourse, name = "Course", - description = "Choose your agility course", + description = "Choose the agility course to run.", position = 1, - section = generalSection + section = courseSection ) default AgilityCourse agilityCourse() { @@ -60,9 +84,9 @@ default AgilityCourse agilityCourse() @ConfigItem( keyName = hitpointsThreshold, name = "Eat at", - description = "Use food below certain hitpoint percent. If there's no food in the inventory, the script stops. Set to 0 in order to disable.", - position = 2, - section = generalSection + description = "Eat when your HP falls below this percent. Set to 0 to disable auto-eating.", + position = 1, + section = foodSection ) default int hitpoints() { @@ -72,9 +96,9 @@ default int hitpoints() @ConfigItem( keyName = "bankFood", name = "Food", - description = "Food to withdraw when banking. None disables food banking. Auto withdraws the best available configured food.", - position = 1, - section = bankingSection + description = "Food to take from the bank. None turns food banking off. Auto picks the best supported food available.", + position = 2, + section = foodSection ) default AgilityFoodOption bankFood() { @@ -84,9 +108,9 @@ default AgilityFoodOption bankFood() @ConfigItem( keyName = "foodWithdrawAmount", name = "Food amount", - description = "Target amount of food to have after banking.", - position = 2, - section = bankingSection + description = "How much food to carry after banking.", + position = 3, + section = foodSection ) @Range(min = 0, max = 28) default int foodWithdrawAmount() @@ -96,10 +120,10 @@ default int foodWithdrawAmount() @ConfigItem( keyName = "bankFoodAt", - name = "Bank under food", - description = "Bank when inventory food count is at or below this amount. 0 disables food banking triggers.", - position = 3, - section = bankingSection + name = "Bank at food", + description = "Go to the bank when your food count is at or below this number. Set to 0 to disable this trigger.", + position = 4, + section = foodSection ) @Range(min = 0, max = 28) default int bankFoodAt() @@ -110,9 +134,9 @@ default int bankFoodAt() @ConfigItem( keyName = "bankPotion", name = "Potion", - description = "Potion to withdraw when banking. None disables potion banking.", - position = 4, - section = bankingSection + description = "Run energy potion to take from the bank and drink when needed. None turns this off.", + position = 1, + section = potionsSection ) default AgilityPotionOption bankPotion() { @@ -122,9 +146,9 @@ default AgilityPotionOption bankPotion() @ConfigItem( keyName = "potionWithdrawAmount", name = "Potion amount", - description = "Target amount of selected potion to have after banking.", - position = 5, - section = bankingSection + description = "How many of the selected potion to carry after banking. A 1-dose and 4-dose potion both count as one potion.", + position = 2, + section = potionsSection ) @Range(min = 0, max = 28) default int potionWithdrawAmount() @@ -133,22 +157,23 @@ default int potionWithdrawAmount() } @ConfigItem( - keyName = "bankOnlyAtCourseStart", - name = "Bank at course start", - description = "Only bank from the ground near the course start. This avoids asking the walker to route from rooftops or awkward course positions.", - position = 6, - section = bankingSection + keyName = "potionDrinkAt", + name = "Drink potion at", + description = "Drink the selected potion when run energy reaches this percent or lower. Set to 0 to disable auto-drinking.", + position = 3, + section = potionsSection ) - default boolean bankOnlyAtCourseStart() + @Range(min = 0, max = 100) + default int potionDrinkAt() { - return true; + return 40; } @ConfigItem( keyName = "bankEquipment", name = "Equipment", - description = "Optional equipment to withdraw and wear when banking from a safe course-start position.", - position = 7, + description = "Optional graceful or agility cape setup to withdraw and wear while banking.", + position = 1, section = bankingSection ) default AgilityEquipmentOption bankEquipment() @@ -159,8 +184,8 @@ default AgilityEquipmentOption bankEquipment() @ConfigItem( keyName = "summerPieWithdrawAmount", name = "Summer pie amount", - description = "Target amount of summer pies to withdraw when banking. 0 disables summer pie banking.", - position = 8, + description = "How many summer pies to carry after banking. Set to 0 if you do not want to bank for pies.", + position = 2, section = bankingSection ) @Range(min = 0, max = 28) @@ -169,10 +194,22 @@ default int summerPieWithdrawAmount() return 0; } + @ConfigItem( + keyName = "useSummerPies", + name = "Use summer pies", + description = "Use summer pies to boost for courses you can reach with a +5 Agility boost. This also lets the script eat another pie if the boost drops on-course.", + position = 3, + section = bankingSection + ) + default boolean useSummerPies() + { + return false; + } + @ConfigItem( keyName = "hpSafetyWait", - name = "Wait when unsafe", - description = "If out of food and HP is too low, wait instead of stopping or continuing.", + name = "Wait for HP", + description = "If you have no usable food and HP is low, wait for health to regenerate before continuing.", position = 1, section = safetySection ) @@ -184,7 +221,7 @@ default boolean hpSafetyWait() @ConfigItem( keyName = "hpSafetyWaitBelow", name = "Wait below HP", - description = "When out of food, wait if HP percentage is below this value.", + description = "Start waiting when you have no usable food and HP falls below this percent.", position = 2, section = safetySection ) @@ -197,7 +234,7 @@ default int hpSafetyWaitBelow() @ConfigItem( keyName = "hpSafetyResumeAt", name = "Resume at HP", - description = "Resume once HP percentage is at or above this value.", + description = "Start running the course again once HP reaches this percent.", position = 3, section = safetySection ) @@ -207,12 +244,24 @@ default int hpSafetyResumeAt() return 50; } + @ConfigItem( + keyName = "logoutWhenOutOfSupplies", + name = "Logout when supplies run out", + description = "If configured food or summer pies are gone, stop the script and log out. Course-level mistakes still only stop the script.", + position = 4, + section = safetySection + ) + default boolean logoutWhenOutOfSupplies() + { + return false; + } + @ConfigItem( keyName = shouldAlch, name = "Alch", - description = "Use Low/High Alchemy while doing agility", - position = 4, - section = generalSection + description = "Cast alchemy spells while running the course.", + position = 1, + section = alchingSection ) default boolean alchemy() { @@ -222,9 +271,9 @@ default boolean alchemy() @ConfigItem( keyName = itemsToAlch, name = "Items to Alch", - description = "Enter items to alch, separated by commas (e.g., Rune sword, Dragon dagger, Mithril platebody)", - position = 5, - section = generalSection + description = "Items to alch, separated by commas. Example: Rune sword, Dragon dagger, Mithril platebody.", + position = 2, + section = alchingSection ) default String itemsToAlch() { @@ -234,9 +283,9 @@ default String itemsToAlch() @ConfigItem( keyName = "efficientAlching", name = "Efficient Alching", - description = "Click obstacle first, then alch, then click again (for obstacles 5+ tiles away)", - position = 6, - section = generalSection + description = "For obstacles at least 5 tiles away, click the obstacle, alch, then click the obstacle again.", + position = 3, + section = alchingSection ) default boolean efficientAlching() { @@ -246,9 +295,9 @@ default boolean efficientAlching() @ConfigItem( keyName = "skipInefficient", name = "Skip Inefficient", - description = "Only alch when obstacle is 5+ tiles away (skip inefficient alchs)", - position = 7, - section = generalSection + description = "Only alch when the next obstacle is far enough away to avoid slowing the course down.", + position = 4, + section = alchingSection ) default boolean skipInefficient() { @@ -258,9 +307,9 @@ default boolean skipInefficient() @ConfigItem( keyName = "alchSkipChance", name = "Alch Skip Chance", - description = "Percentage chance to skip alching on any obstacle (0-100)", - position = 8, - section = generalSection + description = "Chance to skip an alch opportunity. 0 always alchs, 100 never alchs.", + position = 5, + section = alchingSection ) @Range(min = 0, max = 100) default int alchSkipChance() diff --git a/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityPlugin.java b/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityPlugin.java index 450a9eaa03..9adc1036da 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityPlugin.java +++ b/src/main/java/net/runelite/client/plugins/microbot/agility/MicroAgilityPlugin.java @@ -2,10 +2,12 @@ import com.google.inject.Provides; import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; import net.runelite.api.Skill; import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.microbot.Microbot; import net.runelite.client.plugins.microbot.PluginConstants; import net.runelite.client.plugins.microbot.agility.courses.AgilityCourseHandler; import net.runelite.api.gameval.ItemID; @@ -35,7 +37,7 @@ @Slf4j public class MicroAgilityPlugin extends Plugin { - public static final String version = "1.3.0"; + public static final String version = "1.3.1"; @Inject private MicroAgilityConfig config; @Inject @@ -81,6 +83,23 @@ public AgilityCourseHandler getCourseHandler() return config.agilityCourse().getHandler(); } + public void notifyUser(String message) + { + try + { + if (Microbot.getClient() != null) + { + Microbot.getClientThread().invoke(() -> + Microbot.getClient().addChatMessage(ChatMessageType.ENGINE, "", message, "Micro Agility", false)); + } + } + catch (Exception ex) + { + log.debug("Unable to add agility message to chat", ex); + } + Microbot.showMessage(message); + } + public List getInventoryFood() { return Rs2Inventory.getInventoryFood().stream().filter(i -> !isSummerPie(i)).collect(Collectors.toList()); @@ -104,7 +123,7 @@ public boolean hasRequiredLevel(AgilityCourseHandler courseHandler) return true; } - if (getSummerPies().isEmpty() || !courseHandler.canBeBoosted()) + if (!config.useSummerPies() || getSummerPies().isEmpty() || !courseHandler.canBeBoosted()) { return false; } @@ -117,6 +136,12 @@ public boolean hasRealRequiredLevel(AgilityCourseHandler courseHandler) return Rs2Player.getRealSkillLevel(Skill.AGILITY) >= courseHandler.getRequiredLevel(); } + public boolean canSummerPieMeetRequirement(AgilityCourseHandler courseHandler) + { + return courseHandler.canBeBoosted() + && Rs2Player.getRealSkillLevel(Skill.AGILITY) + 5 >= courseHandler.getRequiredLevel(); + } + private boolean isSummerPie(Rs2ItemModel item) { return item != null && (item.getId() == ItemID.SUMMER_PIE || item.getId() == ItemID.HALF_SUMMER_PIE); diff --git a/src/main/java/net/runelite/client/plugins/microbot/agility/enums/AgilityPotionOption.java b/src/main/java/net/runelite/client/plugins/microbot/agility/enums/AgilityPotionOption.java index 2dbcf1606c..6ccc8624e2 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/agility/enums/AgilityPotionOption.java +++ b/src/main/java/net/runelite/client/plugins/microbot/agility/enums/AgilityPotionOption.java @@ -3,22 +3,56 @@ import lombok.Getter; import net.runelite.api.gameval.ItemID; +import java.util.Arrays; + @Getter public enum AgilityPotionOption { - NONE("None", -1), - STAMINA_4("Stamina potion(4)", ItemID._4DOSESTAMINA), - STAMINA_3("Stamina potion(3)", ItemID._3DOSESTAMINA), - STAMINA_2("Stamina potion(2)", ItemID._2DOSESTAMINA), - STAMINA_1("Stamina potion(1)", ItemID._1DOSESTAMINA); + NONE("None", false), + STAMINA("Stamina potion", true, + ItemID._4DOSESTAMINA, + ItemID._3DOSESTAMINA, + ItemID._2DOSESTAMINA, + ItemID._1DOSESTAMINA), + EXTENDED_STAMINA("Extended stamina potion", true, + ItemID._4DOSE2STAMINA, + ItemID._3DOSE2STAMINA, + ItemID._2DOSE2STAMINA, + ItemID._1DOSE2STAMINA), + SUPER_ENERGY("Super energy potion", false, + ItemID._4DOSE2ENERGY, + ItemID._3DOSE2ENERGY, + ItemID._2DOSE2ENERGY, + ItemID._1DOSE2ENERGY), + ENERGY("Energy potion", false, + ItemID._4DOSE1ENERGY, + ItemID._3DOSE1ENERGY, + ItemID._2DOSE1ENERGY, + ItemID._1DOSE1ENERGY), + EXTREME_ENERGY("Extreme energy potion", false, + ItemID._4DOSE3ENERGY, + ItemID._3DOSE3ENERGY, + ItemID._2DOSE3ENERGY, + ItemID._1DOSE3ENERGY), + STAMINA_MIX("Stamina mix", true, + ItemID.BRUTAL_2DOSESTAMINA, + ItemID.BRUTAL_1DOSESTAMINA), + SUPER_ENERGY_MIX("Super energy mix", false, + ItemID.BRUTAL_2DOSE2ENERGY, + ItemID.BRUTAL_1DOSE2ENERGY), + ENERGY_MIX("Energy mix", false, + ItemID.BRUTAL_2DOSE1ENERGY, + ItemID.BRUTAL_1DOSE1ENERGY); private final String displayName; - private final int itemId; + private final boolean staminaEffect; + private final int[] itemIdsHighToLow; - AgilityPotionOption(String displayName, int itemId) + AgilityPotionOption(String displayName, boolean staminaEffect, int... itemIdsHighToLow) { this.displayName = displayName; - this.itemId = itemId; + this.staminaEffect = staminaEffect; + this.itemIdsHighToLow = itemIdsHighToLow; } public boolean isNone() @@ -26,6 +60,23 @@ public boolean isNone() return this == NONE; } + public boolean matches(int itemId) + { + return Arrays.stream(itemIdsHighToLow).anyMatch(id -> id == itemId); + } + + public int[] getItemIdsLowToHigh() + { + int[] ids = Arrays.copyOf(itemIdsHighToLow, itemIdsHighToLow.length); + for (int left = 0, right = ids.length - 1; left < right; left++, right--) + { + int temp = ids[left]; + ids[left] = ids[right]; + ids[right] = temp; + } + return ids; + } + @Override public String toString() { From 24c7f9fa1cc26f346511abb1e586c4ec03977d78 Mon Sep 17 00:00:00 2001 From: infuse21 Date: Sun, 5 Jul 2026 17:19:25 +0100 Subject: [PATCH 2/2] Clean up config descriptions to be clearer and reorganized Consolidate potion config by potion type instead of separate dose entries. Withdraw higher-dose potions first and drink lower-dose potions first. Add optional potion drinking at configured run energy some other stuff should be better --- .../microbot/agility/AgilitySupplyManager.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java b/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java index 8f8709bea9..f699c2144b 100644 --- a/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java +++ b/src/main/java/net/runelite/client/plugins/microbot/agility/AgilitySupplyManager.java @@ -23,7 +23,7 @@ import java.util.function.BooleanSupplier; import java.util.stream.Collectors; -public class AgilitySupplyManager +class AgilitySupplyManager { private static final long BANK_RETRY_COOLDOWN_MS = 30_000; private static final long FOOD_BANK_UNAVAILABLE_RETRY_MS = 300_000; @@ -63,7 +63,7 @@ public class AgilitySupplyManager private boolean pendingSupplyLogout = false; private String pendingSupplyStopMessage = null; - public AgilitySupplyManager(MicroAgilityPlugin plugin, MicroAgilityConfig config, BooleanSupplier shuttingDown, Runnable shutdown) + AgilitySupplyManager(MicroAgilityPlugin plugin, MicroAgilityConfig config, BooleanSupplier shuttingDown, Runnable shutdown) { this.plugin = plugin; this.config = config; @@ -71,7 +71,7 @@ public AgilitySupplyManager(MicroAgilityPlugin plugin, MicroAgilityConfig config this.shutdown = shutdown; } - public void reset() + void reset() { lastBankFailureAt = 0; lastFoodBankUnavailableAt = 0; @@ -79,12 +79,12 @@ public void reset() clearPendingSupplyStop(); } - public InventorySnapshot createInventorySnapshot() + InventorySnapshot createInventorySnapshot() { return new InventorySnapshot(plugin.getInventoryFood(), plugin.getSummerPies(), getConfiguredPotionCount()); } - public boolean handleSummerPies(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, InventorySnapshot inventorySnapshot) + boolean handleSummerPies(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, InventorySnapshot inventorySnapshot) { if (!shouldUseSummerPies(courseHandler)) { @@ -115,7 +115,7 @@ public boolean handleSummerPies(AgilityCourseHandler courseHandler, WorldPoint p return true; } - public boolean handlePreLevelCheck(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, + boolean handlePreLevelCheck(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, boolean hasRequiredLevel, InventorySnapshot inventorySnapshot) { boolean requiresBoost = !plugin.hasRealRequiredLevel(courseHandler); @@ -173,12 +173,12 @@ public boolean handlePreLevelCheck(AgilityCourseHandler courseHandler, WorldPoin return true; } - public boolean handleFoodOrHealthSafety(InventorySnapshot inventorySnapshot) + boolean handleFoodOrHealthSafety(InventorySnapshot inventorySnapshot) { return handleFood(inventorySnapshot) || handleHealthSafety(inventorySnapshot); } - public boolean handleBeforeObstacle(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, + boolean handleBeforeObstacle(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex, InventorySnapshot inventorySnapshot) { if (wearConfiguredEquipmentFromInventory()) @@ -193,7 +193,7 @@ public boolean handleBeforeObstacle(AgilityCourseHandler courseHandler, WorldPoi || handleHealthSafety(inventorySnapshot); } - public boolean shouldWalkToCourseStartForSummerPie(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex) + boolean shouldWalkToCourseStartForSummerPie(AgilityCourseHandler courseHandler, WorldPoint playerWorldLocation, int currentObstacleIndex) { return shouldUseSummerPies(courseHandler) && !isOnCourse(currentObstacleIndex)