using System.Xml.Linq; using Microsoft.Xna.Framework; using Barotrauma.Networking; #if CLIENT using Microsoft.Xna.Framework.Graphics; using Barotrauma.Particles; #endif namespace Barotrauma.Items.Components { class Propulsion : ItemComponent { enum UsableIn { Air, Water, Both }; private float force; private float useState; private UsableIn usableIn; [Serialize(0.0f, false), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)] public float Force { get { return force; } set { force = value; } } #if CLIENT private string particles; [Serialize("", false)] public string Particles { get { return particles; } set { particles = value; } } #endif public Propulsion(Item item, XElement element) : base(item,element) { switch (element.GetAttributeString("usablein", "both").ToLowerInvariant()) { case "air": usableIn = UsableIn.Air; break; case "water": usableIn = UsableIn.Water; break; case "both": default: usableIn = UsableIn.Both; break; } ResetSoundRange(); } public override bool Use(float deltaTime, Character character = null) { if (character == null || character.Removed) return false; if (!character.IsKeyDown(InputType.Aim) || character.Stun > 0.0f) return false; IsActive = true; useState = 0.1f; if (character.AnimController.InWater) { if (usableIn == UsableIn.Air) return true; } else { if (usableIn == UsableIn.Water) return true; } Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position); //move upwards if the cursor is at the position of the character if (!MathUtils.IsValid(dir)) dir = Vector2.UnitY; Vector2 propulsion = dir * force; if (character.AnimController.InWater) character.AnimController.TargetMovement = dir; foreach (Limb limb in character.AnimController.Limbs) { if (limb.WearingItems.Find(w => w.WearableComponent.Item == this.item) == null) continue; limb.body.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } character.AnimController.Collider.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); if (character.SelectedItems[0] == item) { character.AnimController.GetLimb(LimbType.RightHand)?.body.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } if (character.SelectedItems[1] == item) { character.AnimController.GetLimb(LimbType.LeftHand)?.body.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } #if CLIENT if (!string.IsNullOrWhiteSpace(particles)) { GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition, item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi), 0.0f, item.CurrentHull); } #endif return true; } public override void Update(float deltaTime, Camera cam) { useState -= deltaTime; if (useState <= 0.0f) IsActive = false; if (item.AiTarget != null) { item.AiTarget.SoundRange = IsActive ? item.AiTarget.MaxSoundRange : item.AiTarget.MinSoundRange; } } public override void Unequip(Character character) { base.Unequip(character); ResetSoundRange(); } private void ResetSoundRange() { if (item.AiTarget != null) { item.AiTarget.SoundRange = item.AiTarget.MinSoundRange; } } } }