C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using Rust;
using UnityEngine;
using System.Linq;
namespace Oxide.Plugins {
[Info("Juggernaut", "k1lly0u", "0.2.43", ResourceId = 0)]
internal class Juggernaut : RustPlugin {
#region Fields
[PluginReference]
Plugin Clans, Friends, LustyMap, EventManager, ServerRewards, Economics;
private static Juggernaut ins;
private StoredData storedData;
private RestoreData restoreData;
private DynamicConfigFile data, restorationData;
private BasePlayer juggernaut = null;
private BaseEntity[] finalSphere = null;
private Vector3 endPos = Vector3.zero;
private Timer nextMatch;
private Timer startMatch;
private Timer eventTimer;
private Timer broadcastTimer;
private Timer openMessage;
private Timer uiTimer;
private double eventEnd;
private double nextTrigger;
private string juggernautIcon;
private bool isOpen;
private bool hasStarted;
private bool initialized;
private bool hasDestinations;
private static bool isUnloading;
private List<ulong> optedIn = new List<ulong>();
private Dictionary<ulong, Destinations> destinationCreator = new Dictionary<ulong, Destinations>();
private const string sphereEnt = "assets/prefabs/visualization/sphere.prefab";
#endregion
#region Oxide Hooks
private void Loaded() {
permission.RegisterPermission("juggernaut.canbe", this);
lang.RegisterMessages(Messages, this);
data = Interface.Oxide.DataFileSystem.GetFile("juggernaut_data");
restorationData = Interface.Oxide.DataFileSystem.GetFile("juggernaut_restoration_data");
isUnloading = false;
}
private void OnServerInitialized() {
ins = this;
LoadData();
if (storedData.destinations.Count > 0) {
hasDestinations = true;
StartEventTimer();
}
else PrintWarning("No destinations have been set! Unable to start the event");
RemoveMapMarker(msg("juggernaut"), false);
RemoveMapMarker(msg("possibleDest"), true);
RemoveMapMarker(msg("destination"), false);
Unsubscribe(nameof(CanNetworkTo));
initialized = true;
}
private void OnServerSave() => SaveRestoreData();
private void Unload() {
isUnloading = true;
if (eventTimer != null) eventTimer.Destroy();
if (nextMatch != null) nextMatch.Destroy();
if (startMatch != null) startMatch.Destroy();
if (openMessage != null) openMessage.Destroy();
if (uiTimer != null) uiTimer.Destroy();
if (broadcastTimer != null) broadcastTimer.Destroy();
foreach (var player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, Main);
CuiHelper.DestroyUi(juggernaut, Compass);
if (juggernaut != null && hasStarted) {
UnlockInventory(juggernaut);
StripInventory(juggernaut);
DestroyEvent();
}
SaveRestoreData();
}
private void OnPlayerInit(BasePlayer player) {
if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.In(1, () => OnPlayerInit(player));
return;
}
if (restoreData.HasRestoreData(player.userID)) restoreData.RestorePlayer(player);
}
private void OnPlayerDisconnected(BasePlayer player) {
if (optedIn.Contains(player.userID)) optedIn.Remove(player.userID);
if (player == juggernaut && hasStarted) {
UnlockInventory(player);
StripInventory(player);
DestroyEvent();
}
}
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null) return;
var victim = entity.ToPlayer();
var attacker = info.InitiatorPlayer;
if (victim != null && victim == juggernaut) {
if (info.Initiator != null && info.Initiator.ShortPrefabName.Equals("beartrap") && configData.Juggernaut.NoBeartrapDamage) {
info.damageTypes.ScaleAll(0);
return;
}
if (info.WeaponPrefab != null && info.WeaponPrefab.ShortPrefabName.Equals("landmine") && configData.Juggernaut.NoLandmineDamage) {
info.damageTypes.ScaleAll(0);
return;
}
if (info.damageTypes.GetMajorityDamageType() == DamageType.Fall && configData.Juggernaut.NoFallDamage) {
info.damageTypes.ScaleAll(0);
return;
}
if (attacker != null) {
if (IsFriend(victim.userID, attacker.userID)) {
info.damageTypes.ScaleAll(0);
SendReply(attacker, msg("ff1", attacker.UserIDString));
return;
}
if (IsClanmate(victim.userID, attacker.userID)) {
info.damageTypes.ScaleAll(0);
SendReply(attacker, msg("ff2", attacker.UserIDString));
return;
}
}
info.damageTypes.ScaleAll(configData.Juggernaut.DefenseMod);
return;
}
if (attacker == null) return;
if (attacker == juggernaut) {
if (!configData.Juggernaut.DamageStructures && (entity is BuildingBlock || entity is SimpleBuildingBlock)) {
info.damageTypes.ScaleAll(0);
return;
}
info.damageTypes.ScaleAll(configData.Juggernaut.AttackMod);
}
}
private void OnEntitySpawned(BaseNetworkable entity) {
if (!initialized || entity == null) return;
var player = entity as BasePlayer;
if (player != null) {
TryRestorePlayer(player);
}
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null) return;
var victim = entity.ToPlayer();
if (victim == null) return;
if (victim == juggernaut) {
if (!configData.Prizes.Inventory) StripInventory(victim);
var attacker = info.InitiatorPlayer;
if (attacker != null) {
if (victim == info.InitiatorPlayer) {
StripInventory(victim);
PrintToChat(msg("juggerSuicide"));
}
else if (!IsFriend(victim.userID, attacker.userID) && !IsClanmate(victim.userID, attacker.userID)) {
PrintToChat(msg("juggerDead"));
if (configData.Prizes.Amount > 0) {
if (configData.Prizes.Economics) Economics?.Call("Deposit", attacker.userID, (double)configData.Prizes.Amount);
if (configData.Prizes.ServerRewards) ServerRewards?.Call("AddPoints", attacker.userID, configData.Prizes.Amount);
}
}
}
else PrintToChat(msg("juggerDead"));
UnlockInventory(victim);
DestroyEvent();
}
}
private object CanNetworkTo(BaseEntity entity, BasePlayer target) {
if (entity == null || finalSphere == null || juggernaut == null || target == null) return null;
if (finalSphere.Contains(entity)) {
if (target != juggernaut) return false;
}
return null;
}
private object OnRunCommand(ConsoleSystem.Arg arg) {
if (!hasStarted || arg.Connection == null || arg.Connection.player == null || arg.cmd.Name != "kill") return null;
var player = arg.Connection.player as BasePlayer;
if (player == null) return null;
if (player == juggernaut) {
SendReply(player, msg("noSuicide", player.UserIDString));
return true;
}
return null;
}
private object OnPlayerCommand(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player != null && juggernaut != null && player == juggernaut) {
string text = arg.GetString(0, "text").ToLower();
if (text.Length > 0 && text[0] == '/' && arg.cmd.FullName == "chat.say") {
if (configData.Game.CommandBlacklist.Any(entry => entry.StartsWith("/") ? text.StartsWith(entry) : text.Substring(1).StartsWith(entry))) {
SendReply(player, msg("blacklistcmd", player.UserIDString));
return false;
}
}
}
return null;
}
#endregion
#region Functions
private void LockInventory(BasePlayer player) {
if (!player.inventory.containerMain.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerMain.SetFlag(ItemContainer.Flag.IsLocked, true);
if (!player.inventory.containerBelt.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerBelt.SetFlag(ItemContainer.Flag.IsLocked, true);
if (!player.inventory.containerWear.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerWear.SetFlag(ItemContainer.Flag.IsLocked, true);
player.inventory.SendSnapshot();
}
private void UnlockInventory(BasePlayer player) {
if (player.inventory.containerMain.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerMain.SetFlag(ItemContainer.Flag.IsLocked, false);
if (player.inventory.containerBelt.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerBelt.SetFlag(ItemContainer.Flag.IsLocked, false);
if (player.inventory.containerWear.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerWear.SetFlag(ItemContainer.Flag.IsLocked, false);
player.inventory.SendSnapshot();
}
private void StartEventTimer() {
optedIn.Clear();
UnsubscribeHooks();
nextMatch = timer.Once(configData.Timers.Interval, CheckConditions);
nextTrigger = GrabCurrentTime() + configData.Timers.Interval;
}
private void CheckConditions() {
if (BasePlayer.activePlayerList.Count >= configData.Conditions.OpenMin) OpenEvent();
}
private void OpenEvent() {
if (string.IsNullOrEmpty(juggernautIcon) && configData.UI.ShowUITimer && !string.IsNullOrEmpty(configData.UI.IconUrl)) Add(configData.UI.IconUrl);
isOpen = true;
startMatch = timer.Once(configData.Timers.Open, StartEvent);
openMessage = timer.Repeat(45, 0, () => PrintToChat(msg("eventOpen")));
nextTrigger = configData.Timers.Open + GrabCurrentTime();
PrintToChat(msg("eventOpen"));
}
private void StartEvent() {
isOpen = false;
if (openMessage != null) openMessage.Destroy();
if (optedIn.Count == 0) {
PrintToChat(msg("noEntrants"));
StartEventTimer();
return;
}
var minEntrants = (int)Math.Round(BasePlayer.activePlayerList.Count * configData.Conditions.Percentage, 0);
if (optedIn.Count < minEntrants) {
PrintToChat(string.Format(msg("notEnoughEntrants"), $"{configData.Conditions.Percentage * 100}%"));
StartEventTimer();
return;
}
SubscribeHooks();
var player = GetRandomPlayer();
if (player == null) {
StartEventTimer();
return;
}
Destinations destinations = storedData.destinations.GetRandom();
endPos = new Vector3(destinations.x2, destinations.y2, destinations.z2);
restoreData.AddData(player);
StripInventory(player);
MovePosition(player, new Vector3(destinations.x1, destinations.y1, destinations.z1));
PrepareJuggernaut(player);
Subscribe(nameof(CanNetworkTo));
CreateSphere();
eventEnd = configData.Timers.Completion + GrabCurrentTime();
nextTrigger = configData.Timers.Completion + GrabCurrentTime();
hasStarted = true;
}
private BasePlayer GetRandomPlayer(int tries = 0) {
if (tries > 4) return null;
ulong playerId = optedIn.GetRandom();
BasePlayer player = BasePlayer.activePlayerList.FirstOrDefault(x => x.userID == playerId);
if (player == null || player.IsSleeping() || player.IsDead()) {
optedIn.Remove(playerId);
if (optedIn.Count == 0) return null;
return GetRandomPlayer(++tries);
}
return player;
}
private void PrepareJuggernaut(BasePlayer player) {
if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.In(1, () => PrepareJuggernaut(player));
return;
}
juggernaut = player;
if (configData.Juggernaut.ResetMetabolism) {
player.metabolism.Reset();
player.health = player.MaxHealth();
player.metabolism.hydration.value = player.metabolism.hydration.max;
player.metabolism.calories.value = player.metabolism.calories.max;
player.metabolism.SendChangesToClient();
}
GiveJuggernautGear();
PrintToChat(string.Format(msg("eventStart"), $"X:{Math.Round(endPos.x, 1)}, Z:{Math.Round(endPos.z, 1)}"));
SendReply(player, string.Format(msg("juggerStart", player.UserIDString), $"X:{Math.Round(endPos.x, 1)}, Z:{Math.Round(endPos.z, 1)}"));
eventTimer = timer.In(configData.Timers.Completion, EventCancel);
if (configData.UI.ShowUITimer) RefreshAllUI();
if (configData.Lusty.Enabled) {
if (configData.Lusty.DestinationAmount > 1 && storedData.destinations.Count >= configData.Lusty.DestinationAmount) {
List<Destinations> destinations = new List<Destinations>(storedData.destinations);
int randomNumber = UnityEngine.Random.Range(1, configData.Lusty.DestinationAmount);
for (int i = 0; i < configData.Lusty.DestinationAmount; i++) {
if (i == randomNumber) {
AddMapMarker(endPos.x, endPos.z, $"{msg("possibleDest")} {i + 1}");
}
else {
Destinations destination = destinations.GetRandom();
destinations.Remove(destination);
AddMapMarker(destination.x2, destination.z2, $"{msg("possibleDest")} {i + 1}");
}
}
}
else AddMapMarker(endPos.x, endPos.z, msg("destination"));
}
if (configData.Game.BroadcastEvery > 0) MapIconUpdater();
}
private void MapIconUpdater() {
broadcastTimer = timer.Repeat(configData.Game.BroadcastEvery, 0, () => {
if (juggernaut != null) {
if (configData.Game.BroadcastEveryLM) {
AddMapMarker(juggernaut.transform.position.x, juggernaut.transform.position.z, msg("juggernaut"));
timer.In(configData.Game.BroadcastLMSeconds, () => RemoveMapMarker(msg("juggernaut"), false));
}
else PrintToChat(string.Format(msg("positionBroadcast"), Math.Round(juggernaut.transform.position.x, 1), Math.Round(juggernaut.transform.position.z, 1)));
}
}
);
}
private void EventCancel() {
PrintToChat(msg("eventCancel"));
TryRestorePlayer(juggernaut);
DestroyEvent();
}
private void EventWin() {
PrintToChat(msg("juggerWin"));
if (configData.Prizes.Inventory) {
var remainingItems = new List<RestoreData.ItemData>();
remainingItems.AddRange(GetItems(juggernaut.inventory.containerBelt));
remainingItems.AddRange(GetItems(juggernaut.inventory.containerMain));
remainingItems.AddRange(GetItems(juggernaut.inventory.containerWear));
if (!storedData.winnerRewards.ContainsKey(juggernaut.userID)) storedData.winnerRewards.Add(juggernaut.userID, remainingItems);
else storedData.winnerRewards[juggernaut.userID] = remainingItems;
}
if (configData.Prizes.ServerRewards || configData.Prizes.Economics) {
if (!storedData.winnerMoney.ContainsKey(juggernaut.userID)) storedData.winnerMoney.Add(juggernaut.userID, new List<Points>());
storedData.winnerMoney[juggernaut.userID].Add(new Points {
isRp = configData.Prizes.ServerRewards, amount = configData.Prizes.Amount
}
);
}
TryRestorePlayer(juggernaut);
DestroyEvent();
}
private void DestroyEvent() {
hasStarted = false;
if (eventTimer != null) eventTimer.Destroy();
if (uiTimer != null) uiTimer.Destroy();
if (broadcastTimer != null) broadcastTimer.Destroy();
foreach (var player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, Main);
CuiHelper.DestroyUi(juggernaut, Compass);
juggernaut = null;
if (finalSphere != null) {
if (finalSphere[0].GetComponent<FinalSphere>()) UnityEngine.Object.Destroy(finalSphere[0].GetComponent<FinalSphere>());
for (int i = 0; i < finalSphere.Length; i++) finalSphere[i].KillMessage();
}
Unsubscribe(nameof(CanNetworkTo));
SaveData();
RemoveMapMarker(msg("juggernaut"), false);
RemoveMapMarker(msg("possibleDest"), true);
RemoveMapMarker(msg("destination"), false);
StartEventTimer();
}
private void TryRestorePlayer(BasePlayer player) {
if (player == null) return;
if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.In(1, () => TryRestorePlayer(player));
return;
}
UnlockInventory(player);
if (restoreData.HasRestoreData(player.userID)) restoreData.RestorePlayer(player);
}
private void GiveJuggernautGear() {
foreach (var entry in configData.Juggernaut.Inventory) {
Item item = null;
if (entry.IsBP) {
item = ItemManager.CreateByItemID(-1887162396, entry.Amount, entry.SkinID);
item.blueprintTarget = ItemManager.itemList.Find(x => x.shortname == entry.Shortname)?.itemid ?? 0;
}
else item = ItemManager.CreateByName(entry.Shortname, entry.Amount, entry.SkinID);
if (item == null) PrintError($"Error creating item: {entry.Shortname}.Check this is a correct shortname!");
else item.MoveToContainer(entry.Container == "wear" ? juggernaut.inventory.containerWear : entry.Container == "belt" ? juggernaut.inventory.containerBelt : juggernaut.inventory.containerMain);
}
LockInventory(juggernaut);
}
private void UnsubscribeHooks() {
Unsubscribe(nameof(OnEntityTakeDamage));
Unsubscribe(nameof(OnEntityDeath));
Unsubscribe(nameof(CanNetworkTo));
}
private void SubscribeHooks() {
Subscribe(nameof(OnEntityTakeDamage));
Subscribe(nameof(OnEntityDeath));
Subscribe(nameof(CanNetworkTo));
}
private double GrabCurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
private string GetGridString(Vector3 position) {
Vector2 adjPosition = new Vector2((World.Size / 2) + position.x, (World.Size / 2) - position.z);
return $"{NumberToString((int)(adjPosition.x / 145))}{((int)(adjPosition.y / 145)) - 1}";
}
private string NumberToString(int number) {
bool a = number > 26;
Char c = (Char)(65 + (a ? number - 26 : number));
return a ? "A" + c : c.ToString();
}
#endregion
#region Teleportation Management
private void MovePosition(BasePlayer player, Vector3 destination) {
if (player.net?.connection != null) player.ClientRPCPlayer(null, player, "StartLoading");
StartSleeping(player);
player.MovePosition(destination);
if (player.net?.connection != null) player.ClientRPCPlayer(null, player, "ForcePositionTo", destination);
if (player.net?.connection != null) player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
player.UpdateNetworkGroup();
player.SendNetworkUpdateImmediate(false);
if (player.net?.connection == null) return;
try {
player.ClearEntityQueue(null);
}
catch {
}
player.SendFullSnapshot();
}
private void StartSleeping(BasePlayer player) {
if (player.IsSleeping()) return;
player.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
if (!BasePlayer.sleepingPlayerList.Contains(player)) BasePlayer.sleepingPlayerList.Add(player);
player.CancelInvoke("InventoryUpdate");
}
#endregion
#region Player Saving and Restoration
public static void StripInventory(BasePlayer player) {
Item[] allItems = player.inventory.AllItems();
for (int i = allItems.Length - 1; i >= 0; i--) {
Item item = allItems[i];
item.RemoveFromContainer();
item.Remove();
}
}
private IEnumerable<RestoreData.ItemData> GetItems(ItemContainer container) {
return container.itemList.Select(item => new RestoreData.ItemData {
itemid = item.info.itemid, amount = item.amount, ammo = item.GetHeldEntity() is BaseProjectile ? (item.GetHeldEntity() as BaseProjectile).primaryMagazine.contents : item.GetHeldEntity() is FlameThrower ? (item.GetHeldEntity() as FlameThrower).ammo : 0, ammotype = (item.GetHeldEntity() as BaseProjectile)?.primaryMagazine.ammoType.shortname ?? null, position = item.position, skin = item.skin, condition = item.condition, maxCondition = item.maxCondition, instanceData = new RestoreData.ItemData.InstanceData(item), contents = item.contents?.itemList.Select(item1 => new RestoreData.ItemData {
itemid = item1.info.itemid, amount = item1.amount, condition = item1.condition
}
).ToArray()
}
);
}
public class RestoreData {
public Hash<ulong, PlayerData> restoreData = new Hash<ulong, PlayerData>();
public void AddData(BasePlayer player) {
restoreData[player.userID] = new PlayerData(player);
}
public void RemoveData(ulong playerId) {
if (HasRestoreData(playerId)) restoreData.Remove(playerId);
}
public bool HasRestoreData(ulong playerId) => restoreData.ContainsKey(playerId);
public void RestorePlayer(BasePlayer player) {
if (isUnloading) {
player.Die();
player.ChatMessage("<color=#ce422b>The plugin has been unloaded!</color> We are unable to restore you at this time, when the plugin has been reloaded you will be restored to your previous state");
return;
}
PlayerData playerData;
if (restoreData.TryGetValue(player.userID, out playerData)) {
StripInventory(player);
ins.UnlockInventory(player);
if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
ins.timer.Once(1, () => RestorePlayer(player));
return;
}
ins.NextTick(() => {
if (player == null || playerData == null) return;
playerData.SetStats(player);
ins.MovePosition(player, playerData.GetPosition());
RestoreAllItems(player, playerData);
}
);
}
}
private void RestoreAllItems(BasePlayer player, PlayerData playerData) {
if (player == null || !player.IsConnected) return;
if (RestoreItems(player, playerData.containerBelt, "belt") && RestoreItems(player, playerData.containerWear, "wear") && RestoreItems(player, playerData.containerMain, "main")) RemoveData(player.userID);
}
private bool RestoreItems(BasePlayer player, ItemData[] itemData, string type) {
ItemContainer container = type == "belt" ? player.inventory.containerBelt : type == "wear" ? player.inventory.containerWear : player.inventory.containerMain;
for (int i = 0; i < itemData.Length; i++) {
Item item = CreateItem(itemData[i]);
item.position = itemData[i].position;
item.SetParent(container);
}
return true;
}
public Item CreateItem(ItemData itemData) {
Item item = ItemManager.CreateByItemID(itemData.itemid, itemData.amount, itemData.skin);
item.condition = itemData.condition;
if (itemData.instanceData != null) itemData.instanceData.Restore(item);
BaseProjectile weapon = item.GetHeldEntity() as BaseProjectile;
if (weapon != null) {
if (!string.IsNullOrEmpty(itemData.ammotype)) weapon.primaryMagazine.ammoType = ItemManager.FindItemDefinition(itemData.ammotype);
weapon.primaryMagazine.contents = itemData.ammo;
}
FlameThrower flameThrower = item.GetHeldEntity() as FlameThrower;
if (flameThrower != null) flameThrower.ammo = itemData.ammo;
if (itemData.contents != null) {
foreach (ItemData contentData in itemData.contents) {
Item newContent = ItemManager.CreateByItemID(contentData.itemid, contentData.amount);
if (newContent != null) {
newContent.condition = contentData.condition;
newContent.MoveToContainer(item.contents);
}
}
}
return item;
}
public class PlayerData {
public float[] stats;
public float[] position;
public ItemData[] containerMain;
public ItemData[] containerWear;
public ItemData[] containerBelt;
public PlayerData() {
}
public PlayerData(BasePlayer player) {
stats = GetStats(player);
position = GetPosition(player.transform.position);
containerBelt = ins.GetItems(player.inventory.containerBelt).ToArray();
containerMain = ins.GetItems(player.inventory.containerMain).ToArray();
containerWear = ins.GetItems(player.inventory.containerWear).ToArray();
}
private float[] GetStats(BasePlayer player) => new float[] {
player.health, player.metabolism.hydration.value, player.metabolism.calories.value
}
;
public void SetStats(BasePlayer player) {
player.health = stats[0];
player.metabolism.hydration.value = stats[1];
player.metabolism.calories.value = stats[2];
player.metabolism.SendChangesToClient();
}
private float[] GetPosition(Vector3 position) => new float[] {
position.x, position.y, position.z
}
;
public Vector3 GetPosition() => new Vector3(position[0], position[1], position[2]);
}
public class ItemData {
public int itemid;
public ulong skin;
public int amount;
public float condition;
public float maxCondition;
public int ammo;
public string ammotype;
public int position;
public InstanceData instanceData;
public ItemData[] contents;
public class InstanceData {
public int dataInt;
public int blueprintTarget;
public int blueprintAmount;
public InstanceData() {
}
public InstanceData(Item item) {
if (item.instanceData == null) return;
dataInt = item.instanceData.dataInt;
blueprintAmount = item.instanceData.blueprintAmount;
blueprintTarget = item.instanceData.blueprintTarget;
}
public void Restore(Item item) {
item.instanceData = new ProtoBuf.Item.InstanceData();
item.instanceData.blueprintAmount = blueprintAmount;
item.instanceData.blueprintTarget = blueprintTarget;
item.instanceData.dataInt = dataInt;
}
}
}
}
#endregion
#region Sphere Creation
private void CreateSphere() {
finalSphere = new SphereEntity[configData.Game.SphereDarkness];
for (int i = 0; i < configData.Game.SphereDarkness; i++) {
var sphere = (SphereEntity)GameManager.server.CreateEntity(sphereEnt, endPos, new Quaternion(), true);
sphere.currentRadius = 5;
sphere.lerpSpeed = 0;
sphere.enableSaving = false;
sphere.Spawn();
finalSphere[i] = sphere;
}
finalSphere[0].gameObject.AddComponent<FinalSphere>();
}
class FinalSphere : MonoBehaviour {
public BaseEntity entity;
void Awake() {
entity = GetComponent<BaseEntity>();
gameObject.layer = (int)Layer.Reserved1;
gameObject.name = $"Juggernaut Final Zone";
enabled = false;
var collider = entity.gameObject.AddComponent<SphereCollider>();
collider.isTrigger = true;
collider.radius = 0.5f;
}
void OnDestroy() {
if (!entity.IsDestroyed) entity.Kill();
}
void OnTriggerEnter(Collider obj) {
if (obj.gameObject.layer == (int)Layer.Player_Server) {
var player = obj?.GetComponentInParent<BasePlayer>();
if (player != null) {
if (player == ins.juggernaut) {
ins.EventWin();
}
}
}
}
}
#endregion
#region Hooks
#region Internal Checks
private bool IsClanmate(ulong playerId, ulong friendId) {
if (!Clans) return false;
object playerTag = Clans?.Call("GetClanOf", playerId);
object friendTag = Clans?.Call("GetClanOf", friendId);
if (playerTag is string && friendTag is string) if (playerTag == friendTag) return true;
return false;
}
private bool IsFriend(ulong playerID, ulong friendID) {
if (!Friends) return false;
return (bool)Friends?.Call("IsFriend", playerID, friendID);
}
private bool IsPlaying(BasePlayer player) {
if (!EventManager) return false;
return (bool)EventManager.Call("isPlaying", player);
}
private void JoinedEvent(BasePlayer player) {
if (optedIn.Contains(player.userID)) optedIn.Remove(player.userID);
}
private void AddMapMarker(float x, float z, string markerName) => LustyMap?.Call("AddTemporaryMarker", x, z, markerName, configData.UI.IconUrl);
private void RemoveMapMarker(string markerName, bool startsWith) {
if (!startsWith) LustyMap?.Call("RemoveTemporaryMarker", markerName);
else LustyMap?.Call("RemoveTemporaryMarkerStartsWith", markerName);
}
#endregion
#region External Checks
object CanTrade(BasePlayer player) {
if (player == juggernaut) return msg("tryTrading", player.UserIDString);
return null;
}
object canRemove(BasePlayer player) {
if (player == juggernaut) return msg("tryRemove", player.UserIDString);
return null;
}
object CanTeleport(BasePlayer player) {
if (player == juggernaut) return msg("tryTP", player.UserIDString);
return null;
}
object canShop(BasePlayer player) {
if (player == juggernaut) return msg("tryShop", player.UserIDString);
return null;
}
#endregion
#endregion
#region UI
public class UI {
static public CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, bool useCursor = false) {
var NewElement = new CuiElementContainer() {
{
new CuiPanel {
Image = {
Color = color
}
, RectTransform = {
AnchorMin = aMin, AnchorMax = aMax
}
, CursorEnabled = useCursor
}
, new CuiElement().Parent = "Hud", panelName
}
}
;
return NewElement;
}
static public void AddImage(ref CuiElementContainer container, string panel, string png, string aMin, string aMax, float fadeOut = 0f) {
container.Add(new CuiElement {
Name = CuiHelper.GetGuid(), Parent = panel, Components = {
new CuiRawImageComponent {
Png = png, Sprite = "assets/content/textures/generic/fulltransparent.tga"
}
, new CuiRectTransformComponent {
AnchorMin = aMin, AnchorMax = aMax
}
}
}
);
}
static public void CreateLabel(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter) {
container.Add(new CuiLabel {
Text = {
Color = color, FontSize = size, Align = align, Text = text
}
, RectTransform = {
AnchorMin = aMin, AnchorMax = aMax
}
}
, panel);
}
public static string Color(string hexColor, float alpha) {
if (hexColor.StartsWith("#")) hexColor = hexColor.TrimStart('#');
int red = int.Parse(hexColor.Substring(0, 2), NumberStyles.AllowHexSpecifier);
int green = int.Parse(hexColor.Substring(2, 2), NumberStyles.AllowHexSpecifier);
int blue = int.Parse(hexColor.Substring(4, 2), NumberStyles.AllowHexSpecifier);
return $"{(double)red / 255} {(double)green / 255} {(double)blue / 255} {alpha}";
}
}
#endregion
#region UI Creation
private const string Main = "JuggernautMain";
private const string Compass = "JuggernautCompass";
private void CreateTimerUI(BasePlayer player) {
var MainCont = UI.CreateElementContainer(Main, UI.Color(configData.UI.UIBackgroundColor, configData.UI.UIOpacity), $"{configData.UI.TimerPosition.XPosition} {configData.UI.TimerPosition.YPosition}", $"{configData.UI.TimerPosition.XPosition + configData.UI.TimerPosition.XDimension} {configData.UI.TimerPosition.YPosition + configData.UI.TimerPosition.YDimension}");
if (!string.IsNullOrEmpty(juggernautIcon)) UI.AddImage(ref MainCont, Main, juggernautIcon, "0.01 0.05", "0.425 0.95");
UI.CreateLabel(ref MainCont, Main, "", GetFormatTime(eventEnd), 15, "0.5 0", "1 1", TextAnchor.MiddleLeft);
CuiHelper.DestroyUi(player, Main);
CuiHelper.AddUi(player, MainCont);
}
private string GetFormatTime(double timeLeft) {
var time = timeLeft - GrabCurrentTime();
double minutes = Math.Floor((double)(time / 60));
time -= (int)(minutes * 60);
return string.Format("{0:00}:{1:00}", minutes, time);
}
private void RefreshAllUI() {
uiTimer = timer.Repeat(1, (int)(eventEnd - GrabCurrentTime()) - 1, () => {
foreach (var player in BasePlayer.activePlayerList) CreateTimerUI(player);
if (configData.UI.ShowCoordsToJuggernaut) ShowCompass();
}
);
}
private void ShowCompass() {
var MainCont = UI.CreateElementContainer(Compass, UI.Color(configData.UI.UIBackgroundColor, configData.UI.UIOpacity), $"{configData.UI.CompassPosition.XPosition} {configData.UI.CompassPosition.YPosition}", $"{configData.UI.CompassPosition.XPosition + configData.UI.CompassPosition.XDimension} {configData.UI.CompassPosition.YPosition + configData.UI.CompassPosition.YDimension}");
UI.CreateLabel(ref MainCont, Compass, "", string.Format(msg("target1", juggernaut.UserIDString), GetGridString(endPos)), 10, "0.05 0.5", "0.95 0.95", TextAnchor.MiddleLeft);
UI.CreateLabel(ref MainCont, Compass, "", string.Format(msg("target2", juggernaut.UserIDString), Math.Round(Vector3.Distance(juggernaut.transform.position, endPos), 2)), 10, "0.05 0.05", "0.95 0.5", TextAnchor.MiddleLeft);
CuiHelper.DestroyUi(juggernaut, Compass);
CuiHelper.AddUi(juggernaut, MainCont);
}
#endregion
#region Imagery
private WWW info;
public void Add(string url) {
info = new WWW(url);
TryDownloadImage();
}
void TryDownloadImage() {
if (!info.isDone) {
timer.In(1, TryDownloadImage);
return;
}
if (!string.IsNullOrEmpty(info.error)) {
PrintError(string.Format("Failed to load the Juggernaut icon! Error: {0}", info.error));
return;
}
else juggernautIcon = FileStorage.server.Store(info.bytes, FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
}
#endregion
#region Commands
[ChatCommand("jug")]
void cmdJuggernaut(BasePlayer player, string command, string[] args) {
if (args.Length == 0) {
SendReply(player, $"<color=#ce422b>{Title}</color><color=#939393> v{Version} -</color> <color=#ce422b>{Author} @ www.chaoscode.io</color>");
SendReply(player, msg("help0", player.UserIDString));
SendReply(player, msg("help1", player.UserIDString));
SendReply(player, msg("help2", player.UserIDString));
SendReply(player, msg("help3", player.UserIDString));
SendReply(player, msg("help4", player.UserIDString));
if (player.IsAdmin) {
SendReply(player, msg("help5", player.UserIDString));
SendReply(player, msg("help6", player.UserIDString));
SendReply(player, msg("help7", player.UserIDString));
SendReply(player, msg("help8", player.UserIDString));
}
return;
}
switch (args[0].ToLower()) {
case "info" : string time = GetFormatTime(nextTrigger);
if (hasStarted) SendReply(player, string.Format(msg("endsIn", player.UserIDString), time));
else if (isOpen) SendReply(player, string.Format(msg("startsIn", player.UserIDString), time));
else SendReply(player, string.Format(msg("nextEvent", player.UserIDString), time));
return;
case "join" : if (!permission.UserHasPermission(player.UserIDString, "juggernaut.canbe")) {
SendReply(player, msg("noPerms", player.UserIDString));
return;
}
if (!isOpen) {
SendReply(player, msg("notOpen", player.UserIDString));
return;
}
if (IsPlaying(player)) {
SendReply(player, msg("playingEM", player.UserIDString));
return;
}
if (!optedIn.Contains(player.userID)) {
optedIn.Add(player.userID);
SendReply(player, msg("enteredDraw", player.UserIDString));
PrintToChat(string.Format(msg("candidate"), player.displayName, optedIn.Count));
}
return;
case "leave" : if (!isOpen) {
SendReply(player, msg("notOpen", player.UserIDString));
return;
}
if (optedIn.Contains(player.userID)) optedIn.Remove(player.userID);
SendReply(player, msg("removedDraw", player.UserIDString));
return;
case "claim" : if (storedData.winnerRewards.ContainsKey(player.userID)) {
foreach(var prize in storedData.winnerRewards[player.userID]) {
Item item = restoreData.CreateItem(prize);
if (item != null) player.GiveItem(item, BaseEntity.GiveItemReason.Generic);
}
SendReply(player, msg("claimSuccess", player.UserIDString));
storedData.winnerRewards.Remove(player.userID);
SaveData();
}
else if (storedData.winnerMoney.ContainsKey(player.userID)) {
foreach(var prize in storedData.winnerMoney[player.userID]) {
if (prize.isRp) ServerRewards?.Call("AddPoints", player.userID, prize.amount);
else Economics?.Call("Deposit", player.userID, (double)prize.amount);
}
SendReply(player, msg("claimSuccess", player.UserIDString));
storedData.winnerMoney.Remove(player.userID);
SaveData();
}
else SendReply(player, msg("noPrizes", player.UserIDString));
return;
case "restore" : if (player == juggernaut) {
SendReply(player, msg("cantRestore", player.UserIDString));
return;
}
if (restoreData.HasRestoreData(player.userID)) {
TryRestorePlayer(player);
return;
}
else SendReply(player, msg("noRestoreData", player.UserIDString));
return;
case "open" : if (player.IsAdmin) {
if (isOpen) {
SendReply(player, msg("alreadyOpen", player.UserIDString));
return;
}
if (!hasDestinations) {
SendReply(player, msg("noDestinations", player.UserIDString));
return;
}
if (hasStarted) {
SendReply(player, msg("alreadyStarted", player.UserIDString));
return;
}
if (nextMatch != null) nextMatch.Destroy();
OpenEvent();
}
return;
case "start" : if (player.IsAdmin) {
if (!isOpen) {
SendReply(player, msg("isntOpen", player.UserIDString));
return;
}
if (hasStarted) {
SendReply(player, msg("alreadyStarted", player.UserIDString));
return;
}
if (startMatch != null) startMatch.Destroy();
if (openMessage != null) openMessage.Destroy();
StartEvent();
}
return;
case "cancel" : if (player.IsAdmin) {
if (!isOpen && !hasStarted) {
SendReply(player, msg("notStarted", player.UserIDString));
return;
}
if (isOpen) {
if (startMatch != null) startMatch.Destroy();
if (openMessage != null) openMessage.Destroy();
isOpen = false;
PrintToChat(msg("adminCancel"));
StartEventTimer();
return;
}
if (hasStarted) {
PrintToChat(msg("adminCancel"));
TryRestorePlayer(juggernaut);
DestroyEvent();
return;
}
}
return;
case "destination" : if (player.IsAdmin) {
if (!destinationCreator.ContainsKey(player.userID)) {
destinationCreator.Add(player
// ... [Code preview truncated due to length. Full source in attached file] ...