using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; namespace Barotrauma.Abilities { class CharacterAbilityApplyForce : CharacterAbility { private readonly float force; private readonly float maxVelocity; private readonly string afflictionIdentifier; private readonly HashSet limbTypes = new HashSet(); public override bool AppliesEffectOnIntervalUpdate => true; public CharacterAbilityApplyForce(CharacterAbilityGroup characterAbilityGroup, ContentXElement abilityElement) : base(characterAbilityGroup, abilityElement) { force = abilityElement.GetAttributeFloat("force", 0f); maxVelocity = abilityElement.GetAttributeFloat("maxvelocity", 10f); afflictionIdentifier = abilityElement.GetAttributeString("afflictionidentifier", ""); string[] limbTypesStr = abilityElement.GetAttributeStringArray("limbtypes", new string[0]); foreach (string limbTypeStr in limbTypesStr) { if (Enum.TryParse(limbTypeStr, out LimbType limbType)) { limbTypes.Add(limbType); } else { DebugConsole.ThrowError($"Error in talent \"{characterAbilityGroup.CharacterTalent.DebugIdentifier}\" - \"{limbTypeStr}\" is not a valid limb type.", contentPackage: abilityElement.ContentPackage); } } } protected override void ApplyEffect() { float strength = 1.0f; if (!string.IsNullOrEmpty(afflictionIdentifier)) { Affliction affliction = Character.CharacterHealth.GetAffliction(afflictionIdentifier); if (affliction == null) { return; } strength = affliction.Strength / affliction.Prefab.MaxStrength; } foreach (Limb limb in Character.AnimController.Limbs) { if (limb.IsSevered || limb.Removed) { continue; } if (limbTypes.Any()) { if (!limbTypes.Contains(limb.type)) { continue; } } if (Character.AnimController.TargetMovement.LengthSquared() < 0.001f) { continue; } limb.body.ApplyForce(Vector2.Normalize(limb.Mass * Character.AnimController.TargetMovement) * force * strength, maxVelocity); } } } }