Client LuaCsForBarotrauma
CheckDataAction.cs
1 #nullable enable
2 using System;
3 
4 namespace Barotrauma
5 {
6 
11  {
12  [Serialize("", IsPropertySaveable.Yes, description: "Identifier of the data to check.")]
13  public Identifier Identifier { get; set; } = Identifier.Empty;
14 
15  [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\".)")]
16  public string Condition { get; set; } = "";
17 
18  [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.")]
19  public bool ForceString { get; set; }
20 
21  [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\".")]
22  public bool CheckAgainstMetadata { get; set; }
23 
24  protected object? value2;
25  protected object? value1;
26 
28 
29  public CheckDataAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
30  {
31  if (string.IsNullOrEmpty(Condition))
32  {
33  Condition = element.GetAttributeString("value", string.Empty)!;
34  if (string.IsNullOrEmpty(Condition))
35  {
36  DebugConsole.ThrowError($"Error in scripted event \"{parentEvent.Prefab.Identifier}\". CheckDataAction with no condition set ({element}).",
37  contentPackage: element?.ContentPackage);
38  }
39  }
40  }
41 
42  public CheckDataAction(ContentXElement element, string parentDebugString) : base(null, element)
43  {
44  if (string.IsNullOrEmpty(Condition))
45  {
46  Condition = element.GetAttributeString("value", string.Empty)!;
47  if (string.IsNullOrEmpty(Condition))
48  {
49  DebugConsole.ThrowError($"Error in scripted event \"{parentDebugString}\". CheckDataAction with no condition set ({element}).",
50  contentPackage: element?.ContentPackage);
51  }
52  }
53  }
54 
55  public bool GetSuccess()
56  {
57  return DetermineSuccess() ?? false;
58  }
59 
60  protected override bool? DetermineSuccess()
61  {
62  if (GameMain.GameSession?.GameMode is not CampaignMode campaignMode) { return false; }
63 
64  (Operator, string value) = PropertyConditional.ExtractComparisonOperatorFromConditionString(Condition);
66  {
67  DebugConsole.ThrowError($"{Condition} is invalid, it should start with an operator followed by a boolean or a floating point value.",
68  contentPackage: ParentEvent?.Prefab?.ContentPackage);
69  return false;
70  }
71 
73  {
74  object? metadata1 = campaignMode.CampaignMetadata.GetValue(Identifier);
75  object? metadata2 = campaignMode.CampaignMetadata.GetValue(value.ToIdentifier());
76 
77  if (metadata1 == null || metadata2 == null)
78  {
79  return Operator switch
80  {
81  PropertyConditional.ComparisonOperatorType.Equals => metadata1 == metadata2,
82  PropertyConditional.ComparisonOperatorType.NotEquals => metadata1 != metadata2,
83  _ => false
84  };
85  }
86 
87  if (!ForceString)
88  {
89  switch (metadata1)
90  {
91  case bool bool1 when metadata2 is bool bool2:
92  return CompareBool(bool1, bool2) ?? false;
93  case float float1 when metadata2 is float float2:
94  return PropertyConditional.CompareFloat(float1, float2, Operator);
95  }
96  }
97 
98  if (metadata1 is string string1 && metadata2 is string string2)
99  {
100  return CompareString(string1, string2) ?? false;
101  }
102 
103  return false;
104  }
105 
106  if (!ForceString)
107  {
108  bool? tryBoolean = TryBoolean(campaignMode, value);
109  if (tryBoolean != null) { return tryBoolean; }
110 
111  bool? tryFloat = TryFloat(campaignMode, value);
112  if (tryFloat != null) { return tryFloat; }
113  }
114 
115  bool? tryString = TryString(campaignMode, value);
116  if (tryString != null) { return tryString; }
117 
118  return false;
119  }
120 
121  private bool? TryBoolean(CampaignMode campaignMode, string value)
122  {
123  if (bool.TryParse(value, out bool b))
124  {
125  return CompareBool(GetBool(campaignMode), b);
126  }
127 
128  DebugConsole.Log($"{value} != bool");
129  return null;
130  }
131 
132  private bool? CompareBool(bool val1, bool val2)
133  {
134  value1 = val1;
135  value2 = val2;
136  switch (Operator)
137  {
138  case PropertyConditional.ComparisonOperatorType.Equals:
139  return val1 == val2;
140  case PropertyConditional.ComparisonOperatorType.NotEquals:
141  return val1 != val2;
142  default:
143  DebugConsole.Log($"Only \"Equals\" and \"Not equals\" operators are allowed for a boolean (was {Operator} for {val2}).");
144  return false;
145  }
146  }
147 
148  private bool? TryFloat(CampaignMode campaignMode, string value)
149  {
150  if (float.TryParse(value, out float f))
151  {
152  return PropertyConditional.CompareFloat(GetFloat(campaignMode), f, Operator);
153  }
154 
155  DebugConsole.Log($"{value} != float");
156  return null;
157  }
158 
159  private bool? TryString(CampaignMode campaignMode, string value)
160  {
161  return CompareString(GetString(campaignMode), value);
162  }
163 
164  private bool? CompareString(string val1, string val2)
165  {
166  value1 = val1;
167  value2 = val2;
168  bool equals = string.Equals(val1, val2, StringComparison.OrdinalIgnoreCase);
169  switch (Operator)
170  {
171  case PropertyConditional.ComparisonOperatorType.Equals:
172  return equals;
173  case PropertyConditional.ComparisonOperatorType.NotEquals:
174  return !equals;
175  default:
176  DebugConsole.Log($"Only \"Equals\" and \"Not equals\" operators are allowed for a string (was {Operator} for {val2}).");
177  return null;
178  }
179  }
180 
181  protected virtual bool GetBool(CampaignMode campaignMode)
182  {
183  return campaignMode.CampaignMetadata.GetBoolean(Identifier);
184  }
185 
186  protected virtual float GetFloat(CampaignMode campaignMode)
187  {
188  return campaignMode.CampaignMetadata.GetFloat(Identifier);
189  }
190 
191  private string GetString(CampaignMode campaignMode)
192  {
193  return campaignMode.CampaignMetadata.GetString(Identifier);
194  }
195 
196  public override string ToDebugString()
197  {
198  string condition = "?";
199  if (value2 != null && value1 != null)
200  {
201  condition = $"{value1.ColorizeObject()} {Operator.ColorizeObject()} {value2.ColorizeObject()}";
202  }
203  else if (!Identifier.IsEmpty)
204  {
205  condition = $"{Identifier} {Condition}".ColorizeObject();
206  }
207 
208  return $"{ToolBox.GetDebugSymbol(succeeded.HasValue)} {nameof(CheckDataAction)} -> (Data: {Identifier.ColorizeObject()}, Success: {succeeded.ColorizeObject()}, Expression: {condition})";
209  }
210  }
211 }
Can be used to check arbitrary campaign metadata set using SetDataAction.
override string ToDebugString()
Rich test to display in debugdraw
virtual float GetFloat(CampaignMode campaignMode)
PropertyConditional.ComparisonOperatorType Operator
CheckDataAction(ScriptedEvent parentEvent, ContentXElement element)
CheckDataAction(ContentXElement element, string parentDebugString)
override? bool DetermineSuccess()
virtual bool GetBool(CampaignMode campaignMode)
string? GetAttributeString(string key, string? def)
readonly ScriptedEvent ParentEvent
Definition: EventAction.cs:106
static GameSession?? GameSession
Definition: GameMain.cs:88
Conditionals are used by some in-game mechanics to require one or more conditions to be met for those...
ComparisonOperatorType
There are several ways to compare properties to values. The comparison operator to use can be specifi...
static bool CompareFloat(float val1, float val2, ComparisonOperatorType op)