public static void rangeCombatLoop(Entity killer, Entity target) { if (!hasValidBowArrow(killer)) { killer.setTarget(null); return; } int hitDelay = getHitDelay(killer, target); if (killer is Player) { ((Player)killer).getWalkingQueue().resetWalkingQueue(); ((Player)killer).getPackets().closeInterfaces(); ((Player)killer).getPackets().clearMapFlag(); ((Player)killer).setLastCombatType(Combat.CombatType.RANGE); } int drawback = getDrawbackGraphic(killer); if (drawback != -1) { killer.setLastGraphics(new Graphics(drawback, 0, 90)); } displayProjectile(killer, target); deductArrow(killer); int arrowType = getArrowType(killer); int usingBow = ((Player)killer).getEquipment().getItemInSlot(ItemData.EQUIP.WEAPON); int usingArrows = ((Player)killer).getEquipment().getItemInSlot(ItemData.EQUIP.ARROWS); int damage1 = Misc.random((int)getDamage((Player)killer, target, usingBow, usingArrows)); int damage2 = usingBow == DARK_BOW?Misc.random((int)getDamage((Player)killer, target, usingBow, usingArrows)) : 0; /* * If the damage of the first attack will kill the target. * Make sure the target doesn't die from that first attack. * But instead split the attack into two attacks. */ if (damage1 >= target.getHp()) { int randomHp = Misc.random(target.getHp()); damage1 = randomHp; damage2 = target.getHp() - randomHp; } else { int hpRemaining = target.getHp() - damage1; if (damage2 > hpRemaining) { damage2 = hpRemaining; } } int totalDamage = damage1 + damage2; Combat.checkIfWillDie(target, (damage1 + damage2)); Event doRangedAttackEvent = new Event(hitDelay); doRangedAttackEvent.setAction(() => { int damage = damage1; if (getBowType(killer) == BOW_TYPE.CROSSBOW) { damage = applyBoltGraphic((Player)killer, target, damage1, arrowType); totalDamage = damage + damage2; } if ((target.getCombatTurns() > 2 || target.getCombatTurns() < 0) && !target.isDead()) { target.setLastAnimation(new Animation(target.getDefenceAnimation())); } target.hit(damage); Combat.addXp(killer, target, totalDamage); Combat.checkRecoil(killer, target, totalDamage); Combat.checkSmite(killer, target, totalDamage); Combat.checkVengeance(killer, target, totalDamage); if (killer is Player && arrowType != -1 && arrowType != BOLT_RACK) { createGroundArrow(killer, target, arrowType); } doRangedAttackEvent.stop(); }); Server.registerEvent(doRangedAttackEvent); //If the bow you are using is a darkbow do a second attack and animation. if (getBowType(killer) == BOW_TYPE.DARK_BOW) { deductArrow(killer); Event displayProjectileEvent = new Event(200); displayProjectileEvent.setAction(() => { displayProjectile(killer, target); displayProjectileEvent.stop(); }); Server.registerEvent(displayProjectileEvent); Event shootArrowEvent = new Event(hitDelay + 400); shootArrowEvent.setAction(() => { target.hit(damage2); if (killer is Player && arrowType != -1 && arrowType != BOLT_RACK) { createGroundArrow(killer, target, arrowType); } shootArrowEvent.stop(); }); Server.registerEvent(shootArrowEvent); } }
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); } }