From 25768d88458494af06aefabfa977c24f94a9f6b2 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Fri, 5 Apr 2019 16:20:11 +0300 Subject: [PATCH] (4b54fb4bf) Refactor AIObjectiveCombat and the reactions to the damage. Fixes bots not reacting to any damage done with repair tools. Now they should flee (but not retaliate). --- .../Source/GameSession/CrewManager.cs | 115 ------------------ .../Source/Items/Components/ItemComponent.cs | 79 ++++++++++++ .../Source/Screens/SubEditorScreen.cs | 49 ++++---- .../Source/Characters/AI/HumanAIController.cs | 65 +++++----- .../AI/Objectives/AIObjectiveCombat.cs | 86 ++++++++----- .../Objectives/AIObjectiveExtinguishFire.cs | 5 +- .../AI/Objectives/AIObjectiveFindSafety.cs | 7 +- .../Items/Components/Holdable/MeleeWeapon.cs | 1 + .../Items/Components/Holdable/RangedWeapon.cs | 1 + .../Items/Components/Holdable/RepairTool.cs | 1 + .../BarotraumaShared/Source/Map/Submarine.cs | 19 +++ 11 files changed, 214 insertions(+), 214 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index 02427dc57..4333dc5c4 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -66,121 +66,6 @@ namespace Barotrauma CanBeFocused = false }; - Point scrollButtonSize = new Point((int)(200 * GUI.Scale), (int)(30 * GUI.Scale)); - - crewArea = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), "", Color.Transparent) - { - CanBeFocused = false - }; - toggleCrewButton = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform) - { AbsoluteOffset = HUDLayoutSettings.CrewArea.Location }, - "", style: "UIToggleButton"); - toggleCrewButton.OnClicked += (GUIButton btn, object userdata) => - { - toggleCrewAreaOpen = !toggleCrewAreaOpen; - foreach (GUIComponent child in btn.Children) - { - child.SpriteEffects = toggleCrewAreaOpen ? SpriteEffects.None : SpriteEffects.FlipHorizontally; - } - return true; - }; - - characterListBox = new GUIListBox(new RectTransform(new Point(100, (int)(crewArea.Rect.Height - scrollButtonSize.Y * 1.6f)), crewArea.RectTransform, Anchor.CenterLeft), false, Color.Transparent, null) - { - //Spacing = (int)(3 * GUI.Scale), - ScrollBarEnabled = false, - ScrollBarVisible = false, - CanBeFocused = false - }; - - scrollButtonUp = new GUIButton(new RectTransform(scrollButtonSize, crewArea.RectTransform, Anchor.TopLeft, Pivot.TopLeft), "", Alignment.Center, "GUIButtonVerticalArrow") - { - Visible = false, - UserData = -1, - OnClicked = ScrollCharacterList - }; - scrollButtonDown = new GUIButton(new RectTransform(scrollButtonSize, crewArea.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), "", Alignment.Center, "GUIButtonVerticalArrow") - { - Visible = false, - UserData = 1, - OnClicked = ScrollCharacterList - }; - scrollButtonDown.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipVertically); - - if (isSinglePlayer) - { - chatBox = new ChatBox(guiFrame, isSinglePlayer: true) - { - OnEnterMessage = (textbox, text) => - { - if (Character.Controlled?.Info == null) - { - textbox.Deselect(); - textbox.Text = ""; - return true; - } - - textbox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Default]; - - if (!string.IsNullOrWhiteSpace(text)) - { - string msgCommand = ChatMessage.GetChatMessageCommand(text, out string msg); - AddSinglePlayerChatMessage( - Character.Controlled.Info.Name, - msg, - ((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled)) ? ChatMessageType.Radio : ChatMessageType.Default, - Character.Controlled); - var headset = GetHeadset(Character.Controlled, true); - if (headset != null && headset.CanTransmit()) - { - headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sendToChat: false); - } - } - textbox.Deselect(); - textbox.Text = ""; - return true; - } - }; - - chatBox.InputBox.OnTextChanged += chatBox.TypingChatMessage; - } - - var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null); - reportButtonFrame = new GUILayoutGroup(new RectTransform( - new Point((HUDLayoutSettings.CrewArea.Height - (int)((reports.Count - 1) * 5 * GUI.Scale)) / reports.Count, HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform)) - { - AbsoluteSpacing = (int)(5 * GUI.Scale), - UserData = "reportbuttons", - CanBeFocused = false - }; - - //report buttons - foreach (Order order in reports) - { - if (!order.TargetAllCharacters || order.SymbolSprite == null) continue; - var btn = new GUIButton(new RectTransform(new Point(reportButtonFrame.Rect.Width), reportButtonFrame.RectTransform), style: null) - { - OnClicked = (GUIButton button, object userData) => - { - if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false; - SetCharacterOrder(null, order, null, Character.Controlled); - HumanAIController.PropagateHullSafety(Character.Controlled, Character.Controlled.CurrentHull); - return true; - }, - UserData = order, - ToolTip = order.Name - }; - - new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") - { - Color = Color.Red * 0.8f, - HoverColor = Color.Red * 1.0f, - PressedColor = Color.Red * 0.6f, - UserData = "highlighted", - CanBeFocused = false, - Visible = false - }; - var characterInfo = new CharacterInfo(subElement); characterInfos.Add(characterInfo); foreach (XElement invElement in subElement.Elements()) diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs index e5c8ea551..5cd9780b0 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/ItemComponent.cs @@ -234,6 +234,85 @@ namespace Barotrauma.Items.Components private set; } + private bool useAlternativeLayout; + public bool UseAlternativeLayout + { + get { return useAlternativeLayout; } + set + { + if (AlternativeLayout != null) + { + if (value == useAlternativeLayout) { return; } + useAlternativeLayout = value; + if (useAlternativeLayout) + { + AlternativeLayout?.ApplyTo(GuiFrame.RectTransform); + } + else + { + DefaultLayout?.ApplyTo(GuiFrame.RectTransform); + } + } + } + + public void ApplyTo(RectTransform target) + { + if (RelativeOffset.HasValue) + { + target.RelativeOffset = RelativeOffset.Value; + } + else if (AbsoluteOffset.HasValue) + { + target.AbsoluteOffset = AbsoluteOffset.Value; + } + if (RelativeSize.HasValue) + { + target.RelativeSize = RelativeSize.Value; + } + else if (AbsoluteSize.HasValue) + { + target.NonScaledSize = AbsoluteSize.Value; + } + if (Anchor.HasValue) + { + target.Anchor = Anchor.Value; + } + if (Pivot.HasValue) + { + target.Pivot = Pivot.Value; + } + else + { + target.Pivot = RectTransform.MatchPivotToAnchor(target.Anchor); + } + target.RecalculateChildren(true, true); + } + } + + public GUIFrame GuiFrame { get; protected set; } + + [Serialize(false, false)] + public bool AllowUIOverlap + { + get; + set; + } + + private ItemComponent linkToUIComponent; + [Serialize("", false)] + public string LinkUIToComponent + { + get; + set; + } + + [Serialize(0, false)] + public int HudPriority + { + get; + private set; + } + private bool shouldMuffleLooping; private float lastMuffleCheckTime; private ItemSound loopingSound; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 4bc964d71..fc1696ce3 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -144,15 +144,10 @@ namespace Barotrauma private void CreateUI() { TopPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), GUI.Canvas) { MinSize = new Point(0, 35) }, "GUIFrameTop"); - - GUIFrame paddedTopPanel = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.55f), TopPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, -0.1f) }, style: null); - - var button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft), TextManager.Get("Back")) - { - OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu - }; - - button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.07f, 0.0f) }, TextManager.Get("OpenSubButton")) + GUIFrame paddedTopPanel = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.55f), TopPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, -0.1f) }, + style: null); + + var button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft), TextManager.Get("OpenSubButton")) { OnClicked = (GUIButton btn, object data) => { @@ -163,7 +158,7 @@ namespace Barotrauma } }; - button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.14f, 0.0f) }, TextManager.Get("SaveSubButton")) + button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.08f, 0.0f) }, TextManager.Get("SaveSubButton")) { OnClicked = (GUIButton btn, object data) => { @@ -174,13 +169,13 @@ namespace Barotrauma } }; - var nameLabel = new GUITextBlock(new RectTransform(new Vector2(0.1f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.21f, 0.0f) }, + var nameLabel = new GUITextBlock(new RectTransform(new Vector2(0.1f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.15f, 0.0f) }, "", font: GUI.LargeFont, textAlignment: Alignment.CenterLeft) { TextGetter = GetSubName }; - linkedSubBox = new GUIDropDown(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform) { RelativeOffset = new Vector2(0.385f, 0.0f) }, + linkedSubBox = new GUIDropDown(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform) { RelativeOffset = new Vector2(0.4f, 0.0f) }, TextManager.Get("AddSubButton"), elementCount: 20) { ToolTip = TextManager.Get("AddSubToolTip") @@ -284,7 +279,7 @@ namespace Barotrauma var paddedTab = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), EntityMenu.RectTransform, Anchor.Center), style: null); - var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedTab.RectTransform) { AbsoluteOffset = new Point(0, 10) }, isHorizontal: true) + var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedTab.RectTransform), isHorizontal: true) { Color = secondaryColor, Stretch = true, @@ -299,7 +294,7 @@ namespace Barotrauma OnClicked = (btn, userdata) => { ClearFilter(); entityFilterBox.Flash(Color.White); return true; } }; - var entityListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.85f), paddedTab.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.06f) }); + var entityListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.85f), paddedTab.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }); var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.1f), entityListHolder.RectTransform, Anchor.TopRight, Pivot.BottomRight), isHorizontal: true) @@ -861,8 +856,6 @@ namespace Barotrauma GUI.AddMessage(TextManager.Get("SubSavedNotification").Replace("[filepath]", Submarine.MainSub.FilePath), Color.Green); - Submarine.RefreshSavedSub(savePath); - linkedSubBox.ClearChildren(); foreach (Submarine sub in Submarine.SavedSubmarines) { @@ -2224,19 +2217,19 @@ namespace Barotrauma Sprite backgroundSprite = LevelGenerationParams.LevelParams.Find(l => l.BackgroundTopSprite != null).BackgroundTopSprite; - using (RenderTarget2D rt = new RenderTarget2D( - GameMain.Instance.GraphicsDevice, - width, height, false, SurfaceFormat.Color, DepthFormat.None)) - using (SpriteBatch spriteBatch = new SpriteBatch(GameMain.Instance.GraphicsDevice)) + Sprite backgroundSprite = LevelGenerationParams.LevelParams.Find(l => l.BackgroundTopSprite != null).BackgroundTopSprite; + if (backgroundSprite != null) { - GameMain.Instance.GraphicsDevice.SetRenderTarget(rt); - - if (backgroundSprite != null) - { - spriteBatch.Begin(); - backgroundSprite.Draw(spriteBatch, Vector2.Zero, new Color(0.025f, 0.075f, 0.131f, 1.0f)); - spriteBatch.End(); - } + spriteBatch.Begin(); + backgroundSprite.Draw(spriteBatch, Vector2.Zero, new Color(0.025f, 0.075f, 0.131f, 1.0f)); + spriteBatch.End(); + } + + spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, transform); + Submarine.Draw(spriteBatch, false); + Submarine.DrawFront(spriteBatch); + Submarine.DrawDamageable(spriteBatch, null); + spriteBatch.End(); spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, transform); Submarine.Draw(spriteBatch, false); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs index f5821b46b..495ba8a2f 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs @@ -293,13 +293,9 @@ namespace Barotrauma if (damage <= 0) { return; } if (attacker == null || attacker.IsDead || attacker.Removed) { - if (objectiveManager.CurrentOrder == null) - { - objectiveManager.GetObjective().Priority = 100; - } - return; + AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced)); } - if (IsFriendly(attacker)) + else if (IsFriendly(attacker)) { if (attacker.AnimController.Anim == Barotrauma.AnimController.Animation.CPR && attacker.SelectedCharacter == Character) { @@ -309,51 +305,50 @@ namespace Barotrauma } if (!attacker.IsRemotePlayer && Character.Controlled != attacker && attacker.AIController != null && attacker.AIController.Enabled) { - // Don't react to damage done by friendly ai, because we know that it's accidental - if (objectiveManager.CurrentOrder == null) - { - objectiveManager.GetObjective().Priority = 100; - } - return; - } - float currentVitality = Character.CharacterHealth.Vitality; - float dmgPercentage = damage / currentVitality * 100; - if (dmgPercentage < currentVitality / 10) - { - // Don't react to a minor amount of (accidental) dmg done by friendly characters - if (objectiveManager.CurrentOrder == null) - { - objectiveManager.GetObjective().Priority = 100; - } - } - if (ObjectiveManager.CurrentObjective is AIObjectiveCombat combatObjective) - { - if (combatObjective.Enemy != attacker) - { - // Replace the old objective with the new. - ObjectiveManager.Objectives.Remove(combatObjective); - objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker)); - } + // Don't retaliate on damage done by friendly ai, because we know that it's accidental + AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced)); } else { - objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker), Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced)); + float currentVitality = Character.CharacterHealth.Vitality; + float dmgPercentage = damage / currentVitality * 100; + if (dmgPercentage < currentVitality / 10) + { + // Don't retaliate on minor (accidental) dmg done by friendly characters + AddCombatObjective(AIObjectiveCombat.CombatMode.Retreat, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced)); + } + else + { + AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive, Rand.Range(0.5f, 1f, Rand.RandSync.Unsynced)); + } } } else + { + AddCombatObjective(AIObjectiveCombat.CombatMode.Defensive); + } + + void AddCombatObjective(AIObjectiveCombat.CombatMode mode, float delay = 0) { if (ObjectiveManager.CurrentObjective is AIObjectiveCombat combatObjective) { - if (combatObjective.Enemy != attacker) + if (combatObjective.Enemy != attacker || (combatObjective.Enemy == null && attacker == null)) { // Replace the old objective with the new. ObjectiveManager.Objectives.Remove(combatObjective); - objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker)); + objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode)); } } else { - objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker)); + if (delay > 0) + { + objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode), delay); + } + else + { + objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode)); + } } } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs index b6d020d2a..6b7dda849 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -47,38 +47,62 @@ namespace Barotrauma private float coolDownTimer; - public AIObjectiveCombat(Character character, Character enemy) : base(character, "") + public enum CombatMode + { + Defensive, + Offensive, // Not implemented + Retreat + } + + public CombatMode Mode { get; private set; } + + public AIObjectiveCombat(Character character, Character enemy, CombatMode mode) : base(character, "") { Enemy = enemy; coolDownTimer = CoolDown; HumanAIController.ObjectiveManager.GetObjective().Priority = 0; + Mode = mode; + if (Enemy == null) + { + Mode = CombatMode.Retreat; + } } protected override void Act(float deltaTime) { coolDownTimer -= deltaTime; - if (Weapon != null && character.Inventory.Items.Contains(_weapon)) + if (abandon) { return; } + switch (Mode) { - Weapon = null; - } - if (Weapon == null) - { - Weapon = GetWeapon(); - } - if (Weapon == null) - { - Escape(deltaTime); - } - else if (Equip(deltaTime)) - { - if (Reload(deltaTime)) - { - Attack(deltaTime); - } - } - if (!abandon) - { - Move(deltaTime); + case CombatMode.Defensive: + if (Weapon != null && character.Inventory.Items.Contains(_weapon)) + { + Weapon = null; + } + if (Weapon == null) + { + Weapon = GetWeapon(); + } + if (Weapon == null) + { + Mode = CombatMode.Retreat; + } + else if (Equip(deltaTime)) + { + if (Reload(deltaTime)) + { + Attack(deltaTime); + } + } + // When defensive, try to retreat to safety. TODO: in offsensive mode, engage the target + Retreat(deltaTime); + break; + case CombatMode.Retreat: + Retreat(deltaTime); + break; + case CombatMode.Offensive: + default: + throw new System.NotImplementedException(); } } @@ -140,20 +164,18 @@ namespace Barotrauma else { //couldn't equip the item, escape - Escape(deltaTime); + //Abandon(deltaTime); return false; } } return true; } - private void Move(float deltaTime) + private void Retreat(float deltaTime) { - // Retreat to safety - // TODO: aggressive behaviour, chasing? if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted)) { - retreatTarget = HumanAIController.ObjectiveManager.GetObjective().FindBestHull(); + retreatTarget = HumanAIController.ObjectiveManager.GetObjective().FindBestHull(new List() { character.CurrentHull }); } if (retreatTarget != null) { @@ -190,7 +212,7 @@ namespace Barotrauma } else if (!reloadWeaponObjective.CanBeCompleted) { - Escape(deltaTime); + Mode = CombatMode.Retreat; } else { @@ -249,16 +271,16 @@ namespace Barotrauma } } - private void Escape(float deltaTime) + private void Abandon(float deltaTime) { abandon = true; SteeringManager.Reset(); - HumanAIController.ObjectiveManager.GetObjective().Priority = 100; + //HumanAIController.ObjectiveManager.GetObjective().Priority = 100; } public override bool IsCompleted() { - bool completed = Enemy == null || Enemy.Removed || Enemy.IsDead || coolDownTimer <= 0; + bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || coolDownTimer <= 0; if (completed) { if (Weapon != null) @@ -270,7 +292,7 @@ namespace Barotrauma } public override bool CanBeCompleted => !abandon && (reloadWeaponObjective == null || reloadWeaponObjective.CanBeCompleted) && (retreatObjective == null || retreatObjective.CanBeCompleted); - public override float GetPriority(AIObjectiveManager objectiveManager) => Enemy == null || Enemy.Removed || Enemy.IsDead ? 0 : 100; + public override float GetPriority(AIObjectiveManager objectiveManager) => (Enemy != null && (Enemy.Removed || Enemy.IsDead)) ? 0 : 100; public override bool IsDuplicate(AIObjective otherObjective) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFire.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFire.cs index d07b4019d..f5965df98 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFire.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFire.cs @@ -86,7 +86,10 @@ namespace Barotrauma character.AIController.SteeringManager.Reset(); character.CursorPosition = fs.Position; - character.SetInput(InputType.Aim, false, true); + if (extinguisher.Item.RequireAimToUse) + { + character.SetInput(InputType.Aim, false, true); + } extinguisher.Use(deltaTime, character); if (!targetHull.FireSources.Contains(fs)) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs index 12c490f57..0b5032321 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs @@ -168,13 +168,14 @@ namespace Barotrauma } } - public Hull FindBestHull() + public Hull FindBestHull(IEnumerable ignoredHulls = null) { - Hull bestHull = character.CurrentHull; - float bestValue = currenthullSafety; + Hull bestHull = null; + float bestValue = 0; foreach (Hull hull in Hull.hullList) { if (hull.Submarine == null) { continue; } + if (ignoredHulls != null && ignoredHulls.Contains(hull)) { continue; } float hullSafety = 0; if (character.Submarine != null && SteeringManager == PathSteering) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs index 978fc07b4..c9210a753 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs @@ -64,6 +64,7 @@ namespace Barotrauma.Items.Components attack = new Attack(subElement, item.Name + ", MeleeWeapon"); } item.IsShootable = true; + // TODO: should define this in xml if we have melee weapons that don't require aim to use item.RequireAimToUse = true; } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs index 0f6f5a0fc..966bd5761 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs @@ -58,6 +58,7 @@ namespace Barotrauma.Items.Components : base(item, element) { item.IsShootable = true; + // TODO: should define this in xml if we have ranged weapons that don't require aim to use item.RequireAimToUse = true; } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index e3f8896ee..c4fcb94ec 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -80,6 +80,7 @@ namespace Barotrauma.Items.Components } } item.IsShootable = true; + // TODO: should define this in xml if we have repair tools that don't require aim to use item.RequireAimToUse = true; InitProjSpecific(element); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index 8db3d7475..9a91a2375 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -533,6 +533,25 @@ namespace Barotrauma { maxX = Math.Min(maxX, ruin.Area.X - 100.0f); } + else + { + maxX = Math.Min(maxX, ruin.Area.X - 100.0f); + } + } + + if (minX < 0.0f && maxX > Level.Loaded.Size.X) + { + //no walls found at either side, just use the initial spawnpos and hope for the best + } + else if (minX < 0) + { + //no wall found at the left side, spawn to the left from the right-side wall + spawnPos.X = maxX - minWidth - 100.0f + subDockingPortOffset; + } + else if (maxX > Level.Loaded.Size.X) + { + //no wall found at right side, spawn to the right from the left-side wall + spawnPos.X = minX + minWidth + 100.0f + subDockingPortOffset; } if (minX < 0.0f && maxX > Level.Loaded.Size.X)