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