Jump to content

Best method to look for grounditems dropped only by monsters you kill


Camaro

Recommended Posts

Consider the following scenario: You are killing monsters around other players who are killing the same monsters with iron arrows. You want to loot the iron arrows dropped by your monsters, but not pick up any other iron arrows on the ground.

What is the best way to achieve this?

I have written some code, but not sure if this is efficient...

        if (myPlayer().getInteracting() != null &&
                Timing.waitCondition(() -> myPlayer().getInteracting().getHealthPercent() == 0, 5000)) {
            LAST_KILL = myPlayer().getInteracting().getPosition();
        } else if (!getCombat().isFighting()) {
            GroundItem item = getGroundItems().closest(g ->
                    g != null &&
                            getMap().canReach(g) &&
                            (g.getName().equals("Iron arrow") &&
                                    g.getAmount() > 4 &&
                                    g.getPosition().equals(LAST_KILL)));
            if (item != null) {
                int count = (int) inventory.getAmount(item.getName());
                if (item.interact("Take")) {
                    Timing.waitCondition(() -> inventory.getAmount(item.getName()) > count, 3000);
                }
            }
        }

Once the monster's health percent, I store that monsters position to a variable. Then I make sure that the ground item's position is the same as the stored position.

Link to comment
Share on other sites

Seem to be having better luck with this

        if (myPlayer().getInteracting() != null) {
            CURR_KILL = myPlayer().getInteracting();
            List<GroundItem> items = getGroundItems().get(CURR_KILL.getX(), CURR_KILL.getY());
            items.removeIf(i -> !i.getName().equals("Bones"));
            if (Timing.waitCondition(() -> {
                List<GroundItem> items2 = getGroundItems().get(CURR_KILL.getX(), CURR_KILL.getY());
                items2.removeIf(i -> !i.getName().equals("Bones"));
                return items.size() < items2.size();
            }, 10000)) {
                GroundItem item = getGroundItems().closest(g ->
                        g != null &&
                                getMap().canReach(g) &&
                                (g.getName().equals("Iron arrow") &&
                                        g.getAmount() > 4 &&
                                        g.getPosition().equals(CURR_KILL.getPosition())));
                if (item != null) {
                    int count = (int) inventory.getAmount(item.getName());
                    if (item.interact("Take")) {
                        Timing.waitCondition(() -> inventory.getAmount(item.getName()) > count, 3000);
                    }
                }
            }
        }

If the player is interacting (fighting) with something, wait until their bones drop. then scan for items.

Link to comment
Share on other sites

I'm guessing this is for ironmen? :)

The key for this would be to not only look for loot where the monster was killed, but to also go through the items you want 1-by-1 to check whether you can loot it, and to remove it from the list if you can't.

import java.util.LinkedList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.osbot.rs07.api.map.Position;
import org.osbot.rs07.api.model.GroundItem;
import org.osbot.rs07.api.model.NPC;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.utility.ConditionalSleep;

public class test extends Script {

	NPC target;
	Position targetTile;
	LinkedList<GroundItem> loot;
	GroundItem nextLoot;
	
	@Override
	public int onLoop() throws InterruptedException {
		
		target = npcs.closest("Something...");
		targetTile = target.getPosition();
		
		{ // once target is dead
			
			loot();
		}
		
		
		return 0;
	}
	
	private void loot() {
		
		if (loot == null) { // let's find some loot
			loot = getGroundItems(targetTile, "Iron arrows", "Bronze arrows", "Bone bolts");
		
		} else if (loot.isEmpty()) { // can't loot anything else
			loot = null;
			
		} else if (nextLoot != null && nextLoot.exists()) { // next loot ready for the taking
			
			if (takeItem(nextLoot)) { 
				// check inventory to make sure we picked it up...
				// tally up a counter....
				// price check.....
				// etc......
			}
			
			nextLoot = null;
			
		} else { // need to get the next loot in the queue
			nextLoot = loot.poll();
		}
	}
	
	private boolean takeItem(GroundItem item) {
		
		boolean taken = false;
		
		ConditionalSleep sleepyTimesUntilWePickupItem;
		
		if (item != null && item.exists()) {
			
			sleepyTimesUntilWePickupItem = new ConditionalSleep(2500) {
				
				@Override
				public boolean condition() throws InterruptedException { // item exists in memory, but not in game
					return item != null && !item.exists();
				}
			};
			
			if (item.interact("Take")) {
				
				taken = sleepyTimesUntilWePickupItem.sleep(); // assume we picked it up
			}
		}
		
		return taken;
	}

	private LinkedList<GroundItem> getGroundItems(Position tile, String... names) {
		return groundItems.get(tile.getX(), tile.getY())
				.stream()
				.filter(item -> Stream.of(names).anyMatch(item.getName()::equalsIgnoreCase))
				.collect(Collectors.toCollection(LinkedList<GroundItem>::new));
	}

	
	
}

Untested btw.

  • Like 1
Link to comment
Share on other sites

        if ((CURR_KILL = myPlayer().getInteracting()) != null) {
            if (CURR_KILL.getHealthPercent() == 0) {
                List<GroundItem> items = getGroundItems().get(CURR_KILL.getX(), CURR_KILL.getY());
                items.removeIf(i -> !i.getName().equals("Bones"));
                if (Timing.waitCondition(() -> {
                    List<GroundItem> items2 = getGroundItems().get(CURR_KILL.getX(), CURR_KILL.getY());
                    items2.removeIf(i -> !i.getName().equals("Bones"));
                    return items.size() < items2.size();
                }, 5000)) {
                    GroundItem item = getGroundItems().closest(g ->
                            g != null &&
                                    getMap().canReach(g) &&
                                    (g.getName().equals("Iron arrow") &&
                                            g.getPosition().equals(CURR_KILL.getPosition())));
                    if (item != null) {
                        int count = (int) inventory.getAmount(item.getName());
                        if (item.interact("Take"))
                            Timing.waitCondition(() -> inventory.getAmount(item.getName()) > count, 3000);
                    }
                }
            }
        }

Believe I have perfected this...
 

Keep looping until the monster I am interacting with has zero health. Then save it's position and wait for the bones to appear. Then loot any arrows with that monsters position.

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