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;
+ }
}
}
}