From 08daab9d879a0ecd279844d0e818457511ebedad Mon Sep 17 00:00:00 2001 From: Regalis Date: Mon, 25 Jan 2016 18:47:19 +0200 Subject: [PATCH] - AI equips a diving suit before going out - placing a firesource outside any hull won't crash the game - scrollbars aren't gray - fixed client crashing if in the lobby when a round ends - fixed password box crashing --- Subsurface/Barotrauma.csproj | 1 + Subsurface/Content/UI/style.xml | 2 +- .../Characters/AI/IndoorsSteeringManager.cs | 24 ++++++ .../Objectives/AIObjectiveFindDivingGear.cs | 76 ++++++++++++++++++ .../AI/Objectives/AIObjectiveFindSafety.cs | 73 +++++++++-------- .../AI/Objectives/AIObjectiveGoTo.cs | 16 ++-- Subsurface/Source/GUI/GUIListBox.cs | 6 +- Subsurface/Source/Map/FireSource.cs | 2 + Subsurface/Source/Networking/GameClient.cs | 4 +- Subsurface/Source/Screens/NetLobbyScreen.cs | 2 + Subsurface/Source/Screens/ServerListScreen.cs | 19 ++++- Subsurface_Solution.v12.suo | Bin 868352 -> 811520 bytes 12 files changed, 177 insertions(+), 48 deletions(-) create mode 100644 Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 60e6af5cd..21105dc66 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -63,6 +63,7 @@ + diff --git a/Subsurface/Content/UI/style.xml b/Subsurface/Content/UI/style.xml index de7bb89eb..31ba04d98 100644 --- a/Subsurface/Content/UI/style.xml +++ b/Subsurface/Content/UI/style.xml @@ -39,7 +39,7 @@ diff --git a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs index 30900b39f..25c199891 100644 --- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs @@ -36,6 +36,12 @@ namespace Barotrauma get { return currentTarget; } } + public bool HasOutdoorsNodes + { + get; + private set; + } + public IndoorsSteeringManager(ISteerable host, bool canOpenDoors) : base(host) { @@ -79,6 +85,8 @@ namespace Barotrauma } currentPath = pathFinder.FindPath(pos, target); + + HasOutdoorsNodes = currentPath.Nodes.Find(n => n.CurrentHull == null) != null; findPathTimer = Rand.Range(1.0f,1.2f); @@ -151,6 +159,22 @@ namespace Barotrauma bool open = currentPath.CurrentNode != null && Math.Sign(door.Item.SimPosition.X - host.SimPosition.X) == Math.Sign(currentPath.CurrentNode.SimPosition.X - host.SimPosition.X); + if (currentPath.CurrentNode==null) + { + open = false; + } + else + { + if (door.LinkedGap.isHorizontal) + { + open = Math.Sign(door.Item.SimPosition.X - character.SimPosition.X) == Math.Sign(currentPath.CurrentNode.SimPosition.X - character.SimPosition.X); + } + else + { + open = Math.Sign(door.Item.SimPosition.Y - character.SimPosition.Y) == Math.Sign(currentPath.CurrentNode.SimPosition.Y - character.SimPosition.Y); + } + } + //toggle the door if it's the previous node and open, or if it's current node and closed if (door.IsOpen != open) { diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs new file mode 100644 index 000000000..6aee02fb7 --- /dev/null +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs @@ -0,0 +1,76 @@ +using Barotrauma.Items.Components; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Barotrauma +{ + class AIObjectiveFindDivingGear : AIObjective + { + private AIObjective subObjective; + + private string gearName; + + public override bool IsCompleted() + { + var item = character.Inventory.FindItem(gearName); + if (item == null) return false; + + var containedItems = item.ContainedItems; + var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f); + return oxygenTank != null; + } + + public AIObjectiveFindDivingGear(Character character, bool needDivingSuit) + : base(character, "") + { + gearName = needDivingSuit ? "Diving Suit" : "diving"; + } + + protected override void Act(float deltaTime) + { + var item = character.Inventory.FindItem(gearName); + if (item == null) + { + //get a diving mask/suit first + if (!(subObjective is AIObjectiveGetItem)) + { + subObjective = new AIObjectiveGetItem(character, gearName, true); + } + } + else + { + var containedItems = item.ContainedItems; + if (containedItems == null) return; + + //check if there's an oxygen tank in the mask + var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f); + + if (oxygenTank != null) + { + //isCompleted = true; + return; + } + + + if (!(subObjective is AIObjectiveContainItem)) + { + subObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent()); + } + } + + if (subObjective != null) + { + subObjective.TryComplete(deltaTime); + + //isCompleted = subObjective.IsCompleted(); + } + } + + public override bool IsDuplicate(AIObjective otherObjective) + { + return otherObjective is AIObjectiveFindDivingGear; + } + } +} diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs index 2c5064c88..a0a7684af 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs @@ -117,45 +117,50 @@ namespace Barotrauma private bool FindDivingGear(float deltaTime) { - - - var item = character.Inventory.FindItem("diving"); - if (item == null) + if (divingGearObjective==null) { - //get a diving mask/suit first - if (!(divingGearObjective is AIObjectiveGetItem)) - { - divingGearObjective = new AIObjectiveGetItem(character, "diving", true); - } - } - else - { - var containedItems = item.ContainedItems; - if (containedItems == null) return true; - - //check if there's an oxygen tank in the mask - var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f); - - if (oxygenTank != null) return true; - - - if (!(divingGearObjective is AIObjectiveContainItem)) - { - divingGearObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent()); - - } + divingGearObjective = new AIObjectiveFindDivingGear(character, false); } - if (divingGearObjective != null) - { - divingGearObjective.TryComplete(deltaTime); + divingGearObjective.TryComplete(deltaTime); + return divingGearObjective.IsCompleted(); - bool isCompleted = divingGearObjective.IsCompleted(); - if (isCompleted) divingGearObjective = null; - return isCompleted; - } + //var item = character.Inventory.FindItem("diving"); + //if (item == null) + //{ + // //get a diving mask/suit first + // if (!(divingGearObjective is AIObjectiveGetItem)) + // { + // divingGearObjective = new AIObjectiveGetItem(character, "diving", true); + // } + //} + //else + //{ + // var containedItems = item.ContainedItems; + // if (containedItems == null) return true; - return false; + // //check if there's an oxygen tank in the mask + // var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f); + + // if (oxygenTank != null) return true; + + + // if (!(divingGearObjective is AIObjectiveContainItem)) + // { + // divingGearObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent()); + // } + //} + + //if (divingGearObjective != null) + //{ + // divingGearObjective.TryComplete(deltaTime); + + // bool isCompleted = divingGearObjective.IsCompleted(); + // if (isCompleted) divingGearObjective = null; + // return isCompleted; + //} + + //return false; } public override bool IsDuplicate(AIObjective otherObjective) diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index d5794beeb..379135caf 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -10,11 +10,11 @@ namespace Barotrauma { class AIObjectiveGoTo : AIObjective { - Entity target; + private Entity target; - Vector2 targetPos; + private Vector2 targetPos; - bool repeat; + private bool repeat; //how long until the path to the target is declared unreachable private float waitUntilPathUnreachable; @@ -90,7 +90,7 @@ namespace Barotrauma { //currTargetPos += target.Submarine.SimPosition; } - else if (target.Submarine==null) + else if (target.Submarine == null) { currTargetPos -= Submarine.Loaded.SimPosition; } @@ -103,9 +103,15 @@ namespace Barotrauma } else { + character.AIController.SteeringManager.SteeringSeek(currTargetPos); - character.AIController.SteeringManager.SteeringSeek(currTargetPos); + var indoorsSteering = character.AIController.SteeringManager as IndoorsSteeringManager; + if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes) + { + + AddSubObjective(new AIObjectiveGetItem(character, "Diving Suit", true)); + } } } diff --git a/Subsurface/Source/GUI/GUIListBox.cs b/Subsurface/Source/GUI/GUIListBox.cs index c3717b7e5..baf8b9de8 100644 --- a/Subsurface/Source/GUI/GUIListBox.cs +++ b/Subsurface/Source/GUI/GUIListBox.cs @@ -135,14 +135,14 @@ namespace Barotrauma if (isHorizontal) { scrollBar = new GUIScrollBar( - new Rectangle(this.rect.X, this.rect.Bottom - 20, this.rect.Width, 20), color, 1.0f, GUI.Style); + new Rectangle(this.rect.X, this.rect.Bottom - 20, this.rect.Width, 20), null, 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); + new Rectangle(this.rect.Right - 20, this.rect.Y, 20, this.rect.Height), null, 1.0f, GUI.Style); } - + frame = new GUIFrame(Rectangle.Empty, style, this); if (style != null) style.Apply(frame, this); diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs index a4a725082..a4c86e6de 100644 --- a/Subsurface/Source/Map/FireSource.cs +++ b/Subsurface/Source/Map/FireSource.cs @@ -85,6 +85,8 @@ namespace Barotrauma private void LimitSize() { + if (hull == null) return; + position.X = Math.Max(hull.Rect.X, position.X); position.Y = Math.Min(hull.Rect.Y, position.Y); diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index e3476c1b3..33202404c 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -595,12 +595,12 @@ namespace Barotrauma.Networking public IEnumerable EndGame(string endMessage) { - GameMain.GameSession.gameMode.End(endMessage); + if (!gameStarted) yield return CoroutineStatus.Success; + GameMain.GameSession.gameMode.End(endMessage); //var messageBox = new GUIMessageBox("The round has ended", endMessage, 400, 300); - if (!gameStarted) yield return CoroutineStatus.Success; gameStarted = false; Character.Controlled = null; diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index 2b41a7f4e..d88d71533 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -494,6 +494,8 @@ namespace Barotrauma SetTraitorsEnabled((YesNoMaybe)index); + if (GameMain.Server != null) GameMain.Server.UpdateNetLobby(null); + return true; } diff --git a/Subsurface/Source/Screens/ServerListScreen.cs b/Subsurface/Source/Screens/ServerListScreen.cs index 15db9d5a9..e167d2266 100644 --- a/Subsurface/Source/Screens/ServerListScreen.cs +++ b/Subsurface/Source/Screens/ServerListScreen.cs @@ -302,15 +302,28 @@ namespace Barotrauma if (serverList.Selected!=null && (serverList.Selected.GetChild("password") as GUITickBox).Selected) { - var msgBox = new GUIMessageBox("Password required:", ""); - var passwordBox = new GUITextBox(new Rectangle(0,40,150,25), Alignment.TopLeft, GUI.Style, msgBox); + var msgBox = new GUIMessageBox("Password required:", "", new string[] { "OK", "Cancel" }); + var passwordBox = new GUITextBox(new Rectangle(0,40,150,25), Alignment.TopLeft, GUI.Style, msgBox.children[0]); passwordBox.UserData = "password"; - var okButton = msgBox.GetChild(); + var okButton = msgBox.Buttons[0]; + var cancelButton = msgBox.Buttons[1]; while (GUIMessageBox.MessageBoxes.Contains(msgBox)) { okButton.Enabled = !string.IsNullOrWhiteSpace(passwordBox.Text); + + if (okButton.Selected) + { + msgBox.Close(null,null); + break; + } + else if (cancelButton.Selected) + { + msgBox.Close(null, null); + yield return CoroutineStatus.Success; + } + yield return CoroutineStatus.Running; } diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index cc8fc2d12f3a9a79e468b9131aa8a0ede7b49dd8..a8e7a3550a6257e90058a6adfd7817aee9f09ab8 100644 GIT binary patch delta 13344 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 delta 16326 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