From 1e200722aed04a671067c65974f4df203c925c48 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Thu, 16 May 2019 05:21:03 +0300 Subject: [PATCH] (81244db07) Implement AIObjectiveFightIntruders. --- .../Source/Characters/Animation/Ragdoll.cs | 26 ++ .../Source/GameSession/CrewManager.cs | 247 +++--------------- .../Source/Screens/CampaignSetupUI.cs | 2 + .../BarotraumaShared/SharedCode.projitems | 1 + .../Source/Characters/AI/HumanAIController.cs | 9 +- .../AI/Objectives/AIObjectiveCombat.cs | 8 +- .../Objectives/AIObjectiveExtinguishFires.cs | 2 +- .../Objectives/AIObjectiveFightIntruders.cs | 43 +++ .../AI/Objectives/AIObjectiveLoop.cs | 1 + .../AI/Objectives/AIObjectiveManager.cs | 13 +- .../Components/Machines/Deconstructor.cs | 19 ++ .../Items/Components/Machines/Steering.cs | 13 + .../BarotraumaShared/Source/Items/Item.cs | 4 + .../BarotraumaShared/Source/Map/Hull.cs | 19 ++ .../BarotraumaShared/Source/PlayerInput.cs | 15 ++ 15 files changed, 194 insertions(+), 228 deletions(-) create mode 100644 Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFightIntruders.cs diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index 8f9276859..bcf133b30 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -152,6 +152,32 @@ namespace Barotrauma } + if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120); + character.MemState.Clear(); + } + } + + partial void ImpactProjSpecific(float impact, Body body) + { + float volume = MathHelper.Clamp(impact - 3.0f, 0.5f, 1.0f); + + if (body.UserData is Limb limb && character.Stun <= 0f) + { + if (impact > 3.0f) { PlayImpactSound(limb); } + } + else if (body.UserData is Limb || body == Collider.FarseerBody) + { + if (!character.IsRemotePlayer && impact > ImpactTolerance) + { + SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider); + } + } + if (Character.Controlled == character) + { + GameMain.GameScreen.Cam.Shake = Math.Min(Math.Max(strongestImpact, GameMain.GameScreen.Cam.Shake), 3.0f); + } + } + if (character.MemState.Count < 1) return; overrideTargetMovement = Vector2.Zero; diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index c888d06cd..5300dbd54 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -74,17 +74,12 @@ namespace Barotrauma public CrewManager(XElement element, bool isSinglePlayer) : this(isSinglePlayer) { - if (GameMain.Client != null) + if (!isSinglePlayer) { - //let the server create random conversations in MP + DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace); return; } - List availableSpeakers = Character.CharacterList.FindAll(c => - c.AIController is HumanAIController && - !c.IsDead && - c.SpeechImpediment <= 100.0f); - pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); - } + if (string.IsNullOrEmpty(text)) { return; } var characterInfo = new CharacterInfo(subElement); characterInfos.Add(characterInfo); @@ -95,6 +90,7 @@ namespace Barotrauma break; } } + ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender)); } partial void InitProjectSpecific() @@ -242,24 +238,27 @@ namespace Barotrauma public IEnumerable GetCharacters() { - if (characterInfos.Contains(characterInfo)) - { - DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace); - return; - } + if (character?.Inventory == null) return null; - characterInfos.Add(characterInfo); + var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent() != null); + if (radioItem == null) return null; + if (requireEquipped && !character.HasEquippedItem(radioItem)) return null; + + return radioItem.GetComponent(); } public IEnumerable GetCharacterInfos() { - if (character == null) + if (GameMain.Client != null) { - DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace); + //let the server create random conversations in MP return; } - characters.Remove(character); - if (removeInfo) characterInfos.Remove(character.Info); + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); } public void AddCharacter(Character character) @@ -633,183 +632,9 @@ namespace Barotrauma { characterListBox.BarScroll = roundedPos; } - var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox") - { - UserData = character, - Color = frame.Color, - SelectedColor = frame.SelectedColor, - HoverColor = frame.HoverColor, - ToolTip = characterToolTip - }; - - var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, - "GUISoundIcon") - { - UserData = "soundicon", - CanBeFocused = false, - Visible = true - }; - soundIcon.Color = new Color(soundIcon.Color, 0.0f); - new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, - "GUISoundIconDisabled") - { - UserData = "soundicondisabled", - CanBeFocused = true, - Visible = false - }; - - if (isSinglePlayer) - { - characterArea.OnClicked = CharacterClicked; - } - else - { - characterArea.CanBeFocused = false; - characterArea.CanBeSelected = false; - } - - var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft), - onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) - { - CanBeFocused = false, - HoverColor = Color.White, - SelectedColor = Color.White, - ToolTip = characterToolTip - }; - - var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height), - characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) }, - character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true) - { - Color = frame.Color, - HoverColor = Color.Transparent, - SelectedColor = Color.Transparent, - CanBeFocused = false, - ToolTip = characterToolTip, - AutoScale = true - }; - - //---------------- order buttons ---------------- - - var orderButtonFrame = new GUILayoutGroup(new RectTransform(new Point(100, frame.Rect.Height), frame.RectTransform) - { AbsoluteOffset = new Point(characterInfoWidth + spacing, 0) }, - isHorizontal: true, childAnchor: Anchor.CenterLeft) - { - AbsoluteSpacing = (int)(10 * GUI.Scale), - UserData = "orderbuttons", - CanBeFocused = false - }; - - //listbox for holding the orders inappropriate for this character - //(so we can easily toggle their visibility) - var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null) - { - ScrollBarEnabled = false, - ScrollBarVisible = false, - Enabled = false, - Spacing = spacing, - ClampMouseRectToParent = false - }; - wrongOrderList.Content.ClampMouseRectToParent = false; - - for (int i = 0; i < orders.Count; i++) - { - var order = orders[i]; - if (order.TargetAllCharacters) continue; - - RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ? - wrongOrderList.Content.RectTransform : - orderButtonFrame.RectTransform; - - var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft), - style: null) - { - UserData = order - }; - - new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") - { - Color = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.8f, - HoverColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 1.0f, - PressedColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.6f, - UserData = "selected", - CanBeFocused = false, - Visible = false - }; - - var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite); - img.Scale = iconSize / (float)img.SourceRect.Width; - img.Color = Color.Lerp(order.Color, frame.Color, 0.5f); - img.ToolTip = order.Name; - img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f); - - btn.OnClicked += (GUIButton button, object userData) => - { - if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false; - - if (btn.GetChildByUserData("selected").Visible) - { - SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled); - } - else - { - if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1) - { - CreateOrderTargetFrame(button, character, order); - } - else - { - SetCharacterOrder(character, order, null, Character.Controlled); - } - } - return true; - }; - btn.UserData = order; - btn.ToolTip = order.Name; - - //divider between different groups of orders - if (i == correctOrderCount - 1 || i == correctOrderCount + neutralOrderCount - 1) - { - //TODO: divider sprite - new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton"); - } - } - - var toggleWrongOrderBtn = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), - "", style: "UIToggleButton") - { - UserData = "togglewrongorder", - CanBeFocused = false - }; - - wrongOrderList.RectTransform.NonScaledSize = new Point( - wrongOrderList.Content.Children.Sum(c => c.Rect.Width + wrongOrderList.Spacing), - wrongOrderList.RectTransform.NonScaledSize.Y); - wrongOrderList.RectTransform.SetAsLastChild(); - - new GUIFrame(new RectTransform(new Point( - wrongOrderList.Rect.Width - toggleWrongOrderBtn.Rect.Width - wrongOrderList.Spacing * 2, - wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), - style: null) - { - CanBeFocused = false - }; - - //scale to fit the content - orderButtonFrame.RectTransform.NonScaledSize = new Point( - orderButtonFrame.Children.Sum(c => c.Rect.Width + orderButtonFrame.AbsoluteSpacing), - orderButtonFrame.RectTransform.NonScaledSize.Y); - - frame.RectTransform.NonScaledSize = new Point( - characterInfoWidth + spacing + (orderButtonFrame.Rect.Width - wrongOrderList.Rect.Width), - frame.RectTransform.NonScaledSize.Y); - - characterListBox.RectTransform.NonScaledSize = new Point( - characterListBox.Content.Children.Max(c => c.Rect.Width) + wrongOrderList.Rect.Width, - characterListBox.RectTransform.NonScaledSize.Y); - characterListBox.Content.RectTransform.NonScaledSize = characterListBox.RectTransform.NonScaledSize; - characterListBox.UpdateScrollBarSize(); - return frame; + soundIcon.Visible = !muted && !mutedLocally; + soundIconDisabled.Visible = muted || mutedLocally; + soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); } private IEnumerable KillCharacterAnim(GUIComponent component) @@ -953,12 +778,6 @@ namespace Barotrauma } return; } - List availableSpeakers = Character.CharacterList.FindAll(c => - c.AIController is HumanAIController && - !c.IsDead && - c.SpeechImpediment <= 100.0f); - pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); - } character.SetOrder(order, option, orderGiver, speak: orderGiver != character); if (IsSinglePlayer) @@ -1016,23 +835,19 @@ namespace Barotrauma } } } - - character.SetOrder(order, option, orderGiver, speak: orderGiver != character); - if (IsSinglePlayer) + //only one target (or an order with no particular targets), just show options + else { - orderGiver?.Speak( - order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null); - } - else if (orderGiver != null) - { - OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver); - if (GameMain.Client != null) + orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas) + { AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) }, + isHorizontal: true, childAnchor: Anchor.BottomLeft) { - GameMain.Client.SendChatMessage(msg); - } - } - DisplayCharacterOrder(character, order); - } + UserData = character, + Stretch = true + }; + //line connecting the order button to the option buttons + //TODO: sprite + new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null); /// /// Create the UI panel that's used to select the target and options for a given order diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index e94318254..a0d807acb 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -66,6 +66,8 @@ namespace Barotrauma private GUILayoutGroup subPreviewContainer; + private GUILayoutGroup subPreviewContainer; + private GUIButton loadGameButton; public Action StartNewGame; diff --git a/Barotrauma/BarotraumaShared/SharedCode.projitems b/Barotrauma/BarotraumaShared/SharedCode.projitems index 8a4a85dc3..3ce8598e9 100644 --- a/Barotrauma/BarotraumaShared/SharedCode.projitems +++ b/Barotrauma/BarotraumaShared/SharedCode.projitems @@ -36,6 +36,7 @@ + diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs index 2a34cf629..d0317ef7d 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs @@ -189,7 +189,7 @@ namespace Barotrauma } } } - if (!(ObjectiveManager.CurrentOrder is AIObjectiveExtinguishFires) && !(ObjectiveManager.CurrentObjective is AIObjectiveExtinguishFires) && !(ObjectiveManager.CurrentObjective is AIObjectiveExtinguishFire)) + if (!ObjectiveManager.IsCurrentObjective() && !ObjectiveManager.IsCurrentObjective()) { var extinguisherItem = Character.Inventory.FindItemByIdentifier("extinguisher") ?? Character.Inventory.FindItemByTag("extinguisher"); if (extinguisherItem != null && Character.HasEquippedItem(extinguisherItem)) @@ -206,7 +206,7 @@ namespace Barotrauma { unequip = item.AllowedSlots.Contains(InvSlotType.RightHand | InvSlotType.LeftHand); } - else if (!(ObjectiveManager.CurrentObjective is AIObjectiveCombat)) + else if (!ObjectiveManager.IsCurrentObjective() && !ObjectiveManager.IsCurrentObjective()) { unequip = item.GetComponent() != null || item.GetComponent() != null; } @@ -315,6 +315,7 @@ namespace Barotrauma { float damage = attackResult.Damage; if (damage <= 0) { return; } + if (ObjectiveManager.CurrentObjective is AIObjectiveFightIntruders) { return; } if (attacker == null || attacker.IsDead || attacker.Removed) { // Ignore damage from falling etc that we shouldn't react to. @@ -468,10 +469,10 @@ namespace Barotrauma public float GetHullSafety(Hull hull) { if (hull == null) { return 0; } - bool ignoreFire = ObjectiveManager.CurrentObjective is AIObjectiveExtinguishFire || ObjectiveManager.CurrentObjective is AIObjectiveExtinguishFires || ObjectiveManager.CurrentOrder is AIObjectiveExtinguishFires; + bool ignoreFire = ObjectiveManager.IsCurrentObjective() || ObjectiveManager.IsCurrentObjective(); bool ignoreWater = HasDivingSuit(Character); bool ignoreOxygen = ignoreWater || HasDivingGear(Character); - bool ignoreEnemies = ObjectiveManager.CurrentObjective is AIObjectiveCombat || ObjectiveManager.CurrentOrder is AIObjectiveCombat; + bool ignoreEnemies = !ObjectiveManager.IsCurrentObjective(); return GetHullSafety(hull, Character, ignoreWater, ignoreOxygen, ignoreFire, ignoreEnemies); } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs index 1a09bb297..fcba33506 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -12,6 +12,7 @@ namespace Barotrauma { public override string DebugTag => "combat"; public override bool KeepDivingGearOn => true; + public bool useCoolDown = true; const float CoolDown = 10.0f; @@ -77,7 +78,10 @@ namespace Barotrauma protected override void Act(float deltaTime) { - coolDownTimer -= deltaTime; + if (useCoolDown) + { + coolDownTimer -= deltaTime; + } if (abandon) { return; } Arm(deltaTime); Move(deltaTime); @@ -373,7 +377,7 @@ namespace Barotrauma public override bool IsCompleted() { - bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || coolDownTimer <= 0; + bool completed = (Enemy != null && (Enemy.Removed || Enemy.IsDead)) || (useCoolDown && coolDownTimer <= 0); if (completed) { if (Weapon != null) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFires.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFires.cs index a6e1e53cf..33cdb2ccf 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFires.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveExtinguishFires.cs @@ -31,7 +31,7 @@ namespace Barotrauma return true; } - protected override float TargetEvaluation() => (objectiveManager.CurrentObjective == this || objectiveManager.CurrentOrder == this) ? 100 : targets.Sum(t => GetFireSeverity(t)); + protected override float TargetEvaluation() => objectiveManager.CurrentObjective == this ? 100 : targets.Sum(t => GetFireSeverity(t)); public static float GetFireSeverity(Hull hull) => hull.FireSources.Sum(fs => fs.Size.X); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFightIntruders.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFightIntruders.cs new file mode 100644 index 000000000..16245b39e --- /dev/null +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFightIntruders.cs @@ -0,0 +1,43 @@ +using Barotrauma.Items.Components; +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; + +namespace Barotrauma +{ + class AIObjectiveFightIntruders : AIObjectiveLoop + { + public override string DebugTag => "fight intruders"; + public override bool KeepDivingGearOn => true; + + public AIObjectiveFightIntruders(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) + : base(character, objectiveManager, priorityModifier) { } + + public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveFightIntruders && otherObjective.Option == Option; + + protected override void FindTargets() + { + if (Option == null) { return; } + base.FindTargets(); + // TODO: add dialog when no targets found and the objective is an order + } + + protected override bool Filter(Character target) + { + if (target == null || target.IsDead || target.Removed) { return false; } + if (HumanAIController == null || HumanAIController.IsFriendly(target)) { return false; } + if (target.Submarine != character.Submarine) { return false; } + if (target.CurrentHull == null && character.Submarine != null) { return false; } + return true; + } + protected override IEnumerable GetList() => Character.CharacterList; + + protected override AIObjective ObjectiveConstructor(Character target) => new AIObjectiveCombat(character, target, AIObjectiveCombat.CombatMode.Offensive, objectiveManager, PriorityModifier) { useCoolDown = false }; + protected override float TargetEvaluation() + { + // TODO: sorting criteria + return 90; + } + } +} diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs index 6a8a5755d..504a751eb 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveLoop.cs @@ -82,6 +82,7 @@ namespace Barotrauma public override void OnSelected() { + base.OnSelected(); if (HumanAIController.ObjectiveManager.CurrentOrder == this) { Reset(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs index 548a9fc0c..2035ad807 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -14,7 +14,7 @@ namespace Barotrauma // Constantly increases the priority of the selected objective, unless overridden public const float baseDevotion = 2; - public List Objectives { get; private set; } + public List Objectives { get; private set; } = new List(); private Character character; @@ -26,10 +26,11 @@ namespace Barotrauma public AIObjective CurrentOrder { get; private set; } public AIObjective CurrentObjective { get; private set; } + public bool IsCurrentObjective() where T : AIObjective => CurrentObjective is T; + public AIObjectiveManager(Character character) { this.character = character; - Objectives = new List(); CreateAutomaticObjectives(); } @@ -56,6 +57,7 @@ namespace Barotrauma foreach (var automaticOrder in character.Info.Job.Prefab.AutomaticOrders) { var orderPrefab = Order.PrefabList.Find(o => o.AITag == automaticOrder.aiTag); + if (orderPrefab == null) { throw new Exception("Could not find a matching prefab by ai tag: " + automaticOrder.aiTag); } // TODO: Similar code is used in CrewManager:815-> DRY var matchingItems = orderPrefab.ItemIdentifiers.Any() ? Item.ItemList.FindAll(it => orderPrefab.ItemIdentifiers.Contains(it.Prefab.Identifier) || it.HasTag(orderPrefab.ItemIdentifiers)) : @@ -174,8 +176,6 @@ namespace Barotrauma } } - // TODO: attack enemies : new AIObjectiveCombat(Character, attacker, AIObjectiveCombat.CombatMode.Offensive, objectiveManager); - public AIObjective CreateObjective(Order order, string option, Character orderGiver, float priorityModifier = 1) { if (order == null) { return null; } @@ -213,7 +213,10 @@ namespace Barotrauma newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier); break; case "extinguishfires": - newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier: priorityModifier); + newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier); + break; + case "fightintruders": + newObjective = new AIObjectiveFightIntruders(character, this, priorityModifier); break; case "steer": var steering = (order?.TargetEntity as Item)?.GetComponent(); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs index 5e0c16b68..8ecdcdec6 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs @@ -544,6 +544,25 @@ namespace Barotrauma.Items.Components } } + if (targetItem.Prefab.DeconstructItems.Any()) + { + inputContainer.Inventory.RemoveItem(targetItem); + Entity.Spawner.AddToRemoveQueue(targetItem); + MoveInputQueue(); + PutItemsToLinkedContainer(); + } + else + { + if (outputContainer.Inventory.Items.All(i => i != null)) + { + targetItem.Drop(dropper: null); + } + else + { + outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true); + } + } + if (targetItem.Prefab.DeconstructItems.Any()) { inputContainer.Inventory.RemoveItem(targetItem); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs index 636a4d351..9f39829d2 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -874,6 +874,19 @@ namespace Barotrauma.Items.Components return true; } + public override void OnItemLoaded() + { + sonar = item.GetComponent(); + } + + public override bool Select(Character character) + { + if (!CanBeSelected) return false; + + user = character; + return true; + } + public override void Update(float deltaTime, Camera cam) { networkUpdateTimer -= deltaTime; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index bf88462fd..ee611526f 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -1292,6 +1292,10 @@ namespace Barotrauma { ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); } + if (!broken) + { + ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); + } ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs index c533a8f74..ae59b864c 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs @@ -455,6 +455,25 @@ namespace Barotrauma } } + public string DisplayName + { + get; + private set; + } + + private string roomName; + [Editable, Serialize("", true, translationTextTag: "RoomName.")] + public string RoomName + { + get { return roomName; } + set + { + if (roomName == value) { return; } + roomName = value; + DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName; + } + } + public override Rectangle Rect { get diff --git a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs index e13028523..8ad826eea 100644 --- a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs +++ b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs @@ -162,6 +162,21 @@ namespace Barotrauma get { return binding; } } + public void SetState() + { + hit = binding.IsHit(); + if (hit) hitQueue = true; + + held = binding.IsDown(); + if (held) heldQueue = true; + } +#endif + + public KeyOrMouse State + { + get { return binding; } + } + public void SetState() { hit = binding.IsHit();