Client LuaCsForBarotrauma
WaitForItemUsedAction.cs
1 #nullable enable
2 
5 using System.Collections.Generic;
6 using System.Linq;
7 
8 namespace Barotrauma
9 {
14  {
15  [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.")]
16  public Identifier ItemTag { get; set; }
17 
18  [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.")]
19  public Identifier UserTag { get; set; }
20 
21  [Serialize("", IsPropertySaveable.Yes, description: "Name of the ItemComponent that the character must use. If empty, the character attempts to use all of them.")]
22  public Identifier TargetItemComponent { get; set; }
23 
24  [Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the target item when it's used.")]
25  public Identifier ApplyTagToItem { get; set; }
26 
27  [Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the user when the target item is used.")]
28  public Identifier ApplyTagToUser{ get; set; }
29 
30  [Serialize("", IsPropertySaveable.Yes, description: "Optional tag to apply to the hull the target item is inside when the item is used.")]
31  public Identifier ApplyTagToHull { get; set; }
32 
33  [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.")]
34  public Identifier ApplyTagToLinkedHulls { get; set; }
35 
36  [Serialize(1, IsPropertySaveable.Yes, description: "How many times does the item need to be used. Defaults to 1.")]
37  public int RequiredUseCount { get; set; }
38 
39  private bool isFinished;
40 
41  private readonly HashSet<Entity> targets = new HashSet<Entity>();
42  private readonly HashSet<ItemComponent> targetComponents = new HashSet<ItemComponent>();
43 
44  private int useCount = 0;
45 
46  private Identifier onUseEventIdentifier;
47  private Identifier OnUseEventIdentifier
48  {
49  get
50  {
51  if (onUseEventIdentifier.IsEmpty)
52  {
53  onUseEventIdentifier = (ParentEvent.Prefab.Identifier + ParentEvent.Actions.IndexOf(this).ToString()).ToIdentifier();
54  }
55  return onUseEventIdentifier;
56  }
57  }
58 
59  public WaitForItemUsedAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
60  {
61  if (ItemTag.IsEmpty)
62  {
63  DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\". {nameof(ItemTag)} not set in {nameof(WaitForItemUsedAction)}.");
64  }
65  }
66 
67  private void OnItemUsed(Item item, Character user)
68  {
69  if (!UserTag.IsEmpty)
70  {
71  if (!ParentEvent.GetTargets(UserTag).Contains(user)) { return; }
72  }
73 
74  useCount++;
75  if (useCount < RequiredUseCount) { return; }
76 
77  if (!ApplyTagToItem.IsEmpty)
78  {
80  }
81  if (!ApplyTagToUser.IsEmpty && user != null)
82  {
84  }
86  DeregisterTargets();
87  isFinished = true;
88  }
89 
90  public override void Update(float deltaTime)
91  {
92  TryRegisterTargets();
93  }
94 
95  private void TryRegisterTargets()
96  {
97  foreach (Entity target in ParentEvent.GetTargets(ItemTag))
98  {
99  //already registered, ignore
100  if (targets.Contains(target)) { continue; }
101  if (target is not Item item) { continue; }
102  if (TargetItemComponent.IsEmpty)
103  {
104  item.GetComponents<ItemComponent>().ForEach(ic => Register(ic));
105  }
106  else if (item.Components.FirstOrDefault(ic => ic.Name == TargetItemComponent) is ItemComponent targetItemComponent)
107  {
108  Register(targetItemComponent);
109  }
110  else
111  {
112 #if DEBUG
113  DebugConsole.ThrowError($"Failed to find the component {TargetItemComponent} on item {item.Prefab.Identifier}");
114 #endif
115  }
116  }
117  void Register(ItemComponent ic)
118  {
119  targets.Add(ic.Item);
120  targetComponents.Add(ic);
121  ic.OnUsed.RegisterOverwriteExisting(
122  OnUseEventIdentifier,
123  i => { OnItemUsed(i.Item, i.User); });
124  }
125  }
126 
127  private void DeregisterTargets()
128  {
129  foreach (ItemComponent ic in targetComponents)
130  {
131  ic.OnUsed.Deregister(OnUseEventIdentifier);
132  }
133  targetComponents.Clear();
134  targets.Clear();
135  }
136 
137 
138  public override bool IsFinished(ref string goTo)
139  {
140  return isFinished;
141  }
142 
143  public override void Reset()
144  {
145  isFinished = false;
146  useCount = 0;
147  DeregisterTargets();
148  }
149 
150  public override string ToDebugString()
151  {
152  return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(WaitForItemUsedAction)} -> ({ItemTag})";
153  }
154  }
155 }
readonly ScriptedEvent ParentEvent
Definition: EventAction.cs:106
void ApplyTagsToHulls(Entity entity, Identifier hullTag, Identifier linkedHullTag)
Definition: EventAction.cs:181
EventPrefab Prefab
Definition: Event.cs:16
The base class for components holding the different functionalities of the item
readonly Identifier Identifier
Definition: Prefab.cs:34
void AddTarget(Identifier tag, Entity target)
List< EventAction > Actions
IEnumerable< Entity > GetTargets(Identifier tag)
Waits for some item(s) to be used before continuing the execution of the event.
override void Update(float deltaTime)
override bool IsFinished(ref string goTo)
Has the action finished.
WaitForItemUsedAction(ScriptedEvent parentEvent, ContentXElement element)
override string ToDebugString()
Rich test to display in debugdraw