-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPlayerSelector.cs
More file actions
153 lines (130 loc) · 5.74 KB
/
Copy pathPlayerSelector.cs
File metadata and controls
153 lines (130 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnboundLib;
using UnityEngine;
namespace ModsPlus
{
/// <summary>
/// <para>A utility component for detecting and reacting to the user clicking on a player.</para>
///
/// Note: This component must be attached to a <c>GameObject</c> along with a collider for clicks to be detected.
/// Recommend a <see cref="SphereCollider"/> of approximately radius <c>3</c> and center <c>(0, 1, 0)</c>; values are based on an object with default scale and no parent objects.
/// </summary>
public class PlayerSelector : MonoBehaviour
{
private static Dictionary<GameObject, List<PlayerSelector>> selectors = new Dictionary<GameObject, List<PlayerSelector>>();
private event Action<Player> OnPlayerClicked;
private bool active = true;
private void OnDisable()
{
Destroy(gameObject);
}
private void OnMouseDown()
{
if (!active) return;
var player = GetComponentInParent<Player>();
OnPlayerClicked?.Invoke(player);
}
private void Remove()
{
active = false;
if (!gameObject.activeInHierarchy)
{
Destroy(gameObject);
return;
}
GetComponent<ParticleSystem>()?.Stop();
Destroy(gameObject, 5f);
}
/// <summary>
/// <para>Clears all player selectors initialized using a prefab with a name containing <c>basePrefabName</c></para>
/// <para>Note: This is potentially dangerous, it is recommended to use <see cref="PlayerSelector.Clear(GameObject)"/> instead</para>
/// </summary>
/// <param name="basePrefabName">Case sensitive</param>
public static void Clear(string basePrefabName)
{
foreach (var key in selectors.Keys.Where(go => go.name.Contains(basePrefabName)))
{
Clear(key);
}
}
/// <summary>
/// Clears all player selectors initialized using the given prefab
/// </summary>
/// <param name="basePrefab"></param>
public static void Clear(GameObject basePrefab)
{
if (selectors.TryGetValue(basePrefab, out List<PlayerSelector> objs))
{
for (int i = 0; i < objs.Count; i++)
{
if (objs[i] == null) continue;
objs[i].Remove();
}
objs.Clear();
}
}
public static void InstantiateOnAll(GameObject selectorPrefab, Action<Player> selectedCallback)
{
InstantiateOn(selectorPrefab, PlayerManager.instance.players, selectedCallback);
}
public static void InstantiateOnEnemies(GameObject selectorPrefab, Action<Player> selectedCallback)
{
int teamId = PlayerManager.instance.players
.Where(p => p.data.view.IsMine)
.Select(p => p.teamID)
.First();
var targets = PlayerManager.instance.players.Where(p => p.teamID != teamId);
InstantiateOn(selectorPrefab, targets, selectedCallback);
}
public static void InstantiateOnFriendlies(GameObject selectorPrefab, Action<Player> selectedCallback)
{
int teamId = PlayerManager.instance.players
.Where(p => p.data.view.IsMine)
.Select(p => p.teamID)
.First();
var targets = PlayerManager.instance.players.Where(p => p.teamID == teamId);
InstantiateOn(selectorPrefab, targets, selectedCallback);
}
/// <summary>
/// Initialize a <see cref="PlayerSelector"/> on each provided <see cref="Player"/>
/// </summary>
/// <param name="selectorPrefab">Base prefab with a <see cref="PlayerSelector"/> attached</param>
/// <param name="selectedCallback">Action to invoke when the user has clicked one of the instantiated <see cref="PlayerSelector"/>s</param>
/// <param name="forceInitializeAllPlayers">(Optional) if true a <see cref="PlayerSelector"/> will be spawned for every player</param>
public static void InstantiateOn(GameObject selectorPrefab, IEnumerable<Player> targets, Action<Player> selectedCallback)
{
if (selectorPrefab == null)
{
ModsPlusPlugin.LOGGER.LogError($"[PlayerSelector] Selector prefab cannot be null!");
return;
}
Clear(selectorPrefab);
if (selectorPrefab.GetComponentInChildren<PlayerSelector>() == null)
{
ModsPlusPlugin.LOGGER.LogError($"[PlayerSelector] The selector prefab provided ({selectorPrefab.name}) does not contain an instance of PlayerSelector!");
return;
}
foreach (var player in targets)
{
var selector = Instantiate(selectorPrefab, player.transform).GetComponentInChildren<PlayerSelector>();
selector.OnPlayerClicked += (target) =>
{
selectedCallback?.Invoke(target);
Clear(selectorPrefab);
};
if (selectors.TryGetValue(selectorPrefab, out List<PlayerSelector> list))
{
list.Add(selector);
}
else
{
selectors.Add(selectorPrefab, new List<PlayerSelector> { selector });
}
}
}
}
}