Code:
package com.rs.game.npc;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.rs.Settings;
import com.rs.cache.Cache;
import com.rs.cache.loaders.ItemDefinitions;
import com.rs.cache.loaders.NPCDefinitions;
import com.rs.cores.CoresManager;
import com.rs.game.Animation;
import com.rs.game.Entity;
import com.rs.game.ForceTalk;
import com.rs.game.Graphics;
import com.rs.game.Hit;
import com.rs.game.World;
import com.rs.game.WorldTile;
import com.rs.game.Hit.HitLook;
import com.rs.game.item.Item;
import com.rs.game.npc.combat.NPCCombat;
import com.rs.game.npc.combat.NPCCombatDefinitions;
import com.rs.game.npc.familiar.Familiar;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.player.actions.HerbCleaning;
import com.rs.game.player.actions.PlayerCombat;
import com.rs.game.player.content.Burying;
import com.rs.game.player.controlers.WarriorsGuildControler;
import com.rs.game.player.controlers.Wilderness;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;
import com.rs.utils.MapAreas;
import com.rs.utils.Misc;
import com.rs.utils.NPCBonuses;
import com.rs.utils.NPCCombatDefinitionsL;
import com.rs.utils.NPCDrops;
import com.rs.utils.Utils;
public class NPC extends Entity implements Serializable {
private static final long serialVersionUID = -4794678936277614443L;
private int id;
private int renderEmote;
private WorldTile respawnTile;
private int mapAreaNameHash;
private boolean canBeAttackFromOutOfArea;
private boolean randomwalk;
private int[] bonuses; // 0 stab, 1 slash, 2 crush,3 mage, 4 range, 5 stab
// def, blahblah till 9
private boolean spawned;
private transient NPCCombat combat;
private WorldTile forceWalk;
private boolean intelligentRouteFinder;
private long lastAttackedByTarget;
private boolean cantInteract;
private int capDamage;
private int lureDelay;
private boolean cantFollowUnderCombat;
private boolean forceAgressive;
private int forceTargetDistance;
private boolean forceFollowClose;
private boolean forceMultiAttacked;
// npc masks
private transient Transformation nextTransformation;
// name changing masks
private String name;
private transient boolean changedName;
private int combatLevel;
private transient boolean changedCombatLevel;
private transient SecondaryBar nextSecondaryBar;
private transient Player owner;
public NPC(int id, WorldTile tile, int mapAreaNameHash, boolean canBeAttackFromOutOfArea) {
this(id, tile, mapAreaNameHash, canBeAttackFromOutOfArea, false);
}
private boolean noDistanceCheck;
public void setNoDistanceCheck(boolean noDistanceCheck) {
this.noDistanceCheck = noDistanceCheck;
}
public boolean isNoDistanceCheck() {
return noDistanceCheck;
}
public void SpawnPrivateNPC(Player owner, int id, boolean isPrivateNpc, int loc) {
this.owner = owner;
// this.id = npcId;
// this.loc = WorldTile.x;
}
public void isPrivateNpc() {
}
public void setSpawned(boolean spawned) {
this.spawned = spawned;
}
public boolean isFamiliar() {
return this instanceof Familiar;
}
public SecondaryBar getNextSecondaryBar() {
return nextSecondaryBar;
}
public void setNextSecondaryBar(SecondaryBar secondaryBar) {
this.nextSecondaryBar = secondaryBar;
}
/*
* creates and adds npc
*/
public NPC(int id, WorldTile tile, int mapAreaNameHash, boolean canBeAttackFromOutOfArea, boolean spawned) {
super(tile);
this.id = id;
this.respawnTile = new WorldTile(tile);
this.mapAreaNameHash = mapAreaNameHash;
this.canBeAttackFromOutOfArea = canBeAttackFromOutOfArea;
this.spawned = spawned;
combatLevel = -1;
setHitpoints(getMaxHitpoints());
setDirection(getRespawnDirection());
setRandomWalk((getDefinitions().walkMask & 0x2) != 0 || forceRandomWalk(id));
bonuses = NPCBonuses.getBonuses(id);
combat = new NPCCombat(this);
capDamage = -1;
lureDelay = 12000;
// npc is inited on creating instance
initEntity();
World.addNPC(this);
World.updateEntityRegion(this);
// npc is started on creating instance
loadMapRegions();
checkMultiArea();
}
@Override
public boolean needMasksUpdate() {
return super.needMasksUpdate() || nextSecondaryBar != null || nextTransformation != null
|| getCustomName() != null || getCustomCombatLevel() >= 0 /*
* * changedName
*/;
}
public void transformIntoNPC(int id) {
setNPC(id);
nextTransformation = new Transformation(id);
}
public void setNPC(int id) {
this.id = id;
bonuses = NPCBonuses.getBonuses(id);
}
@Override
public void resetMasks() {
super.resetMasks();
nextTransformation = null;
changedCombatLevel = false;
changedName = false;
nextSecondaryBar = null;
}
public int getMapAreaNameHash() {
return mapAreaNameHash;
}
public boolean canBeAttackFromOutOfArea() {
return canBeAttackFromOutOfArea;
}
public NPCDefinitions getDefinitions() {
return NPCDefinitions.getNPCDefinitions(id);
}
public NPCCombatDefinitions getCombatDefinitions() {
return NPCCombatDefinitionsL.getNPCCombatDefinitions(id);
}
@Override
public int getMaxHitpoints() {
return getCombatDefinitions().getHitpoints();
}
public int getId() {
return id;
}
public static void main(String[] args) throws IOException {
Cache.init();
}
public void processNPC() {
if (isDead())
return;
if (!combat.process()) { // if not under combat
if (!isForceWalking()) {// combat still processed for attack delay
// go down
// random walk
if (!cantInteract) {
if (!checkAgressivity()) {
if (getFreezeDelay() < Utils.currentTimeMillis()) {
if (((hasRandomWalk()) && World.getRotation(getPlane(), getX(), getY()) == 0) // temporary
// fix
&& Math.random() * 1000.0 < 100.0) {
int moveX = (int) Math.round(Math.random() * 10.0 - 5.0);
int moveY = (int) Math.round(Math.random() * 10.0 - 5.0);
resetWalkSteps();
if (getMapAreaNameHash() != -1) {
if (!MapAreas.isAtArea(getMapAreaNameHash(), this)) {
forceWalkRespawnTile();
return;
}
addWalkSteps(getX() + moveX, getY() + moveY, 5);
} else
addWalkSteps(respawnTile.getX() + moveX, respawnTile.getY() + moveY, 5);
}
}
}
}
}
}
// if (getCombat().getTarget() instanceof Player) {
// }
if (this.getDefinitions().getName().contains("Revenant")) {
setForceAgressive(true);
}
if (this.getDefinitions().getName().contains("Revenant")) {
final Player player = getCombat().getTarget() instanceof Player ? (Player) getCombat().getTarget() : null;
if (player != null) {
if (player.containsForinthry()) {
this.setForceAgressive(false);
}
}
}
if (this.getDefinitions().getName().contains("Revenant")) {
final Player player = getCombat().getTarget() instanceof Player ? (Player) getCombat().getTarget() : null;
if (player != null) {
if (player.containsForinthry()) {
getCombat().setTarget(null);
}
this.setForceAgressive(false);
}
}
if (id == 11512)
setName("Donator Manager");
if (id == 2253)
setName("Player Listings");
if (id == 705)
setName("Melee shop");
if (id == 1861)
setName("Range shop");
if (id == 4707)
setName("Magic shop");
if (id == 9371)
setName("<img=4> Ironman Shop");
if (id == 882)
setName("Recipe of Disaster");
if (id == 3374)
setName("Skilling Task Manager");
if (id == 455)
setName("Herblore Supplies");
if (id == 4511)
setName("Lunar Diplomacy");
if (id == 219)
setName("Supplies/Resources");
if (isForceWalking()) {
if (getFreezeDelay() < Utils.currentTimeMillis()) {
setRandomWalk(false);
if (id == 519)
setRandomWalk(false);
if (id == 219)
setRandomWalk(false);
if (id == 455)
setRandomWalk(false);
if (id == 550)
setRandomWalk(false);
if (id == 546)
setRandomWalk(false);
if (id == 549)
setRandomWalk(false);
if (id == 683)
setRandomWalk(false);
if (id == 2676)
setRandomWalk(false);
if (id == 948)
setRandomWalk(false);
if (id == 2676)
setRandomWalk(false);
if (id == 948)
setRandomWalk(false);
if (id == 445)
setRandomWalk(false);
if (id == 3299)
setRandomWalk(false);
if (id == 2732)
setRandomWalk(false);
if (id == 4906)
setRandomWalk(false);
if (id == 3706)
setRandomWalk(false);
if (getX() != forceWalk.getX() || getY() != forceWalk.getY()) {
if (!hasWalkSteps())
addWalkSteps(forceWalk.getX(), forceWalk.getY(), getSize(), true);
if (!hasWalkSteps()) { // failing finding route
setNextWorldTile(new WorldTile(forceWalk)); // force
// tele
// to
// the
// forcewalk
// place
forceWalk = null; // so ofc reached forcewalk place
}
} else
// walked till forcewalk place
forceWalk = null;
}
}
}
@Override
public void processEntity() {
super.processEntity();
processNPC();
}
public int getRespawnDirection() {
NPCDefinitions definitions = getDefinitions();
if (definitions.anInt853 << 32 != 0 && definitions.respawnDirection > 0 && definitions.respawnDirection <= 8)
return (4 + definitions.respawnDirection) << 11;
return 0;
}
/*
* forces npc to random walk even if cache says no, used because of fake cache
* information
*/
private static boolean forceRandomWalk(int npcId) {
switch (npcId) {
case 11226:
return true;
default:
return false;
}
}
@Override
public void handleIngoingHit(final Hit hit) {
if (capDamage != -1 && hit.getDamage() > capDamage)
hit.setDamage(capDamage);
if (hit.getLook() != HitLook.MELEE_DAMAGE && hit.getLook() != HitLook.RANGE_DAMAGE
&& hit.getLook() != HitLook.MAGIC_DAMAGE)
return;
Entity source = hit.getSource();
if (source == null)
return;
if (source instanceof Player) {
final Player p2 = (Player) source;
if (p2.getPrayer().hasPrayersOn()) {
if (p2.getPrayer().usingPrayer(1, 18)) {
final NPC target = this;
if (hit.getDamage() > 0)
World.sendProjectile(p2, this, 2263, 11, 11, 20, 5, 0, 0);
p2.heal(hit.getDamage() / 5);
p2.getPrayer().drainPrayer(hit.getDamage() / 5);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2264));
if (hit.getDamage() > 0)
World.sendProjectile(target, p2, 2263, 11, 11, 20, 5, 0, 0);
}
}, 1);
}
if (hit.getDamage() == 0)
return;
if (!p2.getPrayer().isBoostedLeech()) {
if (hit.getLook() == HitLook.MELEE_DAMAGE) {
if (p2.getPrayer().usingPrayer(1, 19)) {
p2.getPrayer().setBoostedLeech(true);
return;
} else if (p2.getPrayer().usingPrayer(1, 1)) { // sap
// att
if (Utils.getRandom(4) == 0) {
if (p2.getPrayer().reachedMax(0)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your sap curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(0);
p2.getPackets().sendGameMessage(
"Your curse drains Attack from the enemy, boosting your Attack.", true);
}
p2.setNextAnimation(new Animation(12569));
p2.setNextGraphics(new Graphics(2214));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2215, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2216));
}
}, 1);
return;
}
} else {
if (p2.getPrayer().usingPrayer(1, 10)) {
if (Utils.getRandom(7) == 0) {
if (p2.getPrayer().reachedMax(3)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your leech curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(3);
p2.getPackets().sendGameMessage(
"Your curse drains Attack from the enemy, boosting your Attack.", true);
}
p2.setNextAnimation(new Animation(12575));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2231, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2232));
}
}, 1);
return;
}
}
if (p2.getPrayer().usingPrayer(1, 14)) {
if (Utils.getRandom(7) == 0) {
if (p2.getPrayer().reachedMax(7)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your leech curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(7);
p2.getPackets().sendGameMessage(
"Your curse drains Strength from the enemy, boosting your Strength.",
true);
}
p2.setNextAnimation(new Animation(12575));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2248, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2250));
}
}, 1);
return;
}
}
}
}
if (hit.getLook() == HitLook.RANGE_DAMAGE) {
if (p2.getPrayer().usingPrayer(1, 2)) { // sap range
if (Utils.getRandom(4) == 0) {
if (p2.getPrayer().reachedMax(1)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your sap curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(1);
p2.getPackets().sendGameMessage(
"Your curse drains Range from the enemy, boosting your Range.", true);
}
p2.setNextAnimation(new Animation(12569));
p2.setNextGraphics(new Graphics(2217));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2218, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2219));
}
}, 1);
return;
}
} else if (p2.getPrayer().usingPrayer(1, 11)) {
if (Utils.getRandom(7) == 0) {
if (p2.getPrayer().reachedMax(4)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your leech curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(4);
p2.getPackets().sendGameMessage(
"Your curse drains Range from the enemy, boosting your Range.", true);
}
p2.setNextAnimation(new Animation(12575));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2236, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2238));
}
});
return;
}
}
}
if (hit.getLook() == HitLook.MAGIC_DAMAGE) {
if (p2.getPrayer().usingPrayer(1, 3)) { // sap mage
if (Utils.getRandom(4) == 0) {
if (p2.getPrayer().reachedMax(2)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your sap curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(2);
p2.getPackets().sendGameMessage(
"Your curse drains Magic from the enemy, boosting your Magic.", true);
}
p2.setNextAnimation(new Animation(12569));
p2.setNextGraphics(new Graphics(2220));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2221, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2222));
}
}, 1);
return;
}
} else if (p2.getPrayer().usingPrayer(1, 12)) {
if (Utils.getRandom(7) == 0) {
if (p2.getPrayer().reachedMax(5)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your leech curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(5);
p2.getPackets().sendGameMessage(
"Your curse drains Magic from the enemy, boosting your Magic.", true);
}
p2.setNextAnimation(new Animation(12575));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2240, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2242));
}
}, 1);
return;
}
}
}
// overall
if (p2.getPrayer().usingPrayer(1, 13)) { // leech defence
if (Utils.getRandom(10) == 0) {
if (p2.getPrayer().reachedMax(6)) {
p2.getPackets().sendGameMessage(
"Your opponent has been weakened so much that your leech curse has no effect.",
true);
} else {
p2.getPrayer().increaseLeechBonus(6);
p2.getPackets().sendGameMessage(
"Your curse drains Defence from the enemy, boosting your Defence.", true);
}
p2.setNextAnimation(new Animation(12575));
p2.getPrayer().setBoostedLeech(true);
World.sendProjectile(p2, this, 2244, 35, 35, 20, 5, 0, 0);
WorldTasksManager.schedule(new WorldTask() {
@Override
public void run() {
setNextGraphics(new Graphics(2246));
}
}, 1);
return;
}
}
}
}
}
}
@Override
public void reset() {
super.reset();
setDirection(getRespawnDirection());
combat.reset();
bonuses = NPCBonuses.getBonuses(id); // back to real bonuses
forceWalk = null;
}
@Override
public void finish() {
if (hasFinished())
return;
setFinished(true);
World.updateEntityRegion(this);
World.removeNPC(this);
}
public void setRespawnTask() {
if (!hasFinished()) {
reset();
setLocation(respawnTile);
finish();
}
CoresManager.slowExecutor.schedule(new Runnable() {
@Override
public void run() {
try {
spawn();
} catch (Exception e) {
e.printStackTrace();
} catch (Error e) {
e.printStackTrace();
}
}
}, getId() == 1265 ? 500 : getCombatDefinitions().getRespawnDelay() * 600, TimeUnit.MILLISECONDS);
}
public void deserialize() {
if (combat == null)
combat = new NPCCombat(this);
spawn();
}
public void spawn() {
setFinished(false);
World.addNPC(this);
setLastRegionId(0);
World.updateEntityRegion(this);
loadMapRegions();
checkMultiArea();
}
public NPCCombat getCombat() {
return combat;
}
@Override
public void sendDeath(Entity source) {
final NPCCombatDefinitions defs = getCombatDefinitions();
resetWalkSteps();
combat.removeTarget();
setNextAnimation(null);
WorldTasksManager.schedule(new WorldTask() {
int loop;
@Override
public void run() {
if (loop == 0) {
setNextAnimation(new Animation(defs.getDeathEmote()));
} else if (loop >= defs.getDeathDelay()) {
drop();
reset();
setLocation(respawnTile);
finish();
if (getId() == 1265)
setRespawnTask();
if (!spawned)
setRespawnTask();
stop();
}
loop++;
}
}, 0, 1);
}
public void drop() {
try {
Drop[] drops = NPCDrops.getDrops(id);
if (drops == null)
return;
Player killer = getMostDamageReceivedSourcePlayer();
if (killer == null)
return;
if (killer.getTask() != null) {
if (getName().contains(killer.getTask().getName())) {
killer.getTask().onMonsterDeath(killer, this);
}
}
// if (killer.slayerTask.getTaskMonstersLeft() > 0) {
// for (String m : killer.slayerTask.getTask().slayable) {
// if (getDefinitions().name.equals(m)) {
// killer.slayerTask.onMonsterDeath(killer, this);
// break;
// }
// } World.sendWorldMessage("<col=ee7600><img=18>[News] "
// +player.getDisplayName() + " found an uncut onyx in the crystal chest.",
// false);
// }
Drop[] possibleDrops = new Drop[drops.length];
int possibleDropsCount = 0;
for (Drop drop : drops) {
if (drop.getRate() == 100)
sendDrop(killer, drop);
else {
if ((Utils.getRandomDouble(99) + 1) <= drop.getRate() * 1.5)
possibleDrops[possibleDropsCount++] = drop;
}
}
if (possibleDropsCount > 0)
sendDrop(killer, possibleDrops[Utils.getRandom(possibleDropsCount - 1)]);
} catch (Exception e) {
e.printStackTrace();
} catch (Error e) {
e.printStackTrace();
}
}
public void sendDrop(Player player, Drop drop) {
int size = getSize();
int bonus = 1;
if (World.doubledrops == true) {
bonus = 2;
}
String dropName = ItemDefinitions.getItemDefinitions(drop.getItemId()).getName().toLowerCase();
Item item = ItemDefinitions.getItemDefinitions(drop.getItemId())
.isStackable() ? new Item(drop.getItemId(),
(drop.getMinAmount() * Settings.DROP_RATE*bonus)
+ Utils.getRandom(drop.getExtraAmount()
* Settings.DROP_RATE*bonus)) : new Item(
drop.getItemId(), drop.getMinAmount()
+ Utils.getRandom(drop.getExtraAmount()));
if (dropName.contains("pernix") || dropName.contains("zamorakian") || dropName.contains("dragon pickaxe") || dropName.contains("callisto") || dropName.contains("saradomin") || dropName.contains("armadyl") || dropName.contains("draconic") || dropName.contains("torva") || dropName.contains("virtus") //Rare drops
|| dropName.contains("bandos")) {
World.sendWorldMessage("<col=ee7600><shad=00000><img=8> " + player.getDisplayName() + " has received a "
+ dropName + " as drop!", false);
}
if (player.getInventory().containsItem(18337, 1)// Bonecrusher
&& item.getDefinitions().getName().toLowerCase()
.contains("bones")) {
player.getSkills().addXp(Skills.PRAYER,
Burying.Bone.forId(drop.getItemId()).getExperience());
return;
}
if (player.getInventory().containsItem(19675, 1)// Herbicide
&& item.getDefinitions().getName().toLowerCase()
.contains("grimy")) {
if (player.getSkills().getLevelForXp(Skills.HERBLORE) >= HerbCleaning.getHerb(item.getId()).getLevel()) {
player.getSkills().addXp(
Skills.HERBLORE,
HerbCleaning.getHerb(drop.getItemId())
.getExperience() * 2);
return;
}
}
World.addGroundItem(new Item(drop.getItemId(), drop.getMinAmount() + Utils.getRandom(drop.getExtraAmount())),
new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
int keyPartChance = Utils.random(1, 100);
if (keyPartChance >= 90) {
int whichHalf = Utils.random(1, 100);
if (whichHalf >= 50) {
World.addGroundItem(new Item(987, 1), new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
} else {
World.addGroundItem(new Item(985, 1), new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
}
}
int charmDrop = Utils.random(1, 100);
if (charmDrop >= 15) {
int charmChance = Utils.random(1, 100);
if (charmChance >= 0 && charmChance <= 20) {
World.addGroundItem(new Item(12158, 1), new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
} else if (charmChance >= 21 && charmChance <= 50) {
World.addGroundItem(new Item(12160, 1), new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
} else if (charmChance >= 51 && charmChance <= 75) {
World.addGroundItem(new Item(12159, 1), new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
} else {
World.addGroundItem(new Item(12163, 1), new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
}
}
if (this.getName().contains("TzHaar")) {
World.addGroundItem(new Item(6529, 100 + Utils.getRandom(900)),
new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane()), player, false, 180, true);
}
if (this.getId() == 6230 || this.getId() == 6231 || this.getId() == 6229
|| this.getId() == 6232 || this.getId() == 6240 || this.getId() == 6241
|| this.getId() == 6242 || this.getId() == 6233 || this.getId() == 6234
|| this.getId() == 6243 || this.getId() == 6244 || this.getId() == 6245
|| this.getId() == 6246 || this.getId() == 6238 || this.getId() == 6239
|| this.getId() == 6227 || this.getId() == 6625 || this.getId() == 6223
|| this.getId() == 6222) {
player.ArmadylKC++;
player.getPackets().sendIComponentText(601, 8, ""+ player.ArmadylKC);
}
if (this.getId() == 6278 || this.getId() == 6277 || this.getId() == 6276
|| this.getId() == 6283 || this.getId() == 6282 || this.getId() == 6280
|| this.getId() == 6281 || this.getId() == 6279 || this.getId() == 6275
|| this.getId() == 6271 || this.getId() == 6272 || this.getId() == 6273
|| this.getId() == 6274 || this.getId() == 6269 || this.getId() == 6270
|| this.getId() == 6268 || this.getId() == 6265 || this.getId() == 6263
|| this.getId() == 6261 || this.getId() == 6260) {
player.BandosKC++;
player.getPackets().sendIComponentText(601, 9, ""+ player.BandosKC);
}
if (this.getId() == 6257 || this.getId() == 6255 || this.getId() == 6256
|| this.getId() == 6258 || this.getId() == 6259 || this.getId() == 6254
|| this.getId() == 6252 || this.getId() == 6250 || this.getId() == 6248
|| this.getId() == 6247) {
player.SaradominKC++;
player.getPackets().sendIComponentText(601, 10, ""+ player.SaradominKC);
}
if (this.getId() == 6221 || this.getId() == 6219 || this.getId() == 6220
|| this.getId() == 6217 || this.getId() == 6216 || this.getId() == 6215
|| this.getId() == 6214 || this.getId() == 6213 || this.getId() == 6212
|| this.getId() == 6211 || this.getId() == 6218 || this.getId() == 6208
|| this.getId() == 6206 || this.getId() == 6204 || this.getId() == 6203) {
player.ZamorakKC++;
player.getPackets().sendIComponentText(601, 11, ""+ player.ZamorakKC);
}
int random = Utils.random(1, 100);
if (random >= 95 && random <= 100) {
if (this.getId() == 116 || this.getId() == 4292 || this.getId() == 4291 || this.getId() == 6078
|| this.getId() == 6079 || this.getId() == 6080 && drop.getItemId() == 8844) {
player.getDialogueManager().startDialogue("SimpleMessage", "There is a defender dropped on the floor!");
WarriorsGuildControler.dropDefender(player, this);
}
}
}
@Override
public int getSize() {
return getDefinitions().size;
}
public int getMaxHit() {
return getCombatDefinitions().getMaxHit();
}
public int[] getBonuses() {
return bonuses;
}
@Override
public double getMagePrayerMultiplier() {
return 0;
}
@Override
public double getRangePrayerMultiplier() {
return 0;
}
@Override
public double getMeleePrayerMultiplier() {
return 0;
}
public WorldTile getRespawnTile() {
return respawnTile;
}
public boolean isUnderCombat() {
return combat.underCombat();
}
@Override
public void setAttackedBy(Entity target) {
super.setAttackedBy(target);
if (target == combat.getTarget() && !(combat.getTarget() instanceof Familiar))
lastAttackedByTarget = Utils.currentTimeMillis();
}
public boolean canBeAttackedByAutoRelatie() {
return Utils.currentTimeMillis() - lastAttackedByTarget > lureDelay;
}
public boolean isForceWalking() {
return forceWalk != null;
}
public void setTarget(Entity entity) {
if (isForceWalking()) // if force walk not gonna get target
return;
combat.setTarget(entity);
lastAttackedByTarget = Utils.currentTimeMillis();
}
public void removeTarget() {
if (combat.getTarget() == null)
return;
combat.removeTarget();
}
public void forceWalkRespawnTile() {
setForceWalk(respawnTile);
}
public void setForceWalk(WorldTile tile) {
resetWalkSteps();
forceWalk = tile;
}
public boolean hasForceWalk() {
return forceWalk != null;
}
public ArrayList<Entity> getPossibleTargets() {
ArrayList<Entity> possibleTarget = new ArrayList<Entity>();
for (int regionId : getMapRegionsIds()) {
List<Integer> playerIndexes = World.getRegion(regionId).getPlayerIndexes();
if (playerIndexes != null) {
for (int npcIndex : playerIndexes) {
Player player = World.getPlayers().get(npcIndex);
if (player == null || player.isDead() || player.hasFinished() || !player.isRunning()
|| !player.withinDistance(this, forceTargetDistance > 0 ? forceTargetDistance
: (getCombatDefinitions().getAttackStyle() == NPCCombatDefinitions.MELEE ? 4
: getCombatDefinitions().getAttackStyle() == NPCCombatDefinitions.SPECIAL
? 64
: 8))
|| (!forceMultiAttacked && (!isAtMultiArea() || !player.isAtMultiArea())
&& player.getAttackedBy() != this
&& (player.getAttackedByDelay() > System.currentTimeMillis()
|| player.getFindTargetDelay() > System.currentTimeMillis()))
|| !clipedProjectile(player, false)
|| (!forceAgressive && !Wilderness.isAtWild(this) && player.getSkills()
.getCombatLevelWithSummoning() >= getDefinitions().combatLevel * 2))
continue;
possibleTarget.add(player);
}
}
}
return possibleTarget;
}
public boolean checkAgressivity() {
// if(!(Wilderness.isAtWild(this) &&
// getDefinitions().hasAttackOption())) {
if (!forceAgressive) {
NPCCombatDefinitions defs = getCombatDefinitions();
if (defs.getAgressivenessType() == NPCCombatDefinitions.PASSIVE)
return false;
}
// }
ArrayList<Entity> possibleTarget = getPossibleTargets();
if (!possibleTarget.isEmpty()) {
Entity target = possibleTarget.get(Utils.getRandom(possibleTarget.size() - 1));
setTarget(target);
target.setAttackedBy(target);
target.setFindTargetDelay(Utils.currentTimeMillis() + 10000);
return true;
}
return false;
}
public boolean isCantInteract() {
return cantInteract;
}
public void setCantInteract(boolean cantInteract) {
this.cantInteract = cantInteract;
if (cantInteract)
combat.reset();
}
public int getCapDamage() {
return capDamage;
}
public void setCapDamage(int capDamage) {
this.capDamage = capDamage;
}
public int getLureDelay() {
return lureDelay;
}
public void setLureDelay(int lureDelay) {
this.lureDelay = lureDelay;
}
public boolean isCantFollowUnderCombat() {
return cantFollowUnderCombat;
}
public void setCantFollowUnderCombat(boolean canFollowUnderCombat) {
this.cantFollowUnderCombat = canFollowUnderCombat;
}
public Transformation getNextTransformation() {
return nextTransformation;
}
@Override
public String toString() {
return getDefinitions().name + " - " + id + " - " + getX() + " " + getY() + " " + getPlane();
}
public boolean isForceAgressive() {
return forceAgressive;
}
public void setForceAgressive(boolean forceAgressive) {
this.forceAgressive = forceAgressive;
}
public int getForceTargetDistance() {
return forceTargetDistance;
}
public void setForceTargetDistance(int forceTargetDistance) {
this.forceTargetDistance = forceTargetDistance;
}
public boolean isForceFollowClose() {
return forceFollowClose;
}
public void setForceFollowClose(boolean forceFollowClose) {
this.forceFollowClose = forceFollowClose;
}
public boolean isForceMultiAttacked() {
return forceMultiAttacked;
}
public void setForceMultiAttacked(boolean forceMultiAttacked) {
this.forceMultiAttacked = forceMultiAttacked;
}
public boolean hasRandomWalk() {
return randomwalk;
}
public void setRandomWalk(boolean forceRandomWalk) {
this.randomwalk = forceRandomWalk;
}
public String getCustomName() {
return name;
}
public void setName(String string) {
this.name = getDefinitions().name.equals(string) ? null : string;
changedName = true;
}
public int getRemote() {
return getDefinitions().renderEmote;
}
public int setRemote(int remote) {
return getDefinitions().renderEmote = remote;
}
public int getCustomCombatLevel() {
return combatLevel;
}
public int getCombatLevel() {
return combatLevel >= 0 ? combatLevel : getDefinitions().combatLevel;
}
public String getName() {
return name != null ? name : getDefinitions().name;
}
public void setCombatLevel(int level) {
combatLevel = getDefinitions().combatLevel == level ? -1 : level;
changedCombatLevel = true;
}
public boolean hasChangedName() {
return changedName;
}
public boolean hasChangedCombatLevel() {
return changedCombatLevel;
}
public WorldTile getMiddleWorldTile() {
int size = getSize();
return new WorldTile(getCoordFaceX(size), getCoordFaceY(size), getPlane());
}
public boolean withinDistance(Player tile, int distance) {
return super.withinDistance(tile, distance);
}
public boolean isIntelligentRouteFinder() {
return intelligentRouteFinder;
}
public void setIntelligentRouteFinder(boolean intelligentRouteFinder) {
this.intelligentRouteFinder = intelligentRouteFinder;
}
}
NPCCombat.java
Code:
package com.rs.game.npc.combat;
import com.rs.game.Animation;
import com.rs.game.Entity;
import com.rs.game.ForceMovement;
import com.rs.game.World;
import com.rs.game.WorldTile;
import com.rs.game.npc.NPC;
import com.rs.game.npc.familiar.Familiar;
import com.rs.game.npc.godwars.zaros.Nex;
import com.rs.game.npc.pest.PestPortal;
import com.rs.game.player.content.Combat;
import com.rs.utils.MapAreas;
import com.rs.utils.Utils;
public final class NPCCombat {
private NPC npc;
private int combatDelay;
private Entity target;
public NPCCombat(NPC npc) {
this.npc = npc;
}
public int getCombatDelay() {
return combatDelay;
}
/*
* returns if under combat
*/
public boolean process() {
if (combatDelay > 0)
combatDelay--;
if (target != null) {
if (!checkAll()) {
removeTarget();
return false;
}
if (combatDelay <= 0)
combatDelay = combatAttack();
return true;
}
return false;
}
/*
* return combatDelay
*/
private int combatAttack() {
Entity target = this.target; // prevents multithread issues
if (target == null)
return 0;
// if hes frooze not gonna attack
if (npc.getFreezeDelay() >= Utils.currentTimeMillis())
return 0;
// check if close to target, if not let it just walk and dont attack
// this gameticket
NPCCombatDefinitions defs = npc.getCombatDefinitions();
int attackStyle = defs.getAttackStyle();
int maxDistance = attackStyle == NPCCombatDefinitions.MELEE || attackStyle == NPCCombatDefinitions.SPECIAL2 ? 0
: 7;
/*
if ((!(npc instanceof Nex)) && !npc.clipedProjectile(target, maxDistance == 0))
return 0;
*/
int distanceX = target.getX() - npc.getX();
int distanceY = target.getY() - npc.getY();
int size = npc.getSize();
/*
* if(npc.hasWalkSteps()) maxDistance += 1;
*/
if (distanceX > size + maxDistance || distanceX < -1 - maxDistance || distanceY > size + maxDistance
|| distanceY < -1 - maxDistance) {
return 0;
}
addAttackedByDelay(target);
return CombatScriptsHandler.specialAttack(npc, target);
}
protected void doDefenceEmote(Entity target) {
/*
* if (target.getNextAnimation() != null) // if has att emote already return;
*/
target.setNextAnimationNoPriority(new Animation(Combat.getDefenceEmote(target)));
}
public Entity getTarget() {
return target;
}
public void addAttackedByDelay(Entity target) { // prevents multithread
// issues
target.setAttackedBy(npc);
target.setAttackedByDelay(Utils.currentTimeMillis() + npc.getCombatDefinitions().getAttackDelay() * 600 + 600); // 8seconds
}
public void setTarget(Entity target) {
this.target = target;
npc.setNextFaceEntity(target);
if (!checkAll()) {
removeTarget();
return;
}
}
public boolean checkAll() {
Entity target = this.target; // prevents multithread issues
if (target == null) {
return false;
}
if (npc.isDead() || npc.hasFinished() || npc.isForceWalking() || target.isDead() || target.hasFinished() || npc.getPlane() != target.getPlane()) {
return false;
}
if (npc.getFreezeDelay() >= Utils.currentTimeMillis())
return true; // if freeze cant move ofc
int distanceX = npc.getX() - npc.getRespawnTile().getX();
int distanceY = npc.getY() - npc.getRespawnTile().getY();
int size = npc.getSize();
int maxDistance;
if (!npc.isNoDistanceCheck() && !npc.isCantFollowUnderCombat()) {
maxDistance = 32;
if (!(npc instanceof Familiar)) {
if (npc.getMapAreaNameHash() != -1) {
// if out his area
if (!MapAreas.isAtArea(npc.getMapAreaNameHash(), npc) || (!npc.canBeAttackFromOutOfArea()
&& !MapAreas.isAtArea(npc.getMapAreaNameHash(), target))) {
npc.forceWalkRespawnTile();
return false;
}
} else if (distanceX > size + maxDistance || distanceX < -1 - maxDistance
|| distanceY > size + maxDistance || distanceY < -1 - maxDistance) {
// if more than 32 distance from respawn place
npc.forceWalkRespawnTile();
return false;
}
}
maxDistance = 16;
distanceX = target.getX() - npc.getX();
distanceY = target.getY() - npc.getY();
if (distanceX > size + maxDistance || distanceX < -1 - maxDistance || distanceY > size + maxDistance || distanceY < -1 - maxDistance) {
return false; // if target distance higher 16
}
} else {
distanceX = target.getX() - npc.getX();
distanceY = target.getY() - npc.getY();
}
// checks for no multi area :)
if (npc instanceof Familiar) {
Familiar familiar = (Familiar) npc;
if (!familiar.canAttack(target))
return false;
} else {
if (!npc.isForceMultiAttacked()) {
if (!target.isAtMultiArea() || !npc.isAtMultiArea()) {
if (npc.getAttackedBy() != target && npc.getAttackedByDelay() > Utils.currentTimeMillis())
return false;
if (target.getAttackedBy() != npc && target.getAttackedByDelay() > Utils.currentTimeMillis())
return false;
}
}
}
if (!npc.isCantFollowUnderCombat()) {
// if is under
int targetSize = target.getSize();
/*
* if (distanceX < size && distanceX > -targetSize && distanceY < size &&
* distanceY > -targetSize && !target.hasWalkSteps()) {
*/
if (!target.hasWalkSteps()
&& Utils.colides(npc.getX(), npc.getY(), size, target.getX(), target.getY(), targetSize)) {
npc.resetWalkSteps();
if (!npc.addWalkSteps(target.getX() + targetSize, npc.getY())) {
npc.resetWalkSteps();
if (!npc.addWalkSteps(target.getX() - size, npc.getY())) {
npc.resetWalkSteps();
if (!npc.addWalkSteps(npc.getX(), target.getY() + targetSize)) {
npc.resetWalkSteps();
if (!npc.addWalkSteps(npc.getX(), target.getY() - size)) {
return true;
}
}
}
}
return true;
}
if (npc.getCombatDefinitions().getAttackStyle() == NPCCombatDefinitions.MELEE && targetSize == 1
&& size == 1 && Math.abs(npc.getX() - target.getX()) == 1
&& Math.abs(npc.getY() - target.getY()) == 1 && !target.hasWalkSteps()) {
if (!npc.addWalkSteps(target.getX(), npc.getY(), 1))
npc.addWalkSteps(npc.getX(), target.getY(), 1);
return true;
}
int attackStyle = npc.getCombatDefinitions().getAttackStyle();
if (npc instanceof Nex) {
Nex nex = (Nex) npc;
maxDistance = nex.isForceFollowClose() ? 0 : 7;
if (!nex.isFlying() && (!npc.clipedProjectile(target, maxDistance == 0 && !forceCheckClipAsRange(target))) || !Utils.isOnRange(npc.getX(), npc.getY(), size, target.getX(), target.getY(), targetSize,
maxDistance)) {
npc.resetWalkSteps();
if (!Utils.isOnRange(npc.getX(), npc.getY(), size, target.getX(), target.getY(), targetSize, 10)) {
int[][] dirs = Utils.getCoordOffsetsNear(size);
for (int dir = 0; dir < dirs[0].length; dir++) {
final WorldTile tile = new WorldTile(new WorldTile(target.getX() + dirs[0][dir],
target.getY() + dirs[1][dir], target.getPlane()));
if (World.isTileFree(tile.getPlane(), tile.getX(), tile.getY(), size)) { // if
// found
// done
npc.setNextForceMovement(new ForceMovement(new WorldTile(npc), 0, tile, 1,
Utils.getMoveDirection(tile.getX() - npc.getX(), tile.getY() - npc.getY())));
npc.setNextAnimation(new Animation(6985));
npc.setNextWorldTile(tile);
nex.setFlying(false);
return true;
}
}
} else
npc.calcFollow(target, 2, true, npc.isIntelligentRouteFinder());
return true;
} else
// if doesnt need to move more stop moving
npc.resetWalkSteps();
} else {
// MAGE_FOLLOW and RANGE_FOLLOW follow close but can attack far
// unlike melee
maxDistance = npc.isForceFollowClose() ? 0
: (attackStyle == NPCCombatDefinitions.MELEE || attackStyle == NPCCombatDefinitions.SPECIAL2
|| attackStyle == NPCCombatDefinitions.SPECIAL) ? 0 : 7;
npc.resetWalkSteps();
// is far from target, moves to it till can attack
if ((!npc.clipedProjectile(target, maxDistance == 0 && !forceCheckClipAsRange(target)))
|| !Utils.isOnRange(npc.getX(), npc.getY(), size, target.getX(), target.getY(), targetSize,
maxDistance)) {
if (!npc.calcFollow(target, npc.getRun() ? 2 : 1, true, npc.isIntelligentRouteFinder())
&& combatDelay < 3 && attackStyle == NPCCombatDefinitions.MELEE)
combatDelay = 3;
return true;
}
// if under target, moves
}
}
return true;
}
private boolean forceCheckClipAsRange(Entity target) {
return target instanceof PestPortal;
}
public void addCombatDelay(int delay) {
combatDelay += delay;
}
public void setCombatDelay(int delay) {
combatDelay = delay;
}
public boolean underCombat() {
return target != null;
}
public void removeTarget() {
this.target = null;
npc.setNextFaceEntity(null);
}
public void reset() {
combatDelay = 0;
target = null;
}
}
While I'm dumping code, here is the test instance controller I am using