public static void resetCombat(Entity killer, int type) { if (killer != null) { killer.setEntityFocus(65535); killer.setTarget(null); killer.getFollow().setFollowing(null); if (type == 1) { killer.setLastAttack(0); killer.setLastAttacked(0); if (killer.getAttacker() != null) { if (killer.getAttacker().getEntityFocus() != -1) { if (killer.getAttacker().getEntityFocus() == killer.getClientIndex()) { killer.getAttacker().setEntityFocus(65535); } } killer.setAttacker(null); } } } }
public static void newAttack(Entity killer, Entity target) { if (killer.getLastAttack() > 0) { /*if (Environment.TickCount - killer.getLastAttack() >= (killer.getAttackSpeed() * 500)) { killer.setCombatTurns(killer.getAttackSpeed()); }*/ } else { killer.setCombatTurns(killer.getAttackSpeed()); } killer.setEntityFocus(target.getClientIndex()); killer.setTarget(target); checkAutoCast(killer, target); killer.setFaceLocation(target.getLocation()); }
public void sendProjectile(Location source, Location dest, int startSpeed, int gfx, int angle, int startHeight, int endHeight, int speed, Entity lockon) { sendProjectileCoords(source); connection.SendPacket(new PacketBuilder().setId(16) .addByte((byte)((byte)angle)) .addByte((byte)((byte)(source.getX() - dest.getX()) * -1)) .addByte((byte)((byte)(source.getY() - dest.getY()) * -1)) .addUShort(lockon is Player ? (-lockon.getClientIndex() - 1) : lockon.getClientIndex() + 1) .addUShort(gfx) .addByte((byte)startHeight) .addByte((byte)endHeight) .addUShort(startSpeed) .addUShort(speed) .addByte((byte)((byte)gfx == 53 ? 0 : 16))//arch..0 if cannon .addByte((byte)64).toPacket()); }
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); } }
public void followEntity() { if (follower == null || entity.isDead() || follower.isDead() || follower.isDestroyed()) { follower = null; return; } if (follower.getLocation().withinDistance(entity.getLocation(), 1)) { return; } if (follower is Player) { if (follower.getEntityFocus() == -1 || follower.getEntityFocus() != entity.getClientIndex()) { entity.setEntityFocus(follower.getClientIndex()); } if (!follower.getLocation().withinDistance(entity.getLocation(), 15)) { setFollowing(null); return; } } //TODO: Starting from here organize all this crap properly. bool sameCoords = false; int x = entity.getLocation().getX(); int y = entity.getLocation().getY(); int targetX = follower.getLocation().getX(); int targetY = follower.getLocation().getY(); int newX = x; int newY = y; if (x == targetX && y == targetY) { sameCoordWait++; if (sameCoordWait < 2) { return; } if (sameCoordWait == 2) { if (Misc.random(3) == 0) { newY--; } else if (Misc.random(3) == 1) { newY++; } else if (Misc.random(3) == 2) { newX--; } else if (Misc.random(3) == 3) { newX++; } sameCoords = true; sameCoordWait = 0; } } if (!sameCoords) { if (targetX > x && targetY == y) { newX++; } else if (targetX < x && targetY == y) { newX--; } else if (targetX == x && targetY > y) { newY++; } else if (targetX == x && targetY < y) { newY--; } else if (targetX > x && targetY > y) { newX++; newY++; } else if (targetX < x && targetY < y) { newX--; newY--; } else if (targetX > x && targetY < y) { newX++; newY--; } else if (targetX < x && targetY > y) { newX--; newY++; } } //if (entity.getLocation().withinDistance(follower.getLocation(), Combat.npcUsesRange((Npc)entity) ? 30 : Combat.getNPCSize(entity, follower))) { // return; //} if (entity is Npc) { Location newLoc = new Location(newX, newY, entity.getLocation().getZ()); if (!newLoc.inArea(((Npc)entity).getMinimumCoords().getX(), ((Npc)entity).getMinimumCoords().getY(), ((Npc)entity).getMaximumCoords().getX(), ((Npc)entity).getMaximumCoords().getY())) { follower = null; return; } if (!sameCoords && newX == targetX && newY == targetY) { return; } } if (follower.getEntityFocus() == -1 || follower.getEntityFocus() != entity.getClientIndex()) { entity.setEntityFocus(follower.getClientIndex()); } /* * if (!entity.getLocation().withinDistance(follower.getLocation())) { * if (((Player)follower).getSummonedNPC() == npc) { * npc.setLastAnimation(new Animation(8298); * npc.setLastGraphics(new Graphics(NPCSizes.getNpcSize(npc.getId()) > 0 ? 1315 : 1314); * npc.setLocation(new Location(targetX, targetY, following.getLocation().getZ())); * npc.setEntityFocus(following.getClientIndex()); * return; * } * }*/ if (entity is Npc) { //npc following a player. ((Npc)entity).getSprites().setSprites(Misc.direction(x, y, newX, newY), -1); if (((Npc)entity).getSprites().getPrimarySprite() != -1) { int sprite = ((Npc)entity).getSprites().getPrimarySprite() >> 1; ((Npc)entity).getSprites().setSprites(sprite, -1); ((Npc)entity).setLocation(new Location(newX, newY, ((Npc)entity).getLocation().getZ())); } } else { //player following a player int diffX = targetX - x; int diffY = targetY - y; //if(Math.Max(Math.Abs(diffX), Math.Abs(diffY)) <= 1) return; //1 step away or on top of player, no need to follow //Try to fix this up to make it look more natural. Because just using the else statement looks ugly. //TODO: Must add sprite direction detection for it to know which way the person is standing so it would be behind him. if (diffX == 0 && diffY == -2) { //go down diffY = -1; } else if (diffX == 0 && diffY == 2) { //go up diffY = 1; } else if (diffX == -2 && diffY == 0) { //go left diffX = -1; } else if (diffX == 2 && diffY == 0) { //go right diffX = 1; } else if ((diffX == 2 && diffY == -2) || (diffX == 2 && diffY == -1) || (diffX == 1 && diffY == -2)) { //left down, down 1 left 2 or down 2 right 1 diffX = 1; diffY = -1; } else if ((diffX == -2 && diffY == 2) || (diffX == -2 && diffY == 1) || (diffX == -1 && diffY == 2)) { //left up, up 1 left 2 or up 2 left 1 diffX = -1; diffY = 1; } else if ((diffX == 2 && diffY == 2) || (diffX == 2 && diffY == 1) || (diffX == 1 && diffY == 2)) { //up right, up 1 right 2, up 2 right 1 diffX = 1; diffY = 1; } else if ((diffX == -2 && diffY == -2) || (diffX == -1 && diffY == -2) || (diffX == -2 && diffY == -1)) { //down left, down 2 left 1 or down 1 right 2 diffX = -1; diffY = -1; } else { if (diffX < 0) { diffX++; } else if (diffX > 0) { diffX--; } if (diffY < 0) { diffY++; } else if (diffY > 0) { diffY--; } } ((Player)entity).getWalkingQueue().forceWalk(diffX, diffY); } }