From 5918e845ac477620ae3da6251181bcb96caa2695 Mon Sep 17 00:00:00 2001 From: Regalis Date: Tue, 20 Sep 2016 18:40:30 +0300 Subject: [PATCH] Progress bars that show the health of wall sections when welding/cutting --- Subsurface/Barotrauma.csproj | 1 + Subsurface/Source/Characters/Character.cs | 51 ++++++++++++++-- .../Source/Characters/HUDProgressBar.cs | 60 +++++++++++++++++++ Subsurface/Source/GUI/GUI.cs | 9 ++- .../Items/Components/Holdable/Pickable.cs | 25 +++----- .../Items/Components/Holdable/RepairTool.cs | 16 +++-- Subsurface/Source/Map/Structure.cs | 19 +++--- 7 files changed, 140 insertions(+), 41 deletions(-) create mode 100644 Subsurface/Source/Characters/HUDProgressBar.cs diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 1dfda18d7..03b92baa8 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -93,6 +93,7 @@ + diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index a9f4fed7d..a0651ba95 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -93,6 +93,8 @@ namespace Barotrauma protected Item closestItem; private Character closestCharacter, selectedCharacter; + private Dictionary hudProgressBars; + protected bool isDead; private CauseOfDeath lastAttackCauseOfDeath; private CauseOfDeath causeOfDeath; @@ -498,6 +500,8 @@ namespace Barotrauma selectedItems = new Item[2]; + hudProgressBars = new Dictionary(); + IsNetworkPlayer = isNetworkPlayer; oxygen = 100.0f; @@ -516,8 +520,6 @@ namespace Barotrauma XDocument doc = ToolBox.TryLoadXml(file); if (doc == null || doc.Root == null) return; - - SpeciesName = ToolBox.GetAttributeString(doc.Root, "name", "Unknown"); @@ -1184,6 +1186,16 @@ namespace Barotrauma { Lights.LightManager.ViewTarget = this; CharacterHUD.Update(deltaTime, this); + + foreach (HUDProgressBar progressBar in hudProgressBars.Values) + { + progressBar.Update(deltaTime); + } + + foreach (var pb in hudProgressBars.Where(pb => pb.Value.FadeTimer<=0.0f).ToList()) + { + hudProgressBars.Remove(pb.Key); + } } if (IsUnconscious) @@ -1292,8 +1304,6 @@ namespace Barotrauma { if (!Enabled) return; - Vector2 pos = DrawPosition; - pos.Y = -pos.Y; if (GameMain.DebugDraw) { @@ -1302,7 +1312,18 @@ namespace Barotrauma if (aiTarget != null) aiTarget.Draw(spriteBatch); } - if (this == controlled) return; + if (this == controlled) + { + foreach (HUDProgressBar progressBar in hudProgressBars.Values) + { + progressBar.Draw(spriteBatch); + } + + return; + } + + Vector2 pos = DrawPosition; + pos.Y = -pos.Y; if (info != null) { @@ -1333,6 +1354,26 @@ namespace Barotrauma } } + /// + /// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object) + /// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time + /// + public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor) + { + HUDProgressBar progressBar = null; + if (!hudProgressBars.TryGetValue(linkedObject, out progressBar)) + { + progressBar = new HUDProgressBar(worldPosition, emptyColor, fullColor); + hudProgressBars.Add(linkedObject, progressBar); + } + + progressBar.WorldPosition = worldPosition; + progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f); + progressBar.Progress = progress; + + return progressBar; + } + public void PlaySound(AIController.AiState state) { if (sounds == null || !sounds.Any()) return; diff --git a/Subsurface/Source/Characters/HUDProgressBar.cs b/Subsurface/Source/Characters/HUDProgressBar.cs new file mode 100644 index 000000000..b6f0f4b2b --- /dev/null +++ b/Subsurface/Source/Characters/HUDProgressBar.cs @@ -0,0 +1,60 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; + +namespace Barotrauma +{ + class HUDProgressBar + { + private float progress; + + public float Progress + { + get { return progress; } + set { progress = MathHelper.Clamp(value, 0.0f, 1.0f); } + } + + public float FadeTimer; + + private Color fullColor, emptyColor; + + public Vector2 WorldPosition; + + public Vector2 Size; + + public HUDProgressBar(Vector2 worldPosition) + : this(worldPosition, Color.Red, Color.Green) + { + } + + public HUDProgressBar(Vector2 worldPosition, Color emptyColor, Color fullColor) + { + this.emptyColor = emptyColor; + this.fullColor = fullColor; + + WorldPosition = worldPosition; + + Size = new Vector2(100.0f, 20.0f); + + FadeTimer = 1.0f; + } + + public void Update(float deltatime) + { + FadeTimer -= deltatime; + } + + public void Draw(SpriteBatch spriteBatch) + { + float a = Math.Min(FadeTimer,1.0f); + + GUI.DrawProgressBar(spriteBatch, + new Vector2(WorldPosition.X - Size.X/2, (WorldPosition.Y + Size.Y/2)), + Size, progress, + Color.Lerp(emptyColor, fullColor, progress) * a, + Color.White * a * 0.8f); + } + + + } +} diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs index 912f87970..bfb32ee68 100644 --- a/Subsurface/Source/GUI/GUI.cs +++ b/Subsurface/Source/GUI/GUI.cs @@ -273,12 +273,15 @@ namespace Barotrauma public static void DrawProgressBar(SpriteBatch sb, Vector2 start, Vector2 size, float progress, Color clr, float depth = 0.0f) { - //outlinecolor = "0.5, 0.57, 0.6, 1.0" > + DrawProgressBar(sb, start, size, progress, clr, new Color(0.5f, 0.57f, 0.6f, 1.0f), depth); + } - DrawRectangle(sb, new Vector2(start.X, -start.Y), size, new Color(0.5f, 0.57f, 0.6f, 1.0f), false, depth); + public static void DrawProgressBar(SpriteBatch sb, Vector2 start, Vector2 size, float progress, Color clr, Color outlineColor, float depth = 0.0f) + { + DrawRectangle(sb, new Vector2(start.X, -start.Y), size, outlineColor, false, depth); int padding = 2; - DrawRectangle(sb, new Rectangle((int)start.X + padding, -(int)(start.Y - padding), (int)((size.X - padding * 2)*progress), (int)size.Y - padding * 2), + DrawRectangle(sb, new Rectangle((int)start.X + padding, -(int)(start.Y - padding), (int)((size.X - padding * 2) * progress), (int)size.Y - padding * 2), clr, true, depth); } diff --git a/Subsurface/Source/Items/Components/Holdable/Pickable.cs b/Subsurface/Source/Items/Components/Holdable/Pickable.cs index 13286a5e4..b4a4df6ca 100644 --- a/Subsurface/Source/Items/Components/Holdable/Pickable.cs +++ b/Subsurface/Source/Items/Components/Holdable/Pickable.cs @@ -7,7 +7,7 @@ using System.Xml.Linq; namespace Barotrauma.Items.Components { - class Pickable : ItemComponent, IDrawableComponent + class Pickable : ItemComponent { protected Character picker; @@ -125,6 +125,13 @@ namespace Barotrauma.Items.Components yield return CoroutineStatus.Success; } + + picker.UpdateHUDProgressBar( + this, + item.WorldPosition, + pickTimer / requiredTime, + Color.Red, Color.Green); + picker.AnimController.Anim = AnimController.Animation.UsingConstruction; picker.AnimController.TargetMovement = Vector2.Zero; @@ -175,23 +182,7 @@ namespace Barotrauma.Items.Components } } } - - public void Draw(SpriteBatch spriteBatch, bool editing = false) - { - if (pickTimer <= 0.0f) - { - Drawable = false; - return; - } - - float progressBarWidth = 100.0f; - - GUI.DrawProgressBar(spriteBatch, item.DrawPosition + new Vector2(-progressBarWidth/2.0f, 50.0f), new Vector2(progressBarWidth, 15.0f), - pickTimer / PickingTime, - Color.Lerp(Color.Red, Color.Green, pickTimer / PickingTime)); - } - public override void Drop(Character dropper) { if (picker == null) diff --git a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs index 442d2bd7c..c5045066f 100644 --- a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs +++ b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs @@ -182,7 +182,13 @@ namespace Barotrauma.Items.Components int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition)); if (sectionIndex < 0) return; - targetStructure.HighLightSection(sectionIndex); + var progressBar = user.UpdateHUDProgressBar( + targetStructure, + targetStructure.SectionPosition(sectionIndex) + targetStructure.Submarine.DrawPosition, + 1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health, + Color.Red, Color.Green); + + progressBar.Size = new Vector2(60.0f, 20.0f); targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess); @@ -195,7 +201,7 @@ namespace Barotrauma.Items.Components (sectionIndex == targetStructure.SectionCount - 2 && i == 1) || (nextSectionLength > 0 && nextSectionLength < Structure.wallSectionSize * 0.3f)) { - targetStructure.HighLightSection(sectionIndex + i); + //targetStructure.HighLightSection(sectionIndex + i); targetStructure.AddDamage(sectionIndex + i, -StructureFixAmount * degreeOfSuccess); } } @@ -213,7 +219,7 @@ namespace Barotrauma.Items.Components ApplyStatusEffects(ActionType.OnUse, targetItem.AllPropertyObjects, deltaTime); } } - + public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective) { Gap leak = objective.OperateTarget as Gap; @@ -222,7 +228,7 @@ namespace Barotrauma.Items.Components float dist = Vector2.Distance(leak.WorldPosition, item.WorldPosition); //too far away -> consider this done and hope the AI is smart enough to move closer - if (dist > range*5.0f) return true; + if (dist > range * 5.0f) return true; //steer closer if almost in range if (dist > range) @@ -240,8 +246,6 @@ namespace Barotrauma.Items.Components //close enough -> stop moving character.AIController.SteeringManager.Reset(); } - - character.CursorPosition = leak.Position; character.SetInput(InputType.Aim, false, true); diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 54578367f..a2fb24ee6 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Xml.Linq; using FarseerPhysics; @@ -21,11 +20,10 @@ namespace Barotrauma public float damage; public Gap gap; - public int GapIndex; + public int GapID; public float lastSentDamage; - public bool isHighLighted; public ConvexHull hull; public WallSection(Rectangle rect) @@ -454,8 +452,6 @@ namespace Barotrauma Point offset = new Point(Math.Abs(rect.Location.X - s.rect.Location.X), Math.Abs(rect.Location.Y - s.rect.Location.Y)); prefab.sprite.DrawTiled(spriteBatch, new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), Vector2.Zero, color, offset); - - s.isHighLighted = false; } } } @@ -503,9 +499,12 @@ namespace Barotrauma return true; } - public void HighLightSection(int sectionIndex) + public WallSection GetSection(int sectionIndex) { - sections[sectionIndex].isHighLighted = true; + if (sectionIndex < 0 || sectionIndex >= sections.Length) return null; + + return sections[sectionIndex]; + } public bool SectionBodyDisabled(int sectionIndex) @@ -798,7 +797,7 @@ namespace Barotrauma s.sections[index].damage = ToolBox.GetAttributeFloat(subElement, "damage", 0.0f); - s.sections[index].GapIndex = ToolBox.GetAttributeInt(subElement, "gap", -1); + s.sections[index].GapID = ToolBox.GetAttributeInt(subElement, "gap", -1); break; } @@ -809,9 +808,9 @@ namespace Barotrauma { foreach (WallSection s in sections) { - if (s.GapIndex == -1) continue; + if (s.GapID == -1) continue; - s.gap = FindEntityByID((ushort)s.GapIndex) as Gap; + s.gap = FindEntityByID((ushort)s.GapID) as Gap; if (s.gap != null) s.gap.ConnectedWall = this; } }