Client LuaCsForBarotrauma
CircuitBoxCursor.cs
1 #nullable enable
2 
3 using System;
4 using Microsoft.Xna.Framework;
5 
6 namespace Barotrauma
7 {
8  [NetworkSerialize]
9  internal readonly record struct NetCircuitBoxCursorInfo(Vector2[] RecordedPositions, Option<Vector2> DragStart, Option<Identifier> HeldItem, ushort CharacterID = 0) : INetSerializableStruct;
10 
11  internal sealed class CircuitBoxCursor
12  {
13  public NetCircuitBoxCursorInfo Info;
14 
15  public CircuitBoxCursor(NetCircuitBoxCursorInfo info)
16  {
17  if (Entity.FindEntityByID(info.CharacterID) is Character c)
18  {
19  Color = GenerateColor(c.Name);
20  }
21 
22  UpdateInfo(info);
23  }
24 
25  public void UpdateInfo(NetCircuitBoxCursorInfo newInfo)
26  {
27  Info = newInfo;
28 
29  newInfo.HeldItem.Match(
30  some: newIdentifier =>
31  HeldPrefab.Match(
32  some: oldPrefab =>
33  {
34  if (oldPrefab.Identifier == newIdentifier) { return; }
35  SetHeldPrefab(newIdentifier);
36  },
37  none: () => SetHeldPrefab(newIdentifier)
38  ),
39  none: () => HeldPrefab = Option.None);
40 
41  prevPosition = DrawPosition;
42 
43  void SetHeldPrefab(Identifier identifier)
44  {
45  ItemPrefab? prefab = ItemPrefab.Prefabs.Find(prefab => prefab.Identifier.Equals(identifier));
46  HeldPrefab = prefab is null ? Option.None : Option.Some(prefab);
47  }
48  }
49 
50  public Option<ItemPrefab> HeldPrefab { get; private set; } = Option.None;
51 
52  public Color Color = Color.White;
53 
54  public static Color GenerateColor(string name)
55  {
56  Random random = new Random(ToolBox.StringToInt(name));
57  return ToolBoxCore.HSVToRGB(random.NextSingle() * 360f, 1f, 1f);
58  }
59 
60  private const float UpdateTimeout = 5f;
61 
62  private float updateTimer;
63  private float positionTimer;
64  private Vector2 prevPosition;
65  public Vector2 DrawPosition;
66 
67  public bool IsActive => updateTimer < UpdateTimeout;
68 
69  public void Update(float deltaTime)
70  {
71  updateTimer += deltaTime;
72 
73  Vector2 finalPosition = Info.RecordedPositions[^1];
74 
75  if (positionTimer > 1f)
76  {
77  DrawPosition = finalPosition;
78  prevPosition = Vector2.Zero;
79  }
80  else
81  {
82  positionTimer += deltaTime;
83 
84  float stepTimer = positionTimer * 10f;
85  int targetPositonIndex = (int)MathF.Floor(stepTimer);
86  int prevPosIndex = targetPositonIndex - 1;
87 
88  Vector2 targetPosition = IsInRange(targetPositonIndex, Info.RecordedPositions.Length)
89  ? Info.RecordedPositions[targetPositonIndex]
90  : finalPosition;
91 
92  Vector2 prevTargetPosition = IsInRange(prevPosIndex, Info.RecordedPositions.Length)
93  ? Info.RecordedPositions[prevPosIndex]
94  : prevPosition;
95 
96  DrawPosition = Vector2.Lerp(prevTargetPosition, targetPosition, MathHelper.Clamp(stepTimer % 1f, 0f, 1f));
97  }
98 
99  static bool IsInRange(int index, int length)
100  => index >= 0 && index < length;
101  }
102 
103  public void ResetTimers()
104  {
105  positionTimer = 0f;
106  updateTimer = 0f;
107  }
108  }
109 }