sombotdude Posted December 22, 2018 Share Posted December 22, 2018 So I've been building a mining script and want a way to check if the rock being mined still exists whilst the player is mining it, say for instance another player manages to mine it before I do and then I can make the bot stop the mining animation and find another rock that has ore it and start mining that. This is my mining function: private void mine(String chosenOre) { // Get rock to mine RS2Object rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object)); if (!playerAnimating()) { // Check if player is not animating if (rockToMine != null) { // Check if rock is not null if (rockToMine.interact("Mine")) { new ConditionalSleep(1000, 500) { @Override public boolean condition() throws InterruptedException { return playerAnimating(); } }.sleep(); } } } } What would be the best way to implement the check for if the rock being mined still exists? I have tried putting within the return of the ConditionalSleep return rockToMine != null as a check but I didnt work, which I am assuming is due to the state of the rock being checked, being the original one from when it had ore in at and not the updated state of the rock that is empty? If so how do you get the updated state of the currently selected object, to then check its current state? Thanks in advance for any help. Quote Link to comment Share on other sites More sharing options...
Muffins Posted December 22, 2018 Share Posted December 22, 2018 check out this Quote Link to comment Share on other sites More sharing options...
sombotdude Posted December 22, 2018 Author Share Posted December 22, 2018 Thanks for the reply, I have actually being using that Explv's code snippet already in this script. So I changed my code to the following: private void mine(String chosenOre) { // Get rock to mine RS2Object rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object)); if (!playerAnimating()) { // Check if player is not animating if (rockToMine != null) { // Check if rock is not null if (rockToMine.interact("Mine")) { new ConditionalSleep(3000, 500) { @Override public boolean condition() throws InterruptedException { return Rock.CLAY.hasOre(rockToMine) && myPlayer().isAnimating(); } }.sleep(); } } } } So in the conditional sleep's return I added the the hasOre check to the currently being mined ore, but it doesnt seem to be making a difference, if the rock gets mined by someone else, it just runs the full length of the animation and then tries to select another rock again. Quote Link to comment Share on other sites More sharing options...
NoxMerc Posted December 22, 2018 Share Posted December 22, 2018 26 minutes ago, sombotdude said: if the rock gets mined by someone else, it just runs the full length of the animation So solve this. You know your player is going to keep animating if the rock is mined out, so maybe your condition shouldn't be relying solely on the player's animation? Quote Link to comment Share on other sites More sharing options...
Explv Posted December 22, 2018 Share Posted December 22, 2018 1 hour ago, sombotdude said: Thanks for the reply, I have actually being using that Explv's code snippet already in this script. So I changed my code to the following: private void mine(String chosenOre) { // Get rock to mine RS2Object rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object)); if (!playerAnimating()) { // Check if player is not animating if (rockToMine != null) { // Check if rock is not null if (rockToMine.interact("Mine")) { new ConditionalSleep(3000, 500) { @Override public boolean condition() throws InterruptedException { return Rock.CLAY.hasOre(rockToMine) && myPlayer().isAnimating(); } }.sleep(); } } } } So in the conditional sleep's return I added the the hasOre check to the currently being mined ore, but it doesnt seem to be making a difference, if the rock gets mined by someone else, it just runs the full length of the animation and then tries to select another rock again. Currently you only mine a new rock if your player isn't animating, so of course it will wait for the animation to complete. You should try doing something like this instead: private RS2Object rock = null; @Override public int onLoop() throws InterruptedException { // If we haven't looked for a rock yet, or the player isn't animating, or the current rock no longer has Clay if (rock == null || !myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock)) { // Find a new rock rock = getObjects().closest(object -> Rock.CLAY.hasOre(object)); // If a rock exists, and we successfully interact with it if (rock != null && rock.interact("Mine")) { new ConditionalSleep(3000, 500) { // Sleep for 3 seconds or until... @Override public boolean condition() throws InterruptedException { // The player is animating, or someone else mined the rock return myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock); } }.sleep(); } } } Quote Link to comment Share on other sites More sharing options...
sombotdude Posted December 22, 2018 Author Share Posted December 22, 2018 47 minutes ago, NoxMerc said: So solve this. You know your player is going to keep animating if the rock is mined out, so maybe your condition shouldn't be relying solely on the player's animation? Yep that's what I thought and was trying to implement with this: new ConditionalSleep(3000, 500) { @Override public boolean condition() throws InterruptedException { return Rock.CLAY.hasOre(rockToMine) && myPlayer().isAnimating(); } }.sleep(); But it still just resulted in the mining animation playing for its full length in almost all cases. Quote Link to comment Share on other sites More sharing options...
NoxMerc Posted December 22, 2018 Share Posted December 22, 2018 Of course, because that's going to break out of the conditional sleep (after 3 seconds or the clay is mined), return to the top of your loop, see that your player is animating, continue. Quote Link to comment Share on other sites More sharing options...
sombotdude Posted December 22, 2018 Author Share Posted December 22, 2018 41 minutes ago, Explv said: Currently you only mine a new rock if your player isn't animating, so of course it will wait for the animation to complete. You should try doing something like this instead: private RS2Object rock = null; @Override public int onLoop() throws InterruptedException { // If we haven't looked for a rock yet, or the player isn't animating, or the current rock no longer has Clay if (rock == null || !myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock)) { // Find a new rock rock = getObjects().closest(object -> Rock.CLAY.hasOre(object)); // If a rock exists, and we successfully interact with it if (rock != null && rock.interact("Mine")) { new ConditionalSleep(3000, 500) { // Sleep for 3 seconds or until... @Override public boolean condition() throws InterruptedException { // The player is animating, or someone else mined the rock return myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock); } }.sleep(); } } } Thanks for the reply, ahh right I see now what I was doing wrong and this looks exactly like what I should be doing. But even using that code it still continues the animation if someone else has mined the rock before my player. I added some extra code to try and get a better understand of what was going on: if (rockToMine == null || !myPlayer().isAnimating() || !Rock.CLAY.hasOre(rockToMine)) { rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object)); if (rockToMine != null && rockToMine.interact("Mine")) { new ConditionalSleep(3000, 1000) { @Override public boolean condition() throws InterruptedException { if (!Rock.CLAY.hasOre(rockToMine)) { log("Rock has no ore!"); return true; } else if (!myPlayer().isAnimating()) { log("Animation finished!"); return true; } else { return false; } } }.sleep(); } } When checking the log, the "Rock has no ore!" never appears, which is confusing as I have watched the bot in times when the rock is empty of ore and the animation is still continuing regardless, it never reaches the "Rock has no ore!" output, just only ever outputting "Animation finished", whenever the animation has finished. I also changed the sleep conditional return to myPlayer().isAnimating() to !myPlayer().isAnimating() as wouldn't I want it to return true if the player had stopped animating, to break the sleep conditional? Quote Link to comment Share on other sites More sharing options...
NoxMerc Posted December 22, 2018 Share Posted December 22, 2018 Two things. The biggest sin you're committing is that you're acquiring an RS2Object, storing it in a variable, and then waiting for one of its properties (modifiedColors) to magically change. Do you see the issue here? The other is that clay respawns relatively quickly. You're checking once every second if the rock (with the magically-updating fields??) doesn't have ore, but what if clay always has ore between one-second intervals? Quote Link to comment Share on other sites More sharing options...
jca Posted December 22, 2018 Share Posted December 22, 2018 (edited) Look at using the stored rocks position and writing a condition that finds the same rock on that position and checks if it doesn’t have ore, rather than checking the referenced rock. private boolean checkRockHasOreAtPosition(Position p){ RS2Object rock = getObjects().getAll() .stream() .filter(obj -> obj.getPosition().equals(p) && Rock.CLAY.hasOre(obj)) .findFirst() .orElse(null); return rock != null; } Something like that Edited December 22, 2018 by jca Quote Link to comment Share on other sites More sharing options...