public bool doSpecialAttack(Entity killer, Entity target) { int weapon = ((Player)killer).getEquipment().getItemInSlot(ItemData.EQUIP.WEAPON); int currentPower = specialAmount; int neededPower = getRequiredAmount(weapon); bool rangeWeapon = false; if (!usingSpecial) { return false; } if (p.getDuel() != null) { if (p.getDuel().ruleEnabled(DuelSession.RULE.NO_SPECIAL_ATTACKS)) { p.getPackets().sendMessage("Special attacks have been disabled for this duel!"); usingSpecial = false; refreshBar(); return false; } } if (neededPower > currentPower) { ((Player)killer).getPackets().sendMessage("You don't have enough special power left."); usingSpecial = false; refreshBar(); return false; } double damage = -1; double damage2 = -1; double damage3 = -1; double damage4 = -1; bool doubleHit = false; int increasedMaxHit = 0; damage = CombatFormula.getSpecialMeleeHit((Player)killer, target, weapon); damage2 = CombatFormula.getSpecialMeleeHit((Player)killer, target, weapon); int hitDelay = killer.getHitDelay(); //int totalDamage = 0; int usingBow = ((Player)killer).getEquipment().getItemInSlot(ItemData.EQUIP.WEAPON); int usingArrows = ((Player)killer).getEquipment().getItemInSlot(ItemData.EQUIP.ARROWS); bool usingRangePrayer = false; if (target is Player) { usingRangePrayer = ((Player)target).getPrayers().getHeadIcon() == PrayerData.RANGE; } switch (weapon) { case 4151: // Whip. killer.setLastAnimation(new Animation(1658)); target.setLastGraphics(new Graphics(341, 0, 100)); if (Misc.random(3) == 0 && damage > 0) { damage = p.getMaxHit(); } else { damage = 0; } if (target is Player) { int energy = ((Player)target).getRunEnergy() / 4; ((Player)killer).setRunEnergy(((Player)killer).getRunEnergy() + energy); ((Player)target).setRunEnergy(((Player)target).getRunEnergy() - energy); if (((Player)killer).getRunEnergy() > 100) { ((Player)killer).setRunEnergy(100); } if (((Player)target).getRunEnergy() < 0) { ((Player)target).setRunEnergy(0); } } break; case 1215: // Dragon daggers. case 1231: case 5680: case 5698: if (damage > 0) { damage = p.getMaxHit(20); damage2 = p.getMaxHit(20); } killer.setLastAnimation(new Animation(1062)); killer.setLastGraphics(new Graphics(252, 0, 100)); doubleHit = true; /*if (misc.random(3) == 0 && CombatFormula.getMeleeHit(p, target) > 0) { if (damage <= (CombatFormula.getMaxHit(p, 20) / 2) && damage2 <= (CombatFormula.getMaxHit(p, 20) / 2)) { damage = (CombatFormula.getMaxHit(p, 20) / 2) + (misc.randomDouble() * CombatFormula.getMaxHit(p, 20)) / 2); damage2 = (CombatFormula.getMaxHit(p, 20) / 2) + (misc.randomDouble() * CombatFormula.getMaxHit(p, 20)) / 2); } } else if (misc.random(2) == 0) { damage = 0; damage2 = 0; }*/ double a = damage + damage2; if (damage > target.getHp()) { damage = target.getHp(); } a -= damage; if (damage2 > a) { damage2 = a; } /*if (damage > target.getHp()) { int randomHp = misc.random(target.getHp()); damage = randomHp; damage2 = target.getHp() - randomHp; } else { int hpRemaining = target.getHp() - damage; if (damage2 > hpRemaining) { damage2 = hpRemaining; } }*/ break; case 1305: // Dragon longsword. killer.setLastAnimation(new Animation(1058)); killer.setLastGraphics(new Graphics(248, 0, 100)); damage = p.getMaxHit(30); break; case 11694: // Armadyl godsword. killer.setLastGraphics(new Graphics(1222, 0, 100)); killer.setLastAnimation(new Animation(7074)); damage += p.getMaxHit() * 0.25; break; case 11696: // Bandos godsword. killer.setLastGraphics(new Graphics(1223, 0, 100)); killer.setLastAnimation(new Animation(7073)); damage += p.getMaxHit() * 0.10; break; case 11698: // Saradomin godsword. killer.setLastGraphics(new Graphics(1220, 0, 100)); killer.setLastAnimation(new Animation(7071)); int newHp = (int)(damage * 0.50); int newPrayer = (int)(damage * 0.25); if (newHp < 10) { newHp = 10; } if (newPrayer < 5) { newPrayer = 5; } ((Player)killer).heal(newHp); ((Player)killer).getSkills().setCurLevel(Skills.SKILL.PRAYER, ((Player)killer).getSkills().getCurLevel(Skills.SKILL.PRAYER) + newPrayer); if (((Player)killer).getSkills().getCurLevel(Skills.SKILL.PRAYER) > ((Player)killer).getSkills().getMaxLevel(Skills.SKILL.PRAYER)) { ((Player)killer).getSkills().setCurLevel(Skills.SKILL.PRAYER, ((Player)killer).getSkills().getMaxLevel(Skills.SKILL.PRAYER)); } break; case 11700: // Zamorak godsword killer.setLastGraphics(new Graphics(1221, 0, 100)); killer.setLastAnimation(new Animation(7070)); target.setLastGraphics(new Graphics(369)); MagicCombat.freezeTarget(31, target); break; case 11730: // Saradomin sword target.setLastGraphics(new Graphics(1207, 0, 100)); killer.setLastAnimation(new Animation(7072)); increasedMaxHit = 16; break; case 1434: // Dragon mace hitDelay = 700; killer.setLastGraphics(new Graphics(251, 0, 75)); killer.setLastAnimation(new Animation(1060)); damage = p.getMaxHit(60); break; case 3204: // Dragon halberd // TODO halberd break; case 4587: // Dragon scimitar killer.setLastGraphics(new Graphics(347, 0, 100)); killer.setLastAnimation(new Animation(451)); if (target is Player) { if (((Player)target).getPrayers().getOverheadPrayer() >= 1 && ((Player)target).getPrayers().getOverheadPrayer() <= 3) { ((Player)target).getPrayers().setOverheadPrayer(0); ((Player)target).getPrayers().setHeadIcon(-1); ((Player)target).getPackets().sendMessage("The Dragon scimitar slashes through your prayer protection!"); ((Player)target).getPackets().sendConfig(95, 0); ((Player)target).getPackets().sendConfig(97, 0); ((Player)target).getPackets().sendConfig(98, 0); ((Player)target).getPackets().sendConfig(99, 0); ((Player)target).getPackets().sendConfig(100, 0); ((Player)target).getPackets().sendConfig(96, 0); } } break; case 14484: // Dragon claws doubleHit = true; killer.setLastGraphics(new Graphics(1950)); killer.setLastAnimation(new Animation(10961)); if (Misc.random(1) == 0 && damage > 0) { if (damage < p.getMaxHit(20) * 0.75) { damage = (p.getMaxHit(20) * 0.75 + (Misc.randomDouble() * (p.getMaxHit(20) * 0.25))); } } damage = (int)Math.Floor(damage); damage2 = (int)Math.Floor(damage * 0.50); damage3 = (int)Math.Floor(damage2 * 0.50); damage4 = (int)Math.Floor(damage3 + 1); break; case 1249: // Dragon spear //TODO leave due to noclipping? break; case 6739: // Dragon axe //TODO find emote and graphic break; case 7158: // Dragon 2h killer.setLastAnimation(new Animation(3157)); killer.setLastGraphics(new Graphics(559)); //TODO multi combat break; case 3101: // Rune claws killer.setLastGraphics(new Graphics(274)); break; case 4153: // Granite maul killer.setLastAnimation(new Animation(1667)); killer.setLastGraphics(new Graphics(340, 0, 100)); //doubleHit = true; break; case 10887: // Barrelchest anchor break; case 11061: // Ancient mace break; case 13902: // Statius' warhammer killer.setLastAnimation(new Animation(10505)); killer.setLastGraphics(new Graphics(1840)); damage += killer.getMaxHit() * 0.25; if (target is Player) { int defenceLevel = ((Player)target).getSkills().getCurLevel(Skills.SKILL.DEFENCE); int newDefence = (int)(defenceLevel * 0.30); if (newDefence < 1) { newDefence = 1; } ((Player)target).getSkills().setCurLevel(Skills.SKILL.DEFENCE, defenceLevel - newDefence); ((Player)target).getPackets().sendSkillLevel(Skills.SKILL.DEFENCE); } break; case 13899: // Vesta's longsword killer.setLastAnimation(new Animation(10502)); damage += killer.getMaxHit() * 0.20; break; case 13905: // Vesta's spear killer.setLastAnimation(new Animation(10499)); killer.setLastGraphics(new Graphics(1835)); break; case 13883: // Morrigans throwing axe break; case 13879: // Morrigans javelin case 8880: // Dorgeshuun crossbow break; case 861: // Magic shortbow case 859: // Magic longbow case 10284: // Magic composite bow rangeWeapon = true; if (p.getEquipment().getAmountInSlot(ItemData.EQUIP.ARROWS) < 2) { p.getPackets().sendMessage("You need 2 arrows to use the Magic bow special attack!"); return false; } damage = (int)CombatFormula.getRangeHit((Player)killer, target, usingBow, usingArrows); damage2 = (int)CombatFormula.getRangeHit((Player)killer, target, usingBow, usingArrows); damage *= 1.05; damage2 *= 1.05; if (usingRangePrayer) { damage *= 0.60; damage2 *= 0.60; } double a1 = damage + damage2; if (damage > target.getHp()) { damage = target.getHp(); } a1 -= damage; if (damage2 > a1) { damage2 = a1; } /*if (damage >= target.getHp()) { int randomHp = misc.random(target.getHp()); damage = randomHp; damage2 = target.getHp() - randomHp; } else { int hpRemaining = target.getHp() - damage; if (damage2 > hpRemaining) { damage2 = hpRemaining; } }*/ p.setLastAnimation(new Animation(1074)); p.setLastGraphics(new Graphics(256, 0, 90)); RangeCombat.deductArrow(killer); RangeCombat.deductArrow(killer); int arrowType = RangeCombat.getArrowType(killer); hitDelay = 1000; int MSpecCounter = 0; Event displayMSpecProjectileEvent = new Event(0); displayMSpecProjectileEvent.setAction(() => { RangeCombat.displayMSpecProjectile(killer, target); MSpecCounter++; if (MSpecCounter == 1) { displayMSpecProjectileEvent.setTick(500); p.setLastGraphics(new Graphics(256, 0, 90)); Event doMSpecHitEvent = new Event(900); doMSpecHitEvent.setAction(() => { doMSpecHitEvent.stop(); target.hit((int)damage2); RangeCombat.createGroundArrow(killer, target, arrowType); }); Server.registerEvent(doMSpecHitEvent); } else { displayMSpecProjectileEvent.stop(); return; } MSpecCounter++; }); Server.registerEvent(displayMSpecProjectileEvent); break; case 805: // Rune thrownaxe rangeWeapon = true; break; case 6724: // Seercull rangeWeapon = true; break; case 11235: // Dark bow rangeWeapon = true; if (p.getEquipment().getAmountInSlot(ItemData.EQUIP.ARROWS) < 2) { p.getPackets().sendMessage("You need 2 arrows to use the Dark bow!"); return false; } int minHit = 8; damage = (int)CombatFormula.getRangeHit((Player)killer, target, usingBow, usingArrows); damage2 = (int)CombatFormula.getRangeHit((Player)killer, target, usingBow, usingArrows); if (usingBow == 11235) { // Dark bow if (usingArrows == 11212) { // Dragon arrows minHit = usingRangePrayer ? 4 : 8; damage *= 1.50; damage2 *= 1.50; if (damage < minHit) { damage = minHit; } if (damage2 < minHit) { damage2 = minHit; } } else { // Other arrow minHit = usingRangePrayer ? 3 : 5; damage *= 1.30; damage2 *= 1.30; if (damage < minHit) { damage = minHit; } if (damage2 < minHit) { damage2 = minHit; } } } if (usingRangePrayer) { damage *= 0.60; damage2 *= 0.60; } double a2 = damage + damage2; if (damage > target.getHp()) { damage = target.getHp(); } a2 -= damage; if (damage2 > a2) { damage2 = a2; } /*if (damage >= target.getHp()) { int randomHp = misc.random(target.getHp()); damage = randomHp; damage2 = target.getHp() - randomHp; } else { int hpRemaining = target.getHp() - damage; if (damage2 > hpRemaining) { damage2 = hpRemaining; } }*/ p.setLastGraphics(new Graphics(RangeCombat.getDrawbackGraphic(killer), 0, 90)); RangeCombat.deductArrow(killer); RangeCombat.deductArrow(killer); hitDelay = RangeCombat.getHitDelay(killer, target); int delayHit = hitDelay; hitDelay = 1200; int arrowType1 = RangeCombat.getArrowType(killer); int DBSpecCounter = 0; Event DBSpecProjectile = new Event(0); DBSpecProjectile.setAction(() => { RangeCombat.displayDBSpecProjectile(killer, target); DBSpecCounter++; if (DBSpecCounter == 1) { DBSpecProjectile.setTick(200); Event rangeHitEvent = new Event(delayHit + 600); rangeHitEvent.setAction(() => { target.hit((int)damage2); rangeHitEvent.stop(); RangeCombat.createGroundArrow(killer, target, arrowType1); }); Server.registerEvent(rangeHitEvent); } else { DBSpecProjectile.stop(); return; } DBSpecCounter++; }); Server.registerEvent(DBSpecProjectile); break; } specialAmount -= neededPower; p.setSpecialAmount(specialAmount); usingSpecial = false; refreshBar(); killer.resetCombatTurns(); bool hitDouble = doubleHit; if (target is Player) { if (!rangeWeapon) { if (((Player)target).getPrayers().getHeadIcon() == PrayerData.MELEE) { damage = (int)(damage * 0.60); } } else { if (((Player)target).getPrayers().getHeadIcon() == PrayerData.RANGE) { damage = (int)(damage * 0.60); } } } damage = ((weapon == 4151) ? damage : (Misc.randomDouble() * damage)); damage2 = Misc.randomDouble() * damage2; int d = (int)((damage == 0 && weapon != 11730) ? 0 : (damage + increasedMaxHit)); int d2 = (int)damage2; int d3 = (int)damage3; // only used for d claws int d4 = (int)damage4; // only used for d claws if (canPoison(weapon)) { if (!target.isPoisoned() && Misc.random(5) == 0 && (hitDouble ? (d2 > 0 || d > 0) : d > 0)) { Server.registerEvent(new PoisonEvent(target, POISON_AMOUNT)); } } int hhitDelay = hitDelay; int totDamage = Convert.ToInt32(damage + damage2 + damage3 + damage4); Combat.checkIfWillDie(target, totDamage); Event hitEvent = new Event(hhitDelay); hitEvent.setAction(() => { hitEvent.stop(); if (!target.isDead()) { target.setLastAnimation(new Animation(target.getDefenceAnimation())); } target.hit(d); if (hitDouble) { target.hit(d2); } if (d3 != -1 || d4 != -1) { target.hit(d3); target.hit(d4); } Combat.checkRecoil(killer, target, totDamage); Combat.checkSmite(killer, target, totDamage); Combat.checkVengeance(killer, target, totDamage); Combat.addXp(killer, target, totDamage); }); Server.registerEvent(hitEvent); return true; }
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); } }