Beispiel #1
0
        /// <summary>
        /// Calculates damage to target with resist chance and stores it in ad
        /// </summary>
        /// <param name="target">spell target</param>
        /// <param name="effectiveness">value from 0..1 to modify damage</param>
        /// <returns>attack data</returns>
        public virtual AttackData CalculateDamageToTarget(GameLiving target, double effectiveness)
        {
            AttackData ad = new AttackData();
            ad.Attacker = m_caster;
            ad.Target = target;
            ad.AttackType = AttackData.eAttackType.Spell;
            ad.SpellHandler = this;
            ad.AttackResult = GameLiving.eAttackResult.HitUnstyled;

            double minVariance;
            double maxVariance;

            CalculateDamageVariance(target, out minVariance, out maxVariance);
            double spellDamage = CalculateDamageBase(target);

            if (m_caster is GamePlayer)
            {
                effectiveness += m_caster.GetModified(eProperty.SpellDamage) * 0.01;

                // Relic bonus applied to damage, does not alter effectiveness or increase cap
                spellDamage *= (1.0 + RelicMgr.GetRelicBonusModifier(m_caster.Realm, eRelicType.Magic));

            }

            // Apply casters effectiveness
            spellDamage *= m_caster.Effectiveness;

            int finalDamage = Util.Random((int)(minVariance * spellDamage), (int)(maxVariance * spellDamage));

            // Live testing done Summer 2009 by Bluraven, Tolakram  Levels 40, 45, 50, 55, 60, 65, 70
            // Damage reduced by chance < 55, no extra damage increase noted with hitchance > 100
            int hitChance = CalculateToHitChance(ad.Target);
            finalDamage = AdjustDamageForHitChance(finalDamage, hitChance);

            // apply spell effectiveness
            finalDamage = (int)(finalDamage * effectiveness);

            if ((m_caster is GamePlayer || (m_caster is GameNPC && (m_caster as GameNPC).Brain is IControlledBrain && m_caster.Realm != 0)))
            {
                if (target is GamePlayer)
                    finalDamage = (int)((double)finalDamage * ServerProperties.Properties.PVP_SPELL_DAMAGE);
                else if (target is GameNPC)
                    finalDamage = (int)((double)finalDamage * ServerProperties.Properties.PVE_SPELL_DAMAGE);
            }

            // Well the PenetrateResistBuff is NOT ResistPierce
            GameSpellEffect penPierce = SpellHandler.FindEffectOnTarget(m_caster, "PenetrateResists");
            if (penPierce != null)
            {
                finalDamage = (int)(finalDamage * (1.0 + penPierce.Spell.Value / 100.0));
            }

            int cdamage = 0;
            if (finalDamage < 0)
                finalDamage = 0;

            eDamageType damageType = DetermineSpellDamageType();

            #region Resists
            eProperty property = target.GetResistTypeForDamage(damageType);
            // The Daoc resistsystem is since 1.65 a 2category system.
            // - First category are Item/Race/Buff/RvrBanners resists that are displayed in the characteroverview.
            // - Second category are resists that are given through RAs like avoidance of magic, brilliance aura of deflection.
            //   Those resist affect ONLY the spelldamage. Not the duration, not the effectiveness of debuffs.
            // so calculation is (finaldamage * Category1Modification) * Category2Modification
            // -> Remark for the future: VampirResistBuff is Category2 too.
            // - avi

            #region Primary Resists
            int primaryResistModifier = ad.Target.GetResist(damageType);

            /* Resist Pierce
             * Resipierce is a special bonus which has been introduced with TrialsOfAtlantis.
             * At the calculation of SpellDamage, it reduces the resistance that the victim recives
             * through ITEMBONUSES for the specified percentage.
             * http://de.daocpedia.eu/index.php/Resistenz_durchdringen (translated)
             */
            int resiPierce = Caster.GetModified(eProperty.ResistPierce);
            GamePlayer ply = Caster as GamePlayer;
            if (resiPierce > 0 && Spell.SpellType != "Archery")
            {
                //substract max ItemBonus of property of target, but atleast 0.
                primaryResistModifier -= Math.Max(0, Math.Min(ad.Target.ItemBonus[(int)property], resiPierce));
            }
            #endregion

            #region Secondary Resists
            //Using the resist BuffBonusCategory2 - its unused in ResistCalculator
            int secondaryResistModifier = target.SpecBuffBonusCategory[(int)property];

            if (secondaryResistModifier > 80)
                secondaryResistModifier = 80;
            #endregion

            int resistModifier = 0;
            //primary resists
            resistModifier += (int)(finalDamage * (double)primaryResistModifier * -0.01);
            //secondary resists
            resistModifier += (int)((finalDamage + (double)resistModifier) * (double)secondaryResistModifier * -0.01);
            //apply resists
            finalDamage += resistModifier;

            #endregion

            // Apply damage cap (this can be raised by effectiveness)
            if (finalDamage > DamageCap(effectiveness))
            {
                finalDamage = (int)DamageCap(effectiveness);
            }

            if (finalDamage < 0)
                finalDamage = 0;

            int criticalchance = (m_caster.SpellCriticalChance);
            if (Util.Chance(Math.Min(50, criticalchance)) && (finalDamage >= 1))
            {
                int critmax = (ad.Target is GamePlayer) ? finalDamage / 2 : finalDamage;
                cdamage = Util.Random(finalDamage / 10, critmax); //think min crit is 10% of damage
            }
            //Andraste
            if(ad.Target is GamePlayer && ad.Target.GetModified(eProperty.Conversion)>0)
            {
                int manaconversion=(int)Math.Round(((double)ad.Damage+(double)ad.CriticalDamage)*(double)ad.Target.GetModified(eProperty.Conversion)/200);
                //int enduconversion=(int)Math.Round((double)manaconversion*(double)ad.Target.MaxEndurance/(double)ad.Target.MaxMana);
                int enduconversion=(int)Math.Round(((double)ad.Damage+(double)ad.CriticalDamage)*(double)ad.Target.GetModified(eProperty.Conversion)/200);
                if(ad.Target.Mana+manaconversion>ad.Target.MaxMana) manaconversion=ad.Target.MaxMana-ad.Target.Mana;
                if(ad.Target.Endurance+enduconversion>ad.Target.MaxEndurance) enduconversion=ad.Target.MaxEndurance-ad.Target.Endurance;
                if(manaconversion<1) manaconversion=0;
                if(enduconversion<1) enduconversion=0;
                if(manaconversion>=1) (ad.Target as GamePlayer).Out.SendMessage("You gain "+manaconversion+" power points", eChatType.CT_Spell, eChatLoc.CL_SystemWindow);
                if(enduconversion>=1) (ad.Target as GamePlayer).Out.SendMessage("You gain "+enduconversion+" endurance points", eChatType.CT_Spell, eChatLoc.CL_SystemWindow);
                ad.Target.Endurance+=enduconversion; if(ad.Target.Endurance>ad.Target.MaxEndurance) ad.Target.Endurance=ad.Target.MaxEndurance;
                ad.Target.Mana+=manaconversion; if(ad.Target.Mana>ad.Target.MaxMana) ad.Target.Mana=ad.Target.MaxMana;
            }

            ad.Damage = finalDamage;
            ad.CriticalDamage = cdamage;
            ad.DamageType = damageType;
            ad.Modifier = resistModifier;

            // Attacked living may modify the attack data.  Primarily used for keep doors and components.
            ad.Target.ModifyAttack(ad);

            m_lastAttackData = ad;
            return ad;
        }
Beispiel #2
0
        public override AttackData CalculateDamageToTarget(GameLiving target, double effectiveness)
        {
            GamePlayer player = Caster as GamePlayer;

            if (player == null)
            {
                return(null);
            }

            InventoryItem weapon = null;

            if (player.ActiveWeaponSlot.ToString() == "TwoHanded")
            {
                weapon = player.Inventory.GetItem((eInventorySlot)12);
            }
            if (player.ActiveWeaponSlot.ToString() == "Standard")
            {
                weapon = player.Inventory.GetItem((eInventorySlot)10);
            }

            if (weapon == null)
            {
                return(null);
            }

            //create the AttackData
            AttackData ad = new AttackData();

            ad.Attacker       = player;
            ad.Target         = target;
            ad.Damage         = 0;
            ad.CriticalDamage = 0;
            ad.WeaponSpeed    = player.AttackSpeed(weapon) / 100;
            ad.DamageType     = player.AttackDamageType(weapon);
            ad.Weapon         = weapon;
            ad.IsOffHand      = weapon.Hand == 2;
            //we need to figure out which armor piece they are going to hit.
            //figure out the attacktype
            switch (weapon.Item_Type)
            {
            default:
            case Slot.RIGHTHAND:
            case Slot.LEFTHAND:
                ad.AttackType = AttackData.eAttackType.MeleeOneHand;
                break;

            case Slot.TWOHAND:
                ad.AttackType = AttackData.eAttackType.MeleeTwoHand;
                break;
            }
            //Throw Weapon is subject to all the conventional attack results, parry, evade, block, etc.
            ad.AttackResult = ad.Target.CalculateEnemyAttackResult(ad, weapon);

            if (ad.AttackResult == GameLiving.eAttackResult.HitUnstyled || ad.AttackResult == GameLiving.eAttackResult.HitStyle)
            {
                //we only need to calculate the damage if the attack was a success.
                double damage = player.AttackDamage(weapon) * effectiveness;

                if (target is GamePlayer)
                {
                    ad.ArmorHitLocation = ((GamePlayer)target).CalculateArmorHitLocation(ad);
                }

                InventoryItem armor = null;
                if (target.Inventory != null)
                {
                    armor = target.Inventory.GetItem((eInventorySlot)ad.ArmorHitLocation);
                }

                //calculate the lowerboundary of the damage
                int lowerboundary = (player.WeaponSpecLevel(weapon) - 1) * 50 / (ad.Target.EffectiveLevel + 1) + 75;
                lowerboundary = Math.Max(lowerboundary, 75);
                lowerboundary = Math.Min(lowerboundary, 125);

                damage *= (player.GetWeaponSkill(weapon) + 90.68) / (ad.Target.GetArmorAF(ad.ArmorHitLocation) + 20 * 4.67);

                //If they have badge of Valor, we need to modify the damage
                if (ad.Attacker.EffectList.GetOfType <BadgeOfValorEffect>() != null)
                {
                    damage *= 1.0 + Math.Min(0.85, ad.Target.GetArmorAbsorb(ad.ArmorHitLocation));
                }
                else
                {
                    damage *= 1.0 - Math.Min(0.85, ad.Target.GetArmorAbsorb(ad.ArmorHitLocation));
                }

                damage *= (lowerboundary + Util.Random(50)) * 0.01;

                ad.Modifier = (int)(damage * (ad.Target.GetResist(ad.DamageType) + SkillBase.GetArmorResist(armor, ad.DamageType)) * -0.01);

                damage += ad.Modifier;

                int       resist   = (int)(damage * ad.Target.GetDamageResist(target.GetResistTypeForDamage(ad.DamageType)) * -0.01);
                eProperty property = ad.Target.GetResistTypeForDamage(ad.DamageType);
                int       secondaryResistModifier = ad.Target.SpecBuffBonusCategory[(int)property];
                int       resistModifier          = 0;
                resistModifier   += (int)((ad.Damage + (double)resistModifier) * (double)secondaryResistModifier * -0.01);
                damage           += resist;
                damage           += resistModifier;
                ad.Modifier      += resist;
                ad.Damage         = (int)damage;
                ad.UncappedDamage = ad.Damage;
                ad.Damage         = Math.Min(ad.Damage, (int)(player.UnstyledDamageCap(weapon) * effectiveness));
                ad.Damage         = (int)((double)ad.Damage * ServerProperties.Properties.PVP_MELEE_DAMAGE);
                if (ad.Damage == 0)
                {
                    ad.AttackResult = DOL.GS.GameLiving.eAttackResult.Missed;
                }
                ad.CriticalDamage = player.GetMeleeCriticalDamage(ad, weapon);
            }
            else
            {
                //They failed, do they do not get disarmed, and the spell is not disabled for the full duration,
                //just the modified swing speed, this is in milliseconds
                int attackSpeed = player.AttackSpeed(weapon);
                player.TempProperties.setProperty(DISABLE, attackSpeed);
            }
            return(ad);
        }
Beispiel #3
0
        public override AttackData CalculateDamageToTarget(GameLiving target, double effectiveness)
        {
            GamePlayer player = Caster as GamePlayer;

            if (player == null)
                return null;

            InventoryItem weapon = null;

            if (player.ActiveWeaponSlot.ToString() == "TwoHanded")
                weapon = player.Inventory.GetItem((eInventorySlot)12);
            if (player.ActiveWeaponSlot.ToString() == "Standard")
                weapon = player.Inventory.GetItem((eInventorySlot)10);

            if (weapon == null)
                return null;

            //create the AttackData
            AttackData ad = new AttackData();
            ad.Attacker = player;
            ad.Target = target;
            ad.Damage = 0;
            ad.CriticalDamage = 0;
            ad.WeaponSpeed = player.AttackSpeed(weapon) / 100;
            ad.DamageType = player.AttackDamageType(weapon);
            ad.Weapon = weapon;
            ad.IsOffHand = weapon.Hand == 2;
            //we need to figure out which armor piece they are going to hit.
            //figure out the attacktype
            switch (weapon.Item_Type)
            {
                default:
                case Slot.RIGHTHAND:
                case Slot.LEFTHAND:
                    ad.AttackType = AttackData.eAttackType.MeleeOneHand;
                    break;
                case Slot.TWOHAND:
                    ad.AttackType = AttackData.eAttackType.MeleeTwoHand;
                    break;
            }
            //Throw Weapon is subject to all the conventional attack results, parry, evade, block, etc.
            ad.AttackResult = ad.Target.CalculateEnemyAttackResult(ad, weapon);

            if (ad.AttackResult == GameLiving.eAttackResult.HitUnstyled || ad.AttackResult == GameLiving.eAttackResult.HitStyle)
            {
                //we only need to calculate the damage if the attack was a success.
                double damage = player.AttackDamage(weapon) * effectiveness;

                if (target is GamePlayer)
                    ad.ArmorHitLocation = ((GamePlayer)target).CalculateArmorHitLocation(ad);

                InventoryItem armor = null;
                if (target.Inventory != null)
                    armor = target.Inventory.GetItem((eInventorySlot)ad.ArmorHitLocation);

                //calculate the lowerboundary of the damage
                int lowerboundary = (player.WeaponSpecLevel(weapon) - 1) * 50 / (ad.Target.EffectiveLevel + 1) + 75;
                lowerboundary = Math.Max(lowerboundary, 75);
                lowerboundary = Math.Min(lowerboundary, 125);

                damage *= (player.GetWeaponSkill(weapon) + 90.68) / (ad.Target.GetArmorAF(ad.ArmorHitLocation) + 20 * 4.67);

                //If they have badge of Valor, we need to modify the damage
                if (ad.Attacker.EffectList.GetOfType<BadgeOfValorEffect>() != null)
                    damage *= 1.0 + Math.Min(0.85, ad.Target.GetArmorAbsorb(ad.ArmorHitLocation));
                else
                    damage *= 1.0 - Math.Min(0.85, ad.Target.GetArmorAbsorb(ad.ArmorHitLocation));

                damage *= (lowerboundary + Util.Random(50)) * 0.01;

                ad.Modifier = (int)(damage * (ad.Target.GetResist(ad.DamageType) + SkillBase.GetArmorResist(armor, ad.DamageType)) * -0.01);

                damage += ad.Modifier;

                int resist = (int)(damage * ad.Target.GetDamageResist(target.GetResistTypeForDamage(ad.DamageType)) * -0.01);
                eProperty property = ad.Target.GetResistTypeForDamage(ad.DamageType);
                int secondaryResistModifier = ad.Target.SpecBuffBonusCategory[(int)property];
                int resistModifier = 0;
                resistModifier += (int)((ad.Damage + (double)resistModifier) * (double)secondaryResistModifier * -0.01);
                damage += resist;
                damage += resistModifier;
                ad.Modifier += resist;
                ad.Damage = (int)damage;
                ad.UncappedDamage = ad.Damage;
                ad.Damage = Math.Min(ad.Damage, (int)(player.UnstyledDamageCap(weapon) * effectiveness));
                ad.Damage = (int)((double)ad.Damage * ServerProperties.Properties.PVP_MELEE_DAMAGE);
                if (ad.Damage == 0) ad.AttackResult = DOL.GS.GameLiving.eAttackResult.Missed;
                ad.CriticalDamage = player.GetMeleeCriticalDamage(ad, weapon);
            }
            else
            {
                //They failed, do they do not get disarmed, and the spell is not disabled for the full duration,
                //just the modified swing speed, this is in milliseconds
                int attackSpeed = player.AttackSpeed(weapon);
                player.TempProperties.setProperty(DISABLE, attackSpeed);
            }
            return ad;
        }