Jump to content

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


Recommended Posts

Posted

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.

Posted

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.

Posted

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

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