v1.4.4.1 (Blood in the Water Update)

This commit is contained in:
Regalis11
2024-04-24 18:09:05 +03:00
parent 89b91d1c3e
commit ff1b8951a7
397 changed files with 15250 additions and 6479 deletions
@@ -1,22 +1,35 @@
using System.Linq;
using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Gives an affliction to a specific character.
/// </summary>
class AfflictionAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the affliction.")]
public Identifier Affliction { get; set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "Strength of the affliction.")]
public float Strength { get; set; }
[Serialize(LimbType.None, IsPropertySaveable.Yes)]
[Serialize(LimbType.None, IsPropertySaveable.Yes, description: "Type of the limb(s) to apply the affliction on. Only valid if the affliction is limb-specific.")]
public LimbType LimbType { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character to apply the affliction on.")]
public Identifier TargetTag { get; set; }
public AfflictionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
[Serialize(false, IsPropertySaveable.Yes, description: "Should the strength be multiplied by the maximum vitality of the target?")]
public bool MultiplyByMaxVitality { get; set; }
public AfflictionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
{
if (Affliction.IsEmpty)
{
DebugConsole.ThrowError($"Error in {nameof(AfflictionAction)}: affliction not defined (use the attribute \"{nameof(Affliction)}\").",
contentPackage: element.ContentPackage);
}
}
private bool isFinished = false;
@@ -40,27 +53,32 @@ namespace Barotrauma
{
if (target != null && target is Character character)
{
float strength = Strength;
if (MultiplyByMaxVitality)
{
strength *= character.MaxVitality;
}
if (LimbType != LimbType.None)
{
var limb = character.AnimController.GetLimb(LimbType);
if (Strength > 0.0f)
if (strength > 0.0f)
{
character.CharacterHealth.ApplyAffliction(limb, afflictionPrefab.Instantiate(Strength), ignoreUnkillability: true);
character.CharacterHealth.ApplyAffliction(limb, afflictionPrefab.Instantiate(strength), ignoreUnkillability: true);
}
else if (Strength < 0.0f)
else if (strength < 0.0f)
{
character.CharacterHealth.ReduceAfflictionOnLimb(limb, Affliction, -Strength);
character.CharacterHealth.ReduceAfflictionOnLimb(limb, Affliction, -strength);
}
}
else
{
if (Strength > 0.0f)
if (strength > 0.0f)
{
character.CharacterHealth.ApplyAffliction(null, afflictionPrefab.Instantiate(Strength), ignoreUnkillability: true);
character.CharacterHealth.ApplyAffliction(null, afflictionPrefab.Instantiate(strength), ignoreUnkillability: true);
}
else if (Strength < 0.0f)
else if (strength < 0.0f)
{
character.CharacterHealth.ReduceAfflictionOnAllLimbs(Affliction, -Strength);
character.CharacterHealth.ReduceAfflictionOnAllLimbs(Affliction, -strength);
}
}
}
@@ -4,24 +4,27 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Check whether a target has a specific affliction.
/// </summary>
internal class CheckAfflictionAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the affliction.")]
public Identifier Identifier { get; set; } = Identifier.Empty;
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character to check.")]
public Identifier TargetTag { get; set; } = Identifier.Empty;
[Serialize("", IsPropertySaveable.Yes, description: "Tag referring to the character who caused the affliction.")]
[Serialize("", IsPropertySaveable.Yes, description: "Tag referring to the character who caused the affliction. Can be used to require the affliction to be caused by a specific character.")]
public Identifier SourceCharacter { get; set; } = Identifier.Empty;
[Serialize(LimbType.None, IsPropertySaveable.Yes, "Only check afflictions on the specified limb type")]
[Serialize(LimbType.None, IsPropertySaveable.Yes, "Only check afflictions on the specified limb type.")]
public LimbType TargetLimb { get; set; }
[Serialize(true, IsPropertySaveable.Yes, "When set to false when TargetLimb is not specified prevent checking limb-specific afflictions")]
[Serialize(true, IsPropertySaveable.Yes, "When set to false, limb-specific afflictions are ignored when not checking a specific limb.")]
public bool AllowLimbAfflictions { get; set; }
[Serialize(0.0f, IsPropertySaveable.Yes, "Minimum strength of the affliction")]
[Serialize(0.0f, IsPropertySaveable.Yes, "Minimum strength of the affliction.")]
public float MinStrength { get; set; }
public CheckAfflictionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -6,20 +6,24 @@ using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Checks whether an arbitrary condition is met. The conditionals work the same way as they do in StatusEffects.
/// </summary>
class CheckConditionalAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the target to check.")]
public Identifier TargetTag { get; set; }
[Serialize(PropertyConditional.LogicalOperatorType.Or, IsPropertySaveable.Yes)]
[Serialize(PropertyConditional.LogicalOperatorType.Or, IsPropertySaveable.Yes, description: "Do all of the conditions need to be met, or is it enough if at least one is? Only valid if there are multiple conditionals.")]
public PropertyConditional.LogicalOperatorType LogicalOperator { get; set; }
private ImmutableArray<PropertyConditional> Conditionals { get; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "A tag to apply to the hull the target is currently in when the check succeeds, as well as all the hulls linked to it.")]
public Identifier ApplyTagToLinkedHulls { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the hull the target item is inside when the item is used.")]
[Serialize("", IsPropertySaveable.Yes, description: "A tag to apply to the hull the target is currently in when the check succeeds.")]
public Identifier ApplyTagToHull { get; set; }
public CheckConditionalAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -4,21 +4,24 @@ using System.Linq;
namespace Barotrauma;
/// <summary>
/// Check whether a specific connection of an item is wired to a specific kind of connection.
/// </summary>
class CheckConnectionAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item to check.")]
public Identifier ItemTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The name of the connection to check on the target item.")]
public Identifier ConnectionName { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item the connection must be wired to. If omitted, it doesn't matter what the connection is wired to.")]
public Identifier ConnectedItemTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The name of the other connection the connection must be wired to. If omitted, it doesn't matter what the connection is wired to.")]
public Identifier OtherConnectionName { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "Minimum number of matching connections for the check to succeed.")]
public int MinAmount { get; set; }
public CheckConnectionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -37,7 +40,7 @@ class CheckConnectionAction : BinaryOptionAction
if (!IsCorrectConnection(connection, ConnectionName)) { continue; }
if (ConnectedItemTag.IsEmpty && OtherConnectionName.IsEmpty)
{
amount += connection.Wires.Count();
amount += connection.Wires.Count;
if (amount >= MinAmount) { return true; }
continue;
}
@@ -1,21 +1,24 @@
#nullable enable
using System;
using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Can be used to check arbitrary campaign metadata set using <see cref="SetDataAction"/>.
/// </summary>
class CheckDataAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the data to check.")]
public Identifier Identifier { get; set; } = Identifier.Empty;
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The condition that must be met for the check to succeed. Uses the same formatting as conditionals (for example, \"gt 5.2\", \"true\", \"lt 10\".)")]
public string Condition { get; set; } = "";
[Serialize(false, IsPropertySaveable.Yes, "Forces the comparison to use string instead of attempting to parse it as a boolean or a float first")]
[Serialize(false, IsPropertySaveable.Yes, "Forces the comparison to use string instead of attempting to parse it as a boolean or a float first. Use this if you know the value is a string.")]
public bool ForceString { get; set; }
[Serialize(false, IsPropertySaveable.Yes, "Performs the comparison against a metadata by identifier instead of a constant value")]
[Serialize(false, IsPropertySaveable.Yes, "Performs the comparison against a metadata by identifier instead of a constant value. Meaning that you could for example check whether the value of \"progress_of_some_event\" is larger than \"progress_of_some_other_event\".")]
public bool CheckAgainstMetadata { get; set; }
protected object? value2;
@@ -6,18 +6,22 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Can be used to do various kinds of checks on items: whether a specific kind of item exists,
/// if it's in a specific character's inventory or in a container, or whether some conditions are met on the item.
/// </summary>
class CheckItemAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Either the tag of the item(s) we want to check, or a character/container the items are inside.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The target item must have one of these identifiers.")]
public string ItemIdentifiers { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The target item must have at least one of these tags.")]
public string ItemTags { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "The minimum number of matching items for the check to succeed.")]
public int Amount { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag of a hull the target must be inside.")]
@@ -29,31 +33,27 @@ namespace Barotrauma
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the found item(s) when the check succeeds.")]
public Identifier ApplyTagToItem { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Does the item need to be equipped for the check to succeed?")]
public bool RequireEquipped { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "If enabled, the doesn't need to be directly inside the container/character we're checking, but can be nested inside multiple containers (e.g. in a toolbelt in a character's inventory).")]
public bool Recursive { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "Can be used to require the item to be in a specific ItemContainer of the target container. For example, the input slots of a fabricator (the first ItemContainer of the fabricator, with an index of 0).")]
public int ItemContainerIndex { get; set; }
private readonly bool checkPercentage;
private float requiredConditionalMatchPercentage;
[Serialize(100.0f, IsPropertySaveable.Yes)]
/// <summary>
/// What percentage of targets do the conditionals need to match for the check to succeed?
/// </summary>
[Serialize(100.0f, IsPropertySaveable.Yes, description: "What percentage of targets do the conditionals need to match for the check to succeed?")]
public float RequiredConditionalMatchPercentage
{
get { return requiredConditionalMatchPercentage; }
set { requiredConditionalMatchPercentage = MathHelper.Clamp(value, 0.0f, 100.0f); }
}
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "When enabled, the number of matching items is compared to the number of matching items there were at the start of the round. Only valid if RequiredConditionalMatchPercentage is set.")]
public bool CompareToInitialAmount { get; set; }
private readonly IReadOnlyList<PropertyConditional> conditionals;
@@ -94,12 +94,12 @@ namespace Barotrauma
private bool EnoughTargets(int totalTargets, int targetsWithConditionalsMatched)
{
if (CompareToInitialAmount)
{
totalTargets = ParentEvent.GetInitialTargetCount(TargetTag);
}
if (checkPercentage)
{
if (CompareToInitialAmount)
{
totalTargets = ParentEvent.GetInitialTargetCount(TargetTag);
}
return MathUtils.Percentage(targetsWithConditionalsMatched, totalTargets) >= RequiredConditionalMatchPercentage;
}
else
@@ -3,6 +3,9 @@ using System.Linq;
namespace Barotrauma;
/// <summary>
/// Check whether a specific mission is currently active, selected for the next round or available.
/// </summary>
class CheckMissionAction : BinaryOptionAction
{
public enum MissionType
@@ -12,16 +15,16 @@ class CheckMissionAction : BinaryOptionAction
Available
}
[Serialize(MissionType.Current, IsPropertySaveable.Yes)]
[Serialize(MissionType.Current, IsPropertySaveable.Yes, description: "Does the mission need to be currently active, selected for the next round or available.")]
public MissionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the mission.")]
public Identifier MissionIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the mission. Ignored if MissionIdentifier is set.")]
public Identifier MissionTag { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "Minimum number of matching missions for the check to succeed.")]
public int MissionCount { get; set; }
public CheckMissionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -1,16 +1,18 @@
using Barotrauma.Networking;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Networking;
namespace Barotrauma
{
/// <summary>
/// Check whether the crew or a specific player has enough money.
/// </summary>
class CheckMoneyAction : BinaryOptionAction
{
[Serialize(0, IsPropertySaveable.Yes)]
[Serialize(0, IsPropertySaveable.Yes, description: "Minimum amount of money the crew or the player must have.")]
public int Amount { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the player to check. If omitted, the crew's shared wallet is checked instead.")]
public Identifier TargetTag { get; set; }
public CheckMoneyAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -1,5 +1,8 @@
namespace Barotrauma;
/// <summary>
/// Checks the state of an Objective created using <see cref="EventObjectiveAction"/>.
/// </summary>
partial class CheckObjectiveAction : BinaryOptionAction
{
public CheckObjectiveAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -2,6 +2,9 @@ using Barotrauma.Extensions;
namespace Barotrauma
{
/// <summary>
/// Check whether a specific character has been given a specific order.
/// </summary>
class CheckOrderAction : BinaryOptionAction
{
public enum OrderPriority
@@ -10,19 +13,19 @@ namespace Barotrauma
Any
}
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character to check.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the order the target character must have.")]
public Identifier OrderIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The option that must be selected for the order. If the order has multiple options (such as turning on or turning off a reactor).")]
public Identifier OrderOption { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entity the order must be targeting. Only valid for orders that can target a specific entity (such as orders to operate a specific turret).")]
public Identifier OrderTargetTag { get; set; }
[Serialize(OrderPriority.Any, IsPropertySaveable.Yes)]
[Serialize(OrderPriority.Any, IsPropertySaveable.Yes, description: "Does the order need to have top priority, or is any priority fine?")]
public OrderPriority Priority { get; set; }
public CheckOrderAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -3,6 +3,9 @@ using System.Linq;
namespace Barotrauma;
/// <summary>
/// Check whether specific kinds of items have been purchased or sold during the round.
/// </summary>
class CheckPurchasedItemsAction : BinaryOptionAction
{
public enum TransactionType
@@ -11,16 +14,16 @@ class CheckPurchasedItemsAction : BinaryOptionAction
Sold
}
[Serialize(TransactionType.Purchased, IsPropertySaveable.Yes)]
[Serialize(TransactionType.Purchased, IsPropertySaveable.Yes, description: "Do the items need to have been purchased or sold?")]
public TransactionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the item that must have been purchased or sold.")]
public Identifier ItemIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item that must have been purchased or sold.")]
public Identifier ItemTag { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "Minimum number of matching items that must have been purchased or sold.")]
public int MinCount { get; set; }
public CheckPurchasedItemsAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -3,9 +3,12 @@ using System.Diagnostics;
namespace Barotrauma
{
/// <summary>
/// Check whether the reputation of the crew for a specific faction meets some criteria (e.g. equal to, larger than or less than some value).
/// </summary>
class CheckReputationAction : CheckDataAction
{
[Serialize(ReputationAction.ReputationType.None, IsPropertySaveable.Yes)]
[Serialize(ReputationAction.ReputationType.None, IsPropertySaveable.Yes, description: "Should the action check the reputation for a given faction, or whichever faction owns the current location.")]
public ReputationAction.ReputationType TargetType { get; set; }
public CheckReputationAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -3,17 +3,20 @@ using System.Collections.Generic;
namespace Barotrauma
{
/// <summary>
/// Check whether a specific character has selected a specific kind of item.
/// </summary>
class CheckSelectedAction : BinaryOptionAction
{
public enum SelectedItemType { Primary, Secondary, Any };
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character to check.")]
public Identifier CharacterTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "If specified, only items that have been given this tag using TagAction are considered valid.")]
public Identifier TargetTag { get; set; }
[Serialize(SelectedItemType.Any, IsPropertySaveable.Yes)]
[Serialize(SelectedItemType.Any, IsPropertySaveable.Yes, description: "How does the item need to be selected? Primary item (i.e. any device you're interacting with), secondary item (such as ladders or chairs which allow interacting with a primary item at the same time), or either?")]
public SelectedItemType ItemType { get; set; }
public CheckSelectedAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -2,12 +2,15 @@
namespace Barotrauma
{
/// <summary>
/// Check whether a specific character has a specific talent.
/// </summary>
internal sealed class CheckTalentAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the talent to check for.")]
public Identifier TalentIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character to check.")]
public Identifier TargetTag { get; set; }
public CheckTalentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -2,9 +2,12 @@
namespace Barotrauma
{
/// <summary>
/// Check the state of the traitor event the action is defined in. Only valid for traitor events.
/// </summary>
class CheckTraitorEventStateAction : BinaryOptionAction
{
[Serialize(TraitorEvent.State.Completed, IsPropertySaveable.Yes)]
[Serialize(TraitorEvent.State.Completed, IsPropertySaveable.Yes, description: "What does the state of the event need to be for the check to succeed?")]
public TraitorEvent.State State { get; set; }
private readonly TraitorEvent? traitorEvent;
@@ -9,7 +9,7 @@ namespace Barotrauma
/// </summary>
class CheckTraitorVoteAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character to check.")]
public Identifier Target { get; set; }
public CheckTraitorVoteAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -4,6 +4,9 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Check whether a specific entity is visible from the perspective of another entity.
/// </summary>
class CheckVisibilityAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entity to do the visibility check from.")]
@@ -1,10 +1,12 @@
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Clears the specific tag from the event (i.e. untagging all the entities that have been previously given the tag).
/// </summary>
class ClearTagAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The tag to clear.")]
public Identifier Tag { get; set; }
private bool isFinished;
@@ -1,31 +1,33 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Makes an NPC switch to a combat state (with options for different kinds of behaviors, such as offensive, arresting or retreating).
/// </summary>
class CombatAction : EventAction
{
[Serialize(AIObjectiveCombat.CombatMode.Offensive, IsPropertySaveable.Yes)]
[Serialize(AIObjectiveCombat.CombatMode.Offensive, IsPropertySaveable.Yes, description: $"What kind of combat mode should the NPC switch to (Defensive, Offensive, Arrest, Retreat, None)?")]
public AIObjectiveCombat.CombatMode CombatMode { get; set; }
[Serialize(false, IsPropertySaveable.Yes, description: "Did this NPC start the fight (as an aggressor)?")]
[Serialize(false, IsPropertySaveable.Yes, description: "Did this NPC start the fight (as an aggressor)? Attacking instigators doesn't reduce reputation or trigger outpost security.")]
public bool IsInstigator { get; set; }
[Serialize(AIObjectiveCombat.CombatMode.None, IsPropertySaveable.Yes)]
[Serialize(AIObjectiveCombat.CombatMode.None, IsPropertySaveable.Yes, description: "How do guards react to this character attacking others?")]
public AIObjectiveCombat.CombatMode GuardReaction { get; set; }
[Serialize(AIObjectiveCombat.CombatMode.None, IsPropertySaveable.Yes)]
[Serialize(AIObjectiveCombat.CombatMode.None, IsPropertySaveable.Yes, description: "How do other NPCs react to this character attacking others?")]
public AIObjectiveCombat.CombatMode WitnessReaction { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The tag of the NPC to switch to combat mode.")]
public Identifier NPCTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character the NPC should attack.")]
public Identifier EnemyTag { get; set; }
[Serialize(120.0f, IsPropertySaveable.Yes)]
[Serialize(120.0f, IsPropertySaveable.Yes, description: "How long it takes for the NPC to \"cool down\" (stop attacking).")]
public float CoolDown { get; set; }
private bool isFinished = false;
@@ -8,6 +8,10 @@ using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Triggers a "conversation popup" with text and support for different branching options.
/// </summary>
partial class ConversationAction : EventAction
{
@@ -26,43 +30,40 @@ namespace Barotrauma
/// </summary>
const float BlockOtherConversationsDuration = 5.0f;
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The text to display in the prompt. Can be the text as-is, or a tag referring to a line in a text file.")]
public string Text { get; set; }
[Serialize(0, IsPropertySaveable.Yes)]
public int DefaultOption { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character who's speaking. Makes a speech bubble icon appear above the character to indicate you can speak with them, and stops the character in place when the conversation triggers. Also allows the conversation to be interrupted if the speaker dies or becomes incapacitated mid-conversation.")]
public Identifier SpeakerTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the player the conversation is shown to. If empty, the conversation is shown to everyone. If SpeakerTag is defined, the conversation is always only shown to the player who interacts with the speaker.")]
public Identifier TargetTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, "Should someone interact with the speaker for the conversation to trigger?")]
public bool WaitForInteraction { get; set; }
[Serialize("", IsPropertySaveable.Yes, "Tag to assign to whoever invokes the conversation")]
[Serialize("", IsPropertySaveable.Yes, "Tag to assign to whoever invokes the conversation.")]
public Identifier InvokerTag { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Should the screen fade to black when the conversation is active?")]
public bool FadeToBlack { get; set; }
[Serialize(true, IsPropertySaveable.Yes, "Should the event end if the conversations is interrupted (e.g. if the speaker dies or falls unconscious mid-conversation). Defaults to true.")]
public bool EndEventIfInterrupted { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of an event sprite to display in the corner of the conversation prompt.")]
public string EventSprite { get; set; }
[Serialize(DialogTypes.Regular, IsPropertySaveable.Yes)]
[Serialize(DialogTypes.Regular, IsPropertySaveable.Yes, description: "Type of the dialog prompt.")]
public DialogTypes DialogType { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Does this conversation continue after this ConversationAction? If you have multiple successive ConversationActions, perhaps with some actions happening in between, you can enable this to prevent the dialog prompt from closing between the actions. Not necessary if the ConversationActions are nested inside each other: those are always considered parts of the same conversation, and shown in the same prompt.")]
public bool ContinueConversation { get; set; }
[Serialize(false, IsPropertySaveable.Yes, description: "If enabled, the event will not stop to wait for the conversation to be dismissed.")]
public bool ContinueAutomatically { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "If SpeakerTag is defined, the conversation is interrupted by default if the speaker and the target end up too far from each other. This can be used to disable that behavior, keeping the dialog prompt open regardless of the distance.")]
public bool IgnoreInterruptDistance { get; set; }
public Character Speaker
@@ -72,6 +73,7 @@ namespace Barotrauma
}
private AIObjective prevIdleObjective, prevGotoObjective;
private AIObjective npcWaitObjective;
public List<SubactionGroup> Options { get; private set; }
@@ -275,6 +277,10 @@ namespace Barotrauma
if (!SpeakerTag.IsEmpty)
{
if (npcWaitObjective != null)
{
npcWaitObjective.ForceHighestPriority = true;
}
if (Speaker != null && !Speaker.Removed && Speaker.CampaignInteractionType == CampaignMode.InteractionType.Talk && Speaker.ActiveConversation?.ParentEvent != this.ParentEvent) { return; }
Speaker = ParentEvent.GetTargets(SpeakerTag).FirstOrDefault(e => e is Character) as Character;
if (Speaker == null || Speaker.Removed)
@@ -386,11 +392,11 @@ namespace Barotrauma
{
prevIdleObjective = humanAI.ObjectiveManager.GetObjective<AIObjectiveIdle>();
prevGotoObjective = humanAI.ObjectiveManager.GetObjective<AIObjectiveGoTo>();
humanAI.SetForcedOrder(
npcWaitObjective = humanAI.SetForcedOrder(
new Order(OrderPrefab.Prefabs["wait"], Barotrauma.Identifier.Empty, null, orderGiver: null));
if (targets.Any())
if (targets.Any() || targetCharacter != null)
{
Entity closestTarget = null;
Entity closestTarget = targetCharacter;
float closestDist = float.MaxValue;
foreach (Entity entity in targets)
{
@@ -5,9 +5,12 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Check whether there's at least / at most some number of entities matching some specific criteria.
/// </summary>
class CountTargetsAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entities to check.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Optional second tag. Can be used if the target must have two different tags.")]
@@ -16,29 +19,19 @@ namespace Barotrauma
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag of a hull the target must be inside.")]
public Identifier HullTag { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "Minimum number of matching entities for the check to succeed. If omitted or negative, there is no minimum amount.")]
public int MinAmount { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "Maximum number of matching entities for the check to succeed. If omitted or negative, there is no maximum amount.")]
public int MaxAmount { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of some other entities to compare the number of targets to. E.g. you could compare the number of entities tagged as \"discoveredhull\" to entities tagged as \"anyhull\". The minimum/maximum amount of entities there must be relative to the other entities is configured using MinPercentageRelativeToTarget and MaxPercentageRelativeToTarget.")]
public Identifier CompareToTarget { get; set; }
[Serialize(-1.0f, IsPropertySaveable.Yes)]
/// <summary>
/// Minimum amount of targets, as a percentage of the number of entities tagged with CompareToTarget
/// E.g. you could compare the number of entities tagged as "discoveredhull" to entities tagged as "anyhull" to require 50% of hulls to be discovered.
/// </summary>
[Serialize(-1.0f, IsPropertySaveable.Yes, description: "Minimum amount of targets, as a percentage of the number of entities tagged with CompareToTarget. E.g. you could compare the number of entities tagged as \"discoveredhull\" to entities tagged as \"anyhull\" to require 50% of hulls to be discovered.")]
public float MinPercentageRelativeToTarget { get; set; }
[Serialize(-1.0f, IsPropertySaveable.Yes)]
/// <summary>
/// Maximum amount of targets, as a percentage of the number of entities tagged with CompareToTarget
/// E.g. you could compare the number of entities tagged as "floodedhull" to entities tagged as "anyhull" to require less than 50% of hulls to be flooded.
/// </summary>
[Serialize(-1.0f, IsPropertySaveable.Yes, description: "Maximum amount of targets, as a percentage of the number of entities tagged with CompareToTarget. E.g. you could compare the number of entities tagged as \"floodedhull\" to entities tagged as \"anyhull\" to require less than 50% of hulls to be flooded.")]
public float MaxPercentageRelativeToTarget { get; set; }
private readonly IReadOnlyList<PropertyConditional> conditionals;
@@ -5,15 +5,19 @@ using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Adds an entry to the "event log" displayed in the mission tab of the tab menu.
/// </summary>
partial class EventLogAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the entry. If there's already an entry with the same id, it gets overwritten.")]
public Identifier Id { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Text to add to the event log. Can be the text as-is, or a tag referring to a line in a text file.")]
public string Text { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character(s) who should see the entry. If empty, the entry is shown to everyone.")]
public Identifier TargetTag { get; set; }
public bool ShowInServerLog { get; set; }
@@ -1,40 +1,81 @@
using System;
namespace Barotrauma
{
/// <summary>
/// Displays an objective in the top-right corner of the screen, or modifies an existing objective in some way.
/// </summary>
partial class EventObjectiveAction : EventAction
{
public enum SegmentActionType { Trigger, Add, AddIfNotFound, Complete, CompleteAndRemove, Remove, Fail, FailAndRemove };
public enum SegmentActionType
{
/// <summary>
/// Legacy support. Triggers an info box segment, with optional support for video clips.
/// </summary>
[Obsolete]
Trigger,
/// <summary>
/// Adds a new objective to the list.
/// </summary>
Add,
/// <summary>
/// Adds a new objective to the list if there are no existing objectives with the same identifier.
/// </summary>
AddIfNotFound,
/// <summary>
/// Marks the objective as completed.
/// </summary>
Complete,
/// <summary>
/// Marks the objective as completed and removes it from the list.
/// </summary>
CompleteAndRemove,
/// <summary>
/// Removes the objective from the list.
/// </summary>
Remove,
/// <summary>
/// Marks the objective as failed.
/// </summary>
Fail,
/// <summary>
/// Marks the objective as failed and removes it from the list.
/// </summary>
FailAndRemove
};
[Serialize(SegmentActionType.Trigger, IsPropertySaveable.Yes)]
[Serialize(SegmentActionType.Add, IsPropertySaveable.Yes, description: "Should the action add a new objective, or do something to an existing objective?")]
public SegmentActionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Arbitrary identifier given to the objective. Can be used to complete/remove/fail the objective later. Also used to fetch the text from the text files.")]
public Identifier Identifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Obsolete, Serialize("", IsPropertySaveable.Yes, description: "Legacy support. Tag of the text to display as an objective in info box segments.")]
public Identifier ObjectiveTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Obsolete, Serialize(true, IsPropertySaveable.Yes, description: "Legacy support. Is this objective possible to complete if it's used in an info box segment.")]
public bool CanBeCompleted { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of a parent objective. If set, this objective is displayed as a subobjective under the parent objective.")]
public Identifier ParentObjectiveId { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Obsolete, Serialize(false, IsPropertySaveable.Yes, description: "Legacy support. Should the video defined by VideoFile play automatically, or wait for the user to play it.")]
public bool AutoPlayVideo { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Obsolete, Serialize("", IsPropertySaveable.Yes, description: "Legacy support. Tag of the main text to display in info box segments.")]
public Identifier TextTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Obsolete, Serialize("", IsPropertySaveable.Yes, description: "Legacy support. Path of a video file to display in info box segments.")]
public string VideoFile { get; set; }
[Serialize(450, IsPropertySaveable.Yes)]
[Obsolete, Serialize(450, IsPropertySaveable.Yes, description: "Legacy support. Width of the info box segment.")]
public int Width { get; set; }
[Serialize(80, IsPropertySaveable.Yes)]
[Obsolete, Serialize(80, IsPropertySaveable.Yes, description: "Legacy support. Height of the info box segment.")]
public int Height { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character(s) to show the objective to.")]
public Identifier TargetTag { get; set; }
private bool isFinished;
@@ -1,17 +1,16 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Starts a fire at the position of a specific target.
/// </summary>
class FireAction : EventAction
{
[Serialize(10.0f, IsPropertySaveable.Yes)]
[Serialize(10.0f, IsPropertySaveable.Yes, description: "Size of the fire (width in pixels).")]
public float Size { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entity to start the fire at.")]
public Identifier TargetTag { get; set; }
public FireAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -2,12 +2,15 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Gives experience to a specific character.
/// </summary>
class GiveExpAction : EventAction
{
[Serialize(0, IsPropertySaveable.Yes)]
[Serialize(0, IsPropertySaveable.Yes, description: "The amount of experience to give. Cannot be negative.")]
public int Amount { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character(s) to give the experience to.")]
public Identifier TargetTag { get; set; }
public GiveExpAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -2,15 +2,18 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Increases the skill level of a specific character.
/// </summary>
class GiveSkillExpAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the skill to increase.")]
public Identifier Skill { get; set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "How much the skill should increase.")]
public float Amount { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character(s) whose skill to increase.")]
public Identifier TargetTag { get; set; }
public GiveSkillExpAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -1,11 +1,14 @@
namespace Barotrauma
{
/// <summary>
/// Makes the event jump to a <see cref="Label"/> somewhere else in the event.
/// </summary>
class GoTo : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Name of the label to jump to.")]
public string Name { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "How many times can this GoTo action be repeated? Can be used to make some parts of an event repeat a limited number of times. If negative or zero, there's no limit.")]
public int MaxTimes { get; set; }
private int counter;
@@ -1,14 +1,17 @@
namespace Barotrauma
{
/// <summary>
/// Makes a specific character invulnerable to damage and unable to die.
/// </summary>
class GodModeAction : EventAction
{
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the godmode be enabled or disabled?")]
public bool Enabled { get; set; }
[Serialize(false, IsPropertySaveable.Yes, description: "Should the character's active afflictions be updated (e.g. applying visual effects of the afflictions)")]
public bool UpdateAfflictions { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character whose godmode to enable/disable.")]
public Identifier TargetTag { get; set; }
public GodModeAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -5,17 +5,20 @@ using System.Linq;
namespace Barotrauma;
/// <summary>
/// Highlights a specific entity.
/// </summary>
partial class HighlightAction : EventAction
{
private static readonly Color highlightColor = Color.Orange;
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entity to highlight.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Only the player controlling this character will see the highlight. If empty, all players will see it.")]
public Identifier TargetCharacter { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the highlight be turned on or off?")]
public bool State { get; set; }
private bool isFinished;
@@ -1,17 +1,20 @@
namespace Barotrauma;
/// <summary>
/// Highlights specific items in a specific inventory.
/// </summary>
partial class InventoryHighlightAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entity or entities whose inventory the item should be highlighted in. Must be a character or an item with an inventory.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the item(s) to highlight.")]
public Identifier ItemIdentifier { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "If the target is an item with multiple ItemContainer components (i.e. multiple inventories), such as a fabricator, this determines which inventory to highlight the item in (0 = first, 1 = second). If negative, it doesn't matter which inventory the item is in.")]
public int ItemContainerIndex { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "If enabled, the action will go look through all the containers in the target inventory (e.g. highlighting a tank in a welding tool in the target inventory).")]
public bool Recursive { get; set; }
private bool isFinished;
@@ -1,7 +1,8 @@
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Defines a point in the event that <see cref="GoTo"/> actions can jump to.
/// </summary>
class Label : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
@@ -0,0 +1,61 @@
namespace Barotrauma;
/// <summary>
/// Enable or disable a specific layer in a specific submarine.
/// </summary>
class LayerAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes, description: "Which layer to enable/disable. Use \"All\" to apply it to all layers.")]
public Identifier Layer { get; set; }
[Serialize(false, IsPropertySaveable.Yes, description: "Whether to enable or disable the layer.")]
public bool Enabled { get; set; }
[Serialize(TagAction.SubType.Any, IsPropertySaveable.Yes, description: "The type of submatine to enable or disable the layer in.")]
public TagAction.SubType SubmarineType { get; set; }
[Serialize(true, IsPropertySaveable.Yes, description: "Should the action continue if it can't find the specified layer in the specified submarine(s).")]
public bool ContinueIfNotFound { get; set; }
public LayerAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
private bool isFinished;
public override bool IsFinished(ref string goTo)
{
return isFinished;
}
public override void Reset()
{
isFinished = false;
}
public override void Update(float deltaTime)
{
if (isFinished) { return; }
bool layerFound = false;
foreach (var submarine in Submarine.Loaded)
{
if (!TagAction.SubmarineTypeMatches(submarine, SubmarineType)) { continue; }
if (submarine.LayerExists(Layer))
{
submarine.SetLayerEnabled(Layer, Enabled, sendNetworkEvent: true);
layerFound = true;
}
}
if (ContinueIfNotFound)
{
isFinished = true;
}
else
{
if (layerFound) { isFinished = true; }
}
}
public override string ToDebugString()
{
return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(LayerAction)} -> ({(Enabled ? "Enable" : "Disable")} {Layer.ColorizeObject()})";
}
}
@@ -1,52 +1,55 @@
namespace Barotrauma
{
/// <summary>
/// Displays a message box, or modifies an existing one.
/// </summary>
partial class MessageBoxAction : EventAction
{
public enum ActionType { Create, ConnectObjective, Close, Clear }
[Serialize(ActionType.Create, IsPropertySaveable.Yes)]
[Serialize(ActionType.Create, IsPropertySaveable.Yes, description: "What do you want to do with the message box (Create, ConnectObjective, Close, Clear)?")]
public ActionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Optional identifier of the tutorial \"segment\" that can be referenced by other event actions.")]
public Identifier Identifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "An arbitrary tag given to the message box. Only required if you're intending to close or clear the box with another MessageBoxAction later.")]
public string Tag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Text displayed in the header of the message box. Can be either the text as-is, or a tag referring to a line in a text file.")]
public Identifier Header { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Text displayed in the body of the message box. Can be either the text as-is, or a tag referring to a line in a text file.")]
public Identifier Text { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Style of the icon displayed in the corner of the message box (optional). The style must be defined in a UIStyle file.")]
public string IconStyle { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Should the button that closes the box be hidden? If it is hidden, you must close the box manually using another MessageBoxAction.")]
public bool HideCloseButton { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character(s) to show the message box to.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The message box is automatically closed on some input (e.g. Select, Use, CrewOrders).")]
public string CloseOnInput { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The message box is automatically closed when the user selects an item that has this tag.")]
public Identifier CloseOnSelectTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The message box is automatically closed when the user picks up an item that has this tag.")]
public Identifier CloseOnPickUpTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The message box is automatically closed when the user equips an item that has this tag.")]
public Identifier CloseOnEquipTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The message box is automatically closed when the user exits a room with this name.")]
public Identifier CloseOnExitRoomName { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The message box is automatically closed when the user is in a room with this name.")]
public Identifier CloseOnInRoomName { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag that will be used to get the text for the objective that is displayed on the screen.")]
public Identifier ObjectiveTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
@@ -7,15 +7,18 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Unlocks a mission in a nearby level or location.
/// </summary>
partial class MissionAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the mission to unlock.")]
public Identifier MissionIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the mission to unlock. If there are multiple missions with the tag, one is chosen randomly.")]
public Identifier MissionTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The mission can only be unlocked in a location that's occupied by this faction.")]
public Identifier RequiredFaction { get; set; }
public ImmutableArray<Identifier> LocationTypes { get; }
@@ -46,7 +49,14 @@ namespace Barotrauma
contentPackage: element.ContentPackage);
}
LocationTypes = element.GetAttributeIdentifierArray("locationtype", Array.Empty<Identifier>()).ToImmutableArray();
random = new MTRandom(parentEvent.RandomSeed);
//the action chooses the same mission if
// 1. event seed is the same (based on level seed, changes when events are completed)
// 2. event is the same (two different events shouldn't choose the same mission)
// 3. the MissionAction is the same (two different actions in the same event shouldn't choose the same mission)
random = new MTRandom(
parentEvent.RandomSeed +
ToolBox.StringToInt(ParentEvent.Prefab.Identifier.Value) +
ParentEvent.Actions.Count);
}
public override bool IsFinished(ref string goTo)
@@ -1,8 +1,12 @@
namespace Barotrauma
{
/// <summary>
/// Changes the state of a specific active mission. The way the states are used depends on the type of mission.
/// </summary>
class MissionStateAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the mission whose state to change.")]
public Identifier MissionIdentifier { get; set; }
public enum OperationType
@@ -11,10 +15,10 @@ namespace Barotrauma
Add
}
[Serialize(OperationType.Set, IsPropertySaveable.Yes)]
[Serialize(OperationType.Set, IsPropertySaveable.Yes, description: "Should the value be added to the state of the mission, or should the state be set to the specified value.")]
public OperationType Operation { get; set; }
[Serialize(0, IsPropertySaveable.Yes)]
[Serialize(0, IsPropertySaveable.Yes, description: "The state to set the mission to, or how much to add to the state of the mission.")]
public int State { get; set; }
private bool isFinished;
@@ -1,17 +1,20 @@
namespace Barotrauma
{
/// <summary>
/// Modifies the current location in some way (e.g. adjusting the faction, type of name).
/// </summary>
class ModifyLocationAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the faction to set as the location's primary faction (optional).")]
public Identifier Faction { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the faction to set as the location's secondary faction (optional).")]
public Identifier SecondaryFaction { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the location type to set as the location's new type (optional)")]
public Identifier Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "New name to give to the location (optional). Can either be the name as-is, or a tag referring to a line in a text file.")]
public Identifier Name { get; set; }
private bool isFinished;
@@ -1,20 +1,21 @@
using System;
using Barotrauma.Networking;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Networking;
namespace Barotrauma
{
/// <summary>
/// Give or remove money from the crew or a specific character.
/// </summary>
class MoneyAction : EventAction
{
public MoneyAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
[Serialize(0, IsPropertySaveable.Yes)]
[Serialize(0, IsPropertySaveable.Yes, description: "Amount of money to give or remove.")]
public int Amount { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "If set, the money is removed from character(s) with this tag.")]
public Identifier TargetTag { get; set; }
private bool isFinished;
@@ -4,20 +4,21 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Changes the team of an NPC. Most common use cases are adding a character to the crew, or turning an NPC hostile to the crew by changing their team to a hostile one.
/// </summary>
class NPCChangeTeamAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the NPC(s) whose team to change.")]
public Identifier NPCTag { get; set; }
[Serialize(CharacterTeamType.None, IsPropertySaveable.Yes)]
[Serialize(CharacterTeamType.None, IsPropertySaveable.Yes, description: "The team to move the NPC to. None = unspecified, Team1 = player crew, Team2 = the team opposing Team1 (= hostile to player crew), FriendlyNPC = friendly to all other teams.")]
public CharacterTeamType TeamID { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Should the NPC be added to the player crew?")]
public bool AddToCrew { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Should the NPC be removed from the player crew?")]
public bool RemoveFromCrew { get; set; }
private bool isFinished = false;
@@ -3,21 +3,24 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Makes an NPC follow or stop following a specific target.
/// </summary>
class NPCFollowAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the NPC(s) that should follow the target.")]
public Identifier NPCTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the target. Can be any type of entity: if it's a static one like a device or a hull, the NPC will just stay at the position of that target.")]
public Identifier TargetTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the NPC start or stop following the target?")]
public bool Follow { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "Maximum number of NPCs to target (e.g. you could choose to only make a specific number of security officers follow the player.)")]
public int MaxTargets { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "The event actions reset when a GoTo action makes the event jump to a different point. Should the NPC stop following the target when the event resets?")]
public bool AbandonOnReset { get; set; }
private bool isFinished = false;
@@ -1,39 +1,43 @@
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Makes an NPC select an item, and operate it if it's something AI characters can operate.
/// </summary>
class NPCOperateItemAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the NPC(s) that should operate the item.")]
public Identifier NPCTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item to operate. If it's not something AI characters can or know how to operate, such as a cabinet or an engine, the NPC will just select it.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("Controller", IsPropertySaveable.Yes, description: "Name of the component to operate. For example, the Controller component of a periscope or the Reactor component of a nuclear reactor.")]
public Identifier ItemComponentName { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the option, if there are several ways the item can be operated. For example, \"powerup\" or \"shutdown\" when operating a reactor.")]
public Identifier OrderOption { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Should the character equip the item before attempting to operate it (only valid if the item is equippable).")]
public bool RequireEquip { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the character start or stop operating the item.")]
public bool Operate { get; set; }
[Serialize(-1, IsPropertySaveable.Yes)]
[Serialize(-1, IsPropertySaveable.Yes, description: "Maximum number of NPCs the action can target. For example, you could only make a specific number of security officers man a periscope.")]
public int MaxTargets { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "The event actions reset when a GoTo action makes the event jump to a different point. Should the NPC stop operating the item when the event resets?")]
public bool AbandonOnReset { get; set; }
private bool isFinished = false;
public NPCOperateItemAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
private List<Character> affectedNpcs = null;
private Item target = null;
@@ -41,7 +45,13 @@ namespace Barotrauma
{
if (isFinished) { return; }
target = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Item;
var potentialTargets = ParentEvent.GetTargets(TargetTag).OfType<Item>();
var nonSelectedItems = potentialTargets.Where(it => it.GetComponent<Controller>()?.User == null);
target =
nonSelectedItems.Any() ?
nonSelectedItems.GetRandomUnsynced() :
potentialTargets.GetRandomUnsynced();
if (target == null) { return; }
int targetCount = 0;
@@ -53,7 +63,6 @@ namespace Barotrauma
if (Operate)
{
ItemComponentName = "Controller".ToIdentifier();
var itemComponent = target.Components.FirstOrDefault(ic => ItemComponentName == ic.Name);
if (itemComponent == null)
{
@@ -1,15 +1,17 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Makes an NPC stop and wait.
/// </summary>
class NPCWaitAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the NPC(s) that should wait.")]
public Identifier NPCTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the NPC start or stop waiting?")]
public bool Wait { get; set; }
private bool isFinished = false;
@@ -35,6 +37,7 @@ namespace Barotrauma
var gotoObjective = new AIObjectiveGoTo(
AIObjectiveGoTo.GetTargetHull(npc) as ISpatialEntity ?? npc, npc, humanAiController.ObjectiveManager, repeat: true)
{
FaceTargetOnCompleted = false,
OverridePriority = 100.0f,
SourceEventAction = this,
IsWaitOrder = true,
@@ -2,6 +2,9 @@
namespace Barotrauma
{
/// <summary>
/// Executes all the child actions when the round ends.
/// </summary>
class OnRoundEndAction : EventAction
{
private readonly SubactionGroup subActions;
@@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Randomly executes either of the child actions (Success or Failure).
/// </summary>
class RNGAction : BinaryOptionAction
{
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "The probability of executing the Success actions. A value between 0-1.")]
public float Chance { get; set; }
public RNGAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -3,15 +3,18 @@ using System.Collections.Immutable;
namespace Barotrauma
{
/// <summary>
/// Removes (deletes) a specific item or items.
/// </summary>
class RemoveItemAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item(s) to remove.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Optional list of identifiers the item(s) must have. You might for example want to go through all tagged items inside a cabinet, but only remove specific types of items.")]
public string ItemIdentifiers { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "Maximum number of items to remove.")]
public int Amount { get; set; }
private readonly ImmutableHashSet<Identifier> itemIdentifierSplit;
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
namespace Barotrauma
{
/// <summary>
/// Adjusts the crew's reputation by some value.
/// </summary>
class ReputationAction : EventAction
{
public enum ReputationType
@@ -17,13 +14,13 @@ namespace Barotrauma
public ReputationAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "Amount of reputation to add or remove.")]
public float Increase { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the faction you want to adjust the reputation for. Ignored if TargetType is set to Location.")]
public Identifier Identifier { get; set; }
[Serialize(ReputationType.None, IsPropertySaveable.Yes)]
[Serialize(ReputationType.None, IsPropertySaveable.Yes, description: "Do you want to adjust the reputation for a specific faction, or whichever faction controls the current location?")]
public ReputationType TargetType { get; set; }
private bool isFinished;
@@ -1,8 +1,10 @@
using System;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Sets a campaign metadata value. The metadata can be any arbitrary data you want to save: for example, whether some event has been completed, the number of times something has been done during the campaign, or at what stage of some multi-part event chain the crew is at.
/// </summary>
class SetDataAction : EventAction
{
public enum OperationType
@@ -14,13 +16,13 @@ namespace Barotrauma
public SetDataAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
[Serialize(OperationType.Set, IsPropertySaveable.Yes)]
[Serialize(OperationType.Set, IsPropertySaveable.Yes, description: "Do you want to set the metadata to a specific value, multiply it, or add to it.")]
public OperationType Operation { get; set; }
[Serialize(null, IsPropertySaveable.Yes)]
[Serialize(null, IsPropertySaveable.Yes, description: "Depending on the operation, the value you want to set the metadata to, multiply it with, or add to it.")]
public string Value { get; set; } = null!;
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the metadata to set. Can be any arbitrary identifier, e.g. itemscollected, my_custom_event_state, specialnpckilled...")]
public Identifier Identifier { get; set; }
private bool isFinished;
@@ -1,8 +1,10 @@
using System;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Adjusts the price multiplier for stores or mechanical repairs in the current location.
/// </summary>
class SetPriceMultiplierAction : EventAction
{
public enum OperationType
@@ -19,13 +21,13 @@ namespace Barotrauma
Mechanical
}
[Serialize(1.0f, IsPropertySaveable.Yes)]
[Serialize(1.0f, IsPropertySaveable.Yes, description: "Value to set as the multiplier, or to multiply, min or max the current multiplier with.")]
public float Multiplier { get; set; }
[Serialize(OperationType.Set, IsPropertySaveable.Yes)]
[Serialize(OperationType.Set, IsPropertySaveable.Yes, description: "Do you want to set the value as the multiplier, multiply the existing multiplier with it, or take the smaller or larger of the values.")]
public OperationType Operation { get; set; }
[Serialize(PriceMultiplierType.Store, IsPropertySaveable.Yes)]
[Serialize(PriceMultiplierType.Store, IsPropertySaveable.Yes, description: "Do you want to set the price multiplier for stores or for mechanical services (hull and item repairs and restoring lost shuttles)?")]
public PriceMultiplierType TargetMultiplier { get; set; }
public SetPriceMultiplierAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -2,6 +2,9 @@
namespace Barotrauma
{
/// <summary>
/// Sets the state of the traitor event. Only valid in traitor events.
/// </summary>
class SetTraitorEventStateAction : EventAction
{
private readonly TraitorEvent? traitorEvent;
@@ -19,7 +22,7 @@ namespace Barotrauma
}
}
[Serialize(TraitorEvent.State.Completed, IsPropertySaveable.Yes)]
[Serialize(TraitorEvent.State.Completed, IsPropertySaveable.Yes, description: "The state to set the traitor event to (Incomplete, Completed or Failed).")]
public TraitorEvent.State State { get; set; }
private bool isFinished;
@@ -1,22 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Performs a skill check and executes either the Success or Failure child actions depending on whether the check succeeds.
/// </summary>
class SkillCheckAction : BinaryOptionAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The identifier of the skill to check.")]
public Identifier RequiredSkill { get; set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "The required skill level for the check to succeed.")]
public float RequiredLevel { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the skill check be probability-based (i.e. if you have half the required skill level, the chance of success is 50%), or should the check always fail when under the required level and always succeed when above? ")]
public bool ProbabilityBased { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character(s) whose skill to check. If there are multiple targets, the action succeeds if any of their skill checks succeeds.")]
public Identifier TargetTag { get; set; }
public SkillCheckAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -6,6 +6,9 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Spawns an entity (e.g. item, NPC, monster).
/// </summary>
class SpawnAction : EventAction
{
public enum SpawnLocationType
@@ -41,16 +44,16 @@ namespace Barotrauma
[Serialize("", IsPropertySaveable.Yes, description: "Tag of an entity with an inventory to spawn the item into.")]
public Identifier TargetInventory { get; set; }
[Serialize(SpawnLocationType.Any, IsPropertySaveable.Yes)]
[Serialize(SpawnLocationType.Any, IsPropertySaveable.Yes, description: "Where should the entity spawn? This can be restricted further with the other spawn point options.")]
public SpawnLocationType SpawnLocation { get; set; }
[Serialize(SpawnType.Human, IsPropertySaveable.Yes)]
[Serialize(SpawnType.Human, IsPropertySaveable.Yes, description: "Type of spawnpoint to spawn the entity at. Ignored if SpawnPointTag is set.")]
public SpawnType SpawnPointType { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of a spawnpoint to spawn the entity at.")]
public Identifier SpawnPointTag { get; set; }
[Serialize(CharacterTeamType.FriendlyNPC, IsPropertySaveable.Yes)]
[Serialize(CharacterTeamType.FriendlyNPC, IsPropertySaveable.Yes, description: "Team of the NPC to spawn. Only valid when spawning a character.")]
public CharacterTeamType TeamID { get; protected set; }
[Serialize(false, IsPropertySaveable.Yes, description: "Should we spawn the entity even when no spawn points with matching tags were found?")]
@@ -61,10 +64,10 @@ namespace Barotrauma
[Serialize(true, IsPropertySaveable.Yes, description: "If false, we won't spawn another character if one with the same identifier has already been spawned.")]
public bool AllowDuplicates { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "Number of entities to spawn.")]
public int Amount { get; set; }
[Serialize(100.0f, IsPropertySaveable.Yes)]
[Serialize(100.0f, IsPropertySaveable.Yes, description: "Random offset to add to the spawn position.")]
public float Offset { get; set; }
[Serialize("", IsPropertySaveable.Yes, "What outpost module tags does the entity prefer to spawn in.")]
@@ -2,13 +2,16 @@ using System.Collections.Generic;
namespace Barotrauma
{
/// <summary>
/// Executes all the StatusEffects defined as child elements of the action.
/// </summary>
partial class StatusEffectAction : EventAction
{
private readonly List<StatusEffect> effects = new List<StatusEffect>();
private readonly int actionIndex;
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the entity or entities the status effect should target.")]
public Identifier TargetTag { get; set; }
public StatusEffectAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
@@ -1,4 +1,4 @@
using Barotrauma.Extensions;
using Barotrauma.Extensions;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -6,26 +6,32 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Tags a specific entity. Tags are used by other actions to refer to specific entities. The tags are event-specific, i.e. you cannot use a tag that was added by another event to refer to an entity.
/// </summary>
class TagAction : EventAction
{
public enum SubType { Any = 0, Player = 1, Outpost = 2, Wreck = 4, BeaconStation = 8 }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "What criteria to use to select the entities to target. Valid values are players, player, traitor, nontraitor, nontraitorplayer, bot, crew, humanprefabidentifier:[id], jobidentifier:[id], structureidentifier:[id], structurespecialtag:[tag], itemidentifier:[id], itemtag:[tag], hull, hullname:[name], submarine:[type], eventtag:[tag].")]
public string Criteria { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "The tag to apply to the target.")]
public Identifier Tag { get; set; }
[Serialize(SubType.Any, IsPropertySaveable.Yes)]
[Serialize(SubType.Any, IsPropertySaveable.Yes, description: "The type of submarine the target needs to be in.")]
public SubType SubmarineType { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, "If set, the target must be in an outpost module that has this tag.")]
public Identifier RequiredModuleTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes, description: "Should incapacitated (e.g. dead, paralyzed, unconscious) characters be ignored, i.e. not considered valid targets?")]
public bool IgnoreIncapacitatedCharacters { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Can items that have been set to be hidden in-game be tagged?")]
public bool AllowHiddenItems { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "If there are multiple matching targets, should all of them be tagged or one chosen randomly?")]
public bool ChooseRandom { get; set; }
[Serialize(false, IsPropertySaveable.Yes, description: "Should the event continue if the TagAction can't find any valid targets?")]
@@ -85,7 +91,7 @@ namespace Barotrauma
private void TagByEventTag(Identifier eventTag)
{
AddTarget(Tag, ParentEvent.GetTargets(eventTag).Where(t => SubmarineTypeMatches(t.Submarine)));
AddTarget(Tag, ParentEvent.GetTargets(eventTag).Where(t => MatchesRequirements(t)));
}
private void TagPlayers()
@@ -157,7 +163,7 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Structure,
e => e is Structure s && SubmarineTypeMatches(s.Submarine) && s.Prefab.Identifier == identifier);
e => e is Structure s && MatchesRequirements(s) && s.Prefab.Identifier == identifier);
}
private void TagStructuresBySpecialTag(Identifier tag)
@@ -165,7 +171,7 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Structure,
e => e is Structure s && SubmarineTypeMatches(s.Submarine) && s.SpecialTag.ToIdentifier() == tag);
e => e is Structure s && MatchesRequirements(s) && s.SpecialTag.ToIdentifier() == tag);
}
private void TagItemsByIdentifier(Identifier identifier)
@@ -173,7 +179,7 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Item,
e => e is Item it && IsValidItem(it) && it.Prefab.Identifier == identifier);
e => e is Item it && it.Prefab.Identifier == identifier && IsValidItem(it));
}
private void TagItemsByTag(Identifier tag)
@@ -181,7 +187,7 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Item,
e => e is Item it && IsValidItem(it) && it.HasTag(tag));
e => e is Item it && it.HasTag(tag) && IsValidItem(it));
}
private void TagHulls()
@@ -189,7 +195,7 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Hull,
e => e is Hull h && SubmarineTypeMatches(h.Submarine));
e => e is Hull h && MatchesRequirements(h));
}
private void TagHullsByName(Identifier name)
@@ -197,7 +203,7 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Hull,
e => e is Hull h && SubmarineTypeMatches(h.Submarine) && h.RoomName.Contains(name.Value, StringComparison.OrdinalIgnoreCase));
e => e is Hull h && MatchesRequirements(h) && h.RoomName.Contains(name.Value, StringComparison.OrdinalIgnoreCase));
}
private void TagSubmarinesByType(Identifier type)
@@ -205,33 +211,76 @@ namespace Barotrauma
AddTargetPredicate(
Tag,
ScriptedEvent.TargetPredicate.EntityType.Submarine,
e => e is Submarine s && SubmarineTypeMatches(s) && (type.IsEmpty || type == s.Info?.Type.ToIdentifier()));
e => e is Submarine s && MatchesRequirements(s) && (type.IsEmpty || type == s.Info?.Type.ToIdentifier()));
}
private bool IsValidItem(Item it)
{
return
(!it.HiddenInGame || AllowHiddenItems) &&
ModuleTagMatches(it) &&
//if the item has just spawned, it may be in a hull but not moved into the coordinate space of the hull yet
//= it.Submarine still null
SubmarineTypeMatches(it.Submarine ?? it.CurrentHull?.Submarine ?? it.ParentInventory?.Owner?.Submarine);
}
private bool MatchesRequirements(Entity e)
{
return ModuleTagMatches(e) && SubmarineTypeMatches(e.Submarine);
}
private bool ModuleTagMatches(Entity e)
{
if (RequiredModuleTag.IsEmpty) { return true; }
if (e?.Submarine == null) { return false; }
Hull hull;
if (e is Character character)
{
hull = character.CurrentHull;
}
else if (e is Item item)
{
hull = item.CurrentHull;
}
else if (e is WayPoint wp)
{
hull = wp.CurrentHull;
}
else if (e is Hull h)
{
hull = h;
}
else
{
DebugConsole.AddWarning($"Potential error in event \"{ParentEvent.Prefab.Identifier}\": {nameof(TagAction)} cannot check the module tags of an entity of the type {e.GetType()}.");
return false;
}
return hull != null && hull.OutpostModuleTags.Contains(RequiredModuleTag);
}
private bool SubmarineTypeMatches(Submarine sub)
{
if (SubmarineType == SubType.Any) { return true; }
return SubmarineTypeMatches(sub, SubmarineType);
}
public static bool SubmarineTypeMatches(Submarine sub, SubType submarineType)
{
if (submarineType == SubType.Any) { return true; }
if (sub == null) { return false; }
switch (sub.Info.Type)
{
case Barotrauma.SubmarineType.Player:
return SubmarineType.HasFlag(SubType.Player) && sub != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle;
return submarineType.HasFlag(SubType.Player) && sub != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle;
case Barotrauma.SubmarineType.Outpost:
case Barotrauma.SubmarineType.OutpostModule:
return SubmarineType.HasFlag(SubType.Outpost);
return submarineType.HasFlag(SubType.Outpost);
case Barotrauma.SubmarineType.Wreck:
return SubmarineType.HasFlag(SubType.Wreck);
return submarineType.HasFlag(SubType.Wreck);
case Barotrauma.SubmarineType.BeaconStation:
return SubmarineType.HasFlag(SubType.BeaconStation);
return submarineType.HasFlag(SubType.BeaconStation);
default:
return false;
}
@@ -1,19 +1,22 @@
namespace Barotrauma;
/// <summary>
/// Teleports a specific entity to a specific spawn point.
/// </summary>
class TeleportAction : EventAction
{
public enum TeleportPosition { MainSub, Outpost }
[Serialize(TeleportPosition.MainSub, IsPropertySaveable.Yes)]
[Serialize(TeleportPosition.MainSub, IsPropertySaveable.Yes, description: "Should the entity be teleported to the main submarine or the outpost?")]
public TeleportPosition Position { get; set; }
[Serialize(SpawnType.Human, IsPropertySaveable.Yes)]
[Serialize(SpawnType.Human, IsPropertySaveable.Yes, description: "The type of the spawnpoint to teleport the character to.")]
public SpawnType SpawnType { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag of the spawnpoint.")]
public string SpawnPointTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the target(s) to teleport.")]
public Identifier TargetTag { get; set; }
private bool isFinished;
@@ -1,10 +1,12 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Waits for a player to trigger the action before continuing. Triggering can mean entering a specific trigger area, or interacting with a specific entity.
/// </summary>
class TriggerAction : EventAction
{
public enum TriggerType
@@ -1,11 +1,14 @@
namespace Barotrauma
{
/// <summary>
/// Triggers another scripted event.
/// </summary>
class TriggerEventAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the event to trigger.")]
public Identifier Identifier { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "If set to true, the event will trigger at the beginning of the next round. Useful for e.g. triggering some scripted event in the outpost after you finish a mission.")]
public bool NextRound { get; set; }
private bool isFinished;
@@ -41,7 +44,7 @@
}
else
{
var ev = eventPrefab.CreateInstance();
var ev = eventPrefab.CreateInstance(GameMain.GameSession.EventManager.RandomSeed);
if (ev != null)
{
GameMain.GameSession.EventManager.QueuedEvents.Enqueue(ev);
@@ -1,5 +1,8 @@
namespace Barotrauma
{
/// <summary>
/// Completes the tutorial. Only valid in tutorial events.
/// </summary>
class TutorialCompleteAction : EventAction
{
private bool isFinished;
@@ -2,17 +2,20 @@ using System.Linq;
namespace Barotrauma;
/// <summary>
/// Displays a tutorial icon next to a specific target.
/// </summary>
class TutorialIconAction : EventAction
{
public enum ActionType { Add, Remove, RemoveTarget, RemoveIcon, Clear };
[Serialize(ActionType.Add, IsPropertySaveable.Yes)]
[Serialize(ActionType.Add, IsPropertySaveable.Yes, description: "What to do with the icon. Add = add an icon, Remove = remove the icon that has the specific target and style, RemoveTarget = remove all icons assigned to the specific target, RemoveIcon = remove all icons with the specific style, Remove = remove all icons.")]
public ActionType Type { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the target to assign the icon to.")]
public Identifier TargetTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Style of the icon.")]
public Identifier IconStyle { get; set; }
private bool isFinished;
@@ -1,5 +1,8 @@
namespace Barotrauma;
/// <summary>
/// Highlights an UI element of some kind. Generally used in tutorials.
/// </summary>
partial class UIHighlightAction : EventAction
{
public enum ElementId
@@ -24,28 +27,28 @@ partial class UIHighlightAction : EventAction
MessageBoxCloseButton
}
[Serialize(ElementId.None, IsPropertySaveable.Yes)]
[Serialize(ElementId.None, IsPropertySaveable.Yes, description: "An arbitrary identifier that must match the userdata of the UI element. The userdatas of the element are hard-coded, so this option is generally intended for the developers' use.")]
public ElementId Id { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "If the element's userdata is an entity or an entity prefab, it's identifier must match this value.")]
public Identifier EntityIdentifier { get; set; }
[Serialize(OrderCategory.Emergency, IsPropertySaveable.Yes)]
[Serialize(OrderCategory.Emergency, IsPropertySaveable.Yes, description: "If the element's userdata is an order category, it must match this.")]
public OrderCategory OrderCategory { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "If the element's userdata is an order, it must match this identifier.")]
public Identifier OrderIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "If the element's userdata is an order with options, it must match this.")]
public Identifier OrderOption { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "If the element's userdata is an order, the order must target an entity with this tag.")]
public Identifier OrderTargetTag { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
[Serialize(true, IsPropertySaveable.Yes, description: "Should the element bounce up an down in addition to being highlighted.")]
public bool Bounce { get; set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes, description: "Should the action highlight the first matching element it finds, or all of them?")]
public bool HighlightMultiple { get; set; }
private bool isFinished;
@@ -1,12 +1,12 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
/// <summary>
/// Unlocks a "locked" pathways between locations, if there are any such paths adjacent to the current location.
/// </summary>
class UnlockPathAction : EventAction
{
public UnlockPathAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
@@ -1,8 +1,11 @@
namespace Barotrauma
{
/// <summary>
/// Waits for a specific amount of time before continuing the execution of the event.
/// </summary>
class WaitAction : EventAction
{
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes, description: "How long to wait (in seconds).")]
public float Time { get; set; }
private float timeRemaining;
@@ -1,22 +1,25 @@
#nullable enable
#nullable enable
using Barotrauma.Items.Components;
using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Waits for some item(s) to be fabricated before continuing the execution of the event.
/// </summary>
class WaitForItemFabricatedAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character who must fabricate the item. If empty, it doesn't matter who fabricates it.")]
public Identifier CharacterTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Identifier of the item that must be fabricated. Optional if ItemTag is set.")]
public Identifier ItemIdentifier { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item that must be fabricated. Optional if ItemIdentifier is set.")]
public Identifier ItemTag { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "Number of items that need to be fabricated.")]
public int Amount { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the fabricated item(s).")]
@@ -48,7 +51,8 @@ namespace Barotrauma
{
if (!ParentEvent.GetTargets(CharacterTag).Contains(character)) { return; }
}
if (item.ContainerIdentifier == ItemTag || item.HasTag(ItemTag))
if ((!ItemIdentifier.IsEmpty && item.Prefab.Identifier == ItemIdentifier) ||
(!ItemTag.IsEmpty && item.HasTag(ItemTag)))
{
if (!ApplyTagToItem.IsEmpty)
{
@@ -7,30 +7,33 @@ using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Waits for some item(s) to be used before continuing the execution of the event.
/// </summary>
class WaitForItemUsedAction : EventAction
{
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the item that must be used. Note that the item needs to have been tagged by the event - this does not refer to the tags that can be set per-item in the sub editor.")]
public Identifier ItemTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Tag of the character that must use the item. If there's multiple matching characters, it's enough if any of them use the item. If empty, it doesn't matter who uses the item.")]
public Identifier UserTag { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
[Serialize("", IsPropertySaveable.Yes, description: "Name of the ItemComponent that the character must use. If empty, the character attempts to use all of them.")]
public Identifier TargetItemComponent { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the target item when it's used.")]
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the target item when it's used.")]
public Identifier ApplyTagToItem { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the user when the target item is used.")]
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the user when the target item is used.")]
public Identifier ApplyTagToUser{ get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the hull the target item is inside when the item is used.")]
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the hull the target item is inside when the item is used.")]
public Identifier ApplyTagToHull { get; set; }
[Serialize("", IsPropertySaveable.Yes, description: "Tag to apply to the hull the target item is inside, and all the hulls it's linked to, when the item is used.")]
[Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the hull the target item is inside, and all the hulls it's linked to, when the item is used.")]
public Identifier ApplyTagToLinkedHulls { get; set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes, description: "How many times does the item need to be used. Defaults to 1.")]
public int RequiredUseCount { get; set; }
private bool isFinished;