示例#1
0
        public static double getDamage(Entity killer, Entity target)
        {
            if (killer is Npc)
            {
                int maxDamage = killer.getMaxHit();
                if (maxDamage > target.getHp())
                {
                    maxDamage = target.getHp();
                }
                if (target is Player)
                {
                    NpcData npcDef         = NpcData.forId(((Npc)killer).getId());
                    int     npcAttackStyle = ((Npc)killer).getAttackType();

                    if (((Player)target).getPrayers().getHeadIcon() == PrayerData.MELEE && npcAttackStyle == NpcData.MELEE)
                    {
                        return(0);
                    }
                    else
                    if (misc.random((int)CombatFormula.getNPCMeleeAttack((Npc)killer)) < misc.random((int)CombatFormula.getMeleeDefence((Player)target, (Player)target)))
                    {
                        return(0);
                    }
                }
                return(misc.random(maxDamage));
            }
            else
            {
                if (target is Npc)
                {
                    if (misc.random((int)CombatFormula.getMeleeAttack((Player)killer)) < misc.random((int)CombatFormula.getNPCMeleeDefence((Npc)target)))
                    {
                        return(0);
                    }
                }
                double damage = CombatFormula.getMeleeHit((Player)killer, target);
                if (target is Player)
                {
                    if (((Player)target).getPrayers().getHeadIcon() == PrayerData.MELEE)
                    {
                        damage = (int)(damage * 0.60);
                    }
                }
                if (damage > target.getHp())
                {
                    damage = target.getHp();
                }
                return(damage);
            }
        }
        private static double getDamage(Player killer, Entity target, int usingBow, int usingArrows)
        {
            double damage = CombatFormula.getRangeHit(killer, target, usingBow, usingArrows);

            if (target is Player)
            {
                int prayerType = ((Player)target).getPrayers().getHeadIcon();
                if (prayerType == PrayerData.RANGE)
                {
                    return(damage * 0.60);
                }
                else
                {
                    return(damage);
                }
            }
            return(damage);
        }
示例#3
0
        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 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);
            }
        }