(ac7ab10b0) Pass AIObjectiveManager reference in the constructors instead of methods so that we can always access it.

This commit is contained in:
Joonas Rikkonen
2019-05-16 05:14:20 +03:00
parent bec7aadfa9
commit 2ae54a01a5
40 changed files with 290 additions and 322 deletions
@@ -37,16 +37,16 @@ namespace Barotrauma
var currentOrder = ObjectiveManager.CurrentOrder; var currentOrder = ObjectiveManager.CurrentOrder;
if (currentOrder != null) if (currentOrder != null)
{ {
GUI.DrawString(spriteBatch, pos + textOffset, $"ORDER: {currentOrder.DebugTag} ({currentOrder.GetPriority(ObjectiveManager).FormatZeroDecimal()})", Color.White, Color.Black); GUI.DrawString(spriteBatch, pos + textOffset, $"ORDER: {currentOrder.DebugTag} ({currentOrder.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
} }
var currentObjective = ObjectiveManager.CurrentObjective; var currentObjective = ObjectiveManager.CurrentObjective;
if (currentObjective != null) if (currentObjective != null)
{ {
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.GetPriority(ObjectiveManager).FormatZeroDecimal()})", Color.White, Color.Black); GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
var subObjective = currentObjective.CurrentSubObjective; var subObjective = currentObjective.CurrentSubObjective;
if (subObjective != null) if (subObjective != null)
{ {
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.GetPriority(ObjectiveManager).FormatZeroDecimal()})", Color.White, Color.Black); GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
} }
} }
} }
@@ -175,6 +175,14 @@ namespace Barotrauma
} }
} }
partial void UpdateLimbLightSource(Limb limb)
{
if (limb.LightSource != null)
{
limb.LightSource.Enabled = enabled;
}
}
private bool wasFiring; private bool wasFiring;
/// <summary> /// <summary>
@@ -233,6 +233,12 @@ namespace Barotrauma
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 }; Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
Tag = tag; Tag = tag;
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, Anchor.Center) { IsFixedSize = false }, style: null);
GUI.Style.Apply(InnerFrame, "", this);
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
Tag = tag;
if (height == 0) if (height == 0)
{ {
string wrappedText = ToolBox.WrapText(text, Content.Rect.Width, GUI.Font); string wrappedText = ToolBox.WrapText(text, Content.Rect.Width, GUI.Font);
@@ -74,47 +74,12 @@ namespace Barotrauma
public CrewManager(XElement element, bool isSinglePlayer) public CrewManager(XElement element, bool isSinglePlayer)
: this(isSinglePlayer) : this(isSinglePlayer)
{ {
guiFrame = new GUIFrame(new RectTransform(Vector2.One, GUICanvas.Instance), null, Color.Transparent) if (!isSinglePlayer)
{ {
CanBeFocused = false DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
}; return;
}
Point scrollButtonSize = new Point((int)(200 * GUI.Scale), (int)(30 * GUI.Scale)); if (string.IsNullOrEmpty(text)) { return; }
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;
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);
var characterInfo = new CharacterInfo(subElement); var characterInfo = new CharacterInfo(subElement);
characterInfos.Add(characterInfo); characterInfos.Add(characterInfo);
@@ -125,66 +90,7 @@ namespace Barotrauma
break; break;
} }
} }
ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
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 img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite, scaleToFit: true)
{
Color = order.Color,
HoverColor = Color.Lerp(order.Color, Color.White, 0.5f),
ToolTip = order.Name
};
}
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
prevUIScale = GUI.Scale;
ToggleCrewAreaOpen = GameMain.Config.CrewMenuOpen;
}
#endregion
#region Character list management
public Rectangle GetCharacterListArea()
{
return characterListBox.Rect;
} }
partial void InitProjectSpecific() partial void InitProjectSpecific()
@@ -332,12 +238,27 @@ namespace Barotrauma
public IEnumerable<Character> GetCharacters() public IEnumerable<Character> GetCharacters()
{ {
return characters; if (character?.Inventory == null) return null;
var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent<WifiComponent>() != null);
if (radioItem == null) return null;
if (requireEquipped && !character.HasEquippedItem(radioItem)) return null;
return radioItem.GetComponent<WifiComponent>();
} }
public IEnumerable<CharacterInfo> GetCharacterInfos() public IEnumerable<CharacterInfo> GetCharacterInfos()
{ {
return characterInfos; if (GameMain.Client != null)
{
//let the server create random conversations in MP
return;
}
List<Character> 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) public void AddCharacter(Character character)
@@ -711,33 +632,9 @@ namespace Barotrauma
{ {
characterListBox.BarScroll = roundedPos; characterListBox.BarScroll = roundedPos;
} }
} soundIcon.Visible = !muted && !mutedLocally;
soundIconDisabled.Visible = muted || mutedLocally;
public void AddCharacterInfo(CharacterInfo characterInfo) soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally");
{
if (characterInfos.Contains(characterInfo))
{
DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace);
return;
}
characterInfos.Add(characterInfo);
}
/// <summary>
/// Remove the character from the crew (and crew menus).
/// </summary>
/// <param name="character">The character to remove</param>
/// <param name="removeInfo">If the character info is also removed, the character will not be visible in the round summary.</param>
public void RemoveCharacter(Character character, bool removeInfo = false)
{
if (character == null)
{
DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace);
return;
}
characters.Remove(character);
if (removeInfo) characterInfos.Remove(character.Info);
} }
private IEnumerable<object> KillCharacterAnim(GUIComponent component) private IEnumerable<object> KillCharacterAnim(GUIComponent component)
@@ -938,23 +835,19 @@ namespace Barotrauma
} }
} }
} }
//only one target (or an order with no particular targets), just show options
character.SetOrder(order, option, orderGiver, speak: orderGiver != character); else
if (IsSinglePlayer)
{ {
orderGiver?.Speak( orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas)
order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null); { AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) },
} isHorizontal: true, childAnchor: Anchor.BottomLeft)
else if (orderGiver != null)
{
OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver);
if (GameMain.Client != null)
{ {
GameMain.Client.SendChatMessage(msg); UserData = character,
} Stretch = true
} };
DisplayCharacterOrder(character, order); //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);
/// <summary> /// <summary>
/// Create the UI panel that's used to select the target and options for a given order /// Create the UI panel that's used to select the target and options for a given order
@@ -22,6 +22,8 @@ namespace Barotrauma
private GUILayoutGroup subPreviewContainer; private GUILayoutGroup subPreviewContainer;
private GUILayoutGroup subPreviewContainer;
private GUIButton loadGameButton; private GUIButton loadGameButton;
public Action<Submarine, string, string> StartNewGame; public Action<Submarine, string, string> StartNewGame;
@@ -1112,6 +1112,8 @@ namespace Barotrauma
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
//goes through all the AItargets, evaluates how preferable it is to attack the target, //goes through all the AItargets, evaluates how preferable it is to attack the target,
//whether the Character can see/hear the target and chooses the most preferable target within //whether the Character can see/hear the target and chooses the most preferable target within
//sight/hearing range //sight/hearing range
@@ -337,18 +337,18 @@ namespace Barotrauma
{ {
// Replace the old objective with the new. // Replace the old objective with the new.
ObjectiveManager.Objectives.Remove(combatObjective); ObjectiveManager.Objectives.Remove(combatObjective);
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode)); objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager));
} }
} }
else else
{ {
if (delay > 0) if (delay > 0)
{ {
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode), delay); objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager), delay);
} }
else else
{ {
objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode)); objectiveManager.AddObjective(new AIObjectiveCombat(Character, attacker, mode, objectiveManager));
} }
} }
} }
@@ -17,8 +17,10 @@ namespace Barotrauma
protected readonly List<AIObjective> subObjectives = new List<AIObjective>(); protected readonly List<AIObjective> subObjectives = new List<AIObjective>();
public float Priority { get; set; } public float Priority { get; set; }
public float PriorityModifier { get; private set; } public float PriorityModifier { get; private set; }
protected readonly Character character; public readonly Character character;
protected string option; public readonly AIObjectiveManager objectiveManager;
public string Option { get; protected set; }
protected bool abandon; protected bool abandon;
/// <summary> /// <summary>
@@ -37,15 +39,12 @@ namespace Barotrauma
protected IndoorsSteeringManager PathSteering => HumanAIController.PathSteering; protected IndoorsSteeringManager PathSteering => HumanAIController.PathSteering;
protected SteeringManager SteeringManager => HumanAIController.SteeringManager; protected SteeringManager SteeringManager => HumanAIController.SteeringManager;
public string Option public AIObjective(Character character, AIObjectiveManager objectiveManager, float priorityModifier, string option = null)
{
get { return option; }
}
public AIObjective(Character character, string option, float priorityModifier)
{ {
this.objectiveManager = objectiveManager;
this.character = character; this.character = character;
this.option = option; Option = option ?? string.Empty;
PriorityModifier = priorityModifier; PriorityModifier = priorityModifier;
#if DEBUG #if DEBUG
IsDuplicate(null); IsDuplicate(null);
@@ -100,22 +99,21 @@ namespace Barotrauma
public void AddSubObjective(AIObjective objective) public void AddSubObjective(AIObjective objective)
{ {
if (subObjectives.Any(o => o.IsDuplicate(objective))) return; if (subObjectives.Any(o => o.IsDuplicate(objective))) { return; }
subObjectives.Add(objective); subObjectives.Add(objective);
} }
public void SortSubObjectives(AIObjectiveManager objectiveManager) public void SortSubObjectives()
{ {
if (subObjectives.None()) { return; } if (subObjectives.None()) { return; }
subObjectives.Sort((x, y) => y.GetPriority(objectiveManager).CompareTo(x.GetPriority(objectiveManager))); subObjectives.Sort((x, y) => y.GetPriority().CompareTo(x.GetPriority()));
CurrentSubObjective = SubObjectives.First(); CurrentSubObjective = SubObjectives.First();
CurrentSubObjective.SortSubObjectives(objectiveManager); CurrentSubObjective.SortSubObjectives();
} }
public virtual float GetPriority(AIObjectiveManager objectiveManager) => Priority * PriorityModifier; public virtual float GetPriority() => Priority * PriorityModifier;
public virtual void Update(AIObjectiveManager objectiveManager, float deltaTime) public virtual void Update(float deltaTime)
{ {
var subObjective = objectiveManager.CurrentObjective?.CurrentSubObjective; var subObjective = objectiveManager.CurrentObjective?.CurrentSubObjective;
if (objectiveManager.CurrentOrder == this) if (objectiveManager.CurrentOrder == this)
@@ -127,7 +125,7 @@ namespace Barotrauma
Priority += Devotion * PriorityModifier * deltaTime; Priority += Devotion * PriorityModifier * deltaTime;
} }
Priority = MathHelper.Clamp(Priority, 0, 100); Priority = MathHelper.Clamp(Priority, 0, 100);
subObjectives.ForEach(so => so.Update(objectiveManager, deltaTime)); subObjectives.ForEach(so => so.Update(deltaTime));
} }
/// <summary> /// <summary>
@@ -10,7 +10,8 @@ namespace Barotrauma
public override string DebugTag => "charge batteries"; public override string DebugTag => "charge batteries";
private readonly IEnumerable<PowerContainer> batteryList; private readonly IEnumerable<PowerContainer> batteryList;
public AIObjectiveChargeBatteries(Character character, string option) : base(character, option) public AIObjectiveChargeBatteries(Character character, AIObjectiveManager objectiveManager, string option, float priorityModifier)
: base(character, objectiveManager, priorityModifier, option)
{ {
batteryList = Item.ItemList.Select(i => i.GetComponent<PowerContainer>()).Where(b => b != null); batteryList = Item.ItemList.Select(i => i.GetComponent<PowerContainer>()).Where(b => b != null);
} }
@@ -23,15 +24,10 @@ namespace Barotrauma
protected override void FindTargets() protected override void FindTargets()
{ {
base.FindTargets(); base.FindTargets();
if (targets.None()) if (targets.None() && objectiveManager.CurrentOrder == this)
{ {
character.Speak(TextManager.Get("DialogNoBatteries"), null, 4.0f, "nobatteries", 10.0f); character.Speak(TextManager.Get("DialogNoBatteries"), null, 4.0f, "nobatteries", 10.0f);
} }
else
{
// Sorting should be handled by the objective manager, because the targets should be subobjectives.
//targets.Sort((x, y) => x.ChargePercentage.CompareTo(y.ChargePercentage));
}
} }
protected override bool Filter(PowerContainer battery) protected override bool Filter(PowerContainer battery)
@@ -45,6 +41,8 @@ namespace Barotrauma
protected override float TargetEvaluation() => targets.Max(t => 100 - t.ChargePercentage); protected override float TargetEvaluation() => targets.Max(t => 100 - t.ChargePercentage);
protected override IEnumerable<PowerContainer> GetList() => batteryList; protected override IEnumerable<PowerContainer> GetList() => batteryList;
protected override AIObjective ObjectiveConstructor(PowerContainer battery) => new AIObjectiveOperateItem(battery, character, Option, false, priorityModifier: PriorityModifier) { IsLoop = true };
protected override AIObjective ObjectiveConstructor(PowerContainer battery)
=> new AIObjectiveOperateItem(battery, character, objectiveManager, Option, false, priorityModifier: PriorityModifier) { IsLoop = true };
} }
} }
@@ -58,11 +58,12 @@ namespace Barotrauma
public CombatMode Mode { get; private set; } public CombatMode Mode { get; private set; }
public AIObjectiveCombat(Character character, Character enemy, CombatMode mode, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveCombat(Character character, Character enemy, CombatMode mode, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
Enemy = enemy; Enemy = enemy;
coolDownTimer = CoolDown; coolDownTimer = CoolDown;
findSafety = HumanAIController.ObjectiveManager.GetObjective<AIObjectiveFindSafety>(); findSafety = objectiveManager.GetObjective<AIObjectiveFindSafety>();
findSafety.Priority = 0; findSafety.Priority = 0;
findSafety.unreachable.Clear(); findSafety.unreachable.Clear();
Mode = mode; Mode = mode;
@@ -185,7 +186,7 @@ namespace Barotrauma
{ {
if (retreatObjective == null || retreatObjective.Target != retreatTarget) if (retreatObjective == null || retreatObjective.Target != retreatTarget)
{ {
retreatObjective = new AIObjectiveGoTo(retreatTarget, character, false, true); retreatObjective = new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true);
} }
retreatObjective.TryComplete(deltaTime); retreatObjective.TryComplete(deltaTime);
} }
@@ -203,7 +204,7 @@ namespace Barotrauma
{ {
if (reloadWeaponObjective == null) if (reloadWeaponObjective == null)
{ {
reloadWeaponObjective = new AIObjectiveContainItem(character, requiredItem.Identifiers, Weapon.GetComponent<ItemContainer>()); reloadWeaponObjective = new AIObjectiveContainItem(character, requiredItem.Identifiers, Weapon.GetComponent<ItemContainer>(), objectiveManager);
} }
} }
} }
@@ -297,7 +298,7 @@ namespace Barotrauma
} }
public override bool CanBeCompleted => !abandon && (reloadWeaponObjective == null || reloadWeaponObjective.CanBeCompleted) && (retreatObjective == null || retreatObjective.CanBeCompleted); 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 : Math.Min(100 * PriorityModifier, 100); public override float GetPriority() => (Enemy != null && (Enemy.Removed || Enemy.IsDead)) ? 0 : Math.Min(100 * PriorityModifier, 100);
public override bool IsDuplicate(AIObjective otherObjective) public override bool IsDuplicate(AIObjective otherObjective)
{ {
@@ -27,7 +27,11 @@ namespace Barotrauma
public AIObjectiveContainItem(Character character, string itemIdentifier, ItemContainer container, float priorityModifier = 1) : this(character, new string[] { itemIdentifier }, container, priorityModifier) { } public AIObjectiveContainItem(Character character, string itemIdentifier, ItemContainer container, float priorityModifier = 1) : this(character, new string[] { itemIdentifier }, container, priorityModifier) { }
public AIObjectiveContainItem(Character character, string[] itemIdentifiers, ItemContainer container, float priorityModifier = 1) : base (character, "", priorityModifier) public AIObjectiveContainItem(Character character, string itemIdentifier, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: this(character, new string[] { itemIdentifier }, container, objectiveManager, priorityModifier) { }
public AIObjectiveContainItem(Character character, string[] itemIdentifiers, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base (character, objectiveManager, priorityModifier)
{ {
this.itemIdentifiers = itemIdentifiers; this.itemIdentifiers = itemIdentifiers;
for (int i = 0; i < itemIdentifiers.Length; i++) for (int i = 0; i < itemIdentifiers.Length; i++)
@@ -64,7 +68,7 @@ namespace Barotrauma
} }
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (objectiveManager.CurrentOrder == this) if (objectiveManager.CurrentOrder == this)
{ {
@@ -88,7 +92,7 @@ namespace Barotrauma
if (itemToContain == null) if (itemToContain == null)
{ {
getItemObjective = new AIObjectiveGetItem(character, itemIdentifiers) getItemObjective = new AIObjectiveGetItem(character, itemIdentifiers, objectiveManager)
{ {
GetItemPriority = GetItemPriority, GetItemPriority = GetItemPriority,
ignoredContainerIdentifiers = ignoredContainerIdentifiers ignoredContainerIdentifiers = ignoredContainerIdentifiers
@@ -111,7 +115,7 @@ namespace Barotrauma
{ {
if (container.Item.CurrentHull != character.CurrentHull || (Vector2.Distance(character.Position, container.Item.Position) > container.Item.InteractDistance && !container.Item.IsInsideTrigger(character.WorldPosition))) if (container.Item.CurrentHull != character.CurrentHull || (Vector2.Distance(character.Position, container.Item.Position) > container.Item.InteractDistance && !container.Item.IsInsideTrigger(character.WorldPosition)))
{ {
goToObjective = new AIObjectiveGoTo(container.Item, character); goToObjective = new AIObjectiveGoTo(container.Item, character, objectiveManager);
AddSubObjective(goToObjective); AddSubObjective(goToObjective);
return; return;
} }
@@ -21,16 +21,19 @@ namespace Barotrauma
private AIObjectiveGoTo goToObjective; private AIObjectiveGoTo goToObjective;
private Item targetItem; private Item targetItem;
public AIObjectiveDecontainItem(Character character, Item targetItem, ItemContainer container, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveDecontainItem(Character character, Item targetItem, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
this.targetItem = targetItem; this.targetItem = targetItem;
this.container = container; this.container = container;
} }
public AIObjectiveDecontainItem(Character character, string itemIdentifier, ItemContainer container, float priorityModifier = 1) : this(character, new string[] { itemIdentifier }, container, priorityModifier) { } public AIObjectiveDecontainItem(Character character, string itemIdentifier, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: this(character, new string[] { itemIdentifier }, container, objectiveManager, priorityModifier) { }
public AIObjectiveDecontainItem(Character character, string[] itemIdentifiers, ItemContainer container, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveDecontainItem(Character character, string[] itemIdentifiers, ItemContainer container, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
this.itemIdentifiers = itemIdentifiers; this.itemIdentifiers = itemIdentifiers;
for (int i = 0; i < itemIdentifiers.Length; i++) for (int i = 0; i < itemIdentifiers.Length; i++)
@@ -59,7 +62,7 @@ namespace Barotrauma
} }
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (objectiveManager.CurrentOrder == this) if (objectiveManager.CurrentOrder == this)
{ {
@@ -103,7 +106,7 @@ namespace Barotrauma
if (Vector2.Distance(character.Position, container.Item.Position) > container.Item.InteractDistance if (Vector2.Distance(character.Position, container.Item.Position) > container.Item.InteractDistance
&& !container.Item.IsInsideTrigger(character.WorldPosition)) && !container.Item.IsInsideTrigger(character.WorldPosition))
{ {
goToObjective = new AIObjectiveGoTo(container.Item, character); goToObjective = new AIObjectiveGoTo(container.Item, character, objectiveManager);
AddSubObjective(goToObjective); AddSubObjective(goToObjective);
return; return;
} }
@@ -20,12 +20,13 @@ namespace Barotrauma
private float useExtinquisherTimer; private float useExtinquisherTimer;
public AIObjectiveExtinguishFire(Character character, Hull targetHull, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveExtinguishFire(Character character, Hull targetHull, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
this.targetHull = targetHull; this.targetHull = targetHull;
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; } if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; }
// Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally) // Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally)
@@ -61,7 +62,7 @@ namespace Barotrauma
if (getExtinguisherObjective == null) if (getExtinguisherObjective == null)
{ {
character.Speak(TextManager.Get("DialogFindExtinguisher"), null, 2.0f, "findextinguisher", 30.0f); character.Speak(TextManager.Get("DialogFindExtinguisher"), null, 2.0f, "findextinguisher", 30.0f);
getExtinguisherObjective = new AIObjectiveGetItem(character, "extinguisher", true); getExtinguisherObjective = new AIObjectiveGetItem(character, "extinguisher", objectiveManager, equip: true);
} }
else else
{ {
@@ -105,7 +106,7 @@ namespace Barotrauma
//go to the first firesource //go to the first firesource
if (gotoObjective == null || !gotoObjective.CanBeCompleted || gotoObjective.IsCompleted()) if (gotoObjective == null || !gotoObjective.CanBeCompleted || gotoObjective.IsCompleted())
{ {
gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(fs.Position), character); gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(fs.Position), character, objectiveManager);
} }
else else
{ {
@@ -10,14 +10,14 @@ namespace Barotrauma
public override bool ForceRun => true; public override bool ForceRun => true;
public override bool KeepDivingGearOn => true; public override bool KeepDivingGearOn => true;
public AIObjectiveExtinguishFires(Character character, float priorityModifier = 1) : base(character, "", priorityModifier) { } public AIObjectiveExtinguishFires(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { }
protected override void FindTargets() protected override void FindTargets()
{ {
base.FindTargets(); base.FindTargets();
if (targets.None()) if (targets.None() && objectiveManager.CurrentOrder == this)
{ {
character?.Speak(TextManager.Get("DialogNoFire"), null, 3.0f, "nofire", 30.0f); character.Speak(TextManager.Get("DialogNoFire"), null, 3.0f, "nofire", 30.0f);
} }
} }
@@ -30,13 +30,13 @@ namespace Barotrauma
return true; return true;
} }
protected override float TargetEvaluation() => (HumanAIController.ObjectiveManager.CurrentObjective == this || HumanAIController.ObjectiveManager.CurrentOrder == this) ? 100 : targets.Sum(t => GetFireSeverity(t)); protected override float TargetEvaluation() => (objectiveManager.CurrentObjective == this || objectiveManager.CurrentOrder == this) ? 100 : targets.Sum(t => GetFireSeverity(t));
public static float GetFireSeverity(Hull hull) => hull.FireSources.Sum(fs => fs.Size.X); public static float GetFireSeverity(Hull hull) => hull.FireSources.Sum(fs => fs.Size.X);
public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveExtinguishFires; public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveExtinguishFires;
protected override IEnumerable<Hull> GetList() => Hull.hullList; protected override IEnumerable<Hull> GetList() => Hull.hullList;
protected override AIObjective ObjectiveConstructor(Hull target) => new AIObjectiveExtinguishFire(character, target, PriorityModifier); protected override AIObjective ObjectiveConstructor(Hull target) => new AIObjectiveExtinguishFire(character, target, objectiveManager, PriorityModifier);
} }
} }
@@ -29,7 +29,7 @@ namespace Barotrauma
return false; return false;
} }
public AIObjectiveFindDivingGear(Character character, bool needDivingSuit, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveFindDivingGear(Character character, bool needDivingSuit, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier)
{ {
gearTag = needDivingSuit ? "divingsuit" : "diving"; gearTag = needDivingSuit ? "divingsuit" : "diving";
} }
@@ -43,7 +43,7 @@ namespace Barotrauma
if (!(subObjective is AIObjectiveGetItem)) if (!(subObjective is AIObjectiveGetItem))
{ {
character.Speak(TextManager.Get("DialogGetDivingGear"), null, 0.0f, "getdivinggear", 30.0f); character.Speak(TextManager.Get("DialogGetDivingGear"), null, 0.0f, "getdivinggear", 30.0f);
subObjective = new AIObjectiveGetItem(character, gearTag, true); subObjective = new AIObjectiveGetItem(character, gearTag, objectiveManager, equip: true);
} }
} }
else else
@@ -67,7 +67,7 @@ namespace Barotrauma
if (!(subObjective is AIObjectiveContainItem) || subObjective.IsCompleted()) if (!(subObjective is AIObjectiveContainItem) || subObjective.IsCompleted())
{ {
character.Speak(TextManager.Get("DialogGetOxygenTank"), null, 0, "getoxygentank", 30.0f); character.Speak(TextManager.Get("DialogGetOxygenTank"), null, 0, "getoxygentank", 30.0f);
subObjective = new AIObjectiveContainItem(character, new string[] { "oxygentank", "oxygensource" }, item.GetComponent<ItemContainer>()); subObjective = new AIObjectiveContainItem(character, new string[] { "oxygentank", "oxygensource" }, item.GetComponent<ItemContainer>(), objectiveManager);
} }
} }
if (subObjective != null) if (subObjective != null)
@@ -77,7 +77,7 @@ namespace Barotrauma
} }
public override bool CanBeCompleted => subObjective == null || subObjective.CanBeCompleted; public override bool CanBeCompleted => subObjective == null || subObjective.CanBeCompleted;
public override float GetPriority(AIObjectiveManager objectiveManager) => MathHelper.Clamp(100 - character.OxygenAvailable, 0, 100); public override float GetPriority() => MathHelper.Clamp(100 - character.OxygenAvailable, 0, 100);
public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveFindDivingGear; public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveFindDivingGear;
} }
} }
@@ -27,7 +27,7 @@ namespace Barotrauma
private AIObjectiveGoTo goToObjective; private AIObjectiveGoTo goToObjective;
private AIObjectiveFindDivingGear divingGearObjective; private AIObjectiveFindDivingGear divingGearObjective;
public AIObjectiveFindSafety(Character character, float priorityModifier = 1) : base(character, "", priorityModifier) { } public AIObjectiveFindSafety(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { }
public override bool IsCompleted() => false; public override bool IsCompleted() => false;
public override bool CanBeCompleted => true; public override bool CanBeCompleted => true;
@@ -41,7 +41,7 @@ namespace Barotrauma
bool hasEquipment = needsDivingSuit ? HumanAIController.HasDivingSuit(character) : HumanAIController.HasDivingGear(character); bool hasEquipment = needsDivingSuit ? HumanAIController.HasDivingSuit(character) : HumanAIController.HasDivingGear(character);
if (!hasEquipment) if (!hasEquipment)
{ {
divingGearObjective = new AIObjectiveFindDivingGear(character, needsDivingSuit); divingGearObjective = new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager);
} }
} }
if (divingGearObjective != null) if (divingGearObjective != null)
@@ -94,7 +94,7 @@ namespace Barotrauma
if (goToObjective.Target != bestHull) if (goToObjective.Target != bestHull)
{ {
// If we need diving gear, we should already have it, if possible. // If we need diving gear, we should already have it, if possible.
goToObjective = new AIObjectiveGoTo(bestHull, character, getDivingGearIfNeeded: false) goToObjective = new AIObjectiveGoTo(bestHull, character, objectiveManager, getDivingGearIfNeeded: false)
{ {
AllowGoingOutside = HumanAIController.HasDivingSuit(character) AllowGoingOutside = HumanAIController.HasDivingSuit(character)
}; };
@@ -102,7 +102,7 @@ namespace Barotrauma
} }
else else
{ {
goToObjective = new AIObjectiveGoTo(bestHull, character, getDivingGearIfNeeded: false) goToObjective = new AIObjectiveGoTo(bestHull, character, objectiveManager, getDivingGearIfNeeded: false)
{ {
AllowGoingOutside = HumanAIController.HasDivingSuit(character) AllowGoingOutside = HumanAIController.HasDivingSuit(character)
}; };
@@ -255,7 +255,7 @@ namespace Barotrauma
return (otherObjective is AIObjectiveFindSafety); return (otherObjective is AIObjectiveFindSafety);
} }
public override void Update(AIObjectiveManager objectiveManager, float deltaTime) public override void Update(float deltaTime)
{ {
if (character.CurrentHull == null) if (character.CurrentHull == null)
{ {
@@ -24,7 +24,7 @@ namespace Barotrauma
get { return leak; } get { return leak; }
} }
public AIObjectiveFixLeak(Gap leak, Character character, float priorityModifier = 1) : base (character, "", priorityModifier) public AIObjectiveFixLeak(Gap leak, Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base (character, objectiveManager, priorityModifier)
{ {
this.leak = leak; this.leak = leak;
} }
@@ -36,7 +36,7 @@ namespace Barotrauma
public override bool CanBeCompleted => !abandon && base.CanBeCompleted; public override bool CanBeCompleted => !abandon && base.CanBeCompleted;
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (leak.Open == 0.0f) { return 0.0f; } if (leak.Open == 0.0f) { return 0.0f; }
// Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally) // Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally)
@@ -61,7 +61,7 @@ namespace Barotrauma
{ {
if (findDivingGear == null) if (findDivingGear == null)
{ {
findDivingGear = new AIObjectiveFindDivingGear(character, true); findDivingGear = new AIObjectiveFindDivingGear(character, true, objectiveManager);
AddSubObjective(findDivingGear); AddSubObjective(findDivingGear);
} }
else if (!findDivingGear.CanBeCompleted) else if (!findDivingGear.CanBeCompleted)
@@ -75,7 +75,7 @@ namespace Barotrauma
if (weldingTool == null) if (weldingTool == null)
{ {
AddSubObjective(new AIObjectiveGetItem(character, "weldingtool", true)); AddSubObjective(new AIObjectiveGetItem(character, "weldingtool", objectiveManager, true));
return; return;
} }
else else
@@ -86,7 +86,7 @@ namespace Barotrauma
var fuelTank = containedItems.FirstOrDefault(i => i.HasTag("weldingfueltank") && i.Condition > 0.0f); var fuelTank = containedItems.FirstOrDefault(i => i.HasTag("weldingfueltank") && i.Condition > 0.0f);
if (fuelTank == null) if (fuelTank == null)
{ {
AddSubObjective(new AIObjectiveContainItem(character, "weldingfueltank", weldingTool.GetComponent<ItemContainer>())); AddSubObjective(new AIObjectiveContainItem(character, "weldingfueltank", weldingTool.GetComponent<ItemContainer>(), objectiveManager));
return; return;
} }
} }
@@ -122,7 +122,7 @@ namespace Barotrauma
} }
else else
{ {
gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character) gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager)
{ {
CloseEnough = reach CloseEnough = reach
}; };
@@ -137,7 +137,7 @@ namespace Barotrauma
{ {
if (operateObjective == null) if (operateObjective == null)
{ {
operateObjective = new AIObjectiveOperateItem(repairTool, character, "", true, leak); operateObjective = new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: leak);
AddSubObjective(operateObjective); AddSubObjective(operateObjective);
} }
else if (!subObjectives.Contains(operateObjective)) else if (!subObjectives.Contains(operateObjective))
@@ -12,14 +12,12 @@ namespace Barotrauma
public override bool KeepDivingGearOn => true; public override bool KeepDivingGearOn => true;
public override bool ForceRun => true; public override bool ForceRun => true;
public AIObjectiveFixLeaks(Character character, float priorityModifier = 1) : base(character, "", priorityModifier) { } public AIObjectiveFixLeaks(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { }
protected override void FindTargets() protected override void FindTargets()
{ {
base.FindTargets(); base.FindTargets();
// Sorting should be handled by the objective manager, because the targets should be subobjectives. // TODO: Add a dialog when no leaks are found and the objective is an order
//targets.Sort((x, y) => GetLeakFixPriority(y).CompareTo(GetLeakFixPriority(x)));
// TODO: Add a dialog when no leaks are found.
} }
protected override bool Filter(Gap gap) protected override bool Filter(Gap gap)
@@ -46,6 +44,6 @@ namespace Barotrauma
public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveFixLeaks; public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveFixLeaks;
protected override float TargetEvaluation() => targets.Max(t => GetLeakSeverity(t)); protected override float TargetEvaluation() => targets.Max(t => GetLeakSeverity(t));
protected override IEnumerable<Gap> GetList() => Gap.GapList; protected override IEnumerable<Gap> GetList() => Gap.GapList;
protected override AIObjective ObjectiveConstructor(Gap gap) => new AIObjectiveFixLeak(gap, character, PriorityModifier); protected override AIObjective ObjectiveConstructor(Gap gap) => new AIObjectiveFixLeak(gap, character, objectiveManager, PriorityModifier);
} }
} }
@@ -27,7 +27,7 @@ namespace Barotrauma
private bool canBeCompleted = true; private bool canBeCompleted = true;
public override bool CanBeCompleted => canBeCompleted; public override bool CanBeCompleted => canBeCompleted;
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (objectiveManager.CurrentOrder == this) if (objectiveManager.CurrentOrder == this)
{ {
@@ -36,16 +36,19 @@ namespace Barotrauma
return 1.0f; return 1.0f;
} }
public AIObjectiveGetItem(Character character, Item targetItem, bool equip = false, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveGetItem(Character character, Item targetItem, AIObjectiveManager objectiveManager, bool equip = false, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
currSearchIndex = -1; currSearchIndex = -1;
this.equip = equip; this.equip = equip;
this.targetItem = targetItem; this.targetItem = targetItem;
} }
public AIObjectiveGetItem(Character character, string itemIdentifier, bool equip = false, float priorityModifier = 1) : this(character, new string[] { itemIdentifier }, equip, priorityModifier) { } public AIObjectiveGetItem(Character character, string itemIdentifier, AIObjectiveManager objectiveManager, bool equip = false, float priorityModifier = 1)
: this(character, new string[] { itemIdentifier }, objectiveManager, equip, priorityModifier) { }
public AIObjectiveGetItem(Character character, string[] itemIdentifiers, bool equip = false, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveGetItem(Character character, string[] itemIdentifiers, AIObjectiveManager objectiveManager, bool equip = false, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
currSearchIndex = -1; currSearchIndex = -1;
this.equip = equip; this.equip = equip;
@@ -99,7 +102,7 @@ namespace Barotrauma
FindTargetItem(); FindTargetItem();
if (targetItem == null || moveToTarget == null) if (targetItem == null || moveToTarget == null)
{ {
HumanAIController.ObjectiveManager.GetObjective<AIObjectiveIdle>().Wander(deltaTime); objectiveManager.GetObjective<AIObjectiveIdle>().Wander(deltaTime);
//SteeringManager.SteeringWander(); //SteeringManager.SteeringWander();
return; return;
} }
@@ -157,7 +160,7 @@ namespace Barotrauma
(itemIdentifiers != null && (itemIdentifiers.Contains("diving") || itemIdentifiers.Contains("divingsuit"))); (itemIdentifiers != null && (itemIdentifiers.Contains("diving") || itemIdentifiers.Contains("divingsuit")));
//don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear //don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear
goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear); goToObjective = new AIObjectiveGoTo(moveToTarget, character, objectiveManager, repeat: false, getDivingGearIfNeeded: !gettingDivingGear);
} }
goToObjective.TryComplete(deltaTime); goToObjective.TryComplete(deltaTime);
@@ -26,7 +26,7 @@ namespace Barotrauma
public bool AllowGoingOutside = false; public bool AllowGoingOutside = false;
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (FollowControlledCharacter && Character.Controlled == null) { return 0.0f; } if (FollowControlledCharacter && Character.Controlled == null) { return 0.0f; }
if (Target != null && Target.Removed) { return 0.0f; } if (Target != null && Target.Removed) { return 0.0f; }
@@ -68,7 +68,7 @@ namespace Barotrauma
#if DEBUG #if DEBUG
DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {(Target != null ? Target.ToString() : TargetPos.ToString())}", Color.Yellow); DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {(Target != null ? Target.ToString() : TargetPos.ToString())}", Color.Yellow);
#endif #endif
if (HumanAIController.ObjectiveManager.CurrentOrder != null) if (objectiveManager.CurrentOrder != null)
{ {
character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f); character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f);
} }
@@ -84,7 +84,8 @@ namespace Barotrauma
public bool FollowControlledCharacter; public bool FollowControlledCharacter;
public AIObjectiveGoTo(Entity target, Character character, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1) : base (character, "", priorityModifier) public AIObjectiveGoTo(Entity target, Character character, AIObjectiveManager objectiveManager, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1)
: base (character, objectiveManager, priorityModifier)
{ {
this.Target = target; this.Target = target;
this.repeat = repeat; this.repeat = repeat;
@@ -95,7 +96,8 @@ namespace Barotrauma
} }
public AIObjectiveGoTo(Vector2 simPos, Character character, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveGoTo(Vector2 simPos, Character character, AIObjectiveManager objectiveManager, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
this.targetPos = simPos; this.targetPos = simPos;
this.repeat = repeat; this.repeat = repeat;
@@ -171,7 +173,7 @@ namespace Barotrauma
{ {
if (findDivingGear == null) if (findDivingGear == null)
{ {
findDivingGear = new AIObjectiveFindDivingGear(character, true); findDivingGear = new AIObjectiveFindDivingGear(character, true, objectiveManager);
AddSubObjective(findDivingGear); AddSubObjective(findDivingGear);
} }
else if (!findDivingGear.CanBeCompleted) else if (!findDivingGear.CanBeCompleted)
@@ -29,7 +29,7 @@ namespace Barotrauma
private readonly List<Hull> targetHulls = new List<Hull>(20); private readonly List<Hull> targetHulls = new List<Hull>(20);
private readonly List<float> hullWeights = new List<float>(20); private readonly List<float> hullWeights = new List<float>(20);
public AIObjectiveIdle(Character character, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveIdle(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier)
{ {
standStillTimer = Rand.Range(-10.0f, 10.0f); standStillTimer = Rand.Range(-10.0f, 10.0f);
walkDuration = Rand.Range(0.0f, 10.0f); walkDuration = Rand.Range(0.0f, 10.0f);
@@ -40,10 +40,8 @@ namespace Barotrauma
public override bool IsLoop { get => true; set => throw new System.Exception("Trying to set the value for IsLoop from: " + System.Environment.StackTrace); } public override bool IsLoop { get => true; set => throw new System.Exception("Trying to set the value for IsLoop from: " + System.Environment.StackTrace); }
public override float GetPriority(AIObjectiveManager objectiveManager) // TODO: take the initiative into account
{ public override float GetPriority() => 1;
return 1.0f;
}
protected override void Act(float deltaTime) protected override void Act(float deltaTime)
{ {
@@ -17,7 +17,8 @@ namespace Barotrauma
protected virtual float IgnoreListClearInterval => 0; protected virtual float IgnoreListClearInterval => 0;
protected virtual float TargetUpdateInterval => 2; protected virtual float TargetUpdateInterval => 2;
public AIObjectiveLoop(Character character, string option, float priorityModifier = 1) : base(character, option, priorityModifier) public AIObjectiveLoop(Character character, AIObjectiveManager objectiveManager, float priorityModifier, string option = null)
: base(character, objectiveManager, priorityModifier, option)
{ {
Reset(); Reset();
} }
@@ -28,9 +29,9 @@ namespace Barotrauma
public override bool IsLoop { get => true; set => throw new System.Exception("Trying to set the value for IsLoop from: " + System.Environment.StackTrace); } public override bool IsLoop { get => true; set => throw new System.Exception("Trying to set the value for IsLoop from: " + System.Environment.StackTrace); }
public override void Update(AIObjectiveManager objectiveManager, float deltaTime) public override void Update(float deltaTime)
{ {
base.Update(objectiveManager, deltaTime); base.Update(deltaTime);
if (IgnoreListClearInterval > 0) if (IgnoreListClearInterval > 0)
{ {
if (ignoreListTimer > IgnoreListClearInterval) if (ignoreListTimer > IgnoreListClearInterval)
@@ -87,7 +88,7 @@ namespace Barotrauma
} }
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (character.Submarine == null) { return 0; } if (character.Submarine == null) { return 0; }
if (targets.None()) { return 0; } if (targets.None()) { return 0; }
@@ -51,8 +51,8 @@ namespace Barotrauma
public void CreateAutomaticObjectives() public void CreateAutomaticObjectives()
{ {
Objectives.Clear(); Objectives.Clear();
AddObjective(new AIObjectiveFindSafety(character)); AddObjective(new AIObjectiveFindSafety(character, this));
AddObjective(new AIObjectiveIdle(character)); AddObjective(new AIObjectiveIdle(character, this));
foreach (var automaticOrder in character.Info.Job.Prefab.AutomaticOrders) foreach (var automaticOrder in character.Info.Job.Prefab.AutomaticOrders)
{ {
var orderPrefab = Order.PrefabList.Find(o => o.AITag == automaticOrder.aiTag); var orderPrefab = Order.PrefabList.Find(o => o.AITag == automaticOrder.aiTag);
@@ -96,7 +96,7 @@ namespace Barotrauma
{ {
var previousObjective = CurrentObjective; var previousObjective = CurrentObjective;
var firstObjective = Objectives.FirstOrDefault(); var firstObjective = Objectives.FirstOrDefault();
if (CurrentOrder != null && firstObjective != null && CurrentOrder.GetPriority(this) > firstObjective.GetPriority(this)) if (CurrentOrder != null && firstObjective != null && CurrentOrder.GetPriority() > firstObjective.GetPriority())
{ {
CurrentObjective = CurrentOrder; CurrentObjective = CurrentOrder;
} }
@@ -113,12 +113,12 @@ namespace Barotrauma
public float GetCurrentPriority() public float GetCurrentPriority()
{ {
return CurrentObjective == null ? 0.0f : CurrentObjective.GetPriority(this); return CurrentObjective == null ? 0.0f : CurrentObjective.GetPriority();
} }
public void UpdateObjectives(float deltaTime) public void UpdateObjectives(float deltaTime)
{ {
CurrentOrder?.Update(this, deltaTime); CurrentOrder?.Update(deltaTime);
for (int i = 0; i < Objectives.Count; i++) for (int i = 0; i < Objectives.Count; i++)
{ {
var objective = Objectives[i]; var objective = Objectives[i];
@@ -138,7 +138,7 @@ namespace Barotrauma
} }
else else
{ {
objective.Update(this, deltaTime); objective.Update(deltaTime);
} }
} }
GetCurrentObjective(); GetCurrentObjective();
@@ -148,9 +148,9 @@ namespace Barotrauma
{ {
if (Objectives.Any()) if (Objectives.Any())
{ {
Objectives.Sort((x, y) => y.GetPriority(this).CompareTo(x.GetPriority(this))); Objectives.Sort((x, y) => y.GetPriority().CompareTo(x.GetPriority()));
} }
CurrentObjective?.SortSubObjectives(this); CurrentObjective?.SortSubObjectives();
} }
public void DoCurrentObjective(float deltaTime) public void DoCurrentObjective(float deltaTime)
@@ -181,7 +181,7 @@ namespace Barotrauma
switch (order.AITag.ToLowerInvariant()) switch (order.AITag.ToLowerInvariant())
{ {
case "follow": case "follow":
newObjective = new AIObjectiveGoTo(orderGiver, character, true, priorityModifier: priorityModifier) newObjective = new AIObjectiveGoTo(orderGiver, character, this, repeat: true, priorityModifier: priorityModifier)
{ {
CloseEnough = 1.5f, CloseEnough = 1.5f,
AllowGoingOutside = true, AllowGoingOutside = true,
@@ -190,38 +190,38 @@ namespace Barotrauma
}; };
break; break;
case "wait": case "wait":
newObjective = new AIObjectiveGoTo(character, character, true, priorityModifier: priorityModifier) newObjective = new AIObjectiveGoTo(character, character, this, repeat: true, priorityModifier: priorityModifier)
{ {
AllowGoingOutside = true AllowGoingOutside = true
}; };
break; break;
case "fixleaks": case "fixleaks":
newObjective = new AIObjectiveFixLeaks(character, priorityModifier: priorityModifier); newObjective = new AIObjectiveFixLeaks(character, this, priorityModifier);
break; break;
case "chargebatteries": case "chargebatteries":
newObjective = new AIObjectiveChargeBatteries(character, option); newObjective = new AIObjectiveChargeBatteries(character, this, option, priorityModifier);
break; break;
case "rescue": case "rescue":
newObjective = new AIObjectiveRescueAll(character, priorityModifier: priorityModifier); newObjective = new AIObjectiveRescueAll(character, this, priorityModifier);
break; break;
case "repairsystems": case "repairsystems":
newObjective = new AIObjectiveRepairItems(character, priorityModifier: priorityModifier) { RequireAdequateSkills = option != "all" }; newObjective = new AIObjectiveRepairItems(character, this, priorityModifier) { RequireAdequateSkills = option != "all" };
break; break;
case "pumpwater": case "pumpwater":
newObjective = new AIObjectivePumpWater(character, option, priorityModifier: priorityModifier); newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier);
break; break;
case "extinguishfires": case "extinguishfires":
newObjective = new AIObjectiveExtinguishFires(character, priorityModifier: priorityModifier); newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier: priorityModifier);
break; break;
case "steer": case "steer":
var steering = (order?.TargetEntity as Item)?.GetComponent<Steering>(); var steering = (order?.TargetEntity as Item)?.GetComponent<Steering>();
if (steering != null) steering.PosToMaintain = steering.Item.Submarine?.WorldPosition; if (steering != null) steering.PosToMaintain = steering.Item.Submarine?.WorldPosition;
if (order.TargetItemComponent == null) { return null; } if (order.TargetItemComponent == null) { return null; }
newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, option, false, null, order.UseController, priorityModifier: priorityModifier) { IsLoop = true }; newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier) { IsLoop = true };
break; break;
default: default:
if (order.TargetItemComponent == null) { return null; } if (order.TargetItemComponent == null) { return null; }
newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, option, false, null, order.UseController, priorityModifier: priorityModifier) { IsLoop = true }; newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier) { IsLoop = true };
break; break;
} }
return newObjective; return newObjective;
@@ -42,7 +42,7 @@ namespace Barotrauma
public ItemComponent Component => component; public ItemComponent Component => component;
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; } if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; }
if (objectiveManager.CurrentOrder == this) if (objectiveManager.CurrentOrder == this)
@@ -55,7 +55,8 @@ namespace Barotrauma
return MathHelper.Clamp(value, 0, max); return MathHelper.Clamp(value, 0, max);
} }
public AIObjectiveOperateItem(ItemComponent item, Character character, string option, bool requireEquip, Entity operateTarget = null, bool useController = false, float priorityModifier = 1) : base (character, option, priorityModifier) public AIObjectiveOperateItem(ItemComponent item, Character character, AIObjectiveManager objectiveManager, string option, bool requireEquip, Entity operateTarget = null, bool useController = false, float priorityModifier = 1)
: base (character, objectiveManager, priorityModifier, option)
{ {
this.component = item ?? throw new System.ArgumentNullException("item", "Attempted to create an AIObjectiveOperateItem with a null target."); this.component = item ?? throw new System.ArgumentNullException("item", "Attempted to create an AIObjectiveOperateItem with a null target.");
this.requireEquip = requireEquip; this.requireEquip = requireEquip;
@@ -107,7 +108,7 @@ namespace Barotrauma
return; return;
} }
AddSubObjective(gotoObjective = new AIObjectiveGoTo(target.Item, character)); AddSubObjective(gotoObjective = new AIObjectiveGoTo(target.Item, character, objectiveManager));
} }
else else
{ {
@@ -119,7 +120,7 @@ namespace Barotrauma
} }
else if (!character.Inventory.Items.Contains(component.Item)) else if (!character.Inventory.Items.Contains(component.Item))
{ {
AddSubObjective(new AIObjectiveGetItem(character, component.Item, true)); AddSubObjective(new AIObjectiveGetItem(character, component.Item, objectiveManager, equip: true));
} }
else else
{ {
@@ -11,7 +11,8 @@ namespace Barotrauma
public override bool KeepDivingGearOn => true; public override bool KeepDivingGearOn => true;
private readonly IEnumerable<Pump> pumpList; private readonly IEnumerable<Pump> pumpList;
public AIObjectivePumpWater(Character character, string option, float priorityModifier = 1) : base(character, option, priorityModifier) public AIObjectivePumpWater(Character character, AIObjectiveManager objectiveManager, string option, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier, option)
{ {
pumpList = character.Submarine.GetItems(true).Select(i => i.GetComponent<Pump>()).Where(p => p != null); pumpList = character.Submarine.GetItems(true).Select(i => i.GetComponent<Pump>()).Where(p => p != null);
} }
@@ -21,8 +22,9 @@ namespace Barotrauma
//availablePumps = allPumps.Where(p => !p.Item.HasTag("ballast") && p.Item.Connections.None(c => c.IsPower && p.Item.GetConnectedComponentsRecursive<Steering>(c).None())).ToList(); //availablePumps = allPumps.Where(p => !p.Item.HasTag("ballast") && p.Item.Connections.None(c => c.IsPower && p.Item.GetConnectedComponentsRecursive<Steering>(c).None())).ToList();
protected override void FindTargets() protected override void FindTargets()
{ {
if (option == null) { return; } if (Option == null) { return; }
base.FindTargets(); base.FindTargets();
// TODO: add dialog when no targets found and the objective is an order
} }
protected override bool Filter(Pump pump) protected override bool Filter(Pump pump)
@@ -31,7 +33,7 @@ namespace Barotrauma
if (pump.Item.Submarine == null) { return false; } if (pump.Item.Submarine == null) { return false; }
if (pump.Item.Submarine.TeamID != character.TeamID) { return false; } if (pump.Item.Submarine.TeamID != character.TeamID) { return false; }
if (character.Submarine != null && !character.Submarine.IsEntityFoundOnThisSub(pump.Item, true)) { return false; } if (character.Submarine != null && !character.Submarine.IsEntityFoundOnThisSub(pump.Item, true)) { return false; }
if (option == "stoppumping") if (Option == "stoppumping")
{ {
if (!pump.IsActive || pump.FlowPercentage == 0.0f) { return false; } if (!pump.IsActive || pump.FlowPercentage == 0.0f) { return false; }
} }
@@ -43,7 +45,7 @@ namespace Barotrauma
return true; return true;
} }
protected override IEnumerable<Pump> GetList() => pumpList; protected override IEnumerable<Pump> GetList() => pumpList;
protected override AIObjective ObjectiveConstructor(Pump pump) => new AIObjectiveOperateItem(pump, character, Option, false) { IsLoop = true }; protected override AIObjective ObjectiveConstructor(Pump pump) => new AIObjectiveOperateItem(pump, character, objectiveManager, Option, false) { IsLoop = true };
protected override float TargetEvaluation() => targets.Max(t => MathHelper.Lerp(100, 0, t.CurrFlow / t.MaxFlow)); protected override float TargetEvaluation() => targets.Max(t => MathHelper.Lerp(100, 0, t.CurrFlow / t.MaxFlow));
} }
} }
@@ -19,12 +19,12 @@ namespace Barotrauma
private float previousCondition = -1; private float previousCondition = -1;
public AIObjectiveRepairItem(Character character, Item item, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveRepairItem(Character character, Item item, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier)
{ {
Item = item; Item = item;
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
// TODO: priority list? // TODO: priority list?
if (Item.Repairables.None()) { return 0; } if (Item.Repairables.None()) { return 0; }
@@ -79,7 +79,7 @@ namespace Barotrauma
{ {
foreach (RelatedItem requiredItem in kvp.Value) foreach (RelatedItem requiredItem in kvp.Value)
{ {
AddSubObjective(new AIObjectiveGetItem(character, requiredItem.Identifiers, true)); AddSubObjective(new AIObjectiveGetItem(character, requiredItem.Identifiers, objectiveManager, true));
} }
} }
return; return;
@@ -131,7 +131,7 @@ namespace Barotrauma
{ {
subObjectives.Remove(goToObjective); subObjectives.Remove(goToObjective);
} }
goToObjective = new AIObjectiveGoTo(Item, character); goToObjective = new AIObjectiveGoTo(Item, character, objectiveManager);
if (repairTool != null) if (repairTool != null)
{ {
//goToObjective.CloseEnough = (HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range)) * 0.75f; //goToObjective.CloseEnough = (HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range)) * 0.75f;
@@ -15,10 +15,16 @@ namespace Barotrauma
/// </summary> /// </summary>
public bool RequireAdequateSkills; public bool RequireAdequateSkills;
public AIObjectiveRepairItems(Character character, float priorityModifier = 1) : base(character, "", priorityModifier) { } public AIObjectiveRepairItems(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { }
public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveRepairItems repairItems && repairItems.RequireAdequateSkills == RequireAdequateSkills; public override bool IsDuplicate(AIObjective otherObjective) => otherObjective is AIObjectiveRepairItems repairItems && repairItems.RequireAdequateSkills == RequireAdequateSkills;
protected override void FindTargets()
{
base.FindTargets();
// TODO: display a dialog when no targets found and the objective is an order
}
protected override void CreateObjectives() protected override void CreateObjectives()
{ {
foreach (var item in targets) foreach (var item in targets)
@@ -69,6 +75,6 @@ namespace Barotrauma
protected override float TargetEvaluation() => targets.Max(t => 100 - t.ConditionPercentage); protected override float TargetEvaluation() => targets.Max(t => 100 - t.ConditionPercentage);
protected override IEnumerable<Item> GetList() => Item.ItemList; protected override IEnumerable<Item> GetList() => Item.ItemList;
protected override AIObjective ObjectiveConstructor(Item item) => new AIObjectiveRepairItem(character, item, PriorityModifier); protected override AIObjective ObjectiveConstructor(Item item) => new AIObjectiveRepairItem(character, item, objectiveManager, PriorityModifier);
} }
} }
@@ -37,7 +37,8 @@ namespace Barotrauma
} }
} }
public AIObjectiveRescue(Character character, Character targetCharacter, float priorityModifier = 1) : base(character, "", priorityModifier) public AIObjectiveRescue(Character character, Character targetCharacter, AIObjectiveManager objectiveManager, float priorityModifier = 1)
: base(character, objectiveManager, priorityModifier)
{ {
Debug.Assert(character != targetCharacter); Debug.Assert(character != targetCharacter);
this.targetCharacter = targetCharacter; this.targetCharacter = targetCharacter;
@@ -58,7 +59,7 @@ namespace Barotrauma
{ {
if (!character.CanInteractWith(targetCharacter)) if (!character.CanInteractWith(targetCharacter))
{ {
AddSubObjective(goToObjective = new AIObjectiveGoTo(targetCharacter, character)); AddSubObjective(goToObjective = new AIObjectiveGoTo(targetCharacter, character, objectiveManager));
} }
else else
{ {
@@ -67,7 +68,7 @@ namespace Barotrauma
} }
else else
{ {
AddSubObjective(new AIObjectiveFindSafety(character)); AddSubObjective(new AIObjectiveFindSafety(character, objectiveManager));
} }
return; return;
} }
@@ -75,7 +76,7 @@ namespace Barotrauma
//target not in water -> we can start applying treatment //target not in water -> we can start applying treatment
if (!character.CanInteractWith(targetCharacter)) if (!character.CanInteractWith(targetCharacter))
{ {
AddSubObjective(goToObjective = new AIObjectiveGoTo(targetCharacter, character)); AddSubObjective(goToObjective = new AIObjectiveGoTo(targetCharacter, character, objectiveManager));
} }
else else
{ {
@@ -186,7 +187,7 @@ namespace Barotrauma
} }
character.DeselectCharacter(); character.DeselectCharacter();
AddSubObjective(new AIObjectiveGetItem(character, suitableItemIdentifiers.ToArray(), true)); AddSubObjective(new AIObjectiveGetItem(character, suitableItemIdentifiers.ToArray(), objectiveManager, equip: true));
} }
character.AnimController.Anim = AnimController.Animation.CPR; character.AnimController.Anim = AnimController.Animation.CPR;
@@ -228,7 +229,7 @@ namespace Barotrauma
return isCompleted || targetCharacter.IsDead; return isCompleted || targetCharacter.IsDead;
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
// TODO: review // TODO: review
if (targetCharacter.AnimController.CurrentHull == null || targetCharacter.IsDead) { return 0.0f; } if (targetCharacter.AnimController.CurrentHull == null || targetCharacter.IsDead) { return 0.0f; }
@@ -15,7 +15,7 @@ namespace Barotrauma
private List<Character> rescueTargets; private List<Character> rescueTargets;
public AIObjectiveRescueAll(Character character, float priorityModifier = 1) : base (character, "", priorityModifier) public AIObjectiveRescueAll(Character character, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier)
{ {
rescueTargets = new List<Character>(); rescueTargets = new List<Character>();
} }
@@ -25,7 +25,7 @@ namespace Barotrauma
return true; return true;
} }
public override float GetPriority(AIObjectiveManager objectiveManager) public override float GetPriority()
{ {
// TODO: review // TODO: review
if (character.Submarine == null) { return 0; } if (character.Submarine == null) { return 0; }
@@ -56,7 +56,7 @@ namespace Barotrauma
{ {
foreach (Character target in rescueTargets) foreach (Character target in rescueTargets)
{ {
AddSubObjective(new AIObjectiveRescue(character, target)); AddSubObjective(new AIObjectiveRescue(character, target, objectiveManager));
} }
} }
@@ -2721,6 +2721,10 @@ namespace Barotrauma
GameMain.GameSession?.CrewManager?.RemoveCharacter(this); GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif #endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT #if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this); GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif #endif
@@ -173,8 +173,8 @@ namespace Barotrauma
var spawnedCharacter = Character.Create(characterInfo, watchmanSpawnpoint.WorldPosition, var spawnedCharacter = Character.Create(characterInfo, watchmanSpawnpoint.WorldPosition,
Level.Loaded.Seed + (outpost == Level.Loaded.StartOutpost ? "start" : "end")); Level.Loaded.Seed + (outpost == Level.Loaded.StartOutpost ? "start" : "end"));
InitializeWatchman(spawnedCharacter); InitializeWatchman(spawnedCharacter);
(spawnedCharacter.AIController as HumanAIController)?.ObjectiveManager.SetOrder( var objectiveManager = (spawnedCharacter.AIController as HumanAIController)?.ObjectiveManager;
new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, repeat: true, getDivingGearIfNeeded: false)); objectiveManager?.SetOrder(new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, objectiveManager, repeat: true, getDivingGearIfNeeded: false));
if (watchmanJob != null) if (watchmanJob != null)
{ {
spawnedCharacter.GiveJobItems(); spawnedCharacter.GiveJobItems();
@@ -126,6 +126,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()) if (targetItem.Prefab.DeconstructItems.Any())
{ {
inputContainer.Inventory.RemoveItem(targetItem); inputContainer.Inventory.RemoveItem(targetItem);
@@ -499,7 +499,7 @@ namespace Barotrauma.Items.Components
//load more fuel if the current maximum output is only 50% of the current load //load more fuel if the current maximum output is only 50% of the current load
if (NeedMoreFuel(minimumOutputRatio: 0.5f)) if (NeedMoreFuel(minimumOutputRatio: 0.5f))
{ {
var containFuelObjective = new AIObjectiveContainItem(character, new string[] { "fuelrod", "reactorfuel" }, item.GetComponent<ItemContainer>()) var containFuelObjective = new AIObjectiveContainItem(character, new string[] { "fuelrod", "reactorfuel" }, item.GetComponent<ItemContainer>(), objective.objectiveManager)
{ {
MinContainedAmount = item.ContainedItems.Count(i => i != null && i.Prefab.Identifier == "fuelrod" || i.HasTag("reactorfuel")) + 1, MinContainedAmount = item.ContainedItems.Count(i => i != null && i.Prefab.Identifier == "fuelrod" || i.HasTag("reactorfuel")) + 1,
GetItemPriority = (Item fuelItem) => GetItemPriority = (Item fuelItem) =>
@@ -588,6 +588,19 @@ namespace Barotrauma.Items.Components
return true; return true;
} }
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void Update(float deltaTime, Camera cam) public override void Update(float deltaTime, Camera cam)
{ {
networkUpdateTimer -= deltaTime; networkUpdateTimer -= deltaTime;
@@ -415,7 +415,7 @@ namespace Barotrauma.Items.Components
if (batteryToLoad.RechargeSpeed < batteryToLoad.MaxRechargeSpeed * 0.4f) if (batteryToLoad.RechargeSpeed < batteryToLoad.MaxRechargeSpeed * 0.4f)
{ {
objective.AddSubObjective(new AIObjectiveOperateItem(batteryToLoad, character, "", false)); objective.AddSubObjective(new AIObjectiveOperateItem(batteryToLoad, character, objective.objectiveManager, option: "", requireEquip: false));
return false; return false;
} }
} }
@@ -454,11 +454,11 @@ namespace Barotrauma.Items.Components
if (container.Inventory.Items[0] != null && container.Inventory.Items[0].Condition <= 0.0f) if (container.Inventory.Items[0] != null && container.Inventory.Items[0].Condition <= 0.0f)
{ {
var removeShellObjective = new AIObjectiveDecontainItem(character, container.Inventory.Items[0], container); var removeShellObjective = new AIObjectiveDecontainItem(character, container.Inventory.Items[0], container, objective.objectiveManager);
objective.AddSubObjective(removeShellObjective); objective.AddSubObjective(removeShellObjective);
} }
var containShellObjective = new AIObjectiveContainItem(character, container.ContainableItems[0].Identifiers[0], container); var containShellObjective = new AIObjectiveContainItem(character, container.ContainableItems[0].Identifiers[0], container, objective.objectiveManager);
character?.Speak(TextManager.Get("DialogLoadTurret").Replace("[itemname]", item.Name), null, 0.0f, "loadturret", 30.0f); character?.Speak(TextManager.Get("DialogLoadTurret").Replace("[itemname]", item.Name), null, 0.0f, "loadturret", 30.0f);
containShellObjective.MinContainedAmount = usableProjectileCount + 1; containShellObjective.MinContainedAmount = usableProjectileCount + 1;
containShellObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier }; containShellObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
@@ -1204,6 +1204,10 @@ namespace Barotrauma
{ {
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); 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); ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; } if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; }
@@ -21,7 +21,7 @@ namespace Barotrauma
protected Vector2 position; protected Vector2 position;
protected Vector2 size; protected Vector2 size;
private bool removed; protected bool removed;
protected bool removed; protected bool removed;
@@ -679,6 +679,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 public override Rectangle Rect
{ {
get get
@@ -162,6 +162,21 @@ namespace Barotrauma
get { return binding; } 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() public void SetState()
{ {
hit = binding.IsHit(); hit = binding.IsHit();
@@ -79,40 +79,6 @@ namespace Barotrauma
} }
public static string Get(string textTag, bool returnNull = false) public static string Get(string textTag, bool returnNull = false)
{
if (!textPacks.ContainsKey(Language))
{
DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
Language = "English";
if (!textPacks.ContainsKey(Language))
{
throw new Exception("No text packs available in English!");
}
}
}
public static string GetFormatted(string textTag, bool returnNull = false, params object[] args)
{
string text = Get(textTag, returnNull);
if (text == null || text.Length == 0)
{
if (returnNull)
{
return null;
}
else
{
DebugConsole.ThrowError("Text \"" + textTag + "\" not found.");
return textTag;
}
}
return string.Format(text, args);
}
// Format: ServerMessage.Identifier1/ServerMessage.Indentifier2~[variable1]=value~[variable2]=value
public static string GetServerMessage(string serverMessage)
{ {
if (!textPacks.ContainsKey(Language)) if (!textPacks.ContainsKey(Language))
{ {