public void Damage(int damage, double penetration, DamageType type, out int damageResistance, out int damageDealt) { Contract.Ensures(Contract.ValueAtReturn(out damageDealt) >= 0); Contract.Ensures(Contract.ValueAtReturn(out damageResistance) >= 0); damageDealt = damage; damageResistance = 0; if (Defender.Has <EquipmentComponent>()) { var equipment = Defender.Get <EquipmentComponent>(); if (equipment.ContainSlot(BodyPartTargetted.Name) && equipment.IsSlotEquipped(BodyPartTargetted.Name)) { var armorEntity = equipment.GetEquippedItemAt(BodyPartTargetted.Name); if (armorEntity.Has <ArmorComponent>()) { var armor = armorEntity.Get <ArmorComponent>(); if (armor.Defenses.ContainsKey(BodyPartTargetted.Name)) { if (Rng.Chance(armor.Defenses[BodyPartTargetted.Name].Coverage / 100.0)) { damageResistance = (int)Math.Floor(armor.Defenses[BodyPartTargetted.Name].Resistances[type] / penetration); damageDealt = Math.Max(damage - damageResistance, 0); Logger.InfoFormat("Damage: {3} reduced to {0} because of {1} [DR: {2}]", damageDealt, armor.OwnerUId, damageResistance, damage); } else { // we hit a chink in the armor damageResistance = 0; Logger.InfoFormat("Hit a chink in the armor, DR = 0"); } } } } } if (Defender.Has <ActorComponent>()) { Defender.Get <ActorComponent>().Disturb(); } if (damageDealt > BodyPartTargetted.MaxHealth) { damageDealt = Math.Min(damage, BodyPartTargetted.MaxHealth); Logger.DebugFormat("Damage reduced to {0} because of {1}'s max health", damageDealt, BodyPartTargetted.Name); } BodyPartTargetted.Health -= damageDealt; BodyPartTargetted.Owner.Health -= damageDealt; Logger.InfoFormat("{0}'s {1} was hurt ({2} damage)", Identifier.GetNameOrId(Defender), BodyPartTargetted.Name, damageDealt); }