From c9cc94f701153d6647f7bf5940023d7d23c350c9 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 26 Nov 2015 23:04:02 +0200 Subject: [PATCH] Crew commands --- Subsurface/Barotrauma.csproj | 10 +- .../Source/Characters/AI/CrewCommander.cs | 160 ++++++++++++++++++ .../Source/Characters/AI/HumanAIController.cs | 7 +- .../AI/Objectives/AIObjectiveGoTo.cs | 7 +- .../AI/Objectives/AIObjectiveManager.cs | 41 ++++- .../AI/Objectives/AIObjectiveOperateItem.cs | 16 +- Subsurface/Source/Characters/AI/Order.cs | 39 +++++ .../Source/Characters/AI/SteeringManager.cs | 4 +- .../{ => Animation}/AnimController.cs | 0 .../{ => Animation}/FishAnimController.cs | 0 .../{ => Animation}/HumanoidAnimController.cs | 0 .../Characters/{ => Animation}/Ragdoll.cs | 9 +- .../BackgroundSprite/BackgroundSprite.cs | 2 + Subsurface/Source/GUI/GUIButton.cs | 20 ++- Subsurface/Source/GUI/GUIListBox.cs | 123 +++++++++----- Subsurface/Source/GameSession/CrewManager.cs | 28 ++- Subsurface/Source/Items/Inventory.cs | 4 +- Subsurface/Source/Map/WayPoint.cs | 5 +- Subsurface_Solution.v12.suo | Bin 830976 -> 813568 bytes 19 files changed, 406 insertions(+), 69 deletions(-) create mode 100644 Subsurface/Source/Characters/AI/CrewCommander.cs create mode 100644 Subsurface/Source/Characters/AI/Order.cs rename Subsurface/Source/Characters/{ => Animation}/AnimController.cs (100%) rename Subsurface/Source/Characters/{ => Animation}/FishAnimController.cs (100%) rename Subsurface/Source/Characters/{ => Animation}/HumanoidAnimController.cs (100%) rename Subsurface/Source/Characters/{ => Animation}/Ragdoll.cs (99%) diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 4d256f821..8658afc07 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -60,6 +60,8 @@ + + @@ -71,7 +73,7 @@ - + @@ -127,10 +129,10 @@ - + - + @@ -160,7 +162,7 @@ - + diff --git a/Subsurface/Source/Characters/AI/CrewCommander.cs b/Subsurface/Source/Characters/AI/CrewCommander.cs new file mode 100644 index 000000000..fd98fd6e3 --- /dev/null +++ b/Subsurface/Source/Characters/AI/CrewCommander.cs @@ -0,0 +1,160 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Barotrauma +{ + class CrewCommander + { + CrewManager crewManager; + + GUIFrame frame; + //GUIListBox characterList; + + public GUIFrame Frame + { + get { return IsOpen ? frame : null; } + } + + public bool IsOpen + { + get; + private set; + } + + public CrewCommander(CrewManager crewManager) + { + this.crewManager = crewManager; + + } + + public void ToggleGUIFrame() + { + IsOpen = !IsOpen; + + if (IsOpen && frame == null) CreateGUIFrame(); + } + + private void CreateGUIFrame() + { + frame = new GUIFrame(Rectangle.Empty, Color.Black * 0.3f); + frame.Padding = new Vector4(200.0f, 100.0f, 200.0f, 100.0f); + + int x = 0, y = 0; + foreach (Character character in crewManager.characters) + { + GUIButton characterButton = new GUIButton(new Rectangle(x,y, 150, 40), "", Color.Transparent, null, frame); + characterButton.UserData = character; + characterButton.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + + + if (character == Character.Controlled) + { + characterButton.CanBeSelected = false; + characterButton.Color = Color.LightGray * 0.3f; + } + else + { + characterButton.HoverColor = Color.LightGray * 0.5f; + characterButton.SelectedColor = Color.Gold * 0.5f; + } + + string name = character.Info.Name.Replace(' ', '\n'); + + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(40, 0, 0, 25), + name, + Color.Transparent, Color.White, + Alignment.Left, Alignment.Left, + null, characterButton, false); + textBlock.Font = GUI.SmallFont; + textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); + + new GUIImage(new Rectangle(-10, -5, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, characterButton); + + x += 160; + } + + x = 0; + y = 150; + foreach (Order command in Order.List) + { + var button = new GUIButton(new Rectangle(x, y, 150, 20), command.Name, GUI.Style, frame); + button.UserData = command; + button.OnClicked = SetOrder; + + x += button.Rect.Width + 10; + } + } + + private bool SetOrder(GUIButton button, object userData) + { + Order order = userData as Order; + + List selectedCharacters = new List(); + foreach (GUIComponent child in frame.children) + { + var characterButton = child as GUIButton; + characterButton.State = GUIComponent.ComponentState.None; + + if (!characterButton.Selected) continue; + characterButton.Selected = false; + + var character = child.UserData as Character; + if (character == null) continue; + + var humanAi = character.AIController as HumanAIController; + if (humanAi == null) continue; + + var existingOrder = characterButton.children.Find(c => c.UserData as Order != null); + if (existingOrder != null) characterButton.RemoveChild(existingOrder); + + var orderFrame = new GUIFrame(new Rectangle(0, characterButton.Rect.Height, 0, 30 + order.Options.Length*15), null, characterButton); + orderFrame.OutlineColor = Color.LightGray * 0.8f; + orderFrame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + orderFrame.UserData = order; + new GUITextBlock(new Rectangle(0,0,0,20), order.DoingText, GUI.Style, Alignment.TopLeft, Alignment.TopCenter, orderFrame); + + var optionList = new GUIListBox(new Rectangle(0,20,0,80), Color.Transparent, null, orderFrame); + optionList.UserData = order; + optionList.OnSelected = SelectOrderOption; + foreach (string option in order.Options) + { + var optionBox = new GUITextBlock(new Rectangle(0,0,0,15), option, GUI.Style, optionList); + optionBox.Font = GUI.SmallFont; + optionBox.UserData = option; + } + + humanAi.SetOrder(order, ""); + } + + //characterList.Deselect(); + + return true; + } + + private bool SelectOrderOption(GUIComponent component, object userData) + { + string option = userData.ToString(); + Order order = component.Parent.UserData as Order; + Character character = component.Parent.Parent.Parent.UserData as Character; + + var humanAi = character.AIController as HumanAIController; + if (humanAi == null) return false; + + humanAi.SetOrder(order, option); + + return true; + } + + public void Draw(SpriteBatch spriteBatch) + { + if (!IsOpen) return; + + frame.Draw(spriteBatch); + } + } +} diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index b092bd76c..961025d0e 100644 --- a/Subsurface/Source/Characters/AI/HumanAIController.cs +++ b/Subsurface/Source/Characters/AI/HumanAIController.cs @@ -58,12 +58,17 @@ namespace Barotrauma Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left; } - float currObjectivePriority = objectiveManager.CurrentObjective == null ? 0.0f : objectiveManager.CurrentObjective.GetPriority(Character); + float currObjectivePriority = objectiveManager.GetCurrentPriority(Character); float moveSpeed = MathHelper.Clamp(currObjectivePriority/10.0f, 1.0f, 3.0f); steeringManager.Update(moveSpeed); } + public void SetOrder(Order order, string option) + { + objectiveManager.SetOrder(order, option); + } + public override void SelectTarget(AITarget target) { selectedAiTarget = target; diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index 63e6a1614..48621d21b 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -14,10 +14,13 @@ namespace Barotrauma Vector2 targetPos; + bool repeat; + public override bool CanBeCompleted { get { + if (repeat) return true; var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager; return (pathSteering.CurrentPath == null || !pathSteering.CurrentPath.Unreachable); } @@ -28,10 +31,11 @@ namespace Barotrauma get { return target; } } - public AIObjectiveGoTo(AITarget target, Character character) + public AIObjectiveGoTo(AITarget target, Character character, bool repeat = false) : base (character) { this.target = target; + this.repeat = false; } @@ -51,6 +55,7 @@ namespace Barotrauma public override bool IsCompleted() { + if (repeat) return false; return Vector2.Distance(target != null ? target.SimPosition : ConvertUnits.ToDisplayUnits(targetPos), character.SimPosition) < 0.5f; } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs index 3f413d27f..d46b9f26b 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -1,4 +1,5 @@ -using System; +using Barotrauma.Items.Components; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -7,14 +8,19 @@ namespace Barotrauma { class AIObjectiveManager { + const float OrderPriority = 50.0f; + private List objectives; private Character character; + + private AIObjective currentOrder; public AIObjective CurrentObjective { get { + if (currentOrder != null) return currentOrder; return objectives.Any() ? objectives[0] : null; } } @@ -33,9 +39,15 @@ namespace Barotrauma objectives.Add(objective); } + public float GetCurrentPriority(Character character) + { + if (currentOrder != null) return OrderPriority; + return (CurrentObjective == null) ? 0.0f : CurrentObjective.GetPriority(character); + } + public void UpdateObjectives() { - if (!objectives.Any()) return; + if (currentOrder != null || !objectives.Any()) return; //remove completed objectives objectives = objectives.FindAll(o => !o.IsCompleted()); @@ -57,8 +69,33 @@ namespace Barotrauma public void DoCurrentObjective(float deltaTime) { + if (currentOrder != null) + { + currentOrder.TryComplete(deltaTime); + return; + } + if (!objectives.Any()) return; objectives[0].TryComplete(deltaTime); } + + public void SetOrder(Order order, string option) + { + switch (order.Name.ToLower()) + { + case "follow": + currentOrder = new AIObjectiveGoTo(Character.Controlled.AiTarget, character, true); + break; + case "operate reactor": + var reactorItem = Item.ItemList.Find(i => i.GetComponent() != null); + if (reactorItem == null) return; + + currentOrder = new AIObjectiveOperateItem(reactorItem.GetComponent(), character); + break; + default: + currentOrder = null; + break; + } + } } } diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs index fe4107793..681189155 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -1,4 +1,6 @@ -using System; +using Barotrauma.Items.Components; +using Microsoft.Xna.Framework; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -7,9 +9,9 @@ namespace Barotrauma { class AIObjectiveOperateItem : AIObjective { - private Item targetItem; + private ItemComponent targetItem; - public AIObjectiveOperateItem(Item item, Character character) + public AIObjectiveOperateItem(ItemComponent item, Character character) :base (character) { targetItem = item; @@ -17,7 +19,13 @@ namespace Barotrauma protected override void Act(float deltaTime) { - //item.AIOperate(float deltaTime, Character character) or something + if (Vector2.Distance(character.SimPosition, targetItem.Item.SimPosition) < targetItem.Item.PickDistance) + { + //targetItem.Pick(character, false, true); + return; + } + + subObjectives.Add(new AIObjectiveGoTo(targetItem.Item.SimPosition, character)); } public override bool IsDuplicate(AIObjective otherObjective) diff --git a/Subsurface/Source/Characters/AI/Order.cs b/Subsurface/Source/Characters/AI/Order.cs new file mode 100644 index 000000000..5f5532566 --- /dev/null +++ b/Subsurface/Source/Characters/AI/Order.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Barotrauma +{ + class Order + { + public static List List; + + public readonly string Name; + public readonly string DoingText; + + Sprite buttonSprite; + + public readonly string[] Options; + + static Order() + { + List = new List(); + + new Order("Follow", "Following"); + new Order("Operate Reactor", "Operating reactor", new string[] {"Power Up", "Shutdown"}); + + new Order("Dismiss", "Dismissed"); + } + + private Order(string name, string doingText, string[] parameters = null) + { + this.Name = name; + this.DoingText = doingText; + this.Options = parameters == null ? new string[0] : parameters; + + List.Add(this); + } + } + +} diff --git a/Subsurface/Source/Characters/AI/SteeringManager.cs b/Subsurface/Source/Characters/AI/SteeringManager.cs index 30a447b00..a25896691 100644 --- a/Subsurface/Source/Characters/AI/SteeringManager.cs +++ b/Subsurface/Source/Characters/AI/SteeringManager.cs @@ -35,9 +35,9 @@ namespace Barotrauma wanderAngle = Rand.Range(0.0f, MathHelper.TwoPi); } - public void SteeringSeek(Vector2 target, float speed = 1.0f) + public void SteeringSeek(Vector2 targetSimPos, float speed = 1.0f) { - steering += DoSteeringSeek(target, speed); + steering += DoSteeringSeek(targetSimPos, speed); } public void SteeringWander(float speed = 1.0f) diff --git a/Subsurface/Source/Characters/AnimController.cs b/Subsurface/Source/Characters/Animation/AnimController.cs similarity index 100% rename from Subsurface/Source/Characters/AnimController.cs rename to Subsurface/Source/Characters/Animation/AnimController.cs diff --git a/Subsurface/Source/Characters/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs similarity index 100% rename from Subsurface/Source/Characters/FishAnimController.cs rename to Subsurface/Source/Characters/Animation/FishAnimController.cs diff --git a/Subsurface/Source/Characters/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs similarity index 100% rename from Subsurface/Source/Characters/HumanoidAnimController.cs rename to Subsurface/Source/Characters/Animation/HumanoidAnimController.cs diff --git a/Subsurface/Source/Characters/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs similarity index 99% rename from Subsurface/Source/Characters/Ragdoll.cs rename to Subsurface/Source/Characters/Animation/Ragdoll.cs index 2428fa4d4..488694d18 100644 --- a/Subsurface/Source/Characters/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -306,7 +306,7 @@ namespace Barotrauma float stairPosY = structure.StairDirection == Direction.Right ? lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X); - if (lowestLimb.Position.Y < stairPosY) return; + if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY) return false; if (targetMovement.Y < 0.5f) { @@ -383,7 +383,9 @@ namespace Barotrauma } public virtual void Draw(SpriteBatch spriteBatch) - { + { + if (simplePhysicsEnabled) return; + foreach (Limb limb in Limbs) { limb.Draw(spriteBatch); @@ -392,7 +394,8 @@ namespace Barotrauma public void DebugDraw(SpriteBatch spriteBatch) { - if (!GameMain.DebugDraw) return; + if (!GameMain.DebugDraw || !character.Enabled) return; + if (simplePhysicsEnabled) return; foreach (Limb limb in Limbs) { diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs index 00859d6a7..a13f75f2d 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSprite.cs @@ -67,6 +67,8 @@ namespace Barotrauma Rand.Range(-prefab.Speed, prefab.Speed), Rand.Range(-prefab.Speed, prefab.Speed), Rand.Range(0.0f, prefab.WanderZAmount)); + + checkWallsTimer = Rand.Range(0.0f, CheckWallsInterval); } diff --git a/Subsurface/Source/GUI/GUIButton.cs b/Subsurface/Source/GUI/GUIButton.cs index 8973d95eb..e5a12ad2c 100644 --- a/Subsurface/Source/GUI/GUIButton.cs +++ b/Subsurface/Source/GUI/GUIButton.cs @@ -39,6 +39,19 @@ namespace Barotrauma } } + public override Color SelectedColor + { + get + { + return base.SelectedColor; + } + set + { + base.SelectedColor = value; + frame.SelectedColor = value; + } + } + public override Color OutlineColor { get { return base.OutlineColor; } @@ -120,7 +133,7 @@ namespace Barotrauma { if (!Visible) return; - if (rect.Contains(PlayerInput.MousePosition) && Enabled && (MouseOn == null || MouseOn == this || IsParentOf(MouseOn))) + if (rect.Contains(PlayerInput.MousePosition) && CanBeSelected && Enabled && (MouseOn == null || MouseOn == this || IsParentOf(MouseOn))) { state = ComponentState.Hover; if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed) @@ -136,6 +149,11 @@ namespace Barotrauma { if (OnClicked(this, UserData) && CanBeSelected) state = ComponentState.Selected; } + else + { + Selected = !Selected; + // state = state == ComponentState.Selected ? ComponentState.None : ComponentState.Selected; + } } } else diff --git a/Subsurface/Source/GUI/GUIListBox.cs b/Subsurface/Source/GUI/GUIListBox.cs index 47c9b8310..16f3ae654 100644 --- a/Subsurface/Source/GUI/GUIListBox.cs +++ b/Subsurface/Source/GUI/GUIListBox.cs @@ -1,13 +1,15 @@ using System; +using System.Linq; using System.Diagnostics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; namespace Barotrauma { public class GUIListBox : GUIComponent { - protected GUIComponent selected; + protected List selected; public delegate bool OnSelectedHandler(GUIComponent component, object obj); public OnSelectedHandler OnSelected; @@ -27,19 +29,26 @@ namespace Barotrauma private bool enabled; + public bool SelectMultiple; + public GUIComponent Selected { get { - return selected; + return selected.Any() ? selected[0] : null; } } + + public List AllSelected + { + get { return selected; } + } public object SelectedData { get { - return (selected == null) ? null : selected.UserData; + return (Selected == null) ? null : Selected.UserData; } } @@ -47,8 +56,8 @@ namespace Barotrauma { get { - if (selected == null) return -1; - return children.FindIndex(x => x == selected); + if (Selected == null) return -1; + return children.FindIndex(x => x == Selected); } } @@ -108,12 +117,14 @@ namespace Barotrauma { } - public GUIListBox(Rectangle rect, Color? color, Alignment alignment, GUIStyle style = null, GUIComponent parent = null) + public GUIListBox(Rectangle rect, Color? color, Alignment alignment, GUIStyle style = null, GUIComponent parent = null, bool isHorizontal = false) : base(style) { this.rect = rect; this.alignment = alignment; + selected = new List(); + if (color!=null) this.color = (Color)color; if (parent != null) @@ -121,8 +132,17 @@ namespace Barotrauma scrollBarHidden = true; - scrollBar = new GUIScrollBar( - new Rectangle(this.rect.X + this.rect.Width-20, this.rect.Y, 20, this.rect.Height), color, 1.0f, GUI.Style); + if (isHorizontal) + { + scrollBar = new GUIScrollBar( + new Rectangle(this.rect.X, this.rect.Bottom-20, this.rect.Width, 20), color, 1.0f, GUI.Style); + } + else + { + scrollBar = new GUIScrollBar( + new Rectangle(this.rect.Right - 20, this.rect.Y, 20, this.rect.Height), color, 1.0f, GUI.Style); + } + frame = new GUIFrame(Rectangle.Empty, style, this); if (style != null) style.Apply(frame, this); @@ -140,16 +160,17 @@ namespace Barotrauma public void Select(object selection) { - foreach (GUIComponent child in children) + for (int i = 0; i < children.Count; i++ ) { - if (child.UserData != selection) continue; - - selected = child; - if (OnSelected != null) OnSelected(selected, selected.UserData); - return; + if (children[i].UserData != selection) continue; + + Select(i); + + if (OnSelected != null) OnSelected(Selected, Selected.UserData); + if (!SelectMultiple) return; } } - + public override void Update(float deltaTime) { if (!Visible) return; @@ -167,17 +188,34 @@ namespace Barotrauma public void Select(int childIndex) { //children[0] is the GUIFrame, ignore it - childIndex += 1; + //childIndex += 1; if (childIndex >= children.Count || childIndex<0) return; - selected = children[childIndex]; - if (OnSelected != null) OnSelected(selected, selected.UserData); + if (SelectMultiple) + { + if (selected.Contains(children[childIndex])) + { + selected.Remove(children[childIndex]); + } + else + { + selected.Add(children[childIndex]); + } + } + else + { + selected.Clear(); + selected.Add(children[childIndex]); + } + + if (OnSelected != null) OnSelected(Selected, Selected.UserData); + } public void Deselect() { - selected = null; + selected.Clear(); } public void UpdateScrollBarSize() @@ -218,14 +256,14 @@ namespace Barotrauma public override void ClearChildren() { base.ClearChildren(); - selected = null; + selected.Clear(); } public override void RemoveChild(GUIComponent child) { base.RemoveChild(child); - if (selected == child) selected = null; + if (selected.Contains(child)) selected.Remove(child); UpdateScrollBarSize(); } @@ -272,8 +310,16 @@ namespace Barotrauma GUIComponent child = children[i]; if (child == frame) continue; - child.Rect = new Rectangle(child.Rect.X, y, child.Rect.Width, child.Rect.Height); - y += child.Rect.Height + spacing; + child.Rect = new Rectangle(x, y, child.Rect.Width, child.Rect.Height); + if (scrollBar.IsHorizontal) + { + x += child.Rect.Width + spacing; + } + else + { + y += child.Rect.Height + spacing; + } + if (child.Rect.Y + child.Rect.Height < rect.Y) continue; if (child.Rect.Y + child.Rect.Height > rect.Y + rect.Height) break; @@ -284,30 +330,31 @@ namespace Barotrauma continue; } - if (selected == child) - { - child.State = ComponentState.Selected; - - if (CheckSelected != null) - { - if (CheckSelected() != selected.UserData) selected = null; - } - } - else if (enabled && child.CanBeFocused && + if (enabled && child.CanBeFocused && (MouseOn == this || (MouseOn != null && this.IsParentOf(MouseOn))) && child.Rect.Contains(PlayerInput.MousePosition)) { child.State = ComponentState.Hover; if (PlayerInput.LeftButtonClicked()) { Debug.WriteLine("clicked"); - selected = child; - if (OnSelected != null) - { - if (!OnSelected(selected, child.UserData)) selected = null; - } + Select(i); + //selected = child; + //if (OnSelected != null) + //{ + // if (!OnSelected(selected, child.UserData)) selected = null; + //} } } + else if(selected.Contains(child)) + { + child.State = ComponentState.Selected; + + if (CheckSelected != null) + { + if (CheckSelected() != child.UserData) selected.Remove(child); + } + } else { child.State = ComponentState.None; diff --git a/Subsurface/Source/GameSession/CrewManager.cs b/Subsurface/Source/GameSession/CrewManager.cs index e7c30ad55..b1b5650e8 100644 --- a/Subsurface/Source/GameSession/CrewManager.cs +++ b/Subsurface/Source/GameSession/CrewManager.cs @@ -12,9 +12,6 @@ namespace Barotrauma public List characters; public List characterInfos; - //public static string mapFile; - //public string saveFile; - private int money; private GUIFrame guiFrame; @@ -24,7 +21,8 @@ namespace Barotrauma private GUIButton crewButton; protected GUIFrame crewFrame; - + private CrewCommander commander; + public int Money { get { return money; } @@ -45,6 +43,8 @@ namespace Barotrauma crewButton = new GUIButton(new Rectangle(0, 00, 100, 20), "Crew", GUI.Style, guiFrame); crewButton.OnClicked = ToggleCrewFrame; + commander = new CrewCommander(this); + money = 10000; } @@ -102,13 +102,19 @@ namespace Barotrauma textBlock.Font = GUI.SmallFont; textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); - new GUIImage(new Rectangle(-10, -10, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); + new GUIImage(new Rectangle(-10, -5, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); } public void Update(float deltaTime) { guiFrame.Update(deltaTime); + if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.I)) + { + commander.ToggleGUIFrame(); + } + + if (commander.Frame != null) commander.Frame.Update(deltaTime); if (crewFrameOpen) crewFrame.Update(deltaTime); } @@ -235,9 +241,15 @@ namespace Barotrauma public void Draw(SpriteBatch spriteBatch) { - guiFrame.Draw(spriteBatch); - - if (crewFrameOpen) crewFrame.Draw(spriteBatch); + if (commander.IsOpen) + { + commander.Draw(spriteBatch); + } + else + { + guiFrame.Draw(spriteBatch); + if (crewFrameOpen) crewFrame.Draw(spriteBatch); + } } public void Save(XElement parentElement) diff --git a/Subsurface/Source/Items/Inventory.cs b/Subsurface/Source/Items/Inventory.cs index 249f0cfae..d492816ec 100644 --- a/Subsurface/Source/Items/Inventory.cs +++ b/Subsurface/Source/Items/Inventory.cs @@ -229,10 +229,10 @@ namespace Barotrauma Vector2 textSize = GUI.Font.MeasureString(toolTip); Vector2 rectSize = textSize * 1.2f; - Vector2 pos = new Vector2(highlightedSlot.Center.X, highlightedSlot.Bottom); + Vector2 pos = new Vector2(highlightedSlot.Center.X, highlightedSlot.Y-rectSize.Y); pos.X = (int)pos.X; pos.Y = (int)pos.Y; - + GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true); spriteBatch.DrawString(GUI.Font, toolTip, new Vector2((int)pos.X + rectSize.X * 0.5f, (int)pos.Y + rectSize.Y * 0.5f), diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index b34ba97af..1b2df74a1 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -89,9 +89,8 @@ namespace Barotrauma Color clr = (isSelected) ? Color.Red : Color.LightGreen; GUI.DrawRectangle(spriteBatch, new Rectangle(pos.X - rect.Width / 2, -pos.Y - rect.Height / 2, rect.Width, rect.Height), clr, true); - - - spriteBatch.DrawString(GUI.SmallFont, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White); + + //spriteBatch.DrawString(GUI.SmallFont, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White); foreach (MapEntity e in linkedTo) { diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 57f3bbb4933d98ca2f7936e395caca01d8d7993a..9226cf21ddc7e053d76faa1a33bf0d9a323a9973 100644 GIT binary patch delta 15730 zcmdUW3tZJzw*T3`$2q^p0S*X=fOtSuL_|bVGBZRZG!h~-Gcr)|6#^nDK2q#DO%KPA zV`ueH2gx~Fnc<_e%`rQo)2Nw|nOQjunRU&~OJO*~NaudxalWCA(GX08~Og#~n0u?|RP!7xhrUQROeul7d!D;4i zchr5iB<=%t3#wKhcFYy#vW}a75Omh}c@+BFl^cJT+dgNs<@HCc6vU$tUUu}A`a~H8 z{sUj5faidn$eoEUyCQy!ITlFiY=>i~^lQl|=*X5Mg^ec1G&_T!VORg|9X^J$-h(Wo&GV<5&njPTk# zj9LAhc?d_CV}u;lHjDoMXck5XKRye`IW;rd7+0WfG6exfJQ!g}Tip1*ylh#7qe_dU znR|r5Wp%ovL9;JgzC;~^GWQ$hmMwd+RvYv$X~&txtp2~n5^Tf5WFdTjIl{yHs|kqS zi=<4){o(xvyAVr4%0s~8h~JK|J7}GU_+H=*AR1|p0)Ih#H-L#;c?n@BlVe|ac=yAI zZbf!2!siekKsW&5dY}&RMF=I6LyH*L{abvF!{;i5Wkwco0N?u&u0;4e!Zpk>Eh0v^ zRd6hg2#pUz%4VPu_%9$ErM^SB68IYNw-9zlI8AUIh=>Z@glIRQ1?Y%rI30h>>ajW2 zc9ew=N69;ZN09a3UX~@O{8P*FJsSUo%Od~cW$DSh%c7yL|IxBM+OLPh^AJBJD(j>3Qr@_k^} zXB`(t^`bRJLauDX=Q2lNb03GjIg&hex`p0dDcyoEyBA4^~U(&pGRmzcvIEK%$V>9;B? z0n3#F*Erzp3MpSIyFN+2fQ_)-F{dB6a3#x?JAeyUJ1(^Jd@1Ifnd&>SJV&KF$FWQ3 z>p1JqQQ2fvo^pKyj!K@ZOhZcf^{Mh@G}}lQQdzIfv6qhqIHw4)Ja!^G%G@?)4=1}z z>MF7#@ft5yx+HHmbk>D2K74&+RJm4KQY*&rm;~0$-1~$WfyX4V=8m<&P~5{Y@3WT} zw~t^gB2|xP=x98<#K@j6#__B~ww1Z^nBcr1fQws?GS_Hkb*Bh+VY7WaSUoMq5fhn5 zl?Q}eWdSJhBye@X_}K%3mC=w8p)(aeu7vXeQ`kP8b|wm0R2QUM`KYDhtE{#YhBk{e zi?s2a7DB_jVXn9OizUpq<5<6OEtXrp|Miyayx3bF-+`fSw zVsa?xuJ8*VF^k}?m#oa{Rkj$95mMMo(h1k6OmJNk1ojv$`jE|_!o!vzzPOpqS6zoB zw1;Is$u9fxn31B3N%O8>Mmn1#CUE;j)*`#c2m&n{qV(WB1mTmuRQ-@amP-cx`U@?c zT_@1VXhEnQj`=5w&4&Dp*&LIM7N=g%5{|R|&|rbk;^%xp8Y;3G*K^VfQnfHlqjN7v z3*^h#At!0hi_$zf11zaHE`;^uF(pE?Seu59T}K%mb6aAm=OMgpG8PIN>bz~mcY)@@YjSpx)BnBfla9LCBkXIMPLGukCDtp zc%EJx#kwSKM07T=95@c-0DFK1sG5eNnZR0n=L742yP4y1SS*j(AT)QRzIU=P=Sn$? z7akPr7#l~6e#-_@Llrppp*_NCAOB4<^aum}uT-P0>sW6xTjC|qegWI@E3pf+3I406 zy*j(=`tLp}s%8=3FWS%Z7A*k2)WZqdz;BS-2{2|s z_8b=6`F(u-0T7Wp31I>72Cx<#y-fGyunr3^pn)fl_ZGLn9Y3iZKQYoz?~S zVeu(OPpuSZxkrn3f!j|D>zGt{y@>Mr2J*&W5#u+O*vA687%O_9qk^Oyujudm{_#M| zz&ZOroUk|ZPoKT|T98rHpoaHnl)K0Ipc=%#s1c(WXNBSw(Y;SJw4WPWlZIYke{$4i zNsibxc4ZpY(m2&#-3z?(n7D+|CQ0m1*)PgLJZqY`wX1WaXy^8P7{uuZO_#2A9i0}$R6ZWU8 zR@9h>hAd-u@$4z$bY@$6=armw+16h_w0rXp%MXw1XvmC?)G}4HvnjOm1WO}(p&Cb1 z#|m2ldhI@@KiT@j`AL_rB(2zfn3mav5E}A;@V2W?RJ@{WgjmmLcQ01puy=>3ctt!K zz)EOQs90dnF;$o*nu_r^(KNv{({y;*>mTI(ZoyaYrF{LDkETY=qkCqFov8UyDTZ48 z1%=J`R_ikq6^c!>VcnLQrsH3csq}_svS`Bkku$PmlK)cl=cm4X&Cz#BC>;ouqHL{0 zRf7*q_hqepmz%A_C^t|_3OtcBAn5K(4?okMT1)rbA@?yv*+OIe-oskGi%Q`LWCP`x&pC4H=sMv1Be590`WjEAOYwN7;dmW zKoZawF!p3Em;naQj6Fh!jdfj^bD;Ek!1_!6FMroPc>SmK@4x!ofExO|vlzlZ94Pf> zuHB;G%wX%MFn0hg-?v-tH`T;SS+xLqtjFtQLZS@*0iO)D8KEtSJme!ef zZW6y>?vYX@GgqRAgJm=~M{?nCiaO!f_T`roI(A!ju;~w$7YjFx@ACR>R8+u%dE#a9 zAaho-&uzPA46Oft|FG##j{n2LJuhFF$RRKS7)0Qr*Y$aP{-@$%3lxe^6~sXmP+p3X z$up0O+t_m9i0$!~(N}Vmgu+j<%sm^nd}Q}F|HdUjVr-Ug+{uHqBpQ54@#hQQ5f(A# zq(zIRp_G)Z7E6hUyE6*YI7_!p)v$SQkf`kn_@uPpJ|Lx%PB#&pRM=zg3T zGCo+siNa%(`cd6rC7f)5Ka&c6;gaA08^BkEv*{5K7s8 z;ub99kZmlTs^3==`HXPs8I`Id#ffC!DJSrn17bOISK>fmc`|s!7e(=NeYV!oN2G3? z#YtBJ$umogrPk%lP8k!WjRA>6{hLGnxcZ^-=T{!uxbJRSb~`M)PQ}uHx&}!>?jUIh zBUZ^qQuPWsjMjFL<`^mo#+Gzc{P#HwjP3qEaTp8+pS3#-jJ6Difnl2)BIRa>fsz0J zhr{4JM)>m_27ZaI(URnzC_c_?9d@;L_K!UJ$16uxm%V%28-kay>6Kz}w5vc;o?Rq# zj=fQb`PAUoKQvXB{px7W+To8yY*)8L`l^kpmU=mtNx^)1wN%1b6|p)!iw{2{rna$3 z;YQg;fBr;_c1@84$34FZrIs*R;^FUzUoogo_O&>k(k^J>{LvEWDGRrpU>6weoTqo9 z@;Ph}A2myQmAThRLt*~h!jkEcm!%w~2L$|Wz*X5}EytGv7(Zt|3;ypM;|#KXh5Enn z7&nUD(aoqD3}XEAV_eEFKgO9%j=o2_@GkSE&lv?&1cS?%w(I)dpIbXbU z>7(y0EgLTej`PXD#RtXt?Eiu}L)D)OIXvevX`{?on=iE8`)Q-_(z6Doc?kYZ5%2XPEUXG{6_3Y<(n*izgPzk|5xeYJ2o!r2Q{1{gNjR} zSb=s`NmFV4QYlP{1H;7wS6P|PE|qc>gQ1M;nQO_FbEG9d;i+*yC5ZwB=g6UC8zqPF zzRRWeW!F+kaMntd=DiSMv%+a^t#pySO^_+ZZdh{r|udR$N$KZ;%{hfwf-sgT`6 zk8GC~vRwKBft-WPL5>STS6cCwG{&+MN2sy882{_bQa7{V%lzlg^B175vQ|n7zsQ4r zi*pm!;z_K<{y>_$32RYFk2o-%=@`#w!vV@;8l>ib|0#(EMTn99Hy(!^ms{Y-F@{$g z6XRI(0#3HuB)4eUfyFzpi_yF~sV9%!Aw40}`VXai*E^EXc3*azVN6zUtV?0=opSp& zsfD>4r8vg!qUc>xL}VUje=m>^7?+o$f%^c%dZfY+rQ9$hR@#>QDDl;&$oBWrbNHttK1}<|Q1!sOLot2H|-XZp-)P=%6gTt{| zl3d53Bx(*yTsmo#JS_>XdYO40r6j#1@0Pwdj@Faa&CE|u zkuS1k%OZK?EAnyX8Yye89cF=!^MD567`cG4QsWHV!CfGqi4EIeO!lVV`JuO~ zj%Wd5wv(*z?u+D!fr4!`Evc2qnalcomi%rH-dZcq73m2s2T|_xFoUW)3ud**RB4)u z!ynq`mfn=ROO|N=b8`I6xzTCDE#6!{%_%!|w_=H9u5+?LF>kAOI)4z`xS>Y1^SQs1 zlSH?lWjmuaAN)j5%idHv($@8Isr!_)g?Uf&W#I7&0E_GW%|v`Tz4tBb${~Lcy7TPU zWT!yr`p3r}I6~>>8~chCDAG!bM0Gv&7|QL9`II*zEvZ57PNzI_3Y7<`36#3p5IiKu zP@g|De?DlVJdjc58@~1m|t zGjGeYMcV&-TU*rfq8i2PcFAFWG-8KuB>wcwanZ&zKajV@y2n@|nQMeBI8RE|u!t9( zlu zsghdq^bk7qjg&xVfWG0U?lWt^i;Nnh z%^KqN|IZG6y#Xm^F zR2~XHY2sPwAfuK-c@wq7m?J4_lR1T=Mwl;ynPu?zIq7((wUIAc%CQ*gO z{1wlgYz}9xY+0fD3Gx~4zt7??y7Ix#^~>caXvYI)JI{W^VqSQJSb zHuT*p!Qm>eedB)Wj_kPmNUeFsgBCu~eOHNRZ7I zGcCUre$4WCJ(AwfmTbH}Lm8)2>9c~FY_n8_`%hEO$gT!7d9aTXMoCPOcx1V3*e_QSL%Z2G3|xQbh{7on<)6_9{HP*|G(#ZMMXdt&5OCpMI#sk!K#309S4P zRM-ctWgS+wGOF%pI59s}S{Sts&^4;L6j8H;(Qjqc-qw%YhR66sfc`yyWS8?$|LB$5Ee_QU} z<7ccs^w)YClB3+m?ZHZmg*?O5SQ`90G(Ip&Nymiplq6a&s`=D#hcQaCnvE+frbLmw zlN!#qbWujeQp0Chs)E;L8y}c!R7#h$U|wTU%gyAe5`uZKO`Re;(&xqTHTNh5VbnBP zhQ;@kG8U@j4G3z(fldt*LEZf!YKlbm21_ERf*ARYkK=iw8SD>R#2%{dX7?Y3zfs**1bg>uy&MFIp_E3-w^C`9vuv`)|}No^@17LB3Uq<#l(dM;V|0CuK22!DCn%^C@K( zTRZ=5RipXeqSY2dqZN8&GY@N3CSvgClqmkfed;l6j$t5Q?RQG4K!qJ}G&}H#X5(=e zm3&6Rt6F!ezh52aT&;qd1!}fT75#NPc|w&0zUQw>szj|vR9r}((%{1Bswz~vTMj3; zq`pJ*i`2yw^O=%is8=h`eM(Ib>9J%bmg;1+(9zleMc}U%qL(Tqk*eRrC_KMW(Y6mNW zsc@^@owrO-&ug@%M)S%>CFn-CKCaC~YB{ey&I`)aHQ`jPD*n_o0BaA|U=(H6s*QAJ zteU|+(HfRCsRvudSH)?~0u8!T3g3A2&ZJ4x? zVL#>q!Y#N+wcRZ2=wvM6o15{bQob(peATj70xK&|VsYeqz9 zZc5uKCzGu}3#QEOS|g>8QU+4Mi!7X47Qu2Kw^^%)D!L2SW|O}X#6!1gC!sd7A-!AX zYf*g6c5NNLN2(z60S(UDv=?P7?WlsBm!0eTgcI6x&1r~g zTfJ6I^+j4X&+VhT8LzF^O2ubA0yv~WdmM~AnF4QDqRG=0yY87-DTop;gEkd?^;(tJ zG-wr!mh>>T^Jtuo(%f1eg^q=yTA=A+v_*sI(4^`~{P=CUU8D*XR_r>rHU{kVv`|Aa zk1I)r8-c@(u$%FkZCW|3$_7xa>5LXev1dTAO%s$fDs*W6)cG4Rl9vwAohZ2j<99Y` zHI%kRkK!>yK>^36*@;y6v=GTZZPL1fASJxim~4t5f4QmY5q! zo30oSY7H}=lsrAvou@B?1iV+jgZXg;-567;DPIqzv{CvlUUN(<7iny7*kqCCwMweJ z55(*S7#cE4Po{?ZbpMdaxbB+{Gi#<7GuzIA-`=O+&KjuK7(E@{xc1TsA_Nhg z7^4@`_WQANC-24eclG`HXj;8jkN2Ke44asit#a-NeO?=()3J}# z{)X^?oHwJEFjbG^aZ~gouuKkub?j@w3a89^uu2QoLavk#!IDHq>6Px~dZI|tQ_x*T z2YtJ~KhR{dp(oYUKs(>jtE>eRDvD=MD4RaLsB|JNdQb0-n_D9zxuC3KVsS;{gqic_ z&nxObVL(bsQEKm`;*_G^DU&Aj@12_3zo>Uo|CHp^eo42a^dFG&=z62x!&LaGZdHv& z(PGhLZ>BOT%2j$t`C1;^;!AElfOUJx+l2q*N2V44B~xcsjxVdCoiFIU zX!;-Z8s{NAn5_O#k7H}S1#QK%ic2eJ7E~6^eE3?6^!(S%A0+sR=|ONE(reqB8blw& zTRTyU3oZLK>3$IfIpe1lPpF(at9WL?kl|N9?kvkMqtzelok9&dwf~HBWi*iS<8$j6 za$O5|8_VHc(2+Ow8Tk`^dTUU0lO7Rjc)oqVXwN-}7`Mk6-YMS2Yoc^)t8zOSWW;Q7 zEPcKgrbf*w-Cw_%v_ZC^pvzDnvAshXeA7^@1=p4Eb$xqV$GDF47_K72#gp;Vv<~z) zTDUgZfyK0}w>8YS!sj=DH?HRU+HbkqezfNj;)bI?19=5&c4?s z;E#-gYneW38Si;~zi5x~Qqq5-7gUSLj`6 z*9JX=-L$TEgjQXxAL=olqZuME;~#Aln}0qw&NWiqa%~-K!+bmIY60&UyBKe1eZP25 zd(7wtH)+O?R&TQOrSiK}ykd6i`7~q|1gGbio@S;(T}{IsDjdssRMRBK((K>rPtxZn zSTNZ&eI()iO%Sbo4Ck1z>3S7&*6V51f;wxf>vfS1CbM{IeoPEy(`e^XyxG}OBB#=A zE`69I?`R`UIRgtL^!NHJZ0yx*Q8SI}tq0Kq>#%5FY=rIOm^CmS+v*9W>^*3$$$ z21Ga2uj(FZFk;CkVX>v%s)zFf>-94@Vr{lWQS)}aer@&ZI+JD^Q;hylPoW3*>WU(H z=ZvHw2lO~ps4@4HQUs*&8MrplBH#(uDKWMi5)0$s(w(P74F+qet13vi90KLe9?r5Cs&j` zQaW*FdBxPq;)0tKyz-oF^2%rbf|-@Y#T8RaCr`hoEp8C?blVGhiC3J_lkeyQ*lXT; zdI2N=Di)0|DfYGJ_NE6FlowS_`TI86Zf~|%`RHZks90Hyu}$~Y{c-8tuCU(PuZNk7 zD}S`OWzy8DlH#I=eeL+9L)V`n9jN?y{oS9T#eUJ6N`9t{*S+&(1>VI93>Y$eXjy4x zMOjISSKQxzZHIfcoemY(Uce`f+j!a=7_u@MxK6u;xVl>fbyo59)4oB=WlpWi#(F?9 z->l`LenQK&)$oby4p;jR_SoCv?cLu@ha396v$%3N==lr!ZL8t!H_#C7?Z2)@gc1+w z%iE2Fm7#5$0~uCNKm5HFXdl;22F(q_x+YvlUe(L7ZPt%hu@6E+zF)NGPDG53GX4>> zMs&K)rpWPea@)-FZlZ3?PptTLwS22?JOcIoVm%>a{CT!=64gdh^HF;B)#(+Vp1 zyK>&`OWQuyHA}3=;HrU!{czYfF4*KfX$>r$A2$+yS{4Tf{rzClZW@e#!3|}6a>TG; zd_SAVu;`3U^9zlUA@Axv)N7`_v0dW-i2-7oKC@t0>Ex-U#Ratbk9w-1s8hLDH9Ifi zMASdf8tmk{7kDTjwa42-%G)LQEEag|n$%RDx>er;&u6B!gqLJkm*cdx2p3;9yYvLw z!F3zY^XMC7ccyhxAQv96z96}d>H;M%P*UM))3)$aC-h+4=CnNB_o`E%-Yb9!UiDrd@p(OEt!J|?DDCfCX#|oa{l20(?vwf++jXXr)NU&Erhd(O2TE_jni|HE3&xW7 z*@p4v>gPV4y!&7EY$F8^8vkru7Ef4Kx1R!Bcz1wzB>ukZgqqitL|#74S`+PxvqsWm unbuGqy2P3rVi5nV@_&Z9j&T8@?upjL?3&}@D(T2G*=nVc&+AEEvi(0GYj3## delta 14906 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