Jump to content

Improved Interact


Dark Magician

Recommended Posts

This is more accurate than the standard GroundItem interact. :D

   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 by Dark Magician
  • Like 1
Link to comment
Share on other sites

            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 by FrostBug
  • Like 1
Link to comment
Share on other sites

            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. biggrin.png

 

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 biggrin.png

Edited by Dark Magician
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by Dark Magician
Link to comment
Share on other sites

Thanks for the information. biggrin.png

 

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 biggrin.png

 

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.

Link to comment
Share on other sites

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 by Dark Magician
Link to comment
Share on other sites

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:

 

7dddb7c92156c4b342a51b15c59fe7b0.png

 

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.

 

 

 

  • Like 3
Link to comment
Share on other sites

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:

 

7dddb7c92156c4b342a51b15c59fe7b0.png

 

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. biggrin.png

 

Will now rewrite and make my method better.

Edited by Dark Magician
Link to comment
Share on other sites

Wow thanks for the information! Very helpful. biggrin.png

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 smile.png

 

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 by Bobrocket
  • Like 1
Link to comment
Share on other sites

 

When I get on my PC, I'll post my interact method so you can get a feel for it smile.png

 

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! smile.png

 

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 by Dark Magician
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...