← Back to changelog
What changed
MLRSCargo · v1.0.7 → v1.0.8 (current)
Diff
3 added · 2 removed · 737 → 738 total lines
1
1
/*
2
2
▄▄▄▄ ███▄ ▄███▓ ▄████ ▄▄▄██▀▀▀▓█████▄▄▄█████▓
3
3
▓█████▄ ▓██▒▀█▀ ██▒ ██▒ ▀█▒ ▒██ ▓█ ▀▓ ██▒ ▓▒
4
4
▒██▒ ▄██▓██ ▓██░▒██░▄▄▄░ ░██ ▒███ ▒ ▓██░ ▒░
5
5
▒██░█▀ ▒██ ▒██ ░▓█ ██▓▓██▄██▓ ▒▓█ ▄░ ▓██▓ ░
6
6
░▓█ ▀█▓▒██▒ ░██▒░▒▓███▀▒ ▓███▒ ░▒████▒ ▒██▒ ░
7
7
░▒▓███▀▒░ ▒░ ░ ░ ░▒ ▒ ▒▓▒▒░ ░░ ▒░ ░ ▒ ░░
8
8
▒░▒ ░ ░ ░ ░ ░ ░ ▒ ░▒░ ░ ░ ░ ░
9
9
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
10
10
░ ░ ░ ░ ░ ░ ░
11
11
Permissions:
12
12
MLRSCargo.admin Required for chat commands
13
13
14
14
Chat Commands:
15
15
/mlrscargotest - Give Admin MLRS Air Strike Smoke Signal
16
16
/mlrscargoreset - Resets the MLRS on all cargoships
17
17
*/
18
18
using Facepunch;
19
19
using Newtonsoft.Json;
20
20
using Oxide.Core.Plugins;
21
21
using System.Collections.Generic;
22
22
using System.Linq;
23
23
using UnityEngine;
24
24
namespace Oxide.Plugins
25
25
{
26
-
[Info("MLRSCargo", "bmgjet", "1.0.7")]
26
+
[Info("MLRSCargo", "bmgjet", "1.0.8")]
27
27
[Description("Places a MLRS on the front of CargoShip")]
28
28
public class MLRSCargo : RustPlugin
29
29
{
30
30
public static MLRSCargo _plugin;
31
31
public List<MLRS> mlrs = new List<MLRS>();
32
32
//Active MRLS to limit to 1 user at a time.
33
33
public static bool active = false;
34
34
//Last player to trigger event
35
35
public BasePlayer thrower;
36
36
//Show Debug Info
37
37
bool showDebug = false;
38
38
//Admining Permission
39
39
public const string AdminPerm = "MLRSCargo.admin";
40
40
41
41
//Reference Kits plugin so kits can be applied to NPCs
42
42
[PluginReference]
43
43
private Plugin Kits;
44
44
45
45
#region Configuration
46
46
private Configuration config;
47
47
private class Configuration
48
48
{
49
49
[JsonProperty("Use Remote Controlled Mode With a Air Strike Signal (Requires you also enabled SpawnReady)")]
50
50
public bool RemoteMode = false;
51
51
52
52
[JsonProperty("SpawnReady (MLRS Spawns Ready To Fire)")]
53
53
public bool Ready = false;
54
54
55
55
[JsonProperty("Cool Down Between MLRS Attacks")]
56
56
public int Delay = 600;
57
57
58
58
//Show announcements in public chat
59
59
[JsonProperty("Show Announcements In Public Chat")]
60
60
public bool PublicAnouncements = false;
61
61
62
62
[JsonProperty("Steam ID To Use As Profile Pic")]
63
63
//Steam ID to use profile pic as announcment chat icon
64
64
public string AnnouncementIcon = "76561199219302299";
65
65
66
66
//Cargo NPCs health multiplyer
67
67
[JsonProperty("Cargo NPCs Health Multiplyer (Boosts Health Of NPCs With In Radius)")]
68
68
public float healthmulti = 3f;
69
69
70
70
[JsonProperty("Cargo NPCs Scan Radius")]
71
71
//Radius to cast NPC Scan
72
72
public float NPCRadius = 50f; //Scan first 1/4 of ship around MLRS
73
73
74
74
[JsonProperty("Give Kit To Found NPCs (Leave Empty For Default)")]
75
75
public string Kitname = "";
76
76
77
77
[JsonProperty("Play Air Raid Siren On AirStrike Signal")]
78
78
//Play SFX over boombox from remote MLRS grenade
79
79
public bool PlaySFX = true;
80
80
81
81
[JsonProperty("URL To Air Raid Sound Effect (Must Be Raw MP3 Stream)")]
82
82
//URL to SFX (Must be a raw mp3 file)
83
83
public string SFXURL = "https://github.com/bmgjet/RocketFail/blob/main/AirRaid.mp3?raw=true";
84
84
85
85
[JsonProperty("MLRS Offset On Cargoship")]
86
86
//Position on cargoship moved from dead center
87
87
public Vector3 CargoOffset = new Vector3(0f, 9.5f, 76f);
88
88
89
89
public string ToJson() => JsonConvert.SerializeObject(this);
90
90
91
91
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
92
92
}
93
93
94
94
protected override void LoadDefaultConfig() { config = new Configuration(); }
95
95
protected override void LoadConfig()
96
96
{
97
97
base.LoadConfig();
98
98
try
99
99
{
100
100
config = Config.ReadObject<Configuration>();
101
101
if (config == null) { throw new JsonException(); }
102
102
103
103
if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys))
104
104
{
105
105
PrintWarning("Configuration appears to be outdated; updating and saving");
106
106
SaveConfig();
107
107
}
108
108
}
109
109
catch
110
110
{
111
111
PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
112
112
LoadDefaultConfig();
113
113
}
114
114
}
115
115
protected override void SaveConfig()
116
116
{
117
117
PrintWarning($"Configuration changes saved to {Name}.json");
118
118
Config.WriteObject(config, true);
119
119
}
120
120
#endregion Configuration
121
121
122
122
private void Init()
123
123
{
124
124
_plugin = this;
125
125
Unsubscribe("OnEntitySpawned");
126
126
permission.RegisterPermission(AdminPerm, this);
127
127
}
128
128
129
129
//Remote control only disable mounting
130
130
object CanMountEntity(BasePlayer bp, BaseMountable bm)
131
131
{
132
132
if (bm.prefabID == 223554808)
133
133
{
134
134
if (config.RemoteMode && config.Ready)
135
135
{
136
136
//Checks its a MLRS thats apart of the event
137
137
MLRSShoot s = bm.GetComponent<MLRSShoot>();
138
138
if (s != null)
139
139
{
140
140
//Has token avaliable.
141
141
if (s.Token)
142
142
{
143
143
s.Token = false;
144
144
//Gives tokwn to player
145
145
GiveMLRSSignal(bp);
146
146
//Disable Mount
147
147
return true;
148
148
}
149
149
else
150
150
{
151
151
rust.SendChatMessage(bp, "<color=orange>Cargo MLRS</color>", "MLRS signal has already been claimed", config.AnnouncementIcon);
152
152
//Disable Mount
153
153
return true;
154
154
}
155
155
}
156
156
}
157
157
}
158
158
//Allow Mount
159
159
return null;
160
160
}
161
161
162
162
//Loads MLRS on cargo as it spawns
163
163
void OnEntitySpawned(CargoShip cs)
164
164
{
165
165
//checks if cargo
166
166
if (cs != null)
167
167
{
168
168
//Creates MLRS
169
169
timer.Once(10f, () =>
170
170
{
171
171
AddMLRS(cs);
172
172
});
173
173
}
174
174
}
175
175
176
176
void OnEntitySpawned(MLRSRocket rocket)
177
177
{
178
178
//Checks if its one of the events rockets
179
179
if (rocket != null && active)
180
180
{
181
181
if (rocket.OwnerID == 0)
182
182
{
183
183
//Sets rocket as last user to trigger the event
184
184
rocket.OwnerID = thrower.userID;
185
185
rocket.creatorEntity = thrower;
186
186
//Create map markers since that event was missed with remote trigger.
187
187
BaseEntity baseEntity2 = GameManager.server.CreateEntity("assets/content/vehicles/mlrs/mlrsrocketmarker.prefab", rocket.transform.position, Quaternion.identity, true);
188
188
baseEntity2.OwnerID = thrower.userID;
189
189
baseEntity2.Spawn();
190
190
baseEntity2.SetParent(rocket, true, false);
191
191
}
192
192
}
193
193
}
194
194
195
195
//Prevent Looting Cargos MLRS when SpawnReady Set
196
196
private void OnLootEntity(BasePlayer player, BaseEntity entity)
197
197
{
198
198
try
199
199
{
200
200
if (!entity.GetParentEntity().GetComponent<MLRSShoot>())
201
201
return;
202
202
if (config.Ready)
203
203
NextTick(player.EndLooting);
204
204
}
205
205
catch { }
206
206
}
207
207
208
208
void OnServerInitialized()
209
209
{
210
210
//Validate Settings
211
211
if (config.Delay < 10)
212
212
{
213
213
Puts("Invalid Delay Must be 10 or greater!");
214
214
config.Delay = 10;
215
215
}
216
216
if (config.RemoteMode && !config.Ready)
217
217
{
218
218
Puts("Spawn Ready Must Be Used With Remote Mode Since CockPit Is Unavaliable!");
219
219
config.Ready = true;
220
220
}
221
221
//try catch since throws errors if server had crashed instead of clean shutdown while cargo is out.
222
222
try
223
223
{
224
224
Subscribe("OnEntitySpawned");
225
225
timer.Once(30, () => { ResetCargoMLRS(); });
226
226
}
227
227
catch { }
228
228
}
229
229
230
230
void Unload()
231
231
{
232
232
//Remove component
233
233
foreach (var ent in mlrs)
234
234
{
235
235
if (ent != null) { continue; }
236
236
if (!ent.IsDestroyed) { ent.Kill(); }
237
237
}
238
238
_plugin = null;
239
239
}
240
240
241
241
void OnExplosiveDropped(BasePlayer bp, BaseEntity be)
242
242
{
243
243
if (bp == null || be == null || be.ShortPrefabName != "grenade.smoke.deployed") return;
244
244
RemoteEvent(bp, be);
245
245
}
246
246
void OnExplosiveThrown(BasePlayer bp, BaseEntity be)
247
247
{
248
248
if (bp == null || be == null || be.ShortPrefabName != "grenade.smoke.deployed") return;
249
249
RemoteEvent(bp, be);
250
250
}
251
251
252
252
private void OnCargoShipEgress(CargoShip cs)
253
253
{
254
254
if (cs != null)
255
255
{
256
256
for (int i = cs.children.Count - 1; i >= 0; i--)
257
257
{
258
258
if (cs.children[i] != null && !cs.children[i].IsDestroyed && cs.children[i] is MLRS)
259
259
{
260
260
cs.children[i].Kill();
261
261
}
262
262
}
263
263
}
264
264
}
265
265
266
266
void RemoteEvent(BasePlayer bp, BaseEntity be)
267
267
{
268
268
//Check if its an event token
269
269
if (be.skinID != 2647098356) return;
270
270
if (showDebug) Puts("Remote Cargo MLRS trigged by " + bp.displayName);
271
271
272
272
RunEffect("assets/bundled/prefabs/fx/smoke_signal_full.prefab", be);
273
273
//Checks if already active event
274
274
if ((be != null && !active) || !config.RemoteMode)
275
275
{
276
276
bool Sucess = false;
277
277
thrower = bp;
278
278
active = true;
279
279
if (config.PlaySFX)
280
280
{
281
281
CreateSound(be, config.SFXURL);
282
282
}
283
283
//delay to allow smoke grenade to travel
284
284
timer.Once(8f, () =>
285
285
{
286
286
if (be == null)
287
287
{
288
288
active = false;
289
289
rust.SendChatMessage(bp, "<color=orange>Cargo MLRS</color>", "Your MLRS signal <color=red>FAILED</color>", config.AnnouncementIcon);
290
290
return;
291
291
}
292
292
Vector3 pos = be.transform.position;
293
293
if (pos != null)
294
294
{
295
295
if (config.PublicAnouncements)
296
296
{
297
297
CreateAnouncment("<color=red>" + bp.displayName + "</color> has called a MLRS strike near <color=orange>" + getGrid(pos) + "</color>");
298
298
}
299
299
//Find all cargo ships and use them
300
300
CargoShip[] cargo = UnityEngine.Object.FindObjectsOfType<CargoShip>();
301
301
foreach (CargoShip ship in cargo)
302
302
{
303
303
//Search if they have MLRS attached
304
304
List<BaseEntity> bef = ship.children;
305
305
//Do a for loop incase future has more then 1 MLRS
306
306
foreach (BaseEntity b in bef.ToArray())
307
307
{
308
308
//Found a MLRS
309
309
if (b is MLRS)
310
310
{
311
311
MLRS TMLRS = b as MLRS;
312
312
if (TMLRS != null)
313
313
{
314
314
//Add the functions componant
315
315
MLRSShoot s = TMLRS.GetComponent<MLRSShoot>();
316
316
if (s == null)
317
317
{
318
318
//Check if any shots have been fired in the foreach loop to prevent refunds
319
319
if (!Sucess)
320
320
{
321
321
rust.SendChatMessage(bp, "<color=orange>Cargo MLRS</color>", "<color=red>Not Avaliable</color=red>", config.AnnouncementIcon);
322
322
bp.GiveItem(CreateItem());
323
323
NextTick(() => { be?.Kill(); });
324
324
}
325
325
return;
326
326
}
327
327
//Sets up target and shoots
328
328
s.SetTarget(pos);
329
329
s.ForceFireRepeat(bp);
330
330
if (showDebug) Puts("Remote Cargo MLRS Shooting");
331
331
Sucess = true;
332
332
timer.Once(10f, () =>
333
333
{
334
334
if (config.PublicAnouncements)
335
335
{
336
336
CreateAnouncment("Status: <color=red>Disabled</color>");
337
337
}
338
338
});
339
339
//Resets the cargo after delay
340
340
if (config.Ready)
341
341
{
342
342
timer.Once(10 + config.Delay, () =>
343
343
{
344
344
ResetCargoMLRS();
345
345
});
346
346
}
347
347
}
348
348
}
349
349
}
350
350
}
351
351
}
352
352
});
353
353
}
354
354
else
355
355
{
356
356
//Returns players token
357
357
rust.SendChatMessage(bp, "<color=orange>Cargo MLRS</color>", "<color=red>Not Avaliable</color=red>", config.AnnouncementIcon);
358
358
bp.GiveItem(CreateItem());
359
359
NextTick(() => { be?.Kill(); });
360
360
}
361
361
}
362
362
363
363
//Find all cargoships on map
364
364
void ResetCargoMLRS()
365
365
{
366
366
CargoShip[] cargo = UnityEngine.Object.FindObjectsOfType<CargoShip>();
367
367
foreach (CargoShip ship in cargo.ToArray())
368
368
{
369
369
//Search if they have MLRS attached
370
370
List<BaseEntity> be = ship.children;
371
371
foreach (BaseEntity b in be.ToArray())
372
372
{
373
373
if (b is MLRS)
374
374
{
375
375
//Kill old one and respawn new to stop mountable spam
376
376
try
377
377
{
378
378
b.Kill();
379
379
}
380
380
catch { }
381
381
AddMLRS(ship);
382
382
}
383
383
}
384
384
}
385
385
}
386
386
387
387
//Removes any duplicated MLRS caused from currupted sav files.
388
388
void CleanDupedMLRS(Vector3 pos)
389
389
{
390
390
int cleaned = 0;
391
391
RaycastHit[] hits = UnityEngine.Physics.SphereCastAll(pos, 150f, Vector3.one);
392
392
foreach (RaycastHit hit in hits.ToArray())
393
393
{
394
394
//Check each hit is a MLRS
395
395
CargoShip cargo = hit.GetEntity()?.GetComponent<CargoShip>();
396
396
397
397
if (cargo != null)
398
398
{
399
399
List<BaseEntity> bef = cargo.children;
400
400
{
401
401
foreach (BaseEntity b in bef)
402
402
{
403
403
if (b is MLRS)
404
404
{
405
405
b.Kill();
406
406
cleaned++;
407
407
}
408
408
}
409
409
}
410
410
}
411
411
}
412
412
MLRS[] MLRSList = UnityEngine.Object.FindObjectsOfType<MLRS>();
413
413
foreach (MLRS mlrs in MLRSList)
414
414
{
415
415
if (mlrs == null) { continue; }
416
416
if (mlrs.transform.position.y == 0 && TerrainMeta.HeightMap.GetHeight(mlrs.transform.position) < -5)
417
417
{
418
418
mlrs.Kill();
419
419
cleaned++;
420
420
}
421
421
}
422
422
if (showDebug) Puts("Cleaned " + cleaned.ToString() + " dupes");
423
423
}
424
424
425
425
void AddMLRS(CargoShip cs)
426
426
{
427
427
if (cs == null) { return; }
428
428
CleanDupedMLRS(cs.transform.position + config.CargoOffset);
429
429
//Rotate MLRS so turret is at front of ship not to hit the mast.
430
430
Vector3 rot = cs.transform.rotation.eulerAngles;
431
431
rot = new Vector3(rot.x, rot.y + 180, rot.z);
432
432
Vector3 pos = new Vector3(cs.transform.position.x, cs.transform.position.y, cs.transform.position.z);
433
433
//Spawn MLRS
434
434
MLRS replacement = GameManager.server.CreateEntity("assets/content/vehicles/mlrs/mlrs.entity.prefab", pos, cs.transform.rotation) as MLRS;
435
435
if (replacement == null) { return; }
436
436
replacement.Spawn();
437
437
replacement.SetParent(cs);
438
438
mlrs.Add(replacement);
439
439
replacement.transform.position = pos;
440
440
replacement.transform.localPosition += config.CargoOffset;
441
441
replacement.transform.rotation = Quaternion.Euler(rot);
442
442
replacement.enabled = true;
443
443
replacement.EnableSaving(false);
444
444
//Add component to over-ride the shoot button and few functions
445
445
replacement.gameObject.AddComponent<MLRSShoot>();
446
446
if (config.Ready || config.RemoteMode)
447
447
{
448
448
//Try catch since some times errors OnServerInitialized if server crashed,
449
449
try
450
450
{
451
451
active = false;
452
452
thrower = null;
453
453
replacement.AdminFixUp();
454
454
}
455
455
catch { }
456
456
}
457
457
replacement.SendNetworkUpdateImmediate();
458
458
if (config.PublicAnouncements)
459
459
{
460
460
CreateAnouncment("Status: <color=green>Active</color>");
461
461
}
462
462
if (showDebug) Puts("Spawned new Cago MLRS");
463
463
////Change NPCs health to make them a little harder for MLRS event
464
464
if (config.healthmulti != 1f)
465
465
{
466
466
//Delay to allow NPCs to spawn
467
467
timer.Once(2f, () =>
468
468
{
469
469
if (replacement != null)
470
470
{
471
471
BoostNPCs(replacement);
472
472
}
473
473
});
474
474
}
475
475
}
476
476
477
477
private void GiveMLRSSignal(BasePlayer player)
478
478
{
479
479
if (showDebug) Puts("Remote Token Given to " + player.displayName);
480
480
//Give skinned smoke grenade item to player
481
481
var item = CreateItem();
482
482
if (item != null && player != null)
483
483
{
484
484
player.GiveItem(item);
485
485
if (config.PublicAnouncements)
486
486
{
487
487
CreateAnouncment("MLRS Remote signal claimed by <color=red>" + player.displayName + "</color>");
488
488
//PrintToChat("MLRS Remote signal claimed by " + player.displayName);
489
489
}
490
490
}
491
491
}
492
492
493
493
private Item CreateItem()
494
494
{
495
495
//create item
496
496
var item = ItemManager.CreateByName("grenade.smoke", 1, 2647098356);
497
497
if (item != null)
498
498
{
499
499
item.text = "MLRS Strike";
500
500
item.name = item.text;
501
501
}
502
502
return item;
503
503
}
504
504
505
505
//Create boombox below grenade for some sfx
506
506
private void CreateSound(BaseEntity player, string url)
507
507
{
508
508
//Checks provided URL
509
509
if (url == "") return;
510
510
//Creates Resizeable Sphere
511
511
SphereEntity sph = (SphereEntity)GameManager.server.CreateEntity("assets/prefabs/visualization/sphere.prefab", default(Vector3), default(Quaternion), true);
512
512
DestroyMeshCollider(sph);
513
513
sph.Spawn();
514
514
//Create boombox
515
515
DeployableBoomBox boombox = GameManager.server.CreateEntity("assets/prefabs/voiceaudio/boombox/boombox.deployed.prefab", default(Vector3), default(Quaternion), true) as DeployableBoomBox;
516
516
DestroyMeshCollider(boombox);
517
517
//Asigns boombox to sphere
518
518
boombox.SetParent(sph);
519
519
boombox.Spawn();
520
520
//Setup boombox
521
521
boombox.pickup.enabled = false;
522
522
boombox.BoxController.ServerTogglePlay(false);
523
523
boombox.BoxController.AssignedRadioBy = player.OwnerID;
524
524
//Resize shpere
525
525
sph.LerpRadiusTo(0.01f, 1f);
526
526
//Delay to allow clean resize
527
527
timer.Once(1f, () =>
528
528
{
529
529
if (sph != null)
530
530
sph.SetParent(player);
531
531
sph.transform.localPosition = new Vector3(0, -1.5f, 0f);
532
532
//Change boombox channel to url
533
533
boombox.BoxController.CurrentRadioIp = url;
534
534
boombox.BoxController.baseEntity.ClientRPC(RpcTarget.NetworkGroup("OnRadioIPChanged"), boombox.BoxController.CurrentRadioIp);
535
535
boombox.BoxController.ServerTogglePlay(true);
536
536
//Suiside timer for sphere and boombox
537
537
timer.Once(40f, () =>
538
538
{
539
539
try
540
540
{
541
541
if (sph != null)
542
542
sph?.Kill();
543
543
}
544
544
catch { }
545
545
});
546
546
});
547
547
sph.SendNetworkUpdateImmediate();
548
548
}
549
549
550
550
//Play visual effects on entity
551
551
private static void RunEffect(string name, BaseEntity entity = null, Vector3 position = new Vector3(), Vector3 offset = new Vector3())
552
552
{
553
553
if (entity != null)
554
554
Effect.server.Run(name, entity, 0, offset, position, null, true);
555
555
else Effect.server.Run(name, position, Vector3.up, null, true);
556
556
}
557
557
558
558
//Gets grid letter from world position
559
559
string getGrid(Vector3 pos)
560
560
{
561
561
//Set base letter
562
562
char letter = 'A';
563
563
var x = Mathf.Floor((pos.x + (ConVar.Server.worldsize / 2)) / 146.3f) % 26;
564
564
var z = (Mathf.Floor(ConVar.Server.worldsize / 146.3f)) - Mathf.Floor((pos.z + (ConVar.Server.worldsize / 2)) / 146.3f);
565
565
letter = (char)(((int)letter) + x);
566
566
//-1 since starts at 0
567
567
return $"{letter}{z - 1}";
568
568
}
569
569
570
570
//Destory collider so player can pass though
571
571
void DestroyMeshCollider(BaseEntity ent)
572
572
{
573
573
foreach (var mesh in ent.GetComponentsInChildren<MeshCollider>())
574
574
{
575
575
UnityEngine.Object.DestroyImmediate(mesh);
576
576
}
577
577
578
578
579
579
}
580
580
581
581
//Sends message to all active players under a steamID
582
582
void CreateAnouncment(string msg)
583
583
{
584
584
foreach (BasePlayer current in BasePlayer.activePlayerList.ToArray())
585
585
{
586
586
if (current.IsConnected)
587
587
{
588
588
rust.SendChatMessage(current, "<color=orange>Cargo MLRS</color>", msg, config.AnnouncementIcon);
589
589
}
590
590
}
591
591
}
592
592
593
593
//FindNPCs and boost them
594
594
private void BoostNPCs(MLRS pos)
595
595
{
596
596
int boosted = 0;
597
597
//Scan area
598
598
RaycastHit[] hits = UnityEngine.Physics.SphereCastAll(pos.transform.position, config.NPCRadius, Vector3.one);
599
599
foreach (RaycastHit hit in hits.ToArray())
600
600
{
601
601
//Check each hit is NPC
602
602
NPCPlayer bnpc = hit.GetEntity()?.GetComponent<NPCPlayer>();
603
603
if (bnpc != null)
604
604
{
605
605
//Checks if kit string is valid
606
606
if (config.Kitname != "")
607
607
{
608
608
//Calls kits plugin
609
609
object success = Kits?.Call("GiveKit", bnpc, config.Kitname);
610
610
//Trys to equip stuff
611
611
Item projectileItem = null;
612
612
foreach (var item in bnpc.inventory.containerBelt.itemList)
613
613
{
614
614
if (item.GetHeldEntity() is BaseProjectile)
615
615
{
616
616
projectileItem = item;
617
617
break;
618
618
}
619
619
}
620
620
if (projectileItem != null)
621
621
{
622
622
bnpc.UpdateActiveItem(projectileItem.uid);
623
623
}
624
624
else bnpc.EquipWeapon();
625
625
}
626
626
//Give a better name
627
627
bnpc.displayName = RandomUsernames.Get(bnpc.userID);
628
628
//Mod health
629
629
bnpc.startHealth *= config.healthmulti;
630
630
bnpc.InitializeHealth(100 * config.healthmulti, 100 * config.healthmulti);
631
631
boosted++;
632
632
}
633
633
}
634
634
if (showDebug) Puts("Boosted " + boosted.ToString() + " NPCs");
635
635
}
636
636
637
637
//Functions for Cargo MLRS
638
638
public class MLRSShoot : FacepunchBehaviour
639
639
{
640
640
public bool Token = true;
641
641
public MLRS me;
642
642
public BasePlayer seatedplayer;
643
643
private void Awake()
644
644
{
645
645
//Gives reference
646
646
me = GetComponent<MLRS>();
647
647
//Check if should be monitoring Seat
648
648
if (!_plugin.config.RemoteMode)
649
649
{
650
650
//Setup update loop
651
651
InvokeRepeating(update, UnityEngine.Random.Range(0f, 1f), 0.15f);
652
652
}
653
653
}
654
654
655
655
//Manually set the target
656
656
public void SetTarget(Vector3 nt)
657
657
{
658
658
me.trueTargetHitPos = nt;
659
659
me.SetUserTargetHitPos(nt);
660
660
me.SetUserTargetHitPos(nt);
661
661
}
662
662
663
663
//Manually fire rockets
664
664
public void ForceFire()
665
665
{
666
666
//_FireNextRocket.Invoke(me, null);
667
667
me.FireNextRocket();
668
668
}
669
669
670
670
public void ForceFireRepeat(BasePlayer bp)
671
671
{
672
672
//Lock taget pos
673
-
me.SetFlag(BaseEntity.Flags.Reserved6, true, false, true);
673
+
me.SetFlagLocal(BaseEntity.Flags.Reserved6, true, false);
674
674
me.nextRocketIndex = me.RocketAmmoCount - 1;
675
+
me.SendNetworkUpdateImmediate();
675
676
//Fire rockets
676
677
InvokeRepeating(ForceFire, 0f, 0.5f);
677
678
}
678
679
679
680
private void update()
680
681
{
681
682
//Try catch to prevent red text on admin cargo remove.
682
683
try
683
684
{
684
685
//Checks for mounted player
685
686
if (me.GetMounted() == null)
686
687
{
687
688
seatedplayer = null;
688
689
return;
689
690
}
690
691
//Check mounted player has changed to stop help text spamming
691
692
if (seatedplayer != me.GetMounted())
692
693
{
693
694
seatedplayer = me.GetMounted();
694
695
seatedplayer.ChatMessage("Hold Left click to <color=red>FIRE!</color>");
695
696
}
696
697
//Triggers manually shooting with left mouse button
697
698
if (seatedplayer != null && seatedplayer.serverInput.IsDown(BUTTON.FIRE_PRIMARY))
698
699
{
699
700
//Triggers normal fire function of press button
700
701
me.IsRealigning = false;
701
702
me.Fire(seatedplayer);
702
703
}
703
704
}
704
705
catch { }
705
706
}
706
707
}
707
708
708
709
//Debug comand
709
710
[ChatCommand("mlrscargotest")]
710
711
private void Cmdmlrscargotest(BasePlayer player, string command, string[] args)
711
712
{
712
713
//Gives admin token without having to visit cargoship
713
714
if (player.IPlayer.HasPermission(AdminPerm))
714
715
{
715
716
GiveMLRSSignal(player);
716
717
}
717
718
else
718
719
{
719
720
player.ChatMessage("No Perm");
720
721
}
721
722
}
722
723
//Reset event
723
724
[ChatCommand("mlrscargoreset")]
724
725
private void Cmdmlrscargoreset(BasePlayer player, string command, string[] args)
725
726
{
726
727
//Respawns MLRS
727
728
if (player.IPlayer.HasPermission(AdminPerm))
728
729
{
729
730
ResetCargoMLRS();
730
731
}
731
732
else
732
733
{
733
734
player.ChatMessage("No Perm");
734
735
}
735
736
}
736
737
}
737
738
}