Jump to content

Improving my combat method


omni4life

Recommended Posts

Hey all, back again for yet another round of questions.

 

I wrote an ultra quick Yak killer today for personal use, however, I have some issues with the combat method and I would love some more experienced users input.

 

This is my method as it stands at the moment:

case ATTACK:
	NPC yak = npcs.closest("Yak");
	if (yak != null && !combat.isFighting() && !yak.isUnderAttack()) {
		yak.interact("Attack");
		status = "Interacting with Yak";
		sleep(random(500,800));
	}
	break;

These are my questions:

 

  1. As my character kills the NPC, the NPC enters its death animation thus rendering !combat.isFighting() false and the method continues to click the NPC attempting to re initiate combat. Is there a check I can implement so that once the NPC I'm fighting begins its death animation I can instantly move onto the next? The clicking a dying NPC looks very botlike, but I'm unsure how to combat it.
  2. Sometimes, despite the fact my character is already under attack from a Yak it will ignore it and attempt to fight a different Yak, spam clicking it and being unable to attack as it isn't a multicombat zone. Is there a reason it's doing this that I can't see or is the !combat.isFighting method just a little bit iffy?

Thanks for any and all help as always! I really appreciate all of your input, ideas and advice.

 

-Omni.

Link to comment
Share on other sites

So what you're doing is:

 

> Finding the nearest yak

> checking if the chosen yak exists

> checking if the chosen yak isn't fighting

> checking if the chosen yak isn't under attack

 

what happens if it's fighting, or it's under attack? it will just wait/repeat cycle

 

INSTEAD,

 

you need to FILTER the yaks, and find the closest one which fits certain criteria: (the above conditions), and NOT find the closest yak, and check if it meets criteria

 

As for the two questions;

 

1. check if the npc's health is above 0, and to make it faster, use the filter I mentioned above

2. you need to check if your character is interacting or being interacted, if it is, don't attack

 

 

 

Edited by Czar
  • Like 2
Link to comment
Share on other sites

public class YakFilter implements Filter<NPC> {

    public boolean match(NPC npc) {
        return npc != null 
            && npc.getName().equals("Yak")
            && npc.getHealth() > 0
    }

}

^ Use a custom filter to find the yaks that aren't dying

Can be used like so:

NPC yak = getNpcs().closest(new YakFilter());
Edited by FrostBug
  • Like 2
Link to comment
Share on other sites

public class YakFilter implements Filter<NPC> {    public boolean match(NPC npc) {        return npc != null             && npc.getName().equals("Yak")            && npc.getHealth() > 0    }}
^ Use a custom filter to find the yaks that aren't dying

Can be used like so:

NPC yak = getNpcs().closest(new YakFilter());

What's the advantage for a custom filter over just an anonymous filter?

Link to comment
Share on other sites

So what you're doing is:

> Finding the nearest yak

> checking if the chosen yak exists

> checking if the chosen yak isn't fighting

> checking if the chosen yak isn't under attack

what happens if it's fighting, or it's under attack? it will just wait/repeat cycle

INSTEAD,

you need to FILTER the yaks, and find the closest one which fits certain criteria: (the above conditions), and NOT find the closest yak, and check if it meets criteria

As for the two questions;

1. check if the npc's health is above 0, and to make it faster, use the filter I mentioned above

2. you need to check if your character is interacting or being interacted, if it is, don't attack

Thanks very much for the advice. With point 2, !combat.isFighting checks of my player is interacting, but not being interacted yes? I'm away from my pc/api at the minute, but which class is interacted under? MyPlayer()?

Thanks for any and all input everyone!

Link to comment
Share on other sites

NPC target = npcs.closest(new Filter<NPC>() {
        @Override
        public boolean match(NPC npc) {
            return npc != null && npc.getName().equals("Yak") && !npc.isUnderAttack() && npc.getHealth() > 0 && map.canReach(npc);
        }
        });

I really don't mean to be spoon fed, but I'm struggling a little bit to understand the implementation. I've only just begun an online course on Java so for the most part I struggle to follow anything outside of states and if statements. I'm hoping to actually move to a node/OOP style next script, but I don't understand it well enough yet. If I post my current code, could you be so kind as to give me a demonstration of how it would be integrated? Either way, I'll keep experimenting with everything so thank you very much to both you and everyone else for your advice and input smile.png!

import org.osbot.rs07.api.model.NPC;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;

import java.awt.*;

@ScriptManifest(author = "Omni4life", info = "Kills Yaks on Neitiznot.", name = "Yakinator", version = 1, logo = "")
public class yakKiller extends Script {

	// Declare all Variables
	public static String status;

	@Override
	public void onStart() {
		log("Yak Killer by Omni4life has begun.");
		log("If you experience any issues while running this script please report them to me on the forums.");
	}

	private enum State {
		ATTACK, WAIT
	};

	private State getState() {
		NPC yak = npcs.closest("Yak");
		if (yak != null)
			return State.ATTACK;
		return State.WAIT;
	}

	@Override
	public int onLoop() throws InterruptedException {
		switch (getState()) {
		case ATTACK:
			NPC yak = npcs.closest("Yak");
			if (yak != null && !combat.isFighting() && !yak.isUnderAttack() && yak.isAttackable()) {
				yak.interact("Attack");
				status = "Interacting with Yak";
				sleep(random(500, 800));
			}
			break;
		case WAIT:
			sleep(random(500, 700));
			break;
		}
		return random(200, 300);
	}

	@Override
	public void onExit() {
		log("Thanks for running Yak Killer");
	}

	@Override
	public void onPaint(Graphics2D g) {

	}

}
Edited by omni4life
Link to comment
Share on other sites

Something like this? (not an expert either smile.png )

case ATTACK:
NPC target = npcs.closest(new Filter<NPC>() {
@Override
public boolean match(NPC npc) {
    return npc != null && npc.getName().equals("Yak") && 
    !npc.isUnderAttack() && npc.getHealth() > 0 && map.canReach(npc);
    }
});
            
if (target != null) {
   target.interact("Attack");
   status = "Interacting with Yak";
   sleep(random(500, 800));
 }

else {
 // No yak available
}

break;
Edited by Appelflapjes
Link to comment
Share on other sites

private State getState() {
		NPC yak = npcs.closest("Yak");
		if (yak != null)
			return State.ATTACK;
		return State.WAIT;
	}

remove this

NPC yak = npcs.closest("Yak");
		if (yak != null)
			return State.ATTACK;
		return State.WAIT;

and you could change it in different ways. Mine may not be the best but it works


		if (!myplayer().isanimating && !myplayer.isUnderAttack)
			return State.ATTACK;
		return State.WAIT;

then your case can be changed from 

case ATTACK:
			NPC yak = npcs.closest("Yak");
			if (yak != null && !combat.isFighting() && !yak.isUnderAttack() && yak.isAttackable()) {
				yak.interact("Attack");
				status = "Interacting with Yak";
				sleep(random(500, 800));
			}
			break;

to..

case ATTACK:
			NPC target = npcs.closest(new Filter<NPC>() //add the whole filter code snippet i gave at top. here

			if (target != null && !combat.isFighting() && target.isAttackable()) {
				target.interact("Attack");
				status = "Interacting with Yak";
				sleep(random(500, 800));
			}
			break;
  • Like 1
Link to comment
Share on other sites

NPC target = npcs.closest(new Filter<NPC>() {
        @Override
        public boolean match(NPC npc) {
            return npc != null && npc.getName().equals("Yak") && !npc.isUnderAttack() && npc.getHealth() > 0 && map.canReach(npc);
        }
        });

The class that frost presented look way cleaner in my opinion. Both you guys had the samething except you had an extra

private State getState() {
		NPC yak = npcs.closest("Yak");
		if (yak != null)
			return State.ATTACK;
		return State.WAIT;
	}
remove this

NPC yak = npcs.closest("Yak");
		if (yak != null)
			return State.ATTACK;
		return State.WAIT;
and you could change it in different ways. Mine may not be the best but it works

		if (!myplayer().isanimating && !myplayer.isUnderAttack)
			return State.ATTACK;
		return State.WAIT;
then your case can be changed from 

to..

case ATTACK:
			NPC target = npcs.closest(new Filter<NPC>() //add the whole filter code snippet i gave at top. here

			if (target != null && !combat.isFighting() && target.isAttackable()) {
				target.interact("Attack");
				status = "Interacting with Yak";
				sleep(random(500, 800));
			}
			break;
  • Like 1
Link to comment
Share on other sites

 

Thanks to everyone for all your help, I really appreciate the lengths you all go to to try and help out new folks around here! After uni today I'll give adding it a go and I'll test it out smile.png. Thanks again!

 
 
NPC Filter + check if another player is interacting with it. smile.png
 
   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 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 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 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));
        }
    }
  NPC yak = getNpcs().closest(new Filter<NPC>() {
                    @Override
                    public boolean match(NPC npc) {
                        return npc != null && npc.exists() && npc.getName().contains("Yak") && npc.isAttackable() && !npc.isUnderAttack() && npc.getHealth() != 0 && !isPlayerInteracting(npc) && map.isWithinRange(myPlayer().getPosition(), npc, 7);
                    }});

                if (isNpcValid(yak)) {
                    interact(yak, "Attack");
                }
Edited by Dark Magician
Link to comment
Share on other sites

            if (p.getInteracting() != null && p.getInteracting() == npc || p.getInteracting() != null && p.getInteracting().getPosition() == npc.getPosition() || p.getInteracting() != null && p.getInteracting().isInteracting(npc)) {
                return true;
            }

 

What am I reading o_O

this whole thing is literally the same as

if(npc == p.getInteracting()) {
    return true;
}
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...