using Barotrauma.Networking; using Barotrauma.Particles; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class Pump : Powered, IServerSerializable, IClientSerializable { private GUIScrollBar isActiveSlider; private GUIScrollBar pumpSpeedSlider; private GUITickBox powerIndicator; private List> pumpOutEmitters = new List>(); private List> pumpInEmitters = new List>(); partial void InitProjSpecific(XElement element) { foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "pumpoutemitter": pumpOutEmitters.Add(new Pair( subElement.GetAttributeVector2("position", Vector2.Zero), new ParticleEmitter(subElement))); break; case "pumpinemitter": pumpInEmitters.Add(new Pair( subElement.GetAttributeVector2("position", Vector2.Zero), new ParticleEmitter(subElement))); break; } } if (GuiFrame == null) { return; } GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), style: null); isActiveSlider = new GUIScrollBar(new RectTransform(new Point(50, 100), paddedFrame.RectTransform, Anchor.CenterLeft), barSize: 0.2f, style: "OnOffLever") { IsBooleanSwitch = true, MinValue = 0.25f, MaxValue = 0.75f }; var sliderHandle = isActiveSlider.GetChild(); sliderHandle.RectTransform.NonScaledSize = new Point(84, sliderHandle.Rect.Height); isActiveSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) => { bool active = scrollBar.BarScroll < 0.5f; if (active == IsActive) return false; targetLevel = null; IsActive = active; if (!IsActive) currPowerConsumption = 0.0f; if (GameMain.Client != null) { correctionTimer = CorrectionDelay; item.CreateClientEvent(this); } return true; }; var rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), paddedFrame.RectTransform, Anchor.CenterRight)) { RelativeSpacing = 0.1f }; powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), rightArea.RectTransform), TextManager.Get("PumpPowered"), style: "IndicatorLightGreen") { CanBeFocused = false }; var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), rightArea.RectTransform) { RelativeOffset = new Vector2(0.25f, 0.0f) }, "", textAlignment: Alignment.BottomLeft); string pumpSpeedStr = TextManager.Get("PumpSpeed"); pumpSpeedText.TextGetter = () => { return pumpSpeedStr + ": " + (int)flowPercentage + " %"; }; var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), rightArea.RectTransform, Anchor.CenterLeft), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), TextManager.Get("PumpOut"), textAlignment: Alignment.Center); pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider") { Step = 0.05f, OnMoved = (GUIScrollBar scrollBar, float barScroll) => { float newValue = barScroll * 200.0f - 100.0f; if (Math.Abs(newValue - FlowPercentage) < 0.1f) return false; FlowPercentage = newValue; if (GameMain.Client != null) { correctionTimer = CorrectionDelay; item.CreateClientEvent(this); } return true; } }; new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), TextManager.Get("PumpIn"), textAlignment: Alignment.Center); } public override void OnItemLoaded() { if (pumpSpeedSlider != null) { pumpSpeedSlider.BarScroll = (flowPercentage + 100.0f) / 200.0f; } } partial void UpdateProjSpecific(float deltaTime) { if (FlowPercentage < 0.0f) { foreach (Pair pumpOutEmitter in pumpOutEmitters) { //only emit "pump out" particles when underwater Vector2 particlePos = item.Rect.Location.ToVector2() + pumpOutEmitter.First; if (item.CurrentHull != null && item.CurrentHull.Surface < particlePos.Y) continue; pumpOutEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpOutEmitter.First * item.Scale, item.CurrentHull, velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, -FlowPercentage / 100.0f)); } } else if (FlowPercentage > 0.0f) { foreach (Pair pumpInEmitter in pumpInEmitters) { pumpInEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpInEmitter.First * item.Scale, item.CurrentHull, velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, FlowPercentage / 100.0f)); } } } public override void UpdateHUD(Character character, float deltaTime, Camera cam) { powerIndicator.Selected = hasPower && IsActive; if (!PlayerInput.LeftButtonHeld()) { isActiveSlider.BarScroll += (IsActive ? -10.0f : 10.0f) * deltaTime; float pumpSpeedScroll = (FlowPercentage + 100.0f) / 200.0f; if (Math.Abs(pumpSpeedScroll - pumpSpeedSlider.BarScroll) > 0.01f) { pumpSpeedSlider.BarScroll = pumpSpeedScroll; } } } public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null) { //flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this msg.WriteRangedInteger(-10, 10, (int)(flowPercentage / 10.0f)); msg.Write(IsActive); } public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime) { if (correctionTimer > 0.0f) { StartDelayedCorrection(type, msg.ExtractBits(5 + 1), sendingTime); return; } FlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f; IsActive = msg.ReadBoolean(); } } }