public static void newMagicAttack(Player p, Entity target, int id, bool ancients) { int index = getSpellIndex(p, id, ancients); bool autoCasting = p.getTemporaryAttribute("autoCasting") != null; bool fakeNPC = target != null && target is Npc && ((Npc)target).getId() == 0; Entity lastAutocastEntity = null; bool frozen = false; if (index == -1) { return; } if (p.getTarget() == null) { if (autoCasting) { if (Location.inMultiCombat(p.getLocation())) { lastAutocastEntity = (Entity)p.getTemporaryAttribute("autocastEntity") == null ? null : (Entity)p.getTemporaryAttribute("autocastEntity"); if (lastAutocastEntity == null || lastAutocastEntity is Player) { p.removeTemporaryAttribute("autoCasting"); Combat.resetCombat(p, 1); return; } if (hitsMulti(p, index)) { Location location = (Location)p.getTemporaryAttribute("autocastLocation"); Entity newTarget = new Npc(0); newTarget.setLocation(location); p.setTarget(newTarget); newMagicAttack(p, newTarget, id, ancients); return; } } else { p.removeTemporaryAttribute("autoCasting"); Combat.resetCombat(p, 1); return; } } else { p.removeTemporaryAttribute("autoCasting"); Combat.resetCombat(p, 1); return; } } else { if (!canCastSpell(p, target, index, fakeNPC)) { p.removeTemporaryAttribute("autoCasting"); Combat.resetCombat(p, 1); return; } } int distance = 8; if (target is Player) { if (((Player)target).getSprites().getPrimarySprite() != -1) { distance = 8; } } if (!fakeNPC) { // we're actually attacking a real npc/player if (!p.getLocation().withinDistance(target.getLocation(), distance)) { p.getFollow().setFollowing(target); Event attemptMagicAttackEvent = new Event(500); int attemptMagicAttackCounter = 0; attemptMagicAttackEvent.setAction(() => { if (p.getLocation().withinDistance(target.getLocation(), distance) && p.getTarget() != null) { attemptMagicAttackEvent.stop(); newMagicAttack(p, target, id, ancients); return; } attemptMagicAttackCounter++; if (attemptMagicAttackCounter >= 12) { attemptMagicAttackEvent.stop(); } }); Server.registerEvent(attemptMagicAttackEvent); return; } } int timeSinceLastCast = autoCasting ? 3500 : 2000; if (Environment.TickCount - p.getLastMagicAttack() < timeSinceLastCast) { p.getWalkingQueue().resetWalkingQueue(); //return; } int time = p.getLastCombatType().Equals(Combat.CombatType.MAGE) ? 1550 : 600; if (Environment.TickCount - p.getLastAttack() < time) { int delay = p.getLastCombatType().Equals(Combat.CombatType.MAGE) ? 1350 : 800; Event attemptMagicAttackEvent = new Event(500); attemptMagicAttackEvent.setAction(() => { if (Environment.TickCount - p.getLastAttack() > delay) { attemptMagicAttackEvent.stop(); newMagicAttack(p, target, id, ancients); } }); Server.registerEvent(attemptMagicAttackEvent); p.getWalkingQueue().resetWalkingQueue(); p.getPackets().clearMapFlag(); p.setLastCombatType(Combat.CombatType.MAGE); return; } if (fakeNPC && !monsterInArea(p, target)) { p.removeTemporaryAttribute("autoCasting"); Combat.resetCombat(p, 1); return; } int endGfx = END_GFX[index]; double damage = Misc.random(CombatFormula.getMagicHit(p, target, getSpellMaxHit(p, index))); bool mp = false; bool magicProtect = mp; if (target is Player) { mp = ((Player)target).getPrayers().getHeadIcon() == PrayerData.MAGIC; } if (magicProtect) { damage *= 0.60; } if (p.getEquipment().getItemInSlot(ItemData.EQUIP.WEAPON) == 8841) { damage *= 1.10; // void mace 10% hit increase. } if (damage == 0 && index != 41 && index != 42 && index != 43 && index != 44 && index != 45 && index != 46 && index != 47) { endGfx = 85; } if (!deleteRunes(p, RUNES[index], RUNE_AMOUNTS[index])) { p.setTarget(null); return; } p.getFollow().setFollowing(null); p.getWalkingQueue().resetWalkingQueue(); p.getPackets().clearMapFlag(); p.setFaceLocation(target.getLocation()); if (HANDS_GFX[index] != -1) { p.setLastGraphics(new Graphics(HANDS_GFX[index], 0, getStartingGraphicHeight(index))); } p.setLastAnimation(new Animation(SPELL_ANIM[index])); p.getPackets().closeInterfaces(); if (target is Player) { ((Player)target).getPackets().closeInterfaces(); } target.setAttacker(p); p.setTarget(target); target.setLastAttacked(Environment.TickCount); p.setLastAttack(Environment.TickCount); p.setLastMagicAttack(Environment.TickCount); p.setCombatTurns(p.getAttackSpeed()); Combat.setSkull(p, target); if (damage > 0) { frozen = freezeTarget(index, target); if (!frozen && index == 31) { endGfx = 1677; } } if (AIR_GFX[index] != -1 || ((index == 31 || index == 27) && target is Player && ((Player)target).getWalkingQueue().isRunning())) { sendProjectile(index, target, p); } if (damage > target.getHp()) { damage = target.getHp(); } if (index == 47 && Misc.random(2) == 0) { endGfx = 85; } Combat.checkIfWillDie(target, damage); Event doMagicAttackEvent = new Event(getSpellHitDelay(index)); doMagicAttackEvent.setAction(() => { doMagicAttackEvent.stop(); if (p == null || p.isDead() || !fakeNPC && (target.isDead() || target.isHidden() || target.isDestroyed())) { return; } if (target.isAutoRetaliating() && target.getTarget() == null && damage > 0) { if (target is Npc) { } else { if (((Player)target).getTemporaryAttribute("autoCastSpell") != null) { int autoCastSpell = (int)((Player)target).getTemporaryAttribute("autoCastSpell"); ((Player)target).setTemporaryAttribute("autoCasting", true); target.setTarget(p); MagicCombat.newMagicAttack((Player)target, p, autoCastSpell, ((Player)target).getTemporaryAttribute("autoCastAncients") != null); } } target.getFollow().setFollowing(p); target.setEntityFocus(p.getClientIndex()); if ((target.getCombatTurns() <= (target.getAttackSpeed() / 2) || target.getCombatTurns() >= (target.getAttackSpeed()))) { target.setCombatTurns(target.getAttackSpeed() / 2); } target.setTarget(p); if (target is Player) { ((Player)target).getWalkingQueue().resetWalkingQueue(); ((Player)target).getPackets().clearMapFlag(); } } addMagicXp(p, target, damage, index, true); target.setLastGraphics(new Graphics(endGfx, 0, getGroundHeight(index, endGfx))); if (index == 47 && endGfx != 85) { // teleblock if (target is Player) { teleblockPlayer(p, (Player)target); } } if (damage != 0) { Combat.checkRecoil(p, target, damage); Combat.checkSmite(p, target, damage); Combat.checkVengeance(p, target, damage); hitInMulti(p, target, index); applyMiasmicEffects(p, target, index); if ((target.getCombatTurns() > 2 || target.getCombatTurns() < 0) && !target.isDead()) { target.setLastAnimation(new Animation(target.getDefenceAnimation())); } if (index != 27) { target.hit((int)damage); if (index == 18 || index == 22 || index == 26 || index == 30) { p.heal(Convert.ToInt32(damage / 4)); } } else if (index == 27) { Event doHitEvent = new Event(1000); doHitEvent.setAction(() => { doHitEvent.stop(); target.hit((int)damage); }); Server.registerEvent(doHitEvent); } } }); Server.registerEvent(doMagicAttackEvent); if (p.getTemporaryAttribute("autoCasting") != null) { if (p.getTemporaryAttribute("autoCastSpell") != null) { if (id != (int)p.getTemporaryAttribute("autoCastSpell")) { p.setTarget(null); return; } } if (!fakeNPC) { p.setTemporaryAttribute("autocastLocation", target.getLocation()); p.setTemporaryAttribute("autocastEntity", target); } Event autoCastSpellEvent = new Event(3500); autoCastSpellEvent.setAction(() => { autoCastSpellEvent.stop(); if (p.getTemporaryAttribute("autoCasting") != null && p.getTemporaryAttribute("autoCastSpell") != null) { int autoCastSpell = (int)p.getTemporaryAttribute("autoCastSpell"); MagicCombat.newMagicAttack(p, p.getTarget(), autoCastSpell, p.getTemporaryAttribute("autoCastAncients") != null); } }); Server.registerEvent(autoCastSpellEvent); } else { p.setTarget(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 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 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); } }