Unstable 1.8.4.0
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -68,7 +69,7 @@ namespace Barotrauma
|
||||
SpeciesGroup,
|
||||
|
||||
/// <summary>
|
||||
/// Check against the target's tags. Only works on items.
|
||||
/// Check against the target's tags. Only works on items and characters.
|
||||
///
|
||||
/// Several tags can be checked against by using a comma-separated list.
|
||||
/// </summary>
|
||||
@@ -104,7 +105,12 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Check against the current World Hostility setting (previously known as "Difficulty").
|
||||
/// </summary>
|
||||
WorldHostility
|
||||
WorldHostility,
|
||||
|
||||
/// <summary>
|
||||
/// Check against the difficulty of the current level.
|
||||
/// </summary>
|
||||
LevelDifficulty
|
||||
}
|
||||
|
||||
public enum LogicalOperatorType
|
||||
@@ -180,6 +186,11 @@ namespace Barotrauma
|
||||
/// Only works on items.
|
||||
/// </summary>
|
||||
public readonly string TargetItemComponent;
|
||||
|
||||
/// <summary>
|
||||
/// When targeting item components, should we require them all to match the conditional or any (default).
|
||||
/// </summary>
|
||||
public readonly LogicalOperatorType ItemComponentComparison;
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the conditionals defined by this element check against the attacking character instead of the attacked character.
|
||||
@@ -205,11 +216,13 @@ namespace Barotrauma
|
||||
|
||||
public static IEnumerable<PropertyConditional> FromXElement(ContentXElement element, Predicate<XAttribute>? predicate = null)
|
||||
{
|
||||
var targetItemComponent = element.GetAttributeString(nameof(TargetItemComponent), "");
|
||||
var targetContainer = element.GetAttributeBool(nameof(TargetContainer), false);
|
||||
var targetSelf = element.GetAttributeBool(nameof(TargetSelf), false);
|
||||
var targetGrandParent = element.GetAttributeBool(nameof(TargetGrandParent), false);
|
||||
var targetContainedItem = element.GetAttributeBool(nameof(TargetContainedItem), false);
|
||||
string targetItemComponent = element.GetAttributeString(nameof(TargetItemComponent), string.Empty);
|
||||
bool targetContainer = element.GetAttributeBool(nameof(TargetContainer), false);
|
||||
bool targetSelf = element.GetAttributeBool(nameof(TargetSelf), false);
|
||||
bool targetGrandParent = element.GetAttributeBool(nameof(TargetGrandParent), false);
|
||||
bool targetContainedItem = element.GetAttributeBool(nameof(TargetContainedItem), false);
|
||||
|
||||
LogicalOperatorType itemComponentComparison = element.GetAttributeEnum(nameof(ItemComponentComparison), LogicalOperatorType.Or);
|
||||
|
||||
ConditionType? overrideConditionType = null;
|
||||
if (element.GetAttributeBool(nameof(ConditionType.SkillRequirement), false))
|
||||
@@ -222,23 +235,22 @@ namespace Barotrauma
|
||||
if (!IsValid(attribute)) { continue; }
|
||||
if (predicate != null && !predicate(attribute)) { continue; }
|
||||
|
||||
var (comparisonOperator, attributeValueString) = ExtractComparisonOperatorFromConditionString(attribute.Value);
|
||||
(ComparisonOperatorType comparisonOperator, string attributeValueString) = ExtractComparisonOperatorFromConditionString(attribute.Value);
|
||||
if (string.IsNullOrWhiteSpace(attributeValueString))
|
||||
{
|
||||
DebugConsole.ThrowError($"Conditional attribute value is empty: {element}", contentPackage: element.ContentPackage);
|
||||
continue;
|
||||
}
|
||||
|
||||
var conditionType = overrideConditionType ??
|
||||
(Enum.TryParse(attribute.Name.LocalName, ignoreCase: true, out ConditionType type)
|
||||
? type
|
||||
: ConditionType.PropertyValueOrAffliction);
|
||||
ConditionType conditionType = overrideConditionType ??
|
||||
(Enum.TryParse(attribute.Name.LocalName, ignoreCase: true, out ConditionType type) ? type : ConditionType.PropertyValueOrAffliction);
|
||||
|
||||
yield return new PropertyConditional(
|
||||
attributeName: attribute.NameAsIdentifier(),
|
||||
comparisonOperator: comparisonOperator,
|
||||
attributeValue: attributeValueString,
|
||||
targetItemComponent: targetItemComponent,
|
||||
itemComponentComparison: itemComponentComparison,
|
||||
targetSelf: targetSelf,
|
||||
targetContainer: targetContainer,
|
||||
targetGrandParent: targetGrandParent,
|
||||
@@ -269,6 +281,7 @@ namespace Barotrauma
|
||||
ComparisonOperatorType comparisonOperator,
|
||||
string attributeValue,
|
||||
string targetItemComponent,
|
||||
LogicalOperatorType itemComponentComparison,
|
||||
bool targetSelf,
|
||||
bool targetContainer,
|
||||
bool targetGrandParent,
|
||||
@@ -278,6 +291,7 @@ namespace Barotrauma
|
||||
AttributeName = attributeName;
|
||||
|
||||
TargetItemComponent = targetItemComponent;
|
||||
ItemComponentComparison = itemComponentComparison;
|
||||
TargetSelf = targetSelf;
|
||||
TargetContainer = targetContainer;
|
||||
TargetGrandParent = targetGrandParent;
|
||||
@@ -421,7 +435,15 @@ namespace Barotrauma
|
||||
}
|
||||
return ComparisonOperatorIsNotEquals;
|
||||
case ConditionType.HasTag:
|
||||
return ItemMatchesTagCondition(target);
|
||||
if (targetChar != null)
|
||||
{
|
||||
return CheckMatchingTags(targetChar.Params.HasTag);
|
||||
}
|
||||
if (target is Item item)
|
||||
{
|
||||
return CheckMatchingTags(item.HasTag);
|
||||
}
|
||||
return ComparisonOperatorIsNotEquals;
|
||||
case ConditionType.HasStatusTag:
|
||||
if (target == null) { return ComparisonOperatorIsNotEquals; }
|
||||
|
||||
@@ -458,14 +480,18 @@ namespace Barotrauma
|
||||
return ComparisonOperatorIsNotEquals
|
||||
? numTagsFound < AttributeValueAsTags.Length // true when some tag wasn't found
|
||||
: numTagsFound >= AttributeValueAsTags.Length; // true when all the tags are found
|
||||
case ConditionType.WorldHostility:
|
||||
{
|
||||
case ConditionType.LevelDifficulty:
|
||||
if (Level.Loaded is { } level)
|
||||
{
|
||||
return NumberMatchesRequirement(level.Difficulty);
|
||||
}
|
||||
return false;
|
||||
case ConditionType.WorldHostility:
|
||||
if (GameMain.GameSession?.Campaign is CampaignMode campaign)
|
||||
{
|
||||
return Compare(campaign.Settings.WorldHostility, cachedHostilityValue, ComparisonOperator);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
bool equals = CheckOnlyEquality(target);
|
||||
return ComparisonOperatorIsNotEquals
|
||||
@@ -547,15 +573,13 @@ namespace Barotrauma
|
||||
? matches <= 0
|
||||
: matches >= AttributeValueAsTags.Length;
|
||||
}
|
||||
|
||||
private bool ItemMatchesTagCondition(ISerializableEntity? target)
|
||||
|
||||
private bool CheckMatchingTags(Func<Identifier, bool> predicate)
|
||||
{
|
||||
if (target is not Item item) { return ComparisonOperatorIsNotEquals; }
|
||||
|
||||
int matches = 0;
|
||||
foreach (var tag in AttributeValueAsTags)
|
||||
foreach (Identifier tag in AttributeValueAsTags)
|
||||
{
|
||||
if (item.HasTag(tag)) { matches++; }
|
||||
if (predicate(tag)) { matches++; }
|
||||
}
|
||||
return SufficientTagMatches(matches);
|
||||
}
|
||||
@@ -563,13 +587,7 @@ namespace Barotrauma
|
||||
public bool TargetTagMatchesTagCondition(Identifier targetTag)
|
||||
{
|
||||
if (targetTag.IsEmpty || Type != ConditionType.HasTag) { return false; }
|
||||
|
||||
int matches = 0;
|
||||
foreach (var tag in AttributeValueAsTags)
|
||||
{
|
||||
if (targetTag == tag) { matches++; }
|
||||
}
|
||||
return SufficientTagMatches(matches);
|
||||
return CheckMatchingTags(targetTag.Equals);
|
||||
}
|
||||
|
||||
private bool NumberMatchesRequirement(float testedValue)
|
||||
@@ -660,5 +678,69 @@ namespace Barotrauma
|
||||
_ => leftValue.CompareTo(rightValue) == 0,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks for child elements of name "conditional" and bundles them with an attribute of name "comparison".
|
||||
/// </summary>
|
||||
public static LogicalComparison? LoadConditionals(ContentXElement element, LogicalOperatorType defaultOperatorType = LogicalOperatorType.And)
|
||||
{
|
||||
var conditionalElements = element.GetChildElements("conditional");
|
||||
if (conditionalElements.None()) { return default; }
|
||||
List<PropertyConditional> conditionals = new();
|
||||
foreach (ContentXElement subElement in conditionalElements)
|
||||
{
|
||||
conditionals.AddRange(FromXElement(subElement));
|
||||
}
|
||||
var logicalOperator = element.GetAttributeEnum("comparison", defaultOperatorType);
|
||||
return new LogicalComparison(conditionals, logicalOperator);
|
||||
}
|
||||
|
||||
public static bool CheckConditionals(ISerializableEntity conditionalTarget, IEnumerable<PropertyConditional> conditionals, LogicalOperatorType logicalOperator)
|
||||
{
|
||||
if (conditionals == null) { return true; }
|
||||
if (conditionals.None()) { return true; }
|
||||
switch (logicalOperator)
|
||||
{
|
||||
case LogicalOperatorType.And:
|
||||
foreach (var conditional in conditionals)
|
||||
{
|
||||
if (!conditional.Matches(conditionalTarget))
|
||||
{
|
||||
// Some conditional didn't match.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// All conditionals matched.
|
||||
return true;
|
||||
case LogicalOperatorType.Or:
|
||||
foreach (var conditional in conditionals)
|
||||
{
|
||||
if (conditional.Matches(conditionalTarget))
|
||||
{
|
||||
// Some conditional matched.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// None of the conditionals matched.
|
||||
return false;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bundles up a bunch of conditionals with a logical operator.
|
||||
/// </summary>
|
||||
public class LogicalComparison
|
||||
{
|
||||
public readonly ImmutableArray<PropertyConditional> Conditionals;
|
||||
public readonly LogicalOperatorType LogicalOperator;
|
||||
|
||||
public LogicalComparison(IEnumerable<PropertyConditional> conditionals, LogicalOperatorType logicalOperator)
|
||||
{
|
||||
Conditionals = conditionals.ToImmutableArray();
|
||||
LogicalOperator = logicalOperator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user