/// <summary> /// Selects a random body part at current attack height /// </summary> public BodyPart GetBodyPart() { if (AttackHeight == null) { GetAttackHeight(); } return(BodyParts.GetBodyPart(AttackHeight.Value)); }
public float CalculateDamage(WorldObject target, WorldObject damageSource, ref bool criticalHit) { var creature = target as Creature; // evasion chance var evadeChance = GetEvadeChance(target); if (Physics.Common.Random.RollDice(0.0f, 1.0f) < evadeChance) { return(0.0f); } // get weapon base damage var baseDamageRange = GetBaseDamage(); var baseDamage = Physics.Common.Random.RollDice(baseDamageRange.Min, baseDamageRange.Max); // get damage mods var powerAccuracyMod = GetPowerAccuracyMod(); var attributeMod = GetAttributeMod(); var damage = baseDamage * attributeMod * powerAccuracyMod; // critical hit var critical = 0.1f; if (Physics.Common.Random.RollDice(0.0f, 1.0f) < critical) { damage = baseDamageRange.Max * attributeMod * powerAccuracyMod * 2.0f; criticalHit = true; } // get random body part @ attack height var bodyPart = BodyParts.GetBodyPart(AttackHeight); // get target armor var armor = GetArmor(target, bodyPart); // get target resistance DamageType damageType; if (damageSource?.ItemType == ItemType.MissileWeapon) { damageType = (DamageType)damageSource.GetProperty(PropertyInt.DamageType); } else { damageType = GetDamageType(); } var resistance = GetResistance(target, bodyPart, damageType); // scale damage for armor and shield var armorMod = SkillFormula.CalcArmorMod(resistance); var shieldMod = creature.GetShieldMod(this, damageType); return(damage * armorMod * shieldMod); }
/// <summary> /// Performs a melee attack for the monster /// </summary> /// <returns>The length in seconds for the attack animation</returns> public float MeleeAttack() { var player = AttackTarget as Player; if (player.Health.Current <= 0) { return(0.0f); } // choose a random combat maneuver var maneuver = GetCombatManeuver(); if (maneuver == null) { return(0.0f); } AttackHeight = maneuver.AttackHeight; // select random body part @ current attack height var bodyPart = BodyParts.GetBodyPart(AttackHeight.Value); DoSwingMotion(AttackTarget, maneuver, out float animLength); PhysicsObj.stick_to_object(AttackTarget.PhysicsObj.ID); var actionChain = new ActionChain(); actionChain.AddDelaySeconds(animLength / 2.0f); actionChain.AddAction(this, () => { if (AttackTarget == null) { return; } var critical = false; var damageType = DamageType.Undef; var damage = CalculateDamage(ref damageType, maneuver, bodyPart, ref critical); if (damage > 0.0f) { player.TakeDamage(this, damageType, damage, bodyPart, critical); } else { player.OnEvade(this, AttackType.Melee); } }); actionChain.EnqueueChain(); // TODO: figure out exact speed / delay formula NextAttackTime = Timer.CurrentTime + animLength + MeleeDelay; return(animLength); }
public float CalculateDamage(WorldObject target, ref bool criticalHit) { // evasion chance var evadeChance = GetEvadeChance(target); if (Physics.Common.Random.RollDice(0.0f, 1.0f) < evadeChance) { return(0.0f); } // get weapon base damage var baseDamageRange = GetBaseDamage(); var baseDamage = Physics.Common.Random.RollDice(baseDamageRange.Min, baseDamageRange.Max); // get damage mods var powerAccuracyMod = GetPowerAccuracyMod(); var attributeMod = GetAttributeMod(); var damage = baseDamage * attributeMod * powerAccuracyMod; // critical hit var critical = 0.1f; if (Physics.Common.Random.RollDice(0.0f, 1.0f) < critical) { damage = baseDamageRange.Max * attributeMod * powerAccuracyMod * 2.0f; criticalHit = true; } // get random body part @ attack height var bodyPart = BodyParts.GetBodyPart(AttackHeight); // get target armor var armor = GetArmor(target, bodyPart); // get target resistance var damageType = GetDamageType(); var resistance = GetResistance(target, bodyPart, damageType); // scale damage for armor damage *= SkillFormula.CalcArmorMod(resistance); return(damage); }
/// <summary> /// Performs a melee attack for the monster /// </summary> /// <returns>The length in seconds for the attack animation</returns> public float MeleeAttack() { var target = AttackTarget as Creature; var targetPlayer = AttackTarget as Player; var targetPet = AttackTarget as CombatPet; var combatPet = this as CombatPet; if (target == null || !target.IsAlive) { Sleep(); return(0.0f); } // choose a random combat maneuver var maneuver = GetCombatManeuver(); if (maneuver == null) { Console.WriteLine($"Combat maneuver null! Stance {CurrentMotionState.Stance}, MotionTable {MotionTableId:X8}"); return(0.0f); } AttackHeight = maneuver.AttackHeight; // select random body part @ current attack height var bodyPart = BodyParts.GetBodyPart(AttackHeight.Value); DoSwingMotion(AttackTarget, maneuver, out float animLength, out var attackFrames); PhysicsObj.stick_to_object(AttackTarget.PhysicsObj.ID); var numStrikes = attackFrames.Count; var actionChain = new ActionChain(); var prevTime = 0.0f; for (var i = 0; i < numStrikes; i++) { actionChain.AddDelaySeconds(attackFrames[i] * animLength - prevTime); prevTime = attackFrames[i] * animLength; actionChain.AddAction(this, () => { if (AttackTarget == null) { return; } var critical = false; var damageType = DamageType.Undef; var shieldMod = 1.0f; var damage = CalculateDamage(ref damageType, maneuver, bodyPart, ref critical, ref shieldMod); if (damage != null) { if (combatPet != null || targetPet != null) { // combat pet inflicting or receiving damage //Console.WriteLine($"{target.Name} taking {Math.Round(damage)} {damageType} damage from {Name}"); target.TakeDamage(this, damageType, damage.Value); EmitSplatter(target, damage.Value); } else { // this is a player taking damage targetPlayer.TakeDamage(this, damageType, damage.Value, bodyPart, critical); if (shieldMod != 1.0f) { var shieldSkill = targetPlayer.GetCreatureSkill(Skill.Shield); Proficiency.OnSuccessUse(targetPlayer, shieldSkill, shieldSkill.Current); // ? } } } else { target.OnEvade(this, CombatType.Melee); } }); } actionChain.EnqueueChain(); // TODO: figure out exact speed / delay formula var meleeDelay = ThreadSafeRandom.Next(MeleeDelayMin, MeleeDelayMax); NextAttackTime = Timers.RunningTime + animLength + meleeDelay; return(animLength); }
/// <summary> /// Performs a melee attack for the monster /// </summary> /// <returns>The length in seconds for the attack animation</returns> public float MeleeAttack() { var target = AttackTarget as Creature; if (target == null || !target.IsAlive) { Sleep(); return(0.0f); } // choose a random combat maneuver var maneuver = GetCombatManeuver(); if (maneuver == null) { Console.WriteLine($"Combat maneuver null! Stance {CurrentMotionState.Stance}, MotionTable {MotionTableId:X8}"); return(0.0f); } AttackHeight = maneuver.AttackHeight; // select random body part @ current attack height var bodyPart = BodyParts.GetBodyPart(AttackHeight.Value); DoSwingMotion(AttackTarget, maneuver, out float animLength); PhysicsObj.stick_to_object(AttackTarget.PhysicsObj.ID); var actionChain = new ActionChain(); actionChain.AddDelaySeconds(animLength / 3.0f); // TODO: get attack frame? actionChain.AddAction(this, () => { if (AttackTarget == null) { return; } var critical = false; var damageType = DamageType.Undef; var shieldMod = 1.0f; var damage = CalculateDamage(ref damageType, maneuver, bodyPart, ref critical, ref shieldMod); var player = AttackTarget as Player; if (damage > 0.0f) { player.TakeDamage(this, damageType, damage, bodyPart, critical); if (shieldMod != 1.0f) { var shieldSkill = player.GetCreatureSkill(Skill.Shield); Proficiency.OnSuccessUse(player, shieldSkill, shieldSkill.Current); // ? } } else { player.OnEvade(this, AttackType.Melee); } }); actionChain.EnqueueChain(); // TODO: figure out exact speed / delay formula var meleeDelay = Physics.Common.Random.RollDice(MeleeDelayMin, MeleeDelayMax); NextAttackTime = Timers.RunningTime + animLength + meleeDelay;; return(animLength); }
public float CalculateDamage(WorldObject target, WorldObject damageSource, ref bool criticalHit, ref bool sneakAttack) { var creature = target as Creature; // evasion chance var evadeChance = GetEvadeChance(target); if (Physics.Common.Random.RollDice(0.0f, 1.0f) < evadeChance) { return(0.0f); } // get weapon base damage var baseDamageRange = GetBaseDamage(); var baseDamage = Physics.Common.Random.RollDice(baseDamageRange.Min, baseDamageRange.Max); // get damage mods var attackType = GetAttackType(); var attributeMod = GetAttributeMod(attackType); var powerAccuracyMod = GetPowerAccuracyMod(); var recklessnessMod = GetRecklessnessMod(this, creature); var sneakAttackMod = GetSneakAttackMod(target); sneakAttack = sneakAttackMod > 1.0f; var damageRatingMod = AdditiveCombine(recklessnessMod, sneakAttackMod, GetRatingMod(EnchantmentManager.GetDamageRating())); //Console.WriteLine("Damage rating: " + ModToRating(damageRatingMod)); var damage = baseDamage * attributeMod * powerAccuracyMod * damageRatingMod; // critical hit var critical = GetWeaponPhysicalCritFrequencyModifier(this); if (Physics.Common.Random.RollDice(0.0f, 1.0f) < critical) { damage = baseDamageRange.Max * attributeMod * powerAccuracyMod * sneakAttackMod * (2.0f + GetWeaponCritMultiplierModifier(this)); criticalHit = true; } // get random body part @ attack height var bodyPart = BodyParts.GetBodyPart(target, AttackHeight.Value); if (bodyPart == null) { return(0.0f); } var creaturePart = new Creature_BodyPart(creature, bodyPart); // get target armor var armor = creaturePart.BaseArmorMod; // get target resistance DamageType damageType; if (damageSource?.ItemType == ItemType.MissileWeapon) { damageType = (DamageType)damageSource.GetProperty(PropertyInt.DamageType); } else { damageType = GetDamageType(); } creaturePart.WeaponResistanceMod = GetWeaponResistanceModifier(this, damageType); var resistance = GetResistance(creaturePart, damageType); // ratings var damageResistRatingMod = GetNegativeRatingMod(creature.EnchantmentManager.GetDamageResistRating()); //Console.WriteLine("Damage resistance rating: " + NegativeModToRating(damageResistRatingMod)); // scale damage for armor and shield var armorMod = SkillFormula.CalcArmorMod(resistance); var shieldMod = creature.GetShieldMod(this, damageType); var slayerMod = GetWeaponCreatureSlayerModifier(this, target as Creature); var elementalDamageMod = GetMissileElementalDamageModifier(this, target as Creature, damageType); return((damage + elementalDamageMod) * armorMod * shieldMod * slayerMod * damageResistRatingMod); }
/// <summary> /// Calculates the creature damage for a physical monster attack /// </summary> public float?CalculateDamagePVP(WorldObject target, WorldObject damageSource, DamageType damageType, ref bool criticalHit, ref bool sneakAttack, ref BodyPart bodyPart) { // verify target player killer var targetPlayer = target as Player; if (targetPlayer == null) { return(null); } // check lifestone protection if (targetPlayer.UnderLifestoneProtection) { targetPlayer.HandleLifestoneProtection(); return(null); } // evasion chance var evadeChance = GetEvadeChance(target); if (ThreadSafeRandom.Next(0.0f, 1.0f) < evadeChance) { return(null); } // get base damage var baseDamageRange = GetBaseDamage(); var baseDamage = ThreadSafeRandom.Next(baseDamageRange.Min, baseDamageRange.Max); // get damage mods var attackType = GetAttackType(); var attributeMod = GetAttributeMod(attackType); var powerAccuracyMod = GetPowerAccuracyMod(); var recklessnessMod = GetRecklessnessMod(this, targetPlayer); var sneakAttackMod = GetSneakAttackMod(target); sneakAttack = sneakAttackMod > 1.0f; var damageRatingMod = AdditiveCombine(recklessnessMod, sneakAttackMod, GetRatingMod(EnchantmentManager.GetDamageRating())); //Console.WriteLine("Damage rating: " + ModToRating(damageRatingMod)); var damage = baseDamage * attributeMod * powerAccuracyMod * damageRatingMod; // critical hit var attackSkill = GetCreatureSkill(GetCurrentWeaponSkill()); var critical = GetWeaponPhysicalCritFrequencyModifier(this, attackSkill); if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical) { damage = baseDamageRange.Max * attributeMod * powerAccuracyMod * sneakAttackMod * (1.0f + GetWeaponCritMultiplierModifier(this, attackSkill)); criticalHit = true; } // select random body part @ current attack height bodyPart = BodyParts.GetBodyPart(AttackHeight.Value); // get armor piece var armor = GetArmor(bodyPart); // get armor modifiers var armorMod = GetArmorMod(armor, damageSource, damageType, attackSkill); // get resistance modifiers (protect/vuln) var resistanceMod = damageSource != null && damageSource.IgnoreMagicResist ? 1.0f : AttackTarget.EnchantmentManager.GetResistanceMod(damageType); // weapon resistance mod? var damageResistRatingMod = GetNegativeRatingMod(AttackTarget.EnchantmentManager.GetDamageResistRating()); // get shield modifier var attackTarget = AttackTarget as Creature; var shieldMod = attackTarget.GetShieldMod(this, damageType); var slayerMod = GetWeaponCreatureSlayerModifier(this, target as Creature); var elementalDamageMod = GetMissileElementalDamageModifier(this, target as Creature, damageType); // scale damage by modifiers var outDamage = (damage + elementalDamageMod) * armorMod * shieldMod * slayerMod * resistanceMod * damageResistRatingMod; return(outDamage); }
public float?CalculateDamage(WorldObject target, WorldObject damageSource, ref bool criticalHit, ref bool sneakAttack) { var creature = target as Creature; // evasion chance var evadeChance = GetEvadeChance(target); if (ThreadSafeRandom.Next(0.0f, 1.0f) < evadeChance) { return(null); } // get weapon base damage var weapon = GetEquippedWeapon(); var baseDamageRange = GetBaseDamage(); var baseDamage = ThreadSafeRandom.Next(baseDamageRange.Min, baseDamageRange.Max); // get damage mods var attackType = GetCombatType(); var attributeMod = GetAttributeMod(weapon); var powerAccuracyMod = GetPowerMod(weapon); var recklessnessMod = GetRecklessnessMod(this, creature); var sneakAttackMod = GetSneakAttackMod(target); sneakAttack = sneakAttackMod > 1.0f; // heritage damge mod var heritageMod = GetHeritageBonus(weapon) ? 1.05f : 1.0f; var damageRatingMod = AdditiveCombine(recklessnessMod, sneakAttackMod, heritageMod, GetRatingMod(EnchantmentManager.GetDamageRating())); //Console.WriteLine("Damage rating: " + ModToRating(damageRatingMod)); var damage = baseDamage * attributeMod * powerAccuracyMod * damageRatingMod; // critical hit var attackSkill = GetCreatureSkill(GetCurrentWeaponSkill()); var critical = GetWeaponCritChanceModifier(this, attackSkill); if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical) { var criticalDamageMod = 1.0f + GetWeaponCritDamageMod(this, attackSkill); damage = baseDamageRange.Max * attributeMod * powerAccuracyMod * sneakAttackMod * criticalDamageMod; criticalHit = true; } // get random body part @ attack height var bodyPart = BodyParts.GetBodyPart(target, AttackHeight.Value); if (bodyPart == null) { return(null); } var creaturePart = new Creature_BodyPart(creature, bodyPart, damageSource != null ? damageSource.IgnoreMagicArmor : false, damageSource != null ? damageSource.IgnoreMagicResist : false); if (weapon != null && weapon.HasImbuedEffect(ImbuedEffectType.ArmorRending)) { creaturePart.WeaponArmorMod = GetArmorRendingMod(attackSkill); } // get target armor var armor = creaturePart.BaseArmorMod; // get target resistance DamageType damageType; if (damageSource?.ItemType == ItemType.MissileWeapon) { damageType = (DamageType)damageSource.GetProperty(PropertyInt.DamageType); } else { damageType = GetDamageType(); } creaturePart.WeaponResistanceMod = GetWeaponResistanceModifier(this, attackSkill, damageType); var resistance = GetResistance(creaturePart, damageType); // ratings var damageResistRatingMod = GetNegativeRatingMod(creature.EnchantmentManager.GetDamageResistRating()); //Console.WriteLine("Damage resistance rating: " + NegativeModToRating(damageResistRatingMod)); // scale damage for armor and shield var armorMod = SkillFormula.CalcArmorMod(resistance); var shieldMod = creature.GetShieldMod(this, damageType); var slayerMod = GetWeaponCreatureSlayerModifier(this, target as Creature); var elementalDamageMod = GetMissileElementalDamageModifier(this, target as Creature, damageType); return((damage + elementalDamageMod) * armorMod * shieldMod * slayerMod * damageResistRatingMod); }
/// <summary> /// Calculates the creature damage for a physical monster attack /// </summary> public float?CalculateDamagePVP(WorldObject target, WorldObject damageSource, DamageType damageType, ref bool criticalHit, ref bool sneakAttack, ref BodyPart bodyPart) { // verify target player killer var targetPlayer = target as Player; if (targetPlayer == null) { return(null); } // check lifestone protection if (targetPlayer.UnderLifestoneProtection) { targetPlayer.HandleLifestoneProtection(); return(null); } // evasion chance var evadeChance = GetEvadeChance(target); if (ThreadSafeRandom.Next(0.0f, 1.0f) < evadeChance) { return(null); } // get base damage var weapon = GetEquippedWeapon(); var baseDamageRange = GetBaseDamage(); var baseDamage = ThreadSafeRandom.Next(baseDamageRange.Min, baseDamageRange.Max); // get damage mods var attackType = GetCombatType(); var attributeMod = GetAttributeMod(weapon); var powerMod = GetPowerMod(weapon); var recklessnessMod = GetRecklessnessMod(this, targetPlayer); var sneakAttackMod = GetSneakAttackMod(target); sneakAttack = sneakAttackMod > 1.0f; // heritage damge mod var heritageMod = GetHeritageBonus(weapon) ? 1.05f : 1.0f; var damageRatingMod = AdditiveCombine(heritageMod, recklessnessMod, sneakAttackMod, GetRatingMod(EnchantmentManager.GetDamageRating()), GetNegativeRatingMod(target.EnchantmentManager.GetDamageResistRating())); //Console.WriteLine("Damage rating: " + ModToRating(damageRatingMod)); var damage = baseDamage * attributeMod * powerMod * damageRatingMod; // critical hit var attackSkill = GetCreatureSkill(GetCurrentWeaponSkill()); var critical = GetWeaponCritChanceModifier(this, attackSkill); if (ThreadSafeRandom.Next(0.0f, 1.0f) < critical) { if (targetPlayer != null && targetPlayer.AugmentationCriticalDefense > 0) { var protChance = targetPlayer.AugmentationCriticalDefense * 0.05f; if (ThreadSafeRandom.Next(0.0f, 1.0f) > protChance) { criticalHit = true; } } else { criticalHit = true; } } if (criticalHit) { // not effective for criticals: recklessness damageRatingMod = AdditiveCombine(heritageMod, sneakAttackMod, GetRatingMod(EnchantmentManager.GetDamageRating()), GetNegativeRatingMod(target.EnchantmentManager.GetDamageResistRating())); damage = baseDamageRange.Max * attributeMod * powerMod * damageRatingMod * (1.0f + GetWeaponCritDamageMod(this, attackSkill)); } // get armor rending mod here? var armorRendingMod = 1.0f; if (weapon != null && weapon.HasImbuedEffect(ImbuedEffectType.ArmorRending)) { armorRendingMod = GetArmorRendingMod(attackSkill); } // select random body part @ current attack height bodyPart = BodyParts.GetBodyPart(AttackHeight.Value); // get armor piece var armor = GetArmorLayers(bodyPart); // get armor modifiers var armorMod = GetArmorMod(damageType, armor, damageSource, armorRendingMod); // get resistance modifiers (protect/vuln) var resistanceMod = damageSource != null && damageSource.IgnoreMagicResist ? 1.0f : AttackTarget.EnchantmentManager.GetResistanceMod(damageType); // weapon resistance mod? var damageResistRatingMod = GetNegativeRatingMod(AttackTarget.EnchantmentManager.GetDamageResistRating()); // get shield modifier var attackTarget = AttackTarget as Creature; var shieldMod = attackTarget.GetShieldMod(this, damageType); var slayerMod = GetWeaponCreatureSlayerModifier(this, target as Creature); var elementalDamageMod = GetMissileElementalDamageModifier(this, target as Creature, damageType); // scale damage by modifiers var outDamage = (damage + elementalDamageMod) * armorMod * shieldMod * slayerMod * resistanceMod * damageResistRatingMod; return(outDamage); }