Unstable v0.19.5.0

This commit is contained in:
Juan Pablo Arce
2022-09-14 12:47:17 -03:00
parent 3f2c843247
commit 1fd2a51bbb
158 changed files with 5702 additions and 4813 deletions
@@ -28,10 +28,7 @@ namespace Barotrauma
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed.");
}
static bool IsTargetTagAttribute(XAttribute attribute)
{
return attribute.Name.ToString().Equals("targettag", System.StringComparison.OrdinalIgnoreCase);
}
static bool IsTargetTagAttribute(XAttribute attribute) => attribute.NameAsIdentifier() == "targettag";
}
private string GetEventName()
@@ -0,0 +1,65 @@
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using System.Linq;
namespace Barotrauma;
class CheckConnectionAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
public Identifier ItemTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier ConnectionName { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier ConnectedItemTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier OtherConnectionName { get; set; }
public CheckConnectionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
protected override bool? DetermineSuccess()
{
var connectTargets = !ConnectedItemTag.IsEmpty ? ParentEvent.GetTargets(ConnectedItemTag) : Enumerable.Empty<Entity>();
foreach (var target in ParentEvent.GetTargets(ItemTag))
{
if (target is not Item targetItem) { continue; }
if (targetItem.GetComponent<ConnectionPanel>() is not ConnectionPanel panel) { continue; }
if (panel.Connections == null || panel.Connections.None()) { continue; }
foreach (var connection in panel.Connections)
{
if (!IsCorrectConnection(connection, ConnectionName)) { continue; }
if (ConnectedItemTag.IsEmpty && OtherConnectionName.IsEmpty)
{
if (connection.Wires.Any()) { return true; }
continue;
}
foreach (var wire in connection.Wires)
{
if (wire.OtherConnection(connection) is not Connection otherConnection) { continue; }
if (ConnectedItemTag.IsEmpty)
{
if (IsCorrectConnection(otherConnection, OtherConnectionName)) { return true; }
}
else if (OtherConnectionName.IsEmpty)
{
if (IsCorrectItem()) { return true; }
}
else
{
if (!IsCorrectConnection(otherConnection, OtherConnectionName)) { continue; }
if (!IsCorrectItem()) { continue; }
return true;
}
bool IsCorrectItem() => connectTargets.Contains(otherConnection.Item);
}
bool IsCorrectConnection(Connection connection, Identifier id) => connection.Name.ToIdentifier() == id;
}
}
return false;
}
}
@@ -14,6 +14,9 @@ namespace Barotrauma
[Serialize("", IsPropertySaveable.Yes)]
public string ItemTags { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
public bool RequireEquipped { get; set; }
private readonly Identifier[] itemIdentifierSplit;
private readonly Identifier[] itemTags;
@@ -30,20 +33,24 @@ namespace Barotrauma
if (!targets.Any()) { return null; }
foreach (var target in targets)
{
if (!(target is Character chr)) { continue; }
if (chr.Inventory == null) { continue; }
if (itemTags.Any(tag => chr.Inventory.FindItemByTag(tag, recursive: true) != null)) { return true; }
foreach (var identifier in itemIdentifierSplit)
if (target is Character character)
{
if (chr.Inventory.FindItemByIdentifier(identifier, recursive: true) != null)
if (RequireEquipped)
{
return true;
if (itemTags.Any(tag => character.HasEquippedItem(tag))) { return true; }
if (itemIdentifierSplit.Any(identifier => character.HasEquippedItem(identifier))) { return true; }
return false;
}
if (character.Inventory is not CharacterInventory inventory) { continue; }
if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; }
if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; }
}
else if (target is Item item && item.OwnInventory is ItemInventory inventory)
{
if (itemTags.Any(tag => inventory.FindItemByTag(tag, recursive: true) is not null)) { return true; }
if (itemIdentifierSplit.Any(identifier => inventory.FindItemByIdentifier(identifier, recursive: true) is not null)) { return true; }
}
}
return false;
}
@@ -15,40 +15,36 @@ namespace Barotrauma
protected override bool? DetermineSuccess()
{
ISerializableEntity target = null;
Character targetCharacter = null;
if (!TargetTag.IsEmpty)
{
foreach (var t in ParentEvent.GetTargets(TargetTag))
{
if (t is ISerializableEntity e)
if (t is Character c)
{
target = e;
targetCharacter = c;
break;
}
}
}
if (target == null)
if (targetCharacter == null)
{
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed.");
return true;
}
if (target is Character character)
{
var currentOrderInfo = character.GetCurrentOrderWithTopPriority();
if (currentOrderInfo?.Identifier == OrderIdentifier)
{
if (OrderOption.IsEmpty)
{
return true;
}
else
{
return currentOrderInfo?.Option == OrderOption;
}
}
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target character was found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
return false;
}
return true;
var currentOrderInfo = targetCharacter.GetCurrentOrderWithTopPriority();
if (currentOrderInfo?.Identifier == OrderIdentifier)
{
if (OrderOption.IsEmpty)
{
return true;
}
else
{
return currentOrderInfo?.Option == OrderOption;
}
}
return false;
}
private string GetEventName()
@@ -0,0 +1,89 @@
using Barotrauma.Extensions;
using System.Collections.Generic;
namespace Barotrauma
{
class CheckSelectedItemAction : BinaryOptionAction
{
public enum SelectedItemType { Primary, Secondary, Any };
[Serialize("", IsPropertySaveable.Yes)]
public Identifier CharacterTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier TargetTag { get; set; }
[Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)]
public SelectedItemType ItemType { get; set; }
public CheckSelectedItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
protected override bool? DetermineSuccess()
{
Character character = null;
if (!CharacterTag.IsEmpty)
{
foreach (var t in ParentEvent.GetTargets(CharacterTag))
{
if (t is Character c)
{
character = c;
break;
}
}
}
if (character == null)
{
DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid character was found for tag \"{CharacterTag}\"! This will cause the check to automatically fail.");
return false;
}
if (!TargetTag.IsEmpty)
{
IEnumerable<Entity> targets = ParentEvent.GetTargets(TargetTag);
if (targets.None())
{
DebugConsole.ShowError($"CheckSelectedItemAction error: {GetEventName()} uses a CheckSelectedItemAction but no valid targets were found for tag \"{TargetTag}\"! This will cause the check to automatically fail.");
return false;
}
foreach (var target in targets)
{
if (target is not Item targetItem)
{
continue;
}
if (IsSelected(targetItem))
{
return true;
}
}
return false;
bool IsSelected(Item item)
{
return ItemType switch
{
SelectedItemType.Any => character.IsAnySelectedItem(item),
SelectedItemType.Primary => character.SelectedItem == item,
SelectedItemType.Secondary => character.SelectedSecondaryItem == item,
_ => false
};
}
}
else
{
return ItemType switch
{
SelectedItemType.Any => !character.HasSelectedAnyItem,
SelectedItemType.Primary => character.SelectedItem == null,
SelectedItemType.Secondary => character.SelectedSecondaryItem == null,
_ => false
};
}
}
private string GetEventName()
{
return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event";
}
}
}
@@ -0,0 +1,49 @@
#nullable enable
namespace Barotrauma
{
internal sealed class CheckTalentAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
public Identifier TalentIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier TargetTag { get; set; }
public CheckTalentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
protected override bool? DetermineSuccess()
{
if (TargetTag.IsEmpty)
{
return false;
}
Character? matchingCharacter = null;
foreach (Entity entity in ParentEvent.GetTargets(TargetTag))
{
if (entity is Character character)
{
matchingCharacter = character;
break;
}
}
return matchingCharacter is not null && matchingCharacter.HasTalent(TalentIdentifier);
}
public override string ToDebugString()
{
string subActionStr = "";
if (succeeded.HasValue)
{
subActionStr = $"\n Sub action: {(succeeded.Value ? Success : Failure)?.CurrentSubAction.ColorizeObject()}";
}
return $"{ToolBox.GetDebugSymbol(DetermineFinished())} {nameof(CheckTalentAction)} -> (Talent: {TalentIdentifier.ColorizeObject()}" +
$" Succeeded: {(succeeded.HasValue ? succeeded.Value.ToString() : "not determined").ColorizeObject()})" +
subActionStr;
}
}
}
@@ -1,10 +1,18 @@
using System;
using System.Linq;
namespace Barotrauma
{
class MessageBoxAction : EventAction
partial class MessageBoxAction : EventAction
{
public enum ActionType { Create, Close }
[Serialize(ActionType.Create, IsPropertySaveable.Yes)]
public ActionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier Identifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public string Tag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier Header { get; set; }
@@ -24,7 +32,7 @@ namespace Barotrauma
public string CloseOnInput { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier CloseOnInteractTag { get; set; }
public Identifier CloseOnSelectTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier CloseOnPickUpTag { get; set; }
@@ -35,8 +43,11 @@ namespace Barotrauma
[Serialize("", IsPropertySaveable.Yes)]
public Identifier CloseOnExitRoomName { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
public bool IsTutorialObjective { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier CloseOnInRoomName { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier ObjectiveTag { get; set; }
private bool isFinished = false;
@@ -45,72 +56,16 @@ namespace Barotrauma
public override void Update(float deltaTime)
{
if (isFinished) { return; }
#if CLIENT
CreateMessageBox();
if (IsTutorialObjective && GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
{
tutorialMode.Tutorial?.TriggerTutorialSegment(new Tutorials.Tutorial.Segment(Text, CreateMessageBox));
}
#endif
UpdateProjSpecific();
isFinished = true;
}
#if CLIENT
public void CreateMessageBox()
{
new GUIMessageBox(
headerText: TextManager.Get(Header),
text: RichString.Rich(TextManager.ParseInputTypes(TextManager.Get(Text).Fallback(Text.ToString()), useColorHighlight: true)),
buttons: Array.Empty<LocalizedString>(),
type: GUIMessageBox.Type.Tutorial,
iconStyle: IconStyle,
autoCloseCondition: GetAutoCloseCondition(),
hideCloseButton: HideCloseButton);
}
#endif
partial void UpdateProjSpecific();
private Func<bool> GetAutoCloseCondition()
{
var character = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Character;
Func<bool> autoCloseCondition = null;
if (!string.IsNullOrEmpty(CloseOnInput) && Enum.TryParse(CloseOnInput, true, out InputType closeOnInput))
{
#if CLIENT
autoCloseCondition = () => PlayerInput.KeyDown(closeOnInput);
#endif
}
else if (!CloseOnInteractTag.IsEmpty)
{
autoCloseCondition = () => character?.SelectedItem != null && character.SelectedItem.HasTag(CloseOnInteractTag);
}
else if (!CloseOnPickUpTag.IsEmpty)
{
autoCloseCondition = () => character?.Inventory != null && character.Inventory.FindItemByTag(CloseOnPickUpTag, recursive: true) != null;
}
else if (!CloseOnEquipTag.IsEmpty)
{
autoCloseCondition = () => character != null && character.HasEquippedItem(CloseOnEquipTag);
}
else if (!CloseOnExitRoomName.IsEmpty)
{
autoCloseCondition = () => character?.CurrentHull != null && character.CurrentHull.RoomName.ToIdentifier() != CloseOnExitRoomName;
}
return autoCloseCondition;
}
public override bool IsFinished(ref string goToLabel) => isFinished;
public override bool IsFinished(ref string goToLabel)
{
return isFinished;
}
public override void Reset() => isFinished = false;
public override void Reset()
{
isFinished = false;
}
public override string ToDebugString()
{
return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MessageBoxAction)}";
}
public override string ToDebugString() => $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MessageBoxAction)}";
}
}
@@ -0,0 +1,48 @@
namespace Barotrauma;
class TeleportAction : EventAction
{
public enum TeleportPosition { MainSub, Outpost }
[Serialize(TeleportPosition.MainSub, IsPropertySaveable.Yes)]
public TeleportPosition Position { get; set; }
[Serialize(SpawnType.Human, IsPropertySaveable.Yes)]
public SpawnType SpawnType { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public string SpawnPointTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier TargetTag { get; set; }
private bool isFinished;
public TeleportAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
public override void Update(float deltaTime)
{
if (isFinished) { return; }
Submarine sub = Position switch
{
TeleportPosition.MainSub => Submarine.MainSub,
TeleportPosition.Outpost => GameMain.GameSession?.Level?.StartOutpost,
_ => null
};
if (WayPoint.GetRandom(spawnType: SpawnType, sub: sub, spawnPointTag: SpawnPointTag) is WayPoint wp)
{
foreach (var target in ParentEvent.GetTargets(TargetTag))
{
if (target is Character c)
{
c.TeleportTo(wp.WorldPosition);
}
}
}
isFinished = true;
}
public override bool IsFinished(ref string goToLabel) => isFinished;
public override void Reset() => isFinished = false;
}
@@ -0,0 +1,27 @@
namespace Barotrauma;
partial class TutorialHighlightAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
public Identifier TargetTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
public bool State { get; set; }
private bool isFinished;
public TutorialHighlightAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
public override void Update(float deltaTime)
{
if (isFinished) { return; }
UpdateProjSpecific();
isFinished = true;
}
partial void UpdateProjSpecific();
public override bool IsFinished(ref string goToLabel) => isFinished;
public override void Reset() => isFinished = false;
}
@@ -0,0 +1,65 @@
using System.Linq;
namespace Barotrauma;
class TutorialIconAction : EventAction
{
public enum ActionType { Add, Remove, RemoveTarget, RemoveIcon, Clear };
[Serialize(ActionType.Add, IsPropertySaveable.Yes)]
public ActionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public string IconStyle { get; set; }
private bool isFinished;
public TutorialIconAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
public override void Update(float deltaTime)
{
if (isFinished) { return; }
#if CLIENT
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
{
if (ParentEvent.GetTargets(TargetTag).FirstOrDefault() is Entity target)
{
if (Type == ActionType.Add)
{
tutorialMode.Tutorial?.Icons.Add((target, IconStyle));
}
else if(Type == ActionType.Remove)
{
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target && i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase));
}
else if (Type == ActionType.RemoveTarget)
{
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.entity == target);
}
else if (Type == ActionType.RemoveIcon)
{
tutorialMode.Tutorial?.Icons.RemoveAll(i => i.iconStyle.Equals(IconStyle, System.StringComparison.OrdinalIgnoreCase));
}
else if (Type == ActionType.Clear)
{
tutorialMode.Tutorial?.Icons.Clear();
}
}
}
#endif
isFinished = true;
}
public override bool IsFinished(ref string goToLabel)
{
return isFinished;
}
public override void Reset()
{
isFinished = false;
}
}
@@ -1,12 +1,8 @@
#if CLIENT
using Barotrauma.Tutorials;
#endif
namespace Barotrauma
{
class TutorialSegmentAction : EventAction
partial class TutorialSegmentAction : EventAction
{
public enum SegmentActionType { Trigger, Complete, Remove };
public enum SegmentActionType { Trigger, Add, Complete, CompleteAndRemove, Remove };
[Serialize(SegmentActionType.Trigger, IsPropertySaveable.Yes)]
public SegmentActionType Type { get; set; }
@@ -15,7 +11,7 @@ namespace Barotrauma
public Identifier Id { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public Identifier ObjectiveTextTag { get; set; }
public Identifier ObjectiveTag { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
public bool AutoPlayVideo { get; set; }
@@ -32,64 +28,21 @@ namespace Barotrauma
[Serialize(80, IsPropertySaveable.Yes)]
public int Height { get; set; }
#if CLIENT
private readonly Tutorial.Segment segment;
#endif
private bool isFinished;
public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
{
#if CLIENT
// Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance)
if (Type == SegmentActionType.Trigger)
{
segment = new Tutorial.Segment(Id, ObjectiveTextTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No,
new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center),
new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height));
}
#endif
}
public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
public override void Update(float deltaTime)
{
if (isFinished) { return; }
#if CLIENT
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
{
if (tutorialMode.Tutorial is Tutorial tutorial)
{
switch (Type)
{
case SegmentActionType.Trigger:
tutorial.TriggerTutorialSegment(segment);
break;
case SegmentActionType.Complete:
tutorial.CompleteTutorialSegment(Id);
break;
case SegmentActionType.Remove:
tutorial.RemoveTutorialSegment(Id);
break;
}
}
}
else
{
DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!");
}
#endif
UpdateProjSpecific();
isFinished = true;
}
public override bool IsFinished(ref string goToLabel)
{
return isFinished;
}
partial void UpdateProjSpecific();
public override void Reset()
{
isFinished = false;
}
public override bool IsFinished(ref string goToLabel) => isFinished;
public override void Reset() => isFinished = false;
}
}