Jump to content

Autofighter Only Loots and Buries Some of the Time


Dot

Recommended Posts

I'm writing a goblin killer after my chicken killer worked out and I'm having a weird problem.

Sometimes it loots coins and buries bones as I expect it to, but most of the time it skips that step and just attacks another goblin. I can't really tell what's going on and I've made a bunch of minor adjustments to the code trying to figure it out. Can anyone give me a hint?

 

I tried moving the calls to loot() and buryBones() to within the attackGoblin() void, as well as some random shit like adding that whole "currentGoblin" thing so it didn't pick a new goblin before the bones/coins actually spawn, but I'm at a loss.

 

Code:

Spoiler

	public int onLoop() throws InterruptedException {

		//skillHandler(currentSkill);

		if (dialogues.isPendingContinuation()) {
			dialogues.clickContinue();
		}

		goblin = npcs.closest("goblin");
		
		if (goblin != null && goblin.exists() && goblin.getHealthPercent() > 0 && !myPlayer().isInteracting(goblin)
				&& !myPlayer().isUnderAttack() && !goblin.isUnderAttack() && map.canReach(goblin) && goblinArea.contains(goblin))
		{
			attackGoblin(goblin);
		}
		
		if (lootOption) {
			loot();
		}

		if (buryBonesOption) {
				buryBones();
		}

		return random(200, 300);
	}

	private void attackGoblin(NPC currentGoblin) throws InterruptedException {
		action = "Attacking";
		currentGoblin.interact("Attack");
		antiBan();
		new ConditionalSleep(25000, 500) {
			@Override
			public boolean condition() throws InterruptedException {
				goblinPosition = currentGoblin.getPosition();
				return !currentGoblin.exists();
			}
		}.sleep();
		antibanAction = "None";
		killCount += 1;
		
	}

	private void loot() throws InterruptedException {
		GroundItem item = getGroundItems().closest(lootItemName);
		if (item != null && item.getPosition().equals(goblinPosition) && !inventory.isFull()) {
			action = "Looting";
			item.interact("Take");
			new ConditionalSleep(2500, 500) {
				@Override
				public boolean condition() throws InterruptedException {
					return !item.exists();
				}
			}.sleep();
		}
	}

	private void buryBones() throws InterruptedException {
		GroundItem bones = getGroundItems().closest("Bones");
		if (bones != null && bones.getPosition().equals(goblinPosition) && !inventory.isFull()) {
			action = "Burying";
			bones.interact("Take");
			new ConditionalSleep(3500, 250) {
				@Override
				public boolean condition() throws InterruptedException {
					return !bones.exists();
				}
			}.sleep();
			inventory.getItem("Bones").interact("Bury");
			sleep(random(200, 800));
		}
	}

 

 

Edited by Dot
Link to comment
Share on other sites

I think what might happen is that it attacks a target. When your target is doing a dying animation, it looks for the next target to attack and attacks the next target when such a target is found. The previous target will drop loot after your next target is already chosen, and thus the goblinPosition variable is already overwritten by the new target's position, therefore the if-statement in your loot() method will not be satisfied. The first thing and (to me) most obvious thing to recommend is that you wait until your target has dropped the loot, but there are also other ways to make it work.

Link to comment
Share on other sites

What you might do is, and also what @dreameo is suggesting:

if (!myPlayer.isUnderAttack() {
	if (lootOption) {
		loot();
	} else if (buryBonesOption) {
		buryBones();
	} else if (goblin != null && goblin.exists() && goblin.getHealthPercent() > 0 && !myPlayer().isInteracting(goblin)
			&& !goblin.isUnderAttack() && map.canReach(goblin) && goblinArea.contains(goblin))
	{
		attackGoblin(goblin);
	}
}

This will solve your problem. This might, however, introduce a new problem. You'll have to test it.

  • Like 1
Link to comment
Share on other sites

Thanks dudes.

My lootOption and buryBonesOption are actually just booleans pulled from the GUI to decide whether the user wants the script to bury bones, but I added a "flag" for those functions and got it working.

 

		if (!myPlayer().isUnderAttack()) {
			
			if (lootOption && !looted) {
				loot();
				looted = true;
			}
	
			if (buryBonesOption && !buried) {
				buryBones();
				buried = true;
			}
			
			if (goblin != null && goblin.exists() && goblin.getHealthPercent() > 0 && !myPlayer().isInteracting(goblin)
					&& !goblin.isUnderAttack() && map.canReach(goblin) && goblinArea.contains(goblin)
					&& looted && buried)
			{
				attackGoblin(goblin);
				looted = false;
				buried = false;
			}
		}

 

Just in case anyone sees this in the future, I was still having the same problem even after doing this, so I added a short sleep() to that start of my loot() and buryBones() functions. Just as @feggit suggested, my script was picking a new target before the items actually appeared on screen. I don't know if there's a better API function for this, but the sleep works fine.

 

Thanks again guys. :)

Link to comment
Share on other sites

I think it would help if you made it so all your loop method does is run a bunch of checks and makes a bunch of calls to other functions. Don't handle anything else. That way, you'll know precisely what your script is doing:

@Override
public int onLoop() throws InterruptedException {

	if (dialogues.isPendingContinuation()) {
		dialogues.clickContinue();
		
	} else if (isFighting()) {
		if (isLowOnHealth()) {
			if (canHeal()) {
				heal();
			} else {
				runAway();
			}
		}
		
	
	} else if (areBonesPresentInInventory()) {
		if (!isIdle()) {
			buryNextBone();
		}
		
	} else if (lootingEnabled && isLootPresent()) {
		if (isInventoryFull()) {
			if (isJunkPresent()) {
				dropJunk();
			} else {
				goBankStuff();
			}
		} else {
			loot();
		}
	
	} else {
		fight();
	}

}

 

  • Like 2
Link to comment
Share on other sites

Somehow still having this problem on my third script. The only thing that makes it work is to have an insanely high ConditionalSleep, which I don't think is proper.

	@Override
	public int onLoop() throws InterruptedException {

		skillHandler();
		
		if (!banking) {
			if (dialogues.isPendingContinuation())
				dialogues.clickContinue();
			else if (!combat.isFighting()) {
				if (lootEnabled && !looted)
					loot();
				else if (bonesEnabled && !buried)
					buryBones();
				else if (looted && buried)
					attack();
			} else if (foodEnabled)
				foodHandler();
		} else if (!inventory.contains(foodName) && !combat.isFighting())
			bankHandler();

		return random(200, 300);
	}
	
	@SuppressWarnings("unchecked")
	private void attack() throws InterruptedException {
		antibanAction = "None";
		target = npcs.closest(n -> n.getName().equalsIgnoreCase(targetName) && n.exists()
								&& n.getHealthPercent() > 0 && !myPlayer().isInteracting(n)
								&& !n.isUnderAttack() && n != null);
		if (!map.canReach(target)) doorHandler.getNextObstacle(target);
		else {
			action = "Attacking";
			target.interact("Attack");
			skipKill = false;
			if (lootEnabled) looted = false;
			if (bonesEnabled) buried = false;
			antiBan();
			new ConditionalSleep(() -> targetPosition = target.getPosition(), 5000, 100) {
				@Override
				public boolean condition() throws InterruptedException {
					if (!combat.isFighting() && target.isUnderAttack()) {
						log("Someone else is fighting that. Looping.");
						skipKill = true;
					}
					return combat.isFighting() || skipKill;
				}
			}.sleep();
			if (!skipKill) killCount += 1;
		}
	}

 

The looted & buried vars are only set within the loot() and bury() functions, but somehow they reset to true even with a 2-3 second sleep time at the start of those functions.

onLoop() is setup in a way that attack() can't be called until loot() and bury() complete. I have tried adding ConditionalSleeps to those functions to wait until the item exists but that seems to have no effect (without a huge timeout).

I'm getting really frustrated. The fuck am I doing wrong?

Edit: I seem to be getting a massive chain of NPE's when my script doesn't loot/bury. No info other than "[ERROR][Bot #1][11/12 08:51:38 PM]: Error in script executor! java.lang.NullPointerException"

 

Edit 2: Huge oversight on my part by having the targetPosition only get updated during the ConditionalSleep and not at any point after attack() has returned. Fairly sure that's where my problem lies.

I think I can solve this by adding a hasDied() function that checks the NPC the player is interacting with for a death animation and stores the targetPosition when it happens, and call bury() and loot() when it returns true.

Edited by Dot
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...