public static void combatLoop(Entity killer) { bool usingRange = killer is Player ? RangeCombat.isUsingRange(killer) : npcUsesRange(killer); Entity target = killer.getTarget(); killer.incrementCombatTurns(); bool autoCasting = killer is Npc ? false : ((Player)killer).getTemporaryAttribute("autoCasting") != null; bool dragonfire = false; bool guthanSpecial = false; //if you are auto casting you are not in combat loop. if (autoCasting) return; //If who you were attacking or who attacked you doesn't exist anymore. [Most important, should be first] if (target == null || (killer.getAttacker() == null && target == null)) { //stop fighting. resetCombat(killer, 1); return; } //If it's the npc attacking and npc isn't owned by a player or player is attacking if ((killer is Npc) && ((Npc)killer).getOwner() == null || killer is Player) { if (killer.getLastAttacked() > 0 || killer.getLastAttack() > 0) { //if the last time npc or player was attacked was 6 seconds ago or last time npc or player attacked was 6 seconds ago if (isXSecondsSinceCombat(killer, killer.getLastAttacked(), 6000) && isXSecondsSinceCombat(killer, killer.getLastAttack(), 6000)) { //stop fighting. resetCombat(killer, 1); return; } } } //If you are a player and using range then your distance is 8 or if you are a npc using range get the npc's attackRange otherwise get the sie of the npc as distance. int distance = (killer is Player && usingRange) ? 8 : killer is Npc && usingRange ? getNpcAttackRange(killer) : getNPCSize(killer, target); //if you the player are not using range and you are attacking another player if (!usingRange && killer is Player && target is Player) { //if the player who is getting attacked is not standing still. if (((Player)target).getSprites().getPrimarySprite() != -1) { //if you are using range on a player who is moving then distance to attack is 11, otherwise no range it's 3. distance = usingRange ? 11 : 3; } } //If all[player vs player], [player vs npc] or [npc vs player] are within distance of each other. if (!killer.getLocation().withinDistance(target.getLocation(), distance) && !target.getLocation().withinDistance(killer.getLocation(), distance)) { return; } //Can you [npc or player] even attack the entity if (!canAttack(killer, target, usingRange)) { //stop fighting. resetCombat(killer, 0); return; } //are you [npc or player] using ranged attacks? if (usingRange) { //if you are a player if (killer is Player) { //Do you have ammo and a bow? if (RangeCombat.hasAmmo(killer) && RangeCombat.hasValidBowArrow(killer)) { ((Player)killer).getWalkingQueue().resetWalkingQueue(); ((Player)killer).getPackets().closeInterfaces(); ((Player)killer).getPackets().clearMapFlag(); } else { //You cannot attack the monster as you don't have ammo or a bow. killer.setTarget(null); return; } } } //are you a player who is attacking a npc. if (target is Npc && killer is Player) { //If you are attacking Zilyana boss. if (((Npc)target).getId() == 6247) { // Zilyana (sara boss) //TODO: Stop any walking err why only zilyana boss?, have to check this out later. ((Player)killer).getWalkingQueue().resetWalkingQueue(); ((Player)killer).getPackets().clearMapFlag(); } } //All the checks above are passed, below starts the actual assigning of target and doing the attack. //if you [npc or player] attacking turn is greater or equal to your attacking speed. if (killer.getCombatTurns() >= killer.getAttackSpeed()) { //if [npc or player] has auto attack back on, and who they are attacking still exists. if (target.isAutoRetaliating() && target.getTarget() == null) { //make the [npc or player] follow who they are trying to attack. target.getFollow().setFollowing(killer); //make the [npc or player] face up to their attacker. target.setEntityFocus(killer.getClientIndex()); if ((target.getCombatTurns() >= (target.getAttackSpeed() / 2)) && target.getAttacker() == null) { target.setCombatTurns(target.getAttackSpeed() / 2); } //assign the [npc or player] who is getting attacked it's target who is attacking them. target.setTarget(killer); //if the person who is getting attacked is a player if (target is Player) { //stop the movement of player who is getting attacked ((Player)target).getWalkingQueue().resetWalkingQueue(); ((Player)target).getPackets().clearMapFlag(); } } //set the attack delay, if you are using range then delay is 2.4 seconds, otherwise magic.. 2.75 seconds. int delay = usingRange ? 2400 : 2750; //if delay has come up. if (Environment.TickCount - killer.getLastMagicAttack() < delay) { //If the player who is attacking using range. if (usingRange && killer is Player) { //Stop the movement of the attacker who is using ranged attacks. ((Player)killer).getWalkingQueue().resetWalkingQueue(); ((Player)killer).getPackets().clearMapFlag(); } return; } //if the attacker is a npc if (killer is Npc) { //perform the npc attack as a killer on your target (most likely a player) if (NPCAttack.npcAttack((Npc)killer, target)) { return; //if the dice 50/50 kicks in and the npc attacking is a dragon. } else if ((Misc.random(2) == 0) && isDragon(killer)) { //do your dragon fire as a dragon npc. doDragonfire(killer, target); //dragonfire was done, variable used to stop some attack animation. dragonfire = true; } } //If the person getting attacked is a player. if (target is Player) { //Close all your interfaces. ((Player)target).getPackets().closeInterfaces(); } //if the attacker [npc or player] has a attack animation and dragonfire variable wasn't set. if ((killer.getAttackAnimation() != 65535) && !dragonfire) { //do your attack animation as a [npc or player]. killer.setLastAnimation(new Animation(killer.getAttackAnimation())); } //If the [player or npc] is using ranged attacks if (!usingRange) { if (target.getCombatTurns() < 0 || target.getCombatTurns() > 0) { //if the [player or npc] getting attacked has a defensive animation. if (target.getDefenceAnimation() != 65535) { //do a blocking/defensive animation. target.setLastAnimation(new Animation(target.getDefenceAnimation())); } } } //make the attacker [player or npc] start following the attacked. killer.getFollow().setFollowing(target); //set a timer for the [player or npc] which indicates the last time they were attacked by killer. target.setLastAttacked(Environment.TickCount); //set a timer for the [player or npc] which indicates the last time they attacked the target. killer.setLastAttack(Environment.TickCount); //reset the combat turns. [this makes sure both attackers don't attack at same time] killer.resetCombatTurns(); //assign the [npc or player] who is getting attacked it's target who is attacking them. target.setAttacker(killer); //set a skulls, the method checks if [player attacks player] also [checks if player is dueling or in fightpits or has skull], otherwise gets skull. setSkull(killer, target); //if the attacker is a player. if (killer is Player) { //set attacking player's combatType to melee attack. ((Player)killer).setLastCombatType(CombatType.MELEE); //close all your interfaces as a attacker ((Player)killer).getPackets().closeInterfaces(); //if you the attacking player is using a special attack. if (((Player)killer).getSpecialAttack().isUsingSpecial()) { //do your special attack on your target which may be a [player or npc] if (((Player)killer).getSpecialAttack().doSpecialAttack(killer, target)) { return; } //if you the attacking player is wearing guthan armour set. } else if (CombatFormula.wearingGuthan((Player)killer)) { //roll a 25% dice. if (Misc.random(4) == 0) { //if dice hits 25%, show some kind of graphics.. killer.setLastGraphics(new Graphics(398, 0)); //set some variable to indicate you are using guthan special. guthanSpecial = true; } } } //if you the [player or npc] is using range. if (usingRange) { //Go into the RangeCombat ranging logic loop processing class. RangeCombat.rangeCombatLoop(killer, target); return; } //if the dragon npc did his dragonfire attack quit right here. if (dragonfire) { return; } //copies guthanSpecial variable to a different variable so it won't change when passed into a Event. bool guthanSpec = guthanSpecial; //get the damage you as the attacker [player or npc] will do on target [player or npc] double damage = getDamage(killer, target); //checks if damage will kill the player, sets a temporary variable 'willDie' checkIfWillDie(target, damage); //trigger the attack event based on the attackers [player or npc] hit delay Event attackEvent = new Event(killer.getHitDelay()); attackEvent.setAction(() => { //stop attack event after this run attackEvent.stop(); //add the XP for the killer [player only]. addXp(killer, target, damage); //set the hit to be sent on the attacked target [player or npc] target.hit((int)damage); //if the attacker [player] is using the Smite prayer drain prayer from target [player] based on damage done checkSmite(killer, target, damage); //if the attack [pla checkRecoil(killer, target, damage); checkVengeance(killer, target, damage); //if you are using the guthanSpecial which does some healing if (guthanSpec) { // heals 30% of the damage, and an added random 70% of the damage killer.heal((int)(damage * 0.30 + (Misc.randomDouble() * (damage * 0.70)))); } //if the target you are attacking is a npc. if (target is Npc) { //if it is Tzhaar monsters, you as the attacker will take 1 damage. if (((Npc)target).getId() == 2736 || ((Npc)target).getId() == 2737) { // Tzhaar lvl 45s killer.hit(1); // their recoil attack } } }); Server.registerEvent(attackEvent); } }