Client LuaCsForBarotrauma
AbilityConditionCharacter.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 
5 namespace Barotrauma.Abilities
6 {
8  {
9  private readonly List<TargetType> targetTypes;
10 
11  private readonly List<PropertyConditional> conditionals = new List<PropertyConditional>();
12 
17  private readonly bool targetAbilityTarget = false;
18 
19  public AbilityConditionCharacter(CharacterTalent characterTalent, ContentXElement conditionElement) : base(characterTalent, conditionElement)
20  {
21  targetTypes = ParseTargetTypes(
22  conditionElement.GetAttributeStringArray("targettypes",
23  conditionElement.GetAttributeStringArray("targettype", Array.Empty<string>())));
24 
25  foreach (ContentXElement subElement in conditionElement.Elements())
26  {
27  if (subElement.NameAsIdentifier() == "conditional")
28  {
29  conditionals.AddRange(PropertyConditional.FromXElement(subElement));
30  }
31  }
32 
33  //don't log this error if this is a subclass of AbilityConditionCharacter
34  //(in that case not having any conditionals here is ok)
35  if (!targetTypes.Any() && !conditionals.Any() && GetType() == typeof(AbilityConditionCharacter))
36  {
37  DebugConsole.ThrowError($"Error in talent \"{characterTalent}\". No target types or conditionals defined - the condition will match any character.",
38  contentPackage: conditionElement.ContentPackage);
39  }
40 
41  targetAbilityTarget = conditionElement.GetAttributeBool(nameof(targetAbilityTarget), this is not AbilityConditionHasPermanentStat);
42  }
43 
44  public sealed override bool MatchesCondition()
45  {
46  //by default data-reliant conditions don't accept null, but in this case it's ok,
47  //because we can assume it's the character who has the talent
48  return MatchesCondition(abilityObject: null);
49  }
50 
51  public sealed override bool MatchesCondition(AbilityObject abilityObject)
52  {
53  return invert ? !MatchesConditionSpecific(abilityObject) : MatchesConditionSpecific(abilityObject);
54  }
55 
56  protected sealed override bool MatchesConditionSpecific(AbilityObject abilityObject)
57  {
58  Character targetCharacter =
59  targetAbilityTarget ?
60  (abilityObject as IAbilityCharacter)?.Character ?? character :
61  character;
62  if (targetCharacter is null) { return false; }
63  if (!IsViableTarget(targetTypes, targetCharacter)) { return false; }
64  foreach (var conditional in conditionals)
65  {
66  if (!conditional.Matches(targetCharacter)) { return false; }
67  }
68  return MatchesCharacter(targetCharacter);
69  }
70 
71  protected virtual bool MatchesCharacter(Character character)
72  {
73  return true;
74  }
75  }
76 }
AbilityConditionCharacter(CharacterTalent characterTalent, ContentXElement conditionElement)
sealed override bool MatchesConditionSpecific(AbilityObject abilityObject)
sealed override bool MatchesCondition(AbilityObject abilityObject)
List< TargetType > ParseTargetTypes(string[] targetTypeStrings)
bool IsViableTarget(IEnumerable< TargetType > targetTypes, Character targetCharacter)
Identifier NameAsIdentifier()
IEnumerable< ContentXElement > Elements()
string?[] GetAttributeStringArray(string key, string[]? def, bool convertToLowerInvariant=false)
Conditionals are used by some in-game mechanics to require one or more conditions to be met for those...
static IEnumerable< PropertyConditional > FromXElement(ContentXElement element, Predicate< XAttribute >? predicate=null)