-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GodModeAreaPlugin.cs
290 lines (265 loc) · 12.6 KB
/
GodModeAreaPlugin.cs
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
extern alias UnityEngineCoreModule;
using Rocket.API.Collections;
using Rocket.Core.Logging;
using Rocket.Core.Plugins;
using Rocket.Core.Utils;
using Rocket.Unturned.Chat;
using Rocket.Unturned.Player;
using SDG.Provider;
using SDG.Unturned;
using UnityEngine.SocialPlatforms;
using UnityCoreModule = UnityEngineCoreModule.UnityEngine;
namespace GodModeArea
{
public class GodModeAreaPlugin : RocketPlugin<GodModeAreaConfiguration>
{
/// <summary>
/// Store the players actual status in god mode
/// </summary>
private readonly Dictionary<string, Dictionary<string, byte>> TemporaryPlayerValues = new();
/// <summary>
/// Stores if player already been notified from exiting god mode
/// </summary>
private readonly List<string> TemporaryGodTaskRunning = new();
/// <summary>
/// This will store the tasks for delay to lose god mode
/// </summary>
private readonly Dictionary<string, CancellationTokenSource> PlayerGodModeTasks = new();
public override void LoadPlugin()
{
base.LoadPlugin();
// Instanciating the player events
Rocket.Unturned.U.Events.OnPlayerConnected += OnPlayerConnected;
Rocket.Unturned.U.Events.OnPlayerDisconnected += OnPlayerDisconnected;
Rocket.Unturned.Events.UnturnedPlayerEvents.OnPlayerUpdatePosition += PositionUpdate;
Logger.Log("GodModeArea by LeandroTheDev");
}
private void PositionUpdate(UnturnedPlayer player, UnityCoreModule.Vector3 position)
{
// Debug
if (Configuration.Instance.DebugExtended)
Logger.Log($"Player: {player.DisplayName}, Mode: {GodModeAreaTools.GodModePlayersId[player.Id]}, Position {player.Position}");
// Check if player is in god mode area
foreach (GodModeAreas area in Configuration.Instance.GodModeAreas)
{
// Verify X position
if (position.x < area.X1 || position.x > area.X2)
{
// Remove the player from godmode
if (!TemporaryGodTaskRunning.Contains(player.Id) && GodModeAreaTools.GodModePlayersId[player.Id])
RemovePlayerFromGodMode(player);
return;
}
// Verify Y position
else if (position.y < area.Y1 || position.y > area.Y2)
{
// Remove the player from godmode
if (!TemporaryGodTaskRunning.Contains(player.Id) && GodModeAreaTools.GodModePlayersId[player.Id])
RemovePlayerFromGodMode(player);
return;
}
// Verifiy Z position
else if (position.z < area.Z1 || position.z > area.Z2)
{
// Remove the player from godmode
if (!TemporaryGodTaskRunning.Contains(player.Id) && GodModeAreaTools.GodModePlayersId[player.Id])
RemovePlayerFromGodMode(player);
return;
}
}
if (!GodModeAreaTools.GodModePlayersId[player.Id])
{
// [Vanilla] Enable the god mode
if (Configuration.Instance.VanillaGodMode) player.GodMode = true;
GodModeAreaTools.GodModePlayersId[player.Id] = true;
// Remove the task from memory
if (PlayerGodModeTasks.TryGetValue(player.Id, out CancellationTokenSource token))
{
token.Cancel();
PlayerGodModeTasks.Remove(player.Id);
}
TemporaryGodTaskRunning.Remove(player.Id);
}
}
private void OnPlayerConnected(UnturnedPlayer player)
{
// [Vanilla] Add the default value for new player
if (Configuration.Instance.VanillaGodMode) player.GodMode = Configuration.Instance.GodModeDefaultValue;
// Add temporary values
GodModeAreaTools.GodModePlayersId.Add(player.Id, Configuration.Instance.GodModeDefaultValue);
// [Custom] Instanciate the events
if (!Configuration.Instance.VanillaGodMode)
{
TemporaryPlayerValues.Add(player.Id, new());
TemporaryPlayerValues[player.Id].Add("Health", player.Health);
player.Events.OnUpdateHealth += PlayerUpdateHealth;
TemporaryPlayerValues[player.Id].Add("Food", player.Hunger);
player.Events.OnUpdateFood += PlayerUpdateFood;
TemporaryPlayerValues[player.Id].Add("Water", player.Thirst);
player.Events.OnUpdateWater += PlayerUpdateWater;
TemporaryPlayerValues[player.Id].Add("Virus", player.Infection);
player.Events.OnUpdateVirus += PlayerUpdateVirus;
}
}
private void OnPlayerDisconnected(UnturnedPlayer player)
{
// Clear Variables
TemporaryPlayerValues.Remove(player.Id);
TemporaryGodTaskRunning.Remove(player.Id);
PlayerGodModeTasks.Remove(player.Id);
GodModeAreaTools.GodModePlayersId.Remove(player.Id);
// [Vanilla] Remove player from godmode
if (Configuration.Instance.VanillaGodMode) player.GodMode = false;
}
private void RemovePlayerFromGodMode(UnturnedPlayer player)
{
// Check if player already been notified
if (!TemporaryGodTaskRunning.Contains(player.Id))
{
// Informate the player the are exiting the zone
UnturnedChat.Say(player, Translate("Exiting_God_Mode", Math.Round(Configuration.Instance.GodModeMillisecondsExitDelay / 1000.0)), Palette.COLOR_R);
TemporaryGodTaskRunning.Add(player.Id);
}
// Cancel previous tasks if exist
if (PlayerGodModeTasks.TryGetValue(player.Id, out CancellationTokenSource token))
{
token.Cancel();
PlayerGodModeTasks.Remove(player.Id);
}
// Create new cancellation token
PlayerGodModeTasks.Add(player.Id, new());
// After delay disable the god mode
Task.Delay(Configuration.Instance.GodModeMillisecondsExitDelay, PlayerGodModeTasks[player.Id].Token).ContinueWith((task) =>
{
// If is cancelled just return
if (task.IsCanceled) return;
// Inform the player
TaskDispatcher.QueueOnMainThread(() =>
{
UnturnedChat.Say(player, Translate("No_Longer_God_Mode"), Palette.COLOR_R);
GodModeAreaTools.GodModePlayersId[player.Id] = false;
TemporaryGodTaskRunning.Remove(player.Id);
// [Vanilla] Remove god mode
if (Configuration.Instance.VanillaGodMode) player.GodMode = false;
// Remove the task from memory
PlayerGodModeTasks.Remove(player.Id);
});
});
}
#region custom god mode
private void PlayerUpdateHealth(UnturnedPlayer player, byte health)
{
// If player is on God Mode
if (GodModeAreaTools.GodModePlayersId[player.Id])
{
// Check the existence of health value from previous attribute
if (TemporaryPlayerValues[player.Id].TryGetValue("Health", out byte previousHealth))
{
if (previousHealth > health)
player.Heal((byte)(previousHealth - health));
}
// If dont exist create one
else TemporaryPlayerValues[player.Id].Add("Health", health);
}
else TemporaryPlayerValues[player.Id]["Health"] = player.Health;
}
private void PlayerUpdateFood(UnturnedPlayer player, byte food)
{
// If player is on God Mode
if (GodModeAreaTools.GodModePlayersId[player.Id])
{
// Check the existence of Food value from previous attribute
if (TemporaryPlayerValues[player.Id].TryGetValue("Food", out byte previousFood))
{
if (previousFood > food + 1)
{
// Bro, why? just why, i take a long time to understand
// how this works
byte total = (byte)(100 - previousFood);
if (total <= 0) player.Hunger = 1;
if (total >= 100) player.Hunger = 99;
else player.Hunger = total;
}
// The variable receives the actual value but
// for the setter hes receive the percentage in 1 to 99
// and for be better the function update is called again
// and finally will return the value correctly
}
// If dont exist create one
else TemporaryPlayerValues[player.Id].Add("Food", food);
}
else TemporaryPlayerValues[player.Id]["Food"] = player.Hunger;
}
private void PlayerUpdateWater(UnturnedPlayer player, byte water)
{
// If player is on God Mode
if (GodModeAreaTools.GodModePlayersId[player.Id])
{
// Check the existence of Water value from previous attribute
if (TemporaryPlayerValues[player.Id].TryGetValue("Water", out byte previousWater))
{
if (previousWater > water + 1)
{
// Bro, why? just why, i take a long time to understand
// how this works
byte total = (byte)(100 - previousWater);
if (total <= 0) player.Thirst = 1;
if (total >= 100) player.Thirst = 99;
else player.Thirst = total;
}
// The variable receives the actual value but
// for the setter hes receive the percentage in 1 to 99
// and for be better the function update is called again
// and finally will return the value correctly,
// now i understand why the vanilla god mode is so bugged
// with player hunger and thirst
}
// If dont exist create one
else TemporaryPlayerValues[player.Id].Add("Water", water);
}
else TemporaryPlayerValues[player.Id]["Water"] = player.Thirst;
}
private void PlayerUpdateVirus(UnturnedPlayer player, byte virus)
{
// If player is on God Mode
if (GodModeAreaTools.GodModePlayersId[player.Id])
{
// Check the existence of Virus value from previous attribute
if (TemporaryPlayerValues[player.Id].TryGetValue("Virus", out byte previousVirus))
{
if (previousVirus > virus + 1)
{
// Bro, why? just why, i take a long time to understand
// how this works
byte total = (byte)(100 - previousVirus);
if (total <= 0) player.Infection = 1;
if (total >= 100) player.Infection = 99;
else player.Infection = total;
}
// The variable receives the actual value but
// for the setter hes receive the percentage in 1 to 99
// and for be better the function update is called again
// and finally will return the value correctly,
// now i understand why the vanilla god mode is so bugged
// with player hunger and thirst
}
// If dont exist create one
else TemporaryPlayerValues[player.Id].Add("Virus", virus);
}
else TemporaryPlayerValues[player.Id]["Virus"] = player.Infection;
}
#endregion
public override TranslationList DefaultTranslations => new()
{
{ "Exiting_God_Mode", "Exiting zone, you have {0} seconds of invulnerability" },
{ "No_Longer_God_Mode", "You are now vulnerable!" },
};
}
static public class GodModeAreaTools
{
/// <summary>
/// Contains a boolean if player is on god mode or not
/// </summary>
static public Dictionary<string, bool> GodModePlayersId = new();
}
}