Jump to content

Perfect Combat


LifezHatred

Recommended Posts

Made this a while ago and thought some people could make use of it
What it does?
Stores Data of Entities that are in combat or are initiating combat
Uses this data to determine what to attack without any mistakes (Doesn't target any npcs already being attacked, or switches to a new target if another player reaches a npc before you. Also it targets npcs that target/attack you)
Thought that this was a little bit more trustworthy than what the API provides and has many uses you can build into it (such as detecting players attacking you and other stuff)
Also as fucked up as it sounds i plan to make a pking bot out of this system (Would rework some of the stuff in it)
But anyways i am aware the code could be cleaned up a little bit but too lazy to go through it
 
3 classes, (or 2 classes and modify your main class) 
Main -
(note have your loop set to 300 (runescape sends data to client every 600 ms, so having it at 300 ensures that no data is missed)
package source;
 
import org.osbot.script.Script;
import org.osbot.script.ScriptManifest;
 
@ScriptManifest(author = "Zach (LifezHatred)", info = "Combat info", name = "Combat", version = 1.0)
public class Main extends Script {
 
        public Combat combat = new Combat(this);
 
        public int onLoop() {
                if(runCombatListener()) {
                        combat.update();
                }
                return 300;
        }
 
        public boolean runCombatListener() {
                return true;
        }
 
}
Combat Class (Factory)
package source;
 
import java.util.ArrayList;
import java.util.List;
 
import org.osbot.script.rs2.model.Character;
import org.osbot.script.rs2.model.Entity;
import org.osbot.script.rs2.model.NPC;
import org.osbot.script.rs2.model.Player;
 
public class Combat {
 
        public Main main;
        public List<CombatEntity> combatEntities;
 
 
        public Combat(Main main) {
                this.main = main;
                combatEntities = new ArrayList<CombatEntity>();
        }
 
        public void update() {
                //Clean Up
                for(CombatEntity combat : combatEntities) {
                        if(combat == null) {
                                combatEntities.remove(combat);
                                continue;
                        }
                        if(!combat.getEntity().exists()) {
                                if(combat.hasAttacked) {
                                        CombatEntity cleanup = combat.getAttacking();
                                        cleanup.attacker = null;
                                        if(cleanup.attacking == combat) {
                                                cleanup.setAttacking(null);
                                                cleanup.setHasAttacked(false);
                                        }
                                }
                        }
                }
                //add new entities
                for(NPC npc : main.client.getLocalNPCs()) {
                        if(npc == null) {
                                continue;
                        }
                        Entity facing = npc.getFacing();
                        if(facing != null) {
                                if(!exists(npc)) {
                                        combatEntities.add(new CombatEntity(npc,facing));
                                }
                        } else {
                                if(exists(npc)) {
                                        CombatEntity remove = getCombatEntity(npc);
                                        combatEntities.remove(remove);
                                }
                        }
                }
                for(Player player : main.client.getLocalPlayers()) {
                        if(player == null) {
                                continue;
                        }
                        Entity facing = player.getFacing();
                        if(facing != null) {
                                if(!exists(player)) {
                                        combatEntities.add(new CombatEntity(player,facing));
                                }
                        } else {
                                if(exists(player)) {
                                        CombatEntity remove = getCombatEntity(player);
                                        combatEntities.remove(remove);
                                }
                        }
                }
                //Updates state of the entities
                for(CombatEntity combat : combatEntities) {
                        if(combat == null) {
                                combatEntities.remove(combat);
                                continue;
                        }
                        Entity facing = ((Character<?>) combat.getEntity()).getFacing();
                        if(combat.getFacing() != facing) { //switched to new target
                                if(combat.getHasAttacked()) {
                                        CombatEntity entity = combat.getAttacking();
                                        combat.setHasAttacked(false);//if switched to new target we do not know if he has fully attacked yet
                                        combat.setFacing(facing);
                                        entity.setAttacker(null);
                                }
                        }
                        if(((Character<?>) combat.getEntity()).getAnimation() != -1) { //made a combat animation (if non combat animation has happened you would no longer be facing a target and wouldn't reach this point)
                                combat.setHasAttacked(true);
                                CombatEntity attacking = getCombatEntity(combat.getFacing());
                                attacking.setAttacker(combat);
                                combat.setAttacking(attacking);
                        }
                }
        }
 
        public boolean attack(int targetId) throws InterruptedException {
                Entity target = getClosestTarget(targetId);
                if(target == null) {
                        return false;
                }
                target.interact("Attack");
                return true;
        }
 
        public boolean attackRandomWithinDistance(int distance, int targetId) throws InterruptedException {
                Entity target = getRandomTarget(distance, targetId);
                if(target == null) {
                        return false;
                }
                target.interact("Attack");
                return true;
        }
 
        public boolean canAttack() {
                CombatEntity myPlayer = getCombatEntity(main.client.getMyPlayer());
                if(myPlayer.isAttacking()) {
                        return false;
                }
                if(myPlayer.getFacing() != null) {
                        CombatEntity facing = getCombatEntity(myPlayer.getFacing());
                        if(facing.getAttacker() != myPlayer) {
                                return true;
                        }
                        return false;
                }
                return true;
        }
 
        public Entity getRandomTarget(int targetId, int distance) { //will still return if being attacked by an aggressive npc
                CombatEntity myPlayer = getCombatEntity(main.client.getMyPlayer());
                for(CombatEntity combat : combatEntities) {
                        if(combat == null) {
                                combatEntities.remove(combat);
                                continue;
                        }
                        if(combat.getFacing() == main.client.getMyPlayer()) {
                                if(combat.beingAttacked() && combat.getAttacker() != myPlayer) {
                                        continue;
                                }
                                return combat.getEntity(); //If being targetted by a npc in an aggressive area, checks if this npc is being attacked by another player
                        }
                }
                List<NPC> attackables = new ArrayList<NPC>();
                for(NPC npc : main.client.getLocalNPCs()) {
                        if(npc == null) {
                                continue;
                        }
                        if(npc.getId() != targetId) {
                                continue;
                        }
                        if(exists(npc)) {
                                CombatEntity combatEntity = getCombatEntity(npc);
                                if(combatEntity.beingAttacked()) {
                                        continue;
                                }
                        }
                        int distanceBetween = main.client.getMyPlayer().getPosition().distance(npc.getPosition());
                        if(distanceBetween < distance) { //checks if this entity is closer or not, if so sets it to the currently known closest npc
                                attackables.add(npc);
                        }
                }
                if(attackables.size() == 0) {
                        return null;
                }
                NPC toReturn = attackables.get((int) (Math.random() * (attackables.size()-1)));
                return toReturn;
        }
 
        public Entity getClosestTarget(int targetId) {
                CombatEntity myPlayer = getCombatEntity(main.client.getMyPlayer());
                for(CombatEntity combat : combatEntities) {
                        if(combat == null) {
                                combatEntities.remove(combat);
                                continue;
                        }
                        if(combat.getFacing() == main.client.getMyPlayer()) {
                                if(combat.beingAttacked() && combat.getAttacker() != myPlayer) {
                                        continue;
                                }
                                return combat.getEntity(); //If being targetted by a npc in an aggressive area, checks if this npc is being attacked by another player
                        }
                }
                NPC closestAttackable = null;
                int distance = 20; //Max distance it'll attack (change if you want O.o)
                for(NPC npc : main.client.getLocalNPCs()) {
                        if(npc == null) {
                                continue;
                        }
                        if(npc.getId() != targetId) {
                                continue;
                        }
                        if(exists(npc)) {
                                CombatEntity combatEntity = getCombatEntity(npc);
                                if(combatEntity.beingAttacked()) {
                                        continue;
                                }
                        }
                        int distanceBetween = main.client.getMyPlayer().getPosition().distance(npc.getPosition());
                        if(distanceBetween < distance) { //checks if this entity is closer or not, if so sets it to the currently known closest npc
                                closestAttackable = npc;
                                distance = distanceBetween;
                        }
                }
                return closestAttackable; //if returns null there is no npcs to attack O.o
        }
 
        public boolean exists(Entity entity) {
                for(CombatEntity check : combatEntities) {
                        if(check == null) {
                                combatEntities.remove(check);
                                continue;
                        }
                        if(check.isEntity(entity)) {
                                return true;
                        }
                }
                return false;
        }
 
        public CombatEntity getCombatEntity(Entity entity) {
                for(CombatEntity check : combatEntities) {
                        if(check == null) {
                                combatEntities.remove(check);
                                continue;
                        }
                        if(check.isEntity(entity)) {
                                return check;
                        }
                }
                return null;
        }
 
}
3rd class CombatEntity (Object)
package source;
 
import org.osbot.script.rs2.model.Entity;
 
public class CombatEntity {
 
        public Entity entity;
        public Entity facing;
        public boolean hasAttacked;
        public CombatEntity attacker = null;
        public CombatEntity attacking = null;
 
        public CombatEntity(Entity entity, Entity facing) {
                this.entity = entity;
                this.facing = facing;
        }
 
        public boolean isEntity(Entity entity) {
                if(this.entity == entity) {
                        return true;
                }
                return false;
        }
 
        public boolean getHasAttacked() {
                return hasAttacked;
        }
 
        public void setHasAttacked(boolean bool) {
                hasAttacked = bool;
        }
 
        public Entity getEntity() {
                return entity;
        }
 
        public Entity getFacing() {
                return facing;
        }
 
        public void setFacing(Entity facing) {
                this.facing = facing;
        }
 
        public CombatEntity getAttacking() {
                return attacking;
        }
 
        public void setAttacking(CombatEntity entity) {
                attacking = entity;
        }
 
        public CombatEntity getAttacker() {
                return attacker;
        }
 
        public void setAttacker(CombatEntity attacker) {
                this.attacker = attacker;
        }
 
        public boolean beingAttacked() {
                if(attacker != null) {
                        return true;
                }
                return false;
        }
 
        public boolean isAttacking() {
                if(attacking != null) {
                        return true;
                }
                return false;
        }
}
 
 
To use this simply have this set to true when your bot is going to be entering combat

        public boolean runCombatListener() {
                if((methods to set true)) {
                        return true;
                }
                return false;
        }
 
And then for attacking, whatever system your using to perform actions use this to check if your character can attack
canAttack()
and if it can attack use these methods to attack an npc //note will always attack an npc attacking you even if its not the type of npc you declare in the npc id

attackRandomWithinDistance(int distance, int targetId)
or
attack(int targetId)

Good luck and have fun with making combat scripts with this code =D

(note might remove for a little bit depending on some things)

Also there is a small anti-leech (null pointer in there) simple fix

 

Edited by LifezHatred
Link to comment
Share on other sites

I use a class that I made to scan all available NPC's for a certain name. It scans through all the NPC's on the map, checks the name and sees if they are facing the player etc. If they are, it adds them to a List for the script to check every so often if they are animating (attacking the player) - if it finds tht, it adds the NPC to the attacking List.

This is all done in a thread, so it doesn't hang the script from running one bit.

Next, it scans through the NPC's and checks what is closest to you and not under attack etc.

The best part about this class, you call getNPC() and it returns the NPC that the script should attack.

Threads are a beautiful thing if you know how to use them.

Link to comment
Share on other sites

  • 2 weeks later...

 

 

Way over complicated, but good job on the contribution.

How is it over complicated O.o

 

Because combat is very script specific. Some should let it auto attack. Some should walk and attack. Some should rotate the camera and attack. I was able to do all this in ~50 lines and it works flawlessly.

 

And this simply keeps track of what is in combat and what isn't in combat, you can add your own attack methods in this hell i  even provided 2

Link to comment
Share on other sites

inb4 OP whines to mod to remove my post.

 

Why would you even need to keep a cache of all the NPC based on whether they are in combat or not? Ultimately, you need one single result. One result that you can instruct your bot to attack, and here's how to:

 

Instructions how-to:

  1. Get a cache of existing monsters.
  2. Filter out the monsters that you aren't interested in.
  3. Sort out the remaining monsters based on distance.
  4. Poll for the first monster in that sorted cache.

You can slap all that in a single method. Heck, I even made an adapter for it.

 

The only purpose I can think of for your code is to gather statistics.

Link to comment
Share on other sites

inb4 OP whines to mod to remove my post.

 

Why would you even need to keep a cache of all the NPC based on whether they are in combat or not? Ultimately, you need one single result. One result that you can instruct your bot to attack, and here's how to:

 

Instructions how-to:

  1. Get a cache of existing monsters.
  2. Filter out the monsters that you aren't interested in.
  3. Sort out the remaining monsters based on distance.
  4. Poll for the first monster in that sorted cache.

You can slap all that in a single method. Heck, I even made an adapter for it.

 

The only purpose I can think of for your code is to gather statistics.

This is a system to keep track of all entities, with this system you can define whether a entity is engaging combat, has actually landed an attack, and if the entity it attack attacked back (this allows the bot to attack npcs that are attacking other players but haven't attacked back, instantly attack the npc that attacked you, and will let you know instantly if someone else reached a monster before you reached it). This system is very useful in areas were monsters are aggressive, such as chaos druids, dragons, etc. Try and figure out exactly what this system is useful for/brings before you bring in something irrelevant (to what this system provides) saying its better.

This is also an alternate to what the API provides, This just defines combat a little better than the API currently does

Edited by LifezHatred
Link to comment
Share on other sites

 

I came here to look for a combat snippet so I can attack the nearest possible monsters and I find a HUGE wall of code lmao. It looks nice, but not the kind of thing I need.

 

Dreamliner do you study engineering by any chance?

Yes I do, Mechanical

 

Please stay on topic, handle anything off topic through pms please

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

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