From 2239281943273591fa45dda21bd337a23fbc22af Mon Sep 17 00:00:00 2001 From: chsami Date: Wed, 3 Sep 2025 19:50:42 +0200 Subject: [PATCH 1/4] Update README.md --- README.md | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/README.md b/README.md index 0756c9fd358..ed3a98ea704 100644 --- a/README.md +++ b/README.md @@ -20,32 +20,6 @@ If you have any questions, please join our [Discord](https://discord.gg/zaGrfqFE If you enjoy my open source work and would like to support me, consider buying me a coffee! Your support helps me stay caffeinated and motivated to keep improving and creating awesome projects. -## Quest Helper Integration - -The integrated Quest Helper works together with other plugins to give a nice unified experience while questing. - -### Not Enough Runes - -If you have the [Not Enough Runes](https://runelite.net/plugin-hub/show/not-enough-runes) plugin installed, you can -right-click item requirements and click `Go to NER...` to look that item up in Not Enough Runes. - -![Not Enough Runes context menu](./images/not-enough-runes-01.png) - -### Shortest Path - -If you have the [Shortest Path](https://runelite.net/plugin-hub/show/shortest-path) plugin installed, you can enable the -the "Use 'Shortest Path' plugin" in the Quest Helper config. - -![](./images/shortest-path-01.png) - -Next time you start a quest, the Shortest Path plugin will help you take the shortest path to the destination. - -![Shortest Path path overlay example](./images/shortest-path-02.png) - -You can configure what teleportation methods, or the aesthetic of the path in the Shortest Path config. - -## Help and discussion - [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-donate-yellow)](https://www.paypal.com/paypalme/MicrobotBE?country.x=BE) From 5ddaf5ab18e9d7cd5a03ac0e24642fce9aa143e0 Mon Sep 17 00:00:00 2001 From: heap-overfl0w Date: Sat, 6 Sep 2025 15:10:23 -0500 Subject: [PATCH 2/4] - Added world hopping logic to Fortis Gem Stall due to long stall respawn times. - Added fuzzy gem bag support because I don't have an account to test this with. My implementation passes the eye test but will need actual testing. --- .../model/FortisGemStallThievingSpot.java | 68 ++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java index 4f5d98b3794..9e84a0de9bb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java @@ -3,11 +3,17 @@ import net.runelite.api.GameObject; import net.runelite.api.Skill; import net.runelite.api.coords.WorldPoint; -import net.runelite.client.plugins.microbot.util.bank.Rs2Bank; +import net.runelite.api.gameval.ItemID; import net.runelite.client.plugins.microbot.util.Global; +import net.runelite.client.plugins.microbot.util.bank.Rs2Bank; import net.runelite.client.plugins.microbot.util.gameobject.Rs2GameObject; +import net.runelite.client.plugins.microbot.util.inventory.Rs2Gembag; +import net.runelite.client.plugins.microbot.util.inventory.Rs2Inventory; +import net.runelite.client.plugins.microbot.util.inventory.Rs2ItemModel; import net.runelite.client.plugins.microbot.util.player.Rs2Player; import net.runelite.client.plugins.microbot.util.walker.Rs2Walker; +import net.runelite.client.plugins.microbot.Microbot; +import net.runelite.client.plugins.microbot.util.security.Login; import javax.inject.Inject; @@ -30,19 +36,59 @@ public void thieve() { } } + if (Rs2Player.hopIfPlayerDetected(1, 0, 2)) { + return; + } + final GameObject stall = Rs2GameObject.getGameObject(STALL_ID, SAFESPOT, 2); if (stall == null) { + boolean started = Microbot.hopToWorld(Login.getRandomWorld(Rs2Player.isMember())); + if (started) { + Global.sleepUntil(Microbot::isLoggedIn, 15000); + } + return; + } + + if (!Rs2GameObject.hasAction(Rs2GameObject.convertToObjectComposition(stall), "Steal-from")) { + boolean started = Microbot.hopToWorld(Login.getRandomWorld(Rs2Player.isMember())); + if (started) { + Global.sleepUntil(Microbot::isLoggedIn, 15000); + } return; } Rs2GameObject.interact(stall, "Steal-from"); Rs2Player.waitForXpDrop(Skill.THIEVING); + + if (Rs2Gembag.hasGemBag()) { + if (Rs2Gembag.isUnknown()) { + Rs2Gembag.checkGemBag(); + } + if (!isGemBagCompletelyFull()) { + if (Rs2Inventory.hasItem(ItemID.GEM_BAG)) { + Rs2Inventory.interact(ItemID.GEM_BAG, "Open"); + Global.sleepUntil(Rs2Gembag::isGemBagOpen, 2000); + } + if (Rs2Gembag.isGemBagOpen() && hasAnyUncutGemInInventory()) { + Rs2Inventory.interact(ItemID.GEM_BAG_OPEN, "Fill"); + } + } + } } @Override public void bank() { Rs2Bank.walkToBankAndUseBank(); - Rs2Bank.depositAll(); + if (!Rs2Bank.isOpen()) return; + + Rs2Bank.depositAll(ItemID.UNCUT_SAPPHIRE); + Rs2Bank.depositAll(ItemID.UNCUT_EMERALD); + Rs2Bank.depositAll(ItemID.UNCUT_RUBY); + Rs2Bank.depositAll(ItemID.UNCUT_DIAMOND); + + Rs2Bank.emptyGemBag(); + + Rs2Bank.depositAllExcept(ItemID.GEM_BAG, ItemID.GEM_BAG_OPEN); Rs2Bank.closeBank(); } @@ -50,4 +96,22 @@ public void bank() { public Integer[] getItemIdsToDrop() { return new Integer[0]; } + + private boolean hasAnyUncutGemInInventory() { + return Rs2Inventory.items(this::isUncutGem).findAny().isPresent(); + } + + private boolean isUncutGem(Rs2ItemModel item) { + String n = item.getName().toLowerCase(); + return n.equals("uncut sapphire") || + n.equals("uncut emerald") || + n.equals("uncut ruby") || + n.equals("uncut diamond"); + } + + private boolean isGemBagCompletelyFull() { + if (Rs2Gembag.isUnknown()) return false; + return Rs2Gembag.getGemBagContents().size() == 5 && + Rs2Gembag.getGemBagContents().stream().allMatch(g -> g.getQuantity() >= 60); + } } From 41bcd2e375667cb6ae76bce9d54f9e3f130b3245 Mon Sep 17 00:00:00 2001 From: heap-overfl0w Date: Sat, 6 Sep 2025 15:25:29 -0500 Subject: [PATCH 3/4] Coderabbit made a good point... Because this stall doesn't give you dragonstones, our gem bag will never be "completely full" (consisting of >= 60 gems of all 5 types) and could cause unnecessary fill attempts. Let's check the 4 types individually. --- .../thieving/stalls/model/FortisGemStallThievingSpot.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java index 9e84a0de9bb..8ac4a12b4e3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java @@ -111,7 +111,10 @@ private boolean isUncutGem(Rs2ItemModel item) { private boolean isGemBagCompletelyFull() { if (Rs2Gembag.isUnknown()) return false; - return Rs2Gembag.getGemBagContents().size() == 5 && - Rs2Gembag.getGemBagContents().stream().allMatch(g -> g.getQuantity() >= 60); + int sapphire = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut sapphire")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int emerald = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut emerald")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int ruby = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut ruby")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int diamond = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut diamond")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + return sapphire >= 60 && emerald >= 60 && ruby >= 60 && diamond >= 60; } } From cf098c7171d41bb2a0d488bde90af8aef15fca78 Mon Sep 17 00:00:00 2001 From: heap-overfl0w Date: Sat, 6 Sep 2025 15:48:31 -0500 Subject: [PATCH 4/4] Stick with ItemID. usage --- .../model/FortisGemStallThievingSpot.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java index 8ac4a12b4e3..e63cd50eee3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/thieving/stalls/model/FortisGemStallThievingSpot.java @@ -102,19 +102,19 @@ private boolean hasAnyUncutGemInInventory() { } private boolean isUncutGem(Rs2ItemModel item) { - String n = item.getName().toLowerCase(); - return n.equals("uncut sapphire") || - n.equals("uncut emerald") || - n.equals("uncut ruby") || - n.equals("uncut diamond"); + int id = item.getId(); + return id == ItemID.UNCUT_SAPPHIRE || + id == ItemID.UNCUT_EMERALD || + id == ItemID.UNCUT_RUBY || + id == ItemID.UNCUT_DIAMOND; } private boolean isGemBagCompletelyFull() { if (Rs2Gembag.isUnknown()) return false; - int sapphire = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut sapphire")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); - int emerald = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut emerald")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); - int ruby = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut ruby")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); - int diamond = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getName().equalsIgnoreCase("uncut diamond")).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int sapphire = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getId() == ItemID.UNCUT_SAPPHIRE).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int emerald = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getId() == ItemID.UNCUT_EMERALD).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int ruby = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getId() == ItemID.UNCUT_RUBY).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); + int diamond = Rs2Gembag.getGemBagContents().stream().filter(i -> i.getId() == ItemID.UNCUT_DIAMOND).findFirst().map(Rs2ItemModel::getQuantity).orElse(0); return sapphire >= 60 && emerald >= 60 && ruby >= 60 && diamond >= 60; } }