Example #1
0
        private float DoCalculateDamage(Creature attacker, Creature defender, WorldObject damageSource)
        {
            var playerAttacker = attacker as Player;
            var playerDefender = defender as Player;

            Attacker = attacker;
            Defender = defender;

            CombatType = attacker.GetCombatType();

            DamageSource = damageSource;

            Weapon = attacker.GetEquippedWeapon();

            AttackType   = attacker.GetAttackType(Weapon, CombatManeuver);
            AttackHeight = attacker.AttackHeight ?? AttackHeight.Medium;

            // check lifestone protection
            if (playerDefender != null && playerDefender.UnderLifestoneProtection)
            {
                LifestoneProtection = true;
                playerDefender.HandleLifestoneProtection();
                return(0.0f);
            }

            if (defender.Invincible ?? false)
            {
                return(0.0f);
            }

            // evasion chance
            EvasionChance = GetEvadeChance(attacker, defender);
            if (EvasionChance > ThreadSafeRandom.Next(0.0f, 1.0f))
            {
                Evaded = true;
                return(0.0f);
            }

            // get base damage
            if (playerAttacker != null)
            {
                GetBaseDamage(playerAttacker, CombatManeuver);
            }
            else
            {
                GetBaseDamage(attacker, CombatManeuver);
            }

            if (GeneralFailure)
            {
                return(0.0f);
            }

            // get damage modifiers
            PowerMod     = attacker.GetPowerMod(Weapon);
            AttributeMod = attacker.GetAttributeMod(Weapon);
            SlayerMod    = WorldObject.GetWeaponCreatureSlayerModifier(attacker, defender);

            // additive?
            ElementalDamageBonus = WorldObject.GetMissileElementalDamageModifier(attacker, defender, DamageType);

            // ratings
            DamageRatingBaseMod = Creature.GetPositiveRating(attacker.GetProperty(PropertyInt.DamageRating) ?? 0);
            RecklessnessMod     = Creature.GetRecklessnessMod(attacker, defender);
            SneakAttackMod      = attacker.GetSneakAttackMod(defender);
            HeritageMod         = attacker.GetHeritageBonus(Weapon) ? 1.05f : 1.0f;

            DamageRatingMod = Creature.AdditiveCombine(DamageRatingBaseMod, RecklessnessMod, SneakAttackMod, HeritageMod, Creature.GetRatingMod(attacker.EnchantmentManager.GetDamageRating()));

            // damage before mitigation
            DamageBeforeMitigation = BaseDamage * AttributeMod * PowerMod * SlayerMod * DamageRatingMod + ElementalDamageBonus;   // additives on the end?

            // critical hit?
            var attackSkill = attacker.GetCreatureSkill(attacker.GetCurrentWeaponSkill());

            CriticalChance = WorldObject.GetWeaponCritChanceModifier(attacker, attackSkill);
            if (CriticalChance > ThreadSafeRandom.Next(0.0f, 1.0f))
            {
                IsCritical = true;

                CriticalDamageMod = 1.0f + WorldObject.GetWeaponCritDamageMod(attacker, attackSkill);

                // recklessness excluded from crits
                RecklessnessMod        = 1.0f;
                DamageRatingMod        = Creature.AdditiveCombine(DamageRatingBaseMod, SneakAttackMod, HeritageMod, Creature.GetRatingMod(attacker.EnchantmentManager.GetDamageRating()));
                DamageBeforeMitigation = BaseDamageRange.Max * AttributeMod * PowerMod * SlayerMod * DamageRatingMod * CriticalDamageMod + ElementalDamageBonus;
            }

            // get armor rending mod here?
            var armorRendingMod = 1.0f;

            if (Weapon != null && Weapon.HasImbuedEffect(ImbuedEffectType.ArmorRending))
            {
                armorRendingMod = WorldObject.GetArmorRendingMod(attackSkill);
            }

            // get body part / armor pieces / armor modifier
            if (playerDefender != null)
            {
                // select random body part @ current attack height
                GetBodyPart(AttackHeight);

                // get armor pieces
                Armor = attacker.GetArmorLayers(BodyPart);    // this uses attacker.AttackTarget

                // get armor modifiers
                ArmorMod = attacker.GetArmorMod(DamageType, Armor, DamageSource, armorRendingMod);
            }
            else
            {
                // select random body part @ current attack height
                GetBodyPart(AttackHeight, defender);
                if (Evaded)
                {
                    return(0.0f);
                }

                Armor = CreaturePart.GetArmorLayers((CombatBodyPart)BiotaPropertiesBodyPart.Key);

                // get target armor
                ArmorMod = CreaturePart.GetArmorMod(DamageType, Armor, DamageSource, armorRendingMod);
            }

            // get resistance modifiers
            WeaponResistanceMod = WorldObject.GetWeaponResistanceModifier(attacker, attackSkill, DamageType);

            if (playerDefender != null)
            {
                ResistanceMod = playerDefender.GetResistanceMod(DamageType, DamageSource, WeaponResistanceMod);
            }
            else
            {
                // todo: move out of creature part, not part-related?
                ResistanceMod = CreaturePart.GetResistanceMod(DamageType, DamageSource, WeaponResistanceMod);
            }

            // damage resistance rating
            DamageResistanceRatingMod = Creature.GetNegativeRatingMod(defender.EnchantmentManager.GetDamageResistRating());

            // get shield modifier
            ShieldMod = defender.GetShieldMod(attacker, DamageType);

            // calculate final output damage
            Damage          = DamageBeforeMitigation * ArmorMod * ShieldMod * ResistanceMod * DamageResistanceRatingMod;
            DamageMitigated = DamageBeforeMitigation - Damage;

            HandleLogging(playerAttacker, playerDefender);

            return(Damage);
        }