(89fea1963) Refactoring and fixing: - Remove relatively expensive HasAccessToPath calls. - Fix finding diving gear subobjective of goto main objective not checking if we need the gear. - Move the abandon checks from CanBeCompleted property under Act method and use the inherited property. Fixes incorrect results when the goto objective is not the active objective. - Improve the support for concurrent sub objectives.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -47,7 +48,7 @@ namespace Barotrauma
|
|||||||
if (currentObjective != null)
|
if (currentObjective != null)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.GetPriority().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.SubObjectives.FirstOrDefault();
|
||||||
if (subObjective != null)
|
if (subObjective != null)
|
||||||
{
|
{
|
||||||
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
|
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
|
||||||
|
|||||||
@@ -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;
|
if (character.MemState.Count < 1) return;
|
||||||
|
|
||||||
overrideTargetMovement = Vector2.Zero;
|
overrideTargetMovement = Vector2.Zero;
|
||||||
|
|||||||
@@ -74,17 +74,12 @@ namespace Barotrauma
|
|||||||
public CrewManager(XElement element, bool isSinglePlayer)
|
public CrewManager(XElement element, bool isSinglePlayer)
|
||||||
: this(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;
|
return;
|
||||||
}
|
}
|
||||||
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
|
if (string.IsNullOrEmpty(text)) { return; }
|
||||||
c.AIController is HumanAIController &&
|
|
||||||
!c.IsDead &&
|
|
||||||
c.SpeechImpediment <= 100.0f);
|
|
||||||
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
|
|
||||||
}
|
|
||||||
|
|
||||||
var characterInfo = new CharacterInfo(subElement);
|
var characterInfo = new CharacterInfo(subElement);
|
||||||
characterInfos.Add(characterInfo);
|
characterInfos.Add(characterInfo);
|
||||||
@@ -95,6 +90,7 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjectSpecific()
|
partial void InitProjectSpecific()
|
||||||
@@ -243,24 +239,27 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public IEnumerable<Character> GetCharacters()
|
public IEnumerable<Character> GetCharacters()
|
||||||
{
|
{
|
||||||
if (characterInfos.Contains(characterInfo))
|
if (character?.Inventory == null) return null;
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
characterInfos.Add(characterInfo);
|
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()
|
||||||
{
|
{
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
characters.Remove(character);
|
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
|
||||||
if (removeInfo) characterInfos.Remove(character.Info);
|
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)
|
||||||
@@ -634,183 +633,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
characterListBox.BarScroll = roundedPos;
|
characterListBox.BarScroll = roundedPos;
|
||||||
}
|
}
|
||||||
var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox")
|
soundIcon.Visible = !muted && !mutedLocally;
|
||||||
{
|
soundIconDisabled.Visible = muted || mutedLocally;
|
||||||
UserData = character,
|
soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally");
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<object> KillCharacterAnim(GUIComponent component)
|
private IEnumerable<object> KillCharacterAnim(GUIComponent component)
|
||||||
@@ -954,12 +779,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<Character> 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);
|
character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
|
||||||
if (IsSinglePlayer)
|
if (IsSinglePlayer)
|
||||||
@@ -1017,23 +836,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
|
||||||
|
|||||||
@@ -186,6 +186,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;
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the character has a diving mask in usable condition plus some oxygen.
|
/// Check whether the character has a diving mask in usable condition plus some oxygen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool HasDivingGear(Character character) => HasItem(character, "diving", "oxygensource");
|
public static bool HasDivingMask(Character character) => HasItem(character, "diving", "oxygensource");
|
||||||
|
|
||||||
public static bool HasItem(Character character, string tag, string containedTag, float conditionPercentage = 0)
|
public static bool HasItem(Character character, string tag, string containedTag, float conditionPercentage = 0)
|
||||||
{
|
{
|
||||||
@@ -528,7 +528,7 @@ namespace Barotrauma
|
|||||||
if (hull == null) { return 0; }
|
if (hull == null) { return 0; }
|
||||||
bool ignoreFire = ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFires>() || ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFire>();
|
bool ignoreFire = ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFires>() || ObjectiveManager.IsCurrentObjective<AIObjectiveExtinguishFire>();
|
||||||
bool ignoreWater = HasDivingSuit(Character);
|
bool ignoreWater = HasDivingSuit(Character);
|
||||||
bool ignoreOxygen = ignoreWater || HasDivingGear(Character);
|
bool ignoreOxygen = ignoreWater || HasDivingMask(Character);
|
||||||
bool ignoreEnemies = ObjectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>();
|
bool ignoreEnemies = ObjectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>();
|
||||||
return GetHullSafety(hull, Character, ignoreWater, ignoreOxygen, ignoreFire, ignoreEnemies);
|
return GetHullSafety(hull, Character, ignoreWater, ignoreOxygen, ignoreFire, ignoreEnemies);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool IsLoop { get; set; }
|
public virtual bool IsLoop { get; set; }
|
||||||
public IEnumerable<AIObjective> SubObjectives => subObjectives;
|
public IEnumerable<AIObjective> SubObjectives => subObjectives;
|
||||||
public AIObjective CurrentSubObjective { get; private set; }
|
|
||||||
|
|
||||||
public event Action Completed;
|
public event Action Completed;
|
||||||
|
|
||||||
@@ -90,11 +89,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subObjectives.Contains(CurrentSubObjective))
|
|
||||||
{
|
|
||||||
CurrentSubObjective = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (AIObjective objective in subObjectives)
|
foreach (AIObjective objective in subObjectives)
|
||||||
{
|
{
|
||||||
objective.TryComplete(deltaTime);
|
objective.TryComplete(deltaTime);
|
||||||
@@ -123,8 +117,14 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (subObjectives.None()) { return; }
|
if (subObjectives.None()) { return; }
|
||||||
subObjectives.Sort((x, y) => y.GetPriority().CompareTo(x.GetPriority()));
|
subObjectives.Sort((x, y) => y.GetPriority().CompareTo(x.GetPriority()));
|
||||||
CurrentSubObjective = SubObjectives.First();
|
if (ConcurrentObjectives)
|
||||||
CurrentSubObjective.SortSubObjectives();
|
{
|
||||||
|
subObjectives.ForEach(so => SortSubObjectives());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subObjectives.First().SortSubObjectives();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual float GetPriority() => Priority * PriorityModifier;
|
public virtual float GetPriority() => Priority * PriorityModifier;
|
||||||
@@ -137,10 +137,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (objectiveManager.WaitTimer <= 0)
|
else if (objectiveManager.WaitTimer <= 0)
|
||||||
{
|
{
|
||||||
var subObjective = objectiveManager.CurrentObjective?.CurrentSubObjective;
|
if (objectiveManager.CurrentObjective != null)
|
||||||
if ((objectiveManager.CurrentObjective == this || subObjective == this))
|
|
||||||
{
|
{
|
||||||
Priority += Devotion * PriorityModifier * deltaTime;
|
if (objectiveManager.CurrentObjective == this || objectiveManager.CurrentObjective.subObjectives.Any(so => so == this))
|
||||||
|
{
|
||||||
|
Priority += Devotion * PriorityModifier * deltaTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Priority = MathHelper.Clamp(Priority, 0, 100);
|
Priority = MathHelper.Clamp(Priority, 0, 100);
|
||||||
subObjectives.ForEach(so => so.Update(deltaTime));
|
subObjectives.ForEach(so => so.Update(deltaTime));
|
||||||
@@ -202,7 +204,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public virtual void OnSelected()
|
public virtual void OnSelected()
|
||||||
{
|
{
|
||||||
//SteeringManager.Reset();
|
// Should we reset steering here?
|
||||||
|
//if (!ConcurrentObjectives)
|
||||||
|
//{
|
||||||
|
// SteeringManager.Reset();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Reset() { }
|
public virtual void Reset() { }
|
||||||
|
|||||||
-1
@@ -27,7 +27,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override float GetPriority()
|
public override float GetPriority()
|
||||||
{
|
{
|
||||||
if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; }
|
|
||||||
if (Character.CharacterList.Any(c => c.CurrentHull == targetHull && !HumanAIController.IsFriendly(c))) { return 0; }
|
if (Character.CharacterList.Any(c => c.CurrentHull == targetHull && !HumanAIController.IsFriendly(c))) { 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)
|
||||||
float dist = Math.Abs(character.WorldPosition.X - targetHull.WorldPosition.X) + Math.Abs(character.WorldPosition.Y - targetHull.WorldPosition.Y) * 2.0f;
|
float dist = Math.Abs(character.WorldPosition.X - targetHull.WorldPosition.X) + Math.Abs(character.WorldPosition.Y - targetHull.WorldPosition.Y) * 2.0f;
|
||||||
|
|||||||
+44
-2
@@ -80,7 +80,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (needsDivingGear)
|
else if (needsDivingGear)
|
||||||
{
|
{
|
||||||
needsEquipment = !HumanAIController.HasDivingGear(character);
|
needsEquipment = !HumanAIController.HasDivingMask(character);
|
||||||
}
|
}
|
||||||
if (needsEquipment)
|
if (needsEquipment)
|
||||||
{
|
{
|
||||||
@@ -601,6 +601,49 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
character.AIController.SteeringManager.Reset();
|
character.AIController.SteeringManager.Reset();
|
||||||
}
|
}
|
||||||
|
if (goToObjective != null) { return; }
|
||||||
|
if (currentHull == null) { return; }
|
||||||
|
//goto objective doesn't exist (a safe hull not found, or a path to a safe hull not found)
|
||||||
|
// -> attempt to manually steer away from hazards
|
||||||
|
Vector2 escapeVel = Vector2.Zero;
|
||||||
|
foreach (FireSource fireSource in currentHull.FireSources)
|
||||||
|
{
|
||||||
|
Vector2 dir = character.Position - fireSource.Position;
|
||||||
|
float distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(fireSource.Position, character.Position), 0.1f, 10.0f);
|
||||||
|
escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier);
|
||||||
|
}
|
||||||
|
foreach (Character enemy in Character.CharacterList)
|
||||||
|
{
|
||||||
|
//don't run from friendly NPCs
|
||||||
|
if (enemy.TeamID == Character.TeamType.FriendlyNPC) { continue; }
|
||||||
|
//friendly NPCs don't run away from anything but characters controlled by EnemyAIController (= monsters)
|
||||||
|
if (character.TeamID == Character.TeamType.FriendlyNPC && !(enemy.AIController is EnemyAIController)) { continue; }
|
||||||
|
if (enemy.CurrentHull == currentHull && !enemy.IsDead && !enemy.IsUnconscious &&
|
||||||
|
(enemy.AIController is EnemyAIController || enemy.TeamID != character.TeamID))
|
||||||
|
{
|
||||||
|
Vector2 dir = character.Position - enemy.Position;
|
||||||
|
float distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(enemy.Position, character.Position), 0.1f, 10.0f);
|
||||||
|
escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (escapeVel != Vector2.Zero)
|
||||||
|
{
|
||||||
|
//only move if we haven't reached the edge of the room
|
||||||
|
if ((escapeVel.X < 0 && character.Position.X > currentHull.Rect.X + 50) ||
|
||||||
|
(escapeVel.X > 0 && character.Position.X < currentHull.Rect.Right - 50))
|
||||||
|
{
|
||||||
|
character.AIController.SteeringManager.SteeringManual(deltaTime, escapeVel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character.AnimController.TargetDir = escapeVel.X < 0.0f ? Direction.Right : Direction.Left;
|
||||||
|
character.AIController.SteeringManager.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character.AIController.SteeringManager.Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +677,6 @@ namespace Barotrauma
|
|||||||
unreachable.Add(hull);
|
unreachable.Add(hull);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!PathSteering.HasAccessToPath(path)) { continue; }
|
|
||||||
int unsafeNodes = path.Nodes.Count(n => n.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
|
int unsafeNodes = path.Nodes.Count(n => n.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
|
||||||
hullSafety /= 1 + unsafeNodes;
|
hullSafety /= 1 + unsafeNodes;
|
||||||
// If the target is not inside a friendly submarine, considerably reduce the hull safety.
|
// If the target is not inside a friendly submarine, considerably reduce the hull safety.
|
||||||
|
|||||||
@@ -346,6 +346,31 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
||||||
|
#endif
|
||||||
|
abandon = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Vector2 gapDiff = Leak.WorldPosition - character.WorldPosition;
|
||||||
|
// TODO: use the collider size/reach?
|
||||||
|
if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150)
|
||||||
|
{
|
||||||
|
HumanAIController.AnimController.Crouching = true;
|
||||||
|
}
|
||||||
|
float reach = ConvertUnits.ToSimUnits(repairTool.Range);
|
||||||
|
bool canOperate = ConvertUnits.ToSimUnits(gapDiff.Length()) < reach;
|
||||||
|
if (canOperate)
|
||||||
|
{
|
||||||
|
TryAddSubObjective(ref operateObjective, () => new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: Leak));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager) { CloseEnough = reach * 0.75f });
|
||||||
|
}
|
||||||
|
var repairTool = weldingTool.GetComponent<RepairTool>();
|
||||||
|
if (repairTool == null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool");
|
||||||
#endif
|
#endif
|
||||||
abandon = true;
|
abandon = true;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,9 +9,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public override string DebugTag => "go to";
|
public override string DebugTag => "go to";
|
||||||
|
|
||||||
const float checkAccessInterval = 1;
|
|
||||||
private float accessCheckTimer;
|
|
||||||
|
|
||||||
private AIObjectiveFindDivingGear findDivingGear;
|
private AIObjectiveFindDivingGear findDivingGear;
|
||||||
private Vector2 targetPos;
|
private Vector2 targetPos;
|
||||||
private bool repeat;
|
private bool repeat;
|
||||||
@@ -36,43 +33,6 @@ namespace Barotrauma
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanBeCompleted
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!abandon)
|
|
||||||
{
|
|
||||||
if (FollowControlledCharacter && Character.Controlled == null)
|
|
||||||
{
|
|
||||||
abandon = true;
|
|
||||||
}
|
|
||||||
else if (Target != null && Target.Removed)
|
|
||||||
{
|
|
||||||
abandon = true;
|
|
||||||
}
|
|
||||||
else if (!repeat && waitUntilPathUnreachable < 0)
|
|
||||||
{
|
|
||||||
if (SteeringManager == PathSteering && PathSteering.CurrentPath != null)
|
|
||||||
{
|
|
||||||
abandon = PathSteering.CurrentPath.Unreachable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (abandon)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {(Target != null ? Target.ToString() : TargetPos.ToString())}", Color.Yellow);
|
|
||||||
#endif
|
|
||||||
if (objectiveManager.CurrentOrder != null)
|
|
||||||
{
|
|
||||||
character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f);
|
|
||||||
}
|
|
||||||
character.AIController.SteeringManager.Reset();
|
|
||||||
}
|
|
||||||
return base.CanBeCompleted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Entity Target { get; private set; }
|
public Entity Target { get; private set; }
|
||||||
|
|
||||||
public Vector2 TargetPos => Target != null ? Target.SimPosition : targetPos;
|
public Vector2 TargetPos => Target != null ? Target.SimPosition : targetPos;
|
||||||
@@ -106,12 +66,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (FollowControlledCharacter)
|
if (FollowControlledCharacter)
|
||||||
{
|
{
|
||||||
if (Character.Controlled == null) { return; }
|
if (Character.Controlled == null)
|
||||||
|
{
|
||||||
|
abandon = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
Target = Character.Controlled;
|
Target = Character.Controlled;
|
||||||
}
|
}
|
||||||
if (Target == character)
|
if (Target == character)
|
||||||
{
|
{
|
||||||
character.AIController.SteeringManager.Reset();
|
character.AIController.SteeringManager.Reset();
|
||||||
|
abandon = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
waitUntilPathUnreachable -= deltaTime;
|
waitUntilPathUnreachable -= deltaTime;
|
||||||
@@ -119,7 +84,17 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
character.SelectedConstruction = null;
|
character.SelectedConstruction = null;
|
||||||
}
|
}
|
||||||
if (Target != null) { character.AIController.SelectTarget(Target.AiTarget); }
|
if (Target != null)
|
||||||
|
{
|
||||||
|
if (Target.Removed)
|
||||||
|
{
|
||||||
|
abandon = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character.AIController.SelectTarget(Target.AiTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
Vector2 currTargetPos = Vector2.Zero;
|
Vector2 currTargetPos = Vector2.Zero;
|
||||||
if (Target == null)
|
if (Target == null)
|
||||||
{
|
{
|
||||||
@@ -153,30 +128,46 @@ namespace Barotrauma
|
|||||||
if (isInside && targetIsOutside && !AllowGoingOutside)
|
if (isInside && targetIsOutside && !AllowGoingOutside)
|
||||||
{
|
{
|
||||||
abandon = true;
|
abandon = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (accessCheckTimer <= 0)
|
else if (!repeat && waitUntilPathUnreachable < 0)
|
||||||
{
|
{
|
||||||
accessCheckTimer = checkAccessInterval;
|
if (SteeringManager == PathSteering && PathSteering.CurrentPath != null)
|
||||||
if (insideSteering && !PathSteering.HasAccessToPath(PathSteering.CurrentPath))
|
|
||||||
{
|
{
|
||||||
abandon = true;
|
abandon = PathSteering.CurrentPath.Unreachable;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (abandon)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {(Target != null ? Target.ToString() : TargetPos.ToString())}", Color.Yellow);
|
||||||
|
#endif
|
||||||
|
if (objectiveManager.CurrentOrder != null)
|
||||||
|
{
|
||||||
|
character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f);
|
||||||
|
}
|
||||||
|
character.AIController.SteeringManager.Reset();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
accessCheckTimer -= deltaTime;
|
character.AIController.SteeringManager.SteeringSeek(currTargetPos);
|
||||||
}
|
if (getDivingGearIfNeeded)
|
||||||
character.AIController.SteeringManager.SteeringSeek(currTargetPos);
|
|
||||||
if (getDivingGearIfNeeded)
|
|
||||||
{
|
|
||||||
if (targetIsOutside ||
|
|
||||||
Target is Hull h && HumanAIController.NeedsDivingGear(h) ||
|
|
||||||
Target is Item i && HumanAIController.NeedsDivingGear(i.CurrentHull) ||
|
|
||||||
Target is Character c && HumanAIController.NeedsDivingGear(c.CurrentHull))
|
|
||||||
{
|
{
|
||||||
TryAddSubObjective(ref findDivingGear, () => new AIObjectiveFindDivingGear(character, true, objectiveManager));
|
var targetHull = Target is Hull h ? h : Target is Item i ? i.CurrentHull : Target is Character c ? c.CurrentHull : character.CurrentHull;
|
||||||
|
bool needsDivingGear = HumanAIController.NeedsDivingGear(targetHull);
|
||||||
|
bool needsDivingSuit = needsDivingGear && (targetIsOutside || targetHull.WaterPercentage > 90);
|
||||||
|
bool needsEquipment = false;
|
||||||
|
if (needsDivingSuit)
|
||||||
|
{
|
||||||
|
needsEquipment = !HumanAIController.HasDivingSuit(character);
|
||||||
|
}
|
||||||
|
else if (needsDivingGear)
|
||||||
|
{
|
||||||
|
needsEquipment = !HumanAIController.HasDivingMask(character);
|
||||||
|
}
|
||||||
|
if (needsEquipment)
|
||||||
|
{
|
||||||
|
TryAddSubObjective(ref findDivingGear, () => new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
if (objectiveManager.CurrentObjective == this)
|
||||||
|
{
|
||||||
|
if (randomTimer > 0)
|
||||||
|
{
|
||||||
|
randomTimer -= deltaTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetRandom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsCompleted() => false;
|
public override bool IsCompleted() => false;
|
||||||
public override bool CanBeCompleted => true;
|
public override bool CanBeCompleted => true;
|
||||||
|
|
||||||
@@ -142,10 +157,9 @@ namespace Barotrauma
|
|||||||
// Check that there is no unsafe or forbidden hulls on the way to the target
|
// Check that there is no unsafe or forbidden hulls on the way to the target
|
||||||
// Only do this when the current hull is ok, because otherwise would block all paths from the current hull to the target hull.
|
// Only do this when the current hull is ok, because otherwise would block all paths from the current hull to the target hull.
|
||||||
var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
|
var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
|
||||||
if (path.Unreachable ||
|
if (path.Unreachable ||
|
||||||
path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) ||
|
path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) ||
|
||||||
IsForbidden(n.CurrentHull)) ||
|
IsForbidden(n.CurrentHull)))
|
||||||
!PathSteering.HasAccessToPath(path))
|
|
||||||
{
|
{
|
||||||
//can't go to this room, remove it from the list and try another room next frame
|
//can't go to this room, remove it from the list and try another room next frame
|
||||||
int index = targetHulls.IndexOf(randomHull);
|
int index = targetHulls.IndexOf(randomHull);
|
||||||
|
|||||||
+4
-1
@@ -25,7 +25,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override float GetPriority()
|
public override float GetPriority()
|
||||||
{
|
{
|
||||||
if (goToObjective != null && !goToObjective.CanBeCompleted) { return 0; }
|
|
||||||
if (component.Item.ConditionPercentage <= 0) { return 0; }
|
if (component.Item.ConditionPercentage <= 0) { return 0; }
|
||||||
if (objectiveManager.CurrentOrder == this)
|
if (objectiveManager.CurrentOrder == this)
|
||||||
{
|
{
|
||||||
@@ -140,6 +139,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
isCompleted = true;
|
isCompleted = true;
|
||||||
}
|
}
|
||||||
|
if (component.AIOperate(deltaTime, character, this))
|
||||||
|
{
|
||||||
|
isCompleted = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -620,6 +620,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);
|
||||||
|
|||||||
@@ -212,6 +212,33 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2? PosToMaintain
|
||||||
|
{
|
||||||
|
get { return posToMaintain; }
|
||||||
|
set { posToMaintain = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ObstacleDebugInfo
|
||||||
|
{
|
||||||
|
public Vector2 Point1;
|
||||||
|
public Vector2 Point2;
|
||||||
|
|
||||||
|
public Vector2? Intersection;
|
||||||
|
|
||||||
|
public float Dot;
|
||||||
|
|
||||||
|
public Vector2 AvoidStrength;
|
||||||
|
|
||||||
|
public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength)
|
||||||
|
{
|
||||||
|
Point1 = edge.Point1;
|
||||||
|
Point2 = edge.Point2;
|
||||||
|
Intersection = intersection;
|
||||||
|
Dot = dot;
|
||||||
|
AvoidStrength = avoidStrength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//edge point 1, edge point 2, avoid strength
|
//edge point 1, edge point 2, avoid strength
|
||||||
private List<ObstacleDebugInfo> debugDrawObstacles = new List<ObstacleDebugInfo>();
|
private List<ObstacleDebugInfo> debugDrawObstacles = new List<ObstacleDebugInfo>();
|
||||||
|
|
||||||
|
|||||||
@@ -1532,6 +1532,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; }
|
||||||
|
|||||||
@@ -341,6 +341,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
|
||||||
|
|||||||
Reference in New Issue
Block a user