Dark Magician Posted August 30, 2015 Share Posted August 30, 2015 (edited) This is more accurate than the standard GroundItem interact. public boolean isNpcValid(NPC npc) { if (npc != null && map.canReach(npc)) { int id = npc.getId(); if (id != -1) { for (NPC i : getNpcs().get(npc.getX(), npc.getY())) { if (i.getId() == id) return true; } } } return false; } public boolean isGroundItemValid(GroundItem item) { if (item != null && item.exists() && map.canReach(item) && item.getPosition().distance(myPlayer().getPosition()) <= 7) { int id = item.getId(); if (id != -1) { for (GroundItem i : getGroundItems().get(item.getX(), item.getY())) { if (i.getId() == id) return true; } } } return false; } public boolean isObjectValid(RS2Object object) { if (object != null && object.exists() && map.canReach(object) && object.isVisible()) { int id = object.getId(); if (id != -1) { for (RS2Object i : getObjects().get(object.getX(), object.getY())) { if (i.getId() == id) return true; } } } return false; } public boolean isPlayerInteracting(NPC npc) { for (Player p : players.getAll()) { if (p.getInteracting() != null && p.getInteracting() == npc || p.getInteracting() != null && p.getInteracting().getPosition() == npc.getPosition() || p.getInteracting() != null && p.getInteracting().isInteracting(npc)) { return true; } } return false; } public void walkPath(Position[] path) throws InterruptedException { Position[] var5 = path; int var4 = path.length; for(int var3 = 0; var3 < var4; ++var3) { Position p = var5[var3]; boolean success; if(this.myPosition().distance(p) <= 16 && this.myPosition().distance(p) >= 3) { do { success = this.walkTile(p); } while(!success); } } } public boolean walkTile(Position p) throws InterruptedException { if(this.myPosition().distance(p) > 13) { Position fail = new Position((p.getX() + this.myPosition().getX()) / 2 + random(-3, 3), (p.getY() + this.myPosition().getY()) / 2 + random(-3, 3), this.myPosition().getZ()); this.walkTile(fail); } this.mouse.click(new MiniMapTileDestination(this.bot, p), false); int var3 = 0; while(this.myPosition().distance(p) > 2 && var3 < 10) { sleep(500L); if(!this.myPlayer().isMoving()) { ++var3; } } return var3 != 10; } public void interact(NPC n, String action) throws InterruptedException { if (map.isWithinRange(n, 7)) { status = "Interacting with " + n.getName(); double x = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterX(); double y = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterY(); mouse.move((int) x, (int) y); if (mouse.getEntitiesOnCursor() != null && mouse.getEntitiesOnCursor().contains(n) && mouse.click(true)) { if (menu.isOpen() && menu.selectAction(action)) { sleep(random(900, 1200)); } else { mouse.moveRandomly(); } } else { camera.toEntity(n); } } else if (n.getPosition().isOnMiniMap(this.client.bot)) { status = "Walking to " + n.getName(); walkTile(n.getPosition()); } else if (localWalker.walk(n)) { status = "Walking to " + n.getName(); sleep(random(900, 1200)); } } public void interact(GroundItem g, String action) throws InterruptedException { if (g.getPosition().distance(myPlayer().getPosition()) <= 1) { status = "Interacting with " + g.getName(); if (g.interact(action)) { sleep(random(900, 1200)); } else { camera.toEntity(g); } } else if (g.getPosition().isOnMiniMap(this.client.bot)) { status = "Walking to " + g.getName(); walkTile(g.getPosition()); } else if (localWalker.walk(g)) { status = "Walking to " + g.getName(); sleep(random(900, 1200)); } } public void interact(RS2Object o, String action) throws InterruptedException { if (o.isVisible()) { status = "Interacting with " + o.getName(); if (o.interact(action)) { sleep(random(900, 1200)); } else { camera.toEntity(o); } } else if (o.getPosition().isOnMiniMap(this.client.bot)) { status = "Walking to " + o.getName(); walkTile(o.getPosition()); } else if (localWalker.walk(o)) { status = "Walking to " + o.getName(); sleep(random(900, 1200)); } } Example: if (isObjectValid(objects.closest(11748))) { interact(objects.closest(11748), "Bank"); sleep(random(1500, 1700)); } else { status = "Walking to Bank"; camera.movePitch(67); camera.moveYaw(270); walkPath(DOOR_TO_BANK); } NPC hillGiant = getNpcs().closest(new Filter<NPC>() { @Override public boolean match(NPC npc) { return npc != null && npc.exists() && npc.getName().contains("Hill Giant") && npc.isAttackable() && !npc.isUnderAttack() && npc.getHealth() != 0 && !isPlayerInteracting(npc) && map.isWithinRange(myPlayer().getPosition(), npc, 7); }}); if (isNpcValid(hillGiant)) { interact(hillGiant, "Attack"); } Edited August 30, 2015 by Dark Magician 1 Quote Link to comment Share on other sites More sharing options...
FrostBug Posted August 30, 2015 Share Posted August 30, 2015 (edited) double x = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterX(); double y = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterY(); mouse.move((int) x, (int) y); This isn't going to work for moving entities tho, or with an async moving camera. Standard entity mousedestinations update the mouse path during the movement, to update the location of the potentially moving entity. In the interact method you even fire some async camera events ;o Also, just throwing this out there, but.. public boolean isNpcValid(NPC npc) { if (npc != null && npc.exists() && map.canReach(npc)) { int id = npc.getId(); if (id != -1) { for (NPC i : getNpcs().get(npc.getX(), npc.getY())) { if (i.getId() == id) return true; } } } return false; } For these, the whole "Is there an entity with this ID at these coordinates" is entirely redundant since you're using the Entity#exists check. Could be cleaned up a bit by removing it Edited August 30, 2015 by FrostBug 1 Quote Link to comment Share on other sites More sharing options...
Botre Posted August 30, 2015 Share Posted August 30, 2015 (edited) Faster AND quicker??? Omg usually it's just faster but not quicker, good job. Edited August 30, 2015 by Botre 3 Quote Link to comment Share on other sites More sharing options...
Dark Magician Posted August 30, 2015 Author Share Posted August 30, 2015 (edited) double x = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterX(); double y = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterY(); mouse.move((int) x, (int) y); This isn't going to work for moving entities tho, or with an async moving camera. Standard entity mousedestinations update the mouse path during the movement, to update the location of the potentially moving entity. Also, just throwing this out there, but.. public boolean isNpcValid(NPC npc) { if (npc != null && npc.exists() && map.canReach(npc)) { int id = npc.getId(); if (id != -1) { for (NPC i : getNpcs().get(npc.getX(), npc.getY())) { if (i.getId() == id) return true; } } } return false; } For these, the whole "Is there an entity with this ID at these coordinates" is entirely redundant since you're using the Entity#exists check. Could be cleaned up a bit by removing it Thanks for the information. Could you give an example on how to do moving Entities. Also reason I'm not using the normal interact is because of the Tile error where it will always fail to find the Hill Giant, which you can see if you drawTile. Faster AND quicker??? Omg usually it's just faster but not quicker, good job. Run Hill Giant Magician V 2.1 Edited August 30, 2015 by Dark Magician Quote Link to comment Share on other sites More sharing options...
Apaec Posted August 30, 2015 Share Posted August 30, 2015 If you're using entity and grounditem#interact in the snippets then it can't be faster! This is faster and quicker than the standard implementation. public void interact(GroundItem g, String action) throws InterruptedException { if (g.getPosition().distance(myPlayer().getPosition()) <= 1) { status = "Interacting with " + g.getName(); if (g.interact(action)) { sleep(random(900, 1200)); } else { camera.toEntity(g); } } else if (g.getPosition().isOnMiniMap(this.client.bot)) { status = "Walking to " + g.getName(); walkTile(g.getPosition()); } else if (localWalker.walk(g)) { status = "Walking to " + g.getName(); sleep(random(900, 1200)); } } public void interact(RS2Object o, String action) throws InterruptedException { if (o.isVisible()) { status = "Interacting with " + o.getName(); if (o.interact(action)) { sleep(random(900, 1200)); } else { camera.toEntity(o); } } else if (o.getPosition().isOnMiniMap(this.client.bot)) { status = "Walking to " + o.getName(); walkTile(o.getPosition()); } else if (localWalker.walk(o)) { status = "Walking to " + o.getName(); sleep(random(900, 1200)); } } x) apa Quote Link to comment Share on other sites More sharing options...
Dark Magician Posted August 30, 2015 Author Share Posted August 30, 2015 (edited) If you're using entity and grounditem#interact in the snippets then it can't be faster! x) apa Sorry to be more correct, mouse movements to the Entity will be quicker and interaction more accurate, excluding Drops and RSObjects, since I prioritized fast NPC interaction whereas Drops and Objects need not be. Will edit my first post. Edited August 30, 2015 by Dark Magician Quote Link to comment Share on other sites More sharing options...
FrostBug Posted August 30, 2015 Share Posted August 30, 2015 Thanks for the information. Could you give an example on how to do moving Entities. Also reason I'm not using the normal interact is because of the Tile error where it will always fail to find the Hill Giant, which you can see if you drawTile. Run Hill Giant Magician V 2.1 well, I don't know anything about this "TIle error" But it's gonna be quite difficult to implement some mouse movement to moving entity without using the OSBot methods, which is what you wanted to avoid from what I understand. Standard interactions use an InteractionEvent, which in turn uses an EntityDestination to move the cursor to the entity. An EntityDestination can be used as such: NPC giant = getNpcs().closest("Hill giant"); getMouse().move(new EntityDestination(getBot(), giant)); But again; this is what the standard interaction does. Quote Link to comment Share on other sites More sharing options...
Dark Magician Posted August 30, 2015 Author Share Posted August 30, 2015 (edited) well, I don't know anything about this "TIle error" But it's gonna be quite difficult to implement some mouse movement to moving entity without using the OSBot methods, which is what you wanted to avoid from what I understand. Standard interactions use an InteractionEvent, which in turn uses an EntityDestination to move the cursor to the entity. An EntityDestination can be used as such: NPC giant = getNpcs().closest("Hill giant"); getMouse().move(new EntityDestination(getBot(), giant)); But again; this is what the standard interaction does. Pretty much the Tile box will not contain the NPC resulting in the mouse not being able to interact with the NPC. I believe this is because the Tile height is wrong. Edited August 30, 2015 by Dark Magician Quote Link to comment Share on other sites More sharing options...
Alek Posted August 30, 2015 Share Posted August 30, 2015 This won't be accurate under a lot of circumstances. 1: double x = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterX(); double y = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterY(); Consider an object with a hollow center as such: Red is the object, green is the bounding box, and the blue X is the center. Under every circumstance you are saying that the destination should be at this position, which is not actually clickable. 2: if (g.interact(action)) { sleep(random(900, 1200)); } This is still calling InteractionEvent, which is walking, updating camera, closing out of open interfaces, calling the mouse move events, mouse click events, menu API, etc. Also the above code would not work well with ground item stacks and probably not NPC stacks either, because the bounding box which you are creating is coming from GraphicUtilities. This is a pretty good start but I would really recommend fully understanding InteractionEvent so you can create your interactions that are tailored to your script. 3 Quote Link to comment Share on other sites More sharing options...
Dark Magician Posted August 30, 2015 Author Share Posted August 30, 2015 (edited) This won't be accurate under a lot of circumstances. 1: double x = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterX(); double y = n.model.getBoundingBox(n.getGridX(), n.getGridY(), n.getZ()).getCenterY(); Consider an object with a hollow center as such: Red is the object, green is the bounding box, and the blue X is the center. Under every circumstance you are saying that the destination should be at this position, which is not actually clickable. 2: if (g.interact(action)) { sleep(random(900, 1200)); } This is still calling InteractionEvent, which is walking, updating camera, closing out of open interfaces, calling the mouse move events, mouse click events, menu API, etc. Also the above code would not work well with ground item stacks and probably not NPC stacks either, because the bounding box which you are creating is coming from GraphicUtilities. This is a pretty good start but I would really recommend fully understanding InteractionEvent so you can create your interactions that are tailored to your script. Wow thanks for the information! Very helpful. Will now rewrite and make my method better. Edited August 30, 2015 by Dark Magician Quote Link to comment Share on other sites More sharing options...
Bobrocket Posted September 1, 2015 Share Posted September 1, 2015 (edited) Wow thanks for the information! Very helpful. Will now rewrite and make my method better. When I get on my PC, I'll post my interact method so you can get a feel for it EDIT Here it is. It's not the best example, it uses while loops (which you shouldn't typically use), and obviously you need external vars (biasDeviation and contextMenuDeviation) for tihs to work. public boolean interactWith(NPC e, String action) throws InterruptedException { if (e == null) { return false; } if (getMenuAPI().isOpen()) { getMouse().click(false); sleep(sleepDeviateRand(5, 15)); } //e.hover(); while (!getMouse().isOnCursor(e)) { e.hover(); /*sleep(sleepDeviateRand(1, 2));*/ } //hover String tooltip = getMenuAPI().getTooltip().toLowerCase(); String estimatedToolTip = (action + " " + e.getName()).toLowerCase(); if ((getFirstAction(e).equals(action) && getMouse().getOnCursorCount() == 1) || tooltip.startsWith(estimatedToolTip)) { getMouse().click(false); log("Left clicked!"); return true; } while (!getMenuAPI().isOpen()) { getMouse().click(true); sleep(sleepDeviateRand(5, 15)); } //open interface sleep(sleepDeviateRand(5, 15)); List<Option> options = getMenuAPI().getMenu(); int rectIndex = -1; for (int i = 0; i < options.size(); i++) { Option o = options.get(i); String s = o.action; if (s.equals(action)) { rectIndex = i; break; } } if (rectIndex == -1) { return false; } Rectangle optionRect = getMenuAPI().getOptionRectangle(rectIndex); int height = optionRect.height; int startX = optionRect.x; int startY = optionRect.y; int width = optionRect.width; int endX = startX + width; int endY = startY + height; int perc = 0; if (contextMenuDeviation > 10) { //We want to get the correct context values if (and only if) we have a suitable context menu dev. value (otherwise we just go for the entire object) float percentage = width / 100; //Keep as much precision as possible percentage *= contextMenuDeviation; perc = (int) percentage; } int centreX = (startX + (width / 2)); if (biasDeviation) { Point p = getMouse().getPosition(); int mouseX = (int) p.getX(); if (mouseX > centreX) { //Right side of the context menu startX = centreX; if (perc > 0) { endX = (startX + (perc / 2)); //We do (perc / 2) because in the calculation we account for the entire width } } else { //Left side of the context menu endX = centreX; if (perc > 0) { startX = (centreX - (perc / 2)); } } } else { startX += (perc / 2); endX -= (perc / 2); } //2px bounds incase the bounding boxes are fucked int randX = getRandom(startX + 1, endX - 1); int randY = getRandom(startY + 1, endY - 1); Area mouseArea = createArea(new Point(randX, randY), 2); //Create a 3x3 box while (!mouseArea.contains((int) getMouse().getPosition().getX(), (int) getMouse().getPosition().getY())) { getMouse().move(randX, randY); sleep(sleepDeviateRand(5, 15)); } //move to option sleep(sleepDeviateRand(5, 15)); while (getMenuAPI().isOpen()) { getMouse().click(false); sleep(sleepDeviateRand(5, 15)); } //click sleep(sleepDeviateRand(25, 45)); return true; } Edited September 1, 2015 by Bobrocket 1 Quote Link to comment Share on other sites More sharing options...
Dark Magician Posted September 1, 2015 Author Share Posted September 1, 2015 (edited) When I get on my PC, I'll post my interact method so you can get a feel for it EDIT Here it is. It's not the best example, it uses while loops (which you shouldn't typically use), and obviously you need external vars (biasDeviation and contextMenuDeviation) for tihs to work. public boolean interactWith(NPC e, String action) throws InterruptedException { if (e == null) { return false; } if (getMenuAPI().isOpen()) { getMouse().click(false); sleep(sleepDeviateRand(5, 15)); } //e.hover(); while (!getMouse().isOnCursor(e)) { e.hover(); /*sleep(sleepDeviateRand(1, 2));*/ } //hover String tooltip = getMenuAPI().getTooltip().toLowerCase(); String estimatedToolTip = (action + " " + e.getName()).toLowerCase(); if ((getFirstAction(e).equals(action) && getMouse().getOnCursorCount() == 1) || tooltip.startsWith(estimatedToolTip)) { getMouse().click(false); log("Left clicked!"); return true; } while (!getMenuAPI().isOpen()) { getMouse().click(true); sleep(sleepDeviateRand(5, 15)); } //open interface sleep(sleepDeviateRand(5, 15)); List<Option> options = getMenuAPI().getMenu(); int rectIndex = -1; for (int i = 0; i < options.size(); i++) { Option o = options.get(i); String s = o.action; if (s.equals(action)) { rectIndex = i; break; } } if (rectIndex == -1) { return false; } Rectangle optionRect = getMenuAPI().getOptionRectangle(rectIndex); int height = optionRect.height; int startX = optionRect.x; int startY = optionRect.y; int width = optionRect.width; int endX = startX + width; int endY = startY + height; int perc = 0; if (contextMenuDeviation > 10) { //We want to get the correct context values if (and only if) we have a suitable context menu dev. value (otherwise we just go for the entire object) float percentage = width / 100; //Keep as much precision as possible percentage *= contextMenuDeviation; perc = (int) percentage; } int centreX = (startX + (width / 2)); if (biasDeviation) { Point p = getMouse().getPosition(); int mouseX = (int) p.getX(); if (mouseX > centreX) { //Right side of the context menu startX = centreX; if (perc > 0) { endX = (startX + (perc / 2)); //We do (perc / 2) because in the calculation we account for the entire width } } else { //Left side of the context menu endX = centreX; if (perc > 0) { startX = (centreX - (perc / 2)); } } } else { startX += (perc / 2); endX -= (perc / 2); } //2px bounds incase the bounding boxes are fucked int randX = getRandom(startX + 1, endX - 1); int randY = getRandom(startY + 1, endY - 1); Area mouseArea = createArea(new Point(randX, randY), 2); //Create a 3x3 box while (!mouseArea.contains((int) getMouse().getPosition().getX(), (int) getMouse().getPosition().getY())) { getMouse().move(randX, randY); sleep(sleepDeviateRand(5, 15)); } //move to option sleep(sleepDeviateRand(5, 15)); while (getMenuAPI().isOpen()) { getMouse().click(false); sleep(sleepDeviateRand(5, 15)); } //click sleep(sleepDeviateRand(25, 45)); return true; } Thanks a lot! My script has gotten me from 40-70 range, so no complaints here. Hill Giant Magician should be on the SDN very soon, free for a limited time! Edited September 1, 2015 by Dark Magician Quote Link to comment Share on other sites More sharing options...