diff --git a/Barotrauma/BarotraumaClient/BarotraumaClient.csproj b/Barotrauma/BarotraumaClient/BarotraumaClient.csproj index 16b41b3b4..3503eb0a8 100644 --- a/Barotrauma/BarotraumaClient/BarotraumaClient.csproj +++ b/Barotrauma/BarotraumaClient/BarotraumaClient.csproj @@ -70,6 +70,7 @@ + diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Controller.cs new file mode 100644 index 000000000..486559bb5 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Controller.cs @@ -0,0 +1,19 @@ +using Microsoft.Xna.Framework.Graphics; + +namespace Barotrauma.Items.Components +{ + partial class Controller : ItemComponent + { + public override void DrawHUD(SpriteBatch spriteBatch, Character character) + { + var focusTarget = GetFocusTarget(); + if (character.ViewTarget == focusTarget) + { + foreach (ItemComponent ic in focusTarget.components) + { + ic.DrawHUD(spriteBatch, character); + } + } + } + } +} diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs index 6c5fdab91..3af4b474c 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs @@ -3,11 +3,40 @@ using Lidgren.Network; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class Turret : Powered, IDrawableComponent, IServerSerializable { + private Sprite crosshairSprite, disabledCrossHairSprite; + + private GUIProgressBar powerIndicator; + + [Editable, Serialize("0.0,0.0,0.0,0.0", true)] + public Color HudTint + { + get; + private set; + } + + [Serialize(false, false)] + public bool ShowChargeIndicator + { + get; + private set; + } + + [Serialize(false, false)] + public bool ShowProjectileIndicator + { + get; + private set; + } + public void Draw(SpriteBatch spriteBatch, bool editing = false) { Vector2 drawPos = new Vector2(item.Rect.X, item.Rect.Y); @@ -41,6 +70,61 @@ namespace Barotrauma.Items.Components } + public override void DrawHUD(SpriteBatch spriteBatch, Character character) + { + if (HudTint.A > 0) + { + GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), + new Color(HudTint.R, HudTint.G, HudTint.B) * (HudTint.A/255.0f), true); + } + + float batteryCharge; + float batteryCapacity; + GetAvailablePower(out batteryCharge, out batteryCapacity); + + List projectiles = GetLoadedProjectiles(false, true); + + float chargeRate = powerConsumption <= 0.0f ? 1.0f : batteryCharge / batteryCapacity; + bool charged = batteryCharge * 3600.0f > powerConsumption; + bool readyToFire = reload <= 0.0f && charged && projectiles.Any(p => p != null); + + if (ShowChargeIndicator && PowerConsumption > 0.0f) + { + powerIndicator.BarSize = chargeRate; + powerIndicator.Color = charged ? Color.Green : Color.Red; + powerIndicator.Draw(spriteBatch); + + int requiredChargeIndicatorPos = (int)((powerConsumption / (batteryCapacity * 3600.0f)) * powerIndicator.Rect.Width); + GUI.DrawRectangle(spriteBatch, + new Rectangle(powerIndicator.Rect.X + requiredChargeIndicatorPos, powerIndicator.Rect.Y, 3, powerIndicator.Rect.Height), + Color.White * 0.5f, true); + } + + if (ShowProjectileIndicator) + { + Point slotSize = new Point(60, 30); + int spacing = 5; + int slotsPerRow = Math.Min(projectiles.Count, 6); + int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1); + Point invSlotPos = new Point(GameMain.GraphicsWidth / 2 - totalWidth / 2, 60); + for (int i = 0; i < projectiles.Count; i++) + { + Inventory.DrawSlot(spriteBatch, + new InventorySlot(new Rectangle(invSlotPos + new Point((i % slotsPerRow) * (slotSize.X + spacing), (int)Math.Floor(i / (float)slotsPerRow) * (slotSize.Y + spacing)), slotSize)), + projectiles[i] == null ? null : projectiles[i].Item, true); + } + } + + if (readyToFire) + { + if (crosshairSprite != null) crosshairSprite.Draw(spriteBatch, PlayerInput.MousePosition); + } + else + { + if (disabledCrossHairSprite != null) disabledCrossHairSprite.Draw(spriteBatch, PlayerInput.MousePosition); + } + } + public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) { UInt16 projectileID = msg.ReadUInt16(); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs index 78a5ee727..8130dea44 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs @@ -362,7 +362,7 @@ namespace Barotrauma } } - protected void DrawSlot(SpriteBatch spriteBatch, InventorySlot slot, Item item, bool drawItem = true) + public static void DrawSlot(SpriteBatch spriteBatch, InventorySlot slot, Item item, bool drawItem = true) { Rectangle rect = slot.Rect; diff --git a/Barotrauma/BarotraumaShared/BarotraumaShared.projitems b/Barotrauma/BarotraumaShared/BarotraumaShared.projitems index d3b1f729b..49dc19662 100644 --- a/Barotrauma/BarotraumaShared/BarotraumaShared.projitems +++ b/Barotrauma/BarotraumaShared/BarotraumaShared.projitems @@ -460,9 +460,15 @@ PreserveNewest + + PreserveNewest + PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Content/Items/Weapons/crosshair.png b/Barotrauma/BarotraumaShared/Content/Items/Weapons/crosshair.png new file mode 100644 index 000000000..e6986481e Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Weapons/crosshair.png differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Weapons/disabledCrosshair.png b/Barotrauma/BarotraumaShared/Content/Items/Weapons/disabledCrosshair.png new file mode 100644 index 000000000..43d809363 Binary files /dev/null and b/Barotrauma/BarotraumaShared/Content/Items/Weapons/disabledCrosshair.png differ diff --git a/Barotrauma/BarotraumaShared/Content/Items/Weapons/railgun.xml b/Barotrauma/BarotraumaShared/Content/Items/Weapons/railgun.xml index 27abb571a..4480fe655 100644 --- a/Barotrauma/BarotraumaShared/Content/Items/Weapons/railgun.xml +++ b/Barotrauma/BarotraumaShared/Content/Items/Weapons/railgun.xml @@ -7,15 +7,20 @@ linkable="true" > - + + powerconsumption="20000.0" + showchargeindicator="true" + showprojectileindicator="true" + hudtint="0.4,0.6,0.7,0.05"> + + diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs index a1e0a2542..b75f1eb4b 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs @@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components } } - class Controller : ItemComponent + partial class Controller : ItemComponent { //where the limbs of the user should be positioned when using the controller private List limbPositions; @@ -167,26 +167,9 @@ namespace Barotrauma.Items.Components character = null; return; } + if (character == null) return; - Entity focusTarget = null; - - if (character == null) return; - - - foreach (Connection c in item.Connections) - { - if (c.Name != "position_out") continue; - - foreach (Connection c2 in c.Recipients) - { - if (c2 == null || c2.Item == null || !c2.Item.Prefab.FocusOnSelected) continue; - - focusTarget = c2.Item; - - break; - } - } - + Entity focusTarget = GetFocusTarget(); if (focusTarget == null) { item.SendSignal(0, XMLExtensions.Vector2ToString(character.CursorWorldPosition), "position_out", character); @@ -210,6 +193,22 @@ namespace Barotrauma.Items.Components } } + private Item GetFocusTarget() + { + foreach (Connection c in item.Connections) + { + if (c.Name != "position_out") continue; + + foreach (Connection c2 in c.Recipients) + { + if (c2 == null || c2.Item == null || !c2.Item.Prefab.FocusOnSelected) continue; + return c2.Item; + } + } + + return null; + } + public override bool Pick(Character picker) { item.SendSignal(0, "1", "signal_out", picker); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs index ae486ed82..2c24e4926 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs @@ -87,6 +87,25 @@ namespace Barotrauma.Items.Components barrelSpritePath, element.GetAttributeVector2("origin", Vector2.Zero)); } + +#if CLIENT + foreach (XElement subElement in element.Elements()) + { + string texturePath = subElement.GetAttributeString("texture", ""); + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "crosshair": + crosshairSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile)); + break; + case "disabledcrosshair": + disabledCrossHairSprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile)); + break; + } + } + + int barWidth = 200; + powerIndicator = new GUIProgressBar(new Rectangle(GameMain.GraphicsWidth / 2 - barWidth / 2, 20, barWidth, 30 ), Color.White, 0.0f); +#endif } public override void Update(float deltaTime, Camera cam) @@ -296,6 +315,19 @@ namespace Barotrauma.Items.Components return availablePower; } + private void GetAvailablePower(out float availableCharge, out float availableCapacity) + { + var batteries = item.GetConnectedComponents(); + + availableCharge = 0.0f; + availableCapacity = 0.0f; + foreach (PowerContainer battery in batteries) + { + availableCharge += battery.Charge; + availableCapacity += battery.Capacity; + } + } + protected override void RemoveComponentSpecific() { base.RemoveComponentSpecific(); @@ -303,7 +335,7 @@ namespace Barotrauma.Items.Components if (barrelSprite != null) barrelSprite.Remove(); } - private List GetLoadedProjectiles(bool returnFirst = false) + private List GetLoadedProjectiles(bool returnFirst = false, bool returnNull = false) { List projectiles = new List(); @@ -312,16 +344,27 @@ namespace Barotrauma.Items.Components var projectileContainer = e as Item; if (projectileContainer == null) continue; - var containedItems = projectileContainer.ContainedItems; - if (containedItems == null) continue; - - for (int i = 0; i < containedItems.Length; i++) + if (returnNull) { - var projectileComponent = containedItems[i].GetComponent(); - if (projectileComponent != null) + var itemContainer = projectileContainer.GetComponent(); + for (int i = 0; i < itemContainer.Inventory.Items.Length; i++) { - projectiles.Add(projectileComponent); - if (returnFirst) return projectiles; + projectiles.Add(itemContainer.Inventory.Items[i]?.GetComponent()); + } + } + else + { + var containedItems = projectileContainer.ContainedItems; + if (containedItems == null) continue; + + for (int i = 0; i < containedItems.Length; i++) + { + var projectileComponent = containedItems[i].GetComponent(); + if (projectileComponent != null) + { + projectiles.Add(projectileComponent); + if (returnFirst) return projectiles; + } } } }