C#:
using System.Collections.Generic;
using Newtonsoft.Json;
using CompanionServer.Handlers;
using Oxide.Plugins.SputnikExtensionMethods;
using UnityEngine;
using System;
using Oxide.Core.Plugins;
using Network;
using Rust;
using System.Collections;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using System.Reflection;
namespace Oxide.Plugins {
[Info("Sputnik", "Sempai#3239", "1.0.8")]
class Sputnik : RustPlugin {
#region Variables
[PluginReference]
Plugin NpcSpawn, PveMode, GUIAnnouncements, DiscordMessages, ZoneManager, RaidableBases;
const bool en = false;
static Sputnik ins;
EventClass eventClass;
static Dictionary<string, List<EntData>> saveData;
Coroutine findSpawnPointsCorountine;
Coroutine autoEventCorountine;
HashSet<string> subscribeMethods = new HashSet<string> {
"OnCardSwipe", "CanHackCrate", "OnLootEntity", "CanLootEntity", "OnEntityDeath", "OnEntityKill", "OnCorpsePopulate", "CanPopulateLoot", "OnCustomLootContainer", "CanEntityTakeDamage", "OnTrapTrigger", "OnTurretTarget", "CanEntityBeTargeted", "OnEntityTakeDamage", "OnPlayerSleep"
}
;
#endregion Variables
#region Hooks
void Init() => Unsubscribes();
void OnServerInitialized() {
PrintWarning("\n-----------------------------\n" + " Author - Sempai#3239\n" + " VK - https://vk.com/rustnastroika/n" + " Forum - https://darkplugins.ru/n" + " Discord - https://discord.gg/5DPTsRmd3G/n" + "-----------------------------");
ins = this;
PostLoadCheck();
UpdateConfig();
LoadDefaultMessages();
LoadData();
FindNewEventPoints();
if (_config.mainConfig.isAutoEvent) autoEventCorountine = ServerMgr.Instance.StartCoroutine(AutoEventCorountine());
}
void Unload() {
StopEvent();
if (findSpawnPointsCorountine != null) ServerMgr.Instance.StopCoroutine(findSpawnPointsCorountine);
if (autoEventCorountine != null) ServerMgr.Instance.StopCoroutine(autoEventCorountine);
}
object OnCardSwipe(CardReader cardReader, Keycard keycard, BasePlayer player) {
if (eventClass == null || player == null || cardReader == null || keycard == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCardReaderUid(cardReader.net.ID);
Item keyCardItem = keycard.GetItem();
if (keyCardItem == null) return null;
if (keyCardItem.info.shortname == ins._config.customCardConfig.shortName && keyCardItem.skin == ins._config.customCardConfig.skinID) {
if (sputnikClass != null && !sputnikClass.cardReaderOpen) {
keyCardItem.LoseCondition(_config.customCardConfig.helthLossScale);
sputnikClass.cardReaderOpen = true;
return true;
}
else if (keyCardItem.skin != 0) return true;
}
else if (sputnikClass != null) InformPlayer(player, "NeedUseCard", _config.prefix);
return null;
}
object CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
if (eventClass == null || player == null || crate == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(crate.net.ID);
if (sputnikClass != null) {
if (!sputnikClass.CanOpenCrate(crate.net.ID)) {
InformPlayer(player, "NeedUseCard", _config.prefix);
return true;
}
else ActionEconomy(player.userID, "LockedCrate");
}
return null;
}
void OnLootEntity(BasePlayer player, LootContainer container) {
if (eventClass == null || player == null || container == null) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(container.net.ID);
if (sputnikClass != null) {
sputnikClass.OnCratelooted(container.net.ID);
ActionEconomy(player.userID, "Crates", container.PrefabName);
}
}
object CanLootEntity(BasePlayer player, LootContainer container) {
if (eventClass == null || player == null || container == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(container.net.ID);
if (sputnikClass != null) {
if (!sputnikClass.CanOpenCrate(container.net.ID)) {
InformPlayer(player, "NeedUseCard", _config.prefix);
return true;
}
}
return null;
}
void OnLootSpawn(LootContainer container) {
if (!_config.customCardConfig.enableSpawnInDefaultCrates || container == null || container.inventory == null) return;
float chance = 0;
if (!_config.customCardConfig.spawnSetting.TryGetValue(container.PrefabName, out chance) || chance == 0) return;
if (UnityEngine.Random.Range(0f, 100f) <= chance) {
Item item = CreateCustomCardItem();
container.inventory.Remove(container.inventory.itemList.FirstOrDefault(x => true));
if (!item.MoveToContainer(container.inventory)) item.Remove();
}
}
object OnEntityTakeDamage(ScientistNPC scientistNPC, HitInfo info) {
if (eventClass == null || scientistNPC == null || info == null || info.Initiator == null) return null;
NpcConfig npcConfig = _config.npcConfigs.FirstOrDefault(x => x.name == scientistNPC.displayName);
if (npcConfig == null) return null;
AutoTurret autoTurret = info.Initiator as AutoTurret;
if (autoTurret == null) return null;
if (eventClass.IsEventTurret(autoTurret.net.ID)) return true;
return null;
}
object OnEntityTakeDamage(AutoTurret autoTurret, HitInfo info) {
if (eventClass == null || autoTurret == null) return null;
if (eventClass.IsEventTurret(autoTurret.net.ID) && (info.InitiatorPlayer == null || !info.InitiatorPlayer.IsRealPlayer())) return true;
return null;
}
void OnEntityDeath(ScientistNPC scientistNPC, HitInfo info) {
if (eventClass == null || scientistNPC == null || info == null) return;
if (info.InitiatorPlayer.IsRealPlayer() && _config.npcConfigs.Any(x => x != null && x.name == scientistNPC.displayName)) ActionEconomy(info.InitiatorPlayer.userID, "Npc");
}
void OnEntityDeath(BasePlayer player, HitInfo info) {
OnPlayerSleep(player);
}
void OnPlayerSleep(BasePlayer player) {
if (eventClass == null || !player.IsRealPlayer()) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromPLayerInZoneUid(player.userID);
if (sputnikClass != null) {
sputnikClass.RemovePlayerFromZone(player);
}
}
void OnCorpsePopulate(BasePlayer entity, NPCPlayerCorpse corpse) {
if (eventClass != null || entity == null || corpse == null) return;
if (entity is ScientistNPC) {
NpcConfig npcConfig = _config.npcConfigs.FirstOrDefault(x => x.name == entity.displayName);
if (npcConfig == null) return;
NextTick(() => {
if (corpse == null) return;
ItemContainer container = corpse.containers[0];
if (npcConfig.typeLootTable == 0) {
for (int i = container.itemList.Count - 1; i >= 0; i--) {
Item item = container.itemList[i];
if (npcConfig.wearItems.Any(x => x.shortName == item.info.shortname)) {
item.RemoveFromContainer();
item.Remove();
}
}
if (npcConfig.deleteCorpse && corpse != null && !corpse.IsDestroyed) corpse.Kill();
return;
}
if (npcConfig.typeLootTable == 2 || npcConfig.typeLootTable == 3) {
if (npcConfig.deleteCorpse && !corpse.IsDestroyed) corpse.Kill();
return;
}
container.ClearItemsContainer();
if (npcConfig.typeLootTable == 1 && npcConfig.lootTable.minAmount > 0) AddToContainerItem(container, npcConfig.lootTable, npcConfig.typeLootTable);
if (npcConfig.deleteCorpse && corpse != null && !corpse.IsDestroyed) corpse.Kill();
}
);
}
}
object OnTrapTrigger(BaseTrap baseTrap, GameObject gameObject) {
if (baseTrap == null) return null;
ScientistNPC scientistNPC = gameObject.ToBaseEntity() as ScientistNPC;
if (scientistNPC != null && _config.npcConfigs.Any(x => x.name == scientistNPC.displayName)) return true;
return null;
}
object OnTurretTarget(AutoTurret turret, BasePlayer player) {
if (eventClass == null || !turret.IsExists() || !player.IsExists()) return null;
if (!eventClass.IsEventTurret(turret.net.ID)) return null;
if (!player.IsRealPlayer()) return true;
return null;
}
#region OtherPlugins
object CanPopulateLoot(ScientistNPC entity, NPCPlayerCorpse corpse) {
if (eventClass == null || entity == null || corpse == null) return null;
NpcConfig npcConfig = _config.npcConfigs.FirstOrDefault(x => x.name == entity.displayName);
if (npcConfig != null && npcConfig.typeLootTable != 2) return true;
return null;
}
object CanPopulateLoot(LootContainer container) {
if (eventClass == null || container == null) return null;
string cratePresetName = null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(container.net.ID);
if (sputnikClass == null) return null;
if (container is HackableLockedCrate) {
if (sputnikClass.lockedCrates.Any(y => y.Key != null && y.Key.net.ID == container.net.ID)) cratePresetName = sputnikClass.lockedCrates[container];
}
else if (sputnikClass.crates.Any(y => y.Key != null && y.Key.net.ID == container.net.ID)) cratePresetName = sputnikClass.crates[container];
if (cratePresetName == null) return null;
CrateConfig crateConfig = _config.crateConfigs.FirstOrDefault(x => x.presetName == cratePresetName);
if (crateConfig != null && crateConfig.typeLootTable != 2) return true;
return null;
}
object OnCustomLootContainer(uint netID) {
if (eventClass == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(netID);
if (sputnikClass == null) return null;
string cratePresetName = null;
if (sputnikClass.lockedCrates.Any(y => y.Key != null && y.Key.net.ID == netID)) cratePresetName = sputnikClass.lockedCrates.FirstOrDefault(y => y.Key != null && y.Key.net.ID == netID).Value;
else if (sputnikClass.crates.Any(y => y.Key != null && y.Key.net.ID == netID)) cratePresetName = sputnikClass.crates.FirstOrDefault(y => y.Key != null && y.Key.net.ID == netID).Value;
if (cratePresetName == null) return null;
CrateConfig crateConfig = _config.crateConfigs.FirstOrDefault(x => x.presetName == cratePresetName);
if (crateConfig != null && crateConfig.typeLootTable != 3) return true;
return null;
}
object CanEntityTakeDamage(AutoTurret autoTurret, HitInfo hitinfo) {
if (eventClass == null || autoTurret == null || hitinfo == null) return null;
if (eventClass.IsEventTurret(autoTurret.net.ID)) {
if (hitinfo.InitiatorPlayer == null || !hitinfo.InitiatorPlayer.IsRealPlayer()) return false;
else return true;
}
return null;
}
object CanEntityTakeDamage(Landmine landmine, HitInfo hitinfo) {
if (eventClass == null || landmine == null || hitinfo == null) return null;
if (eventClass.IsEventMine(landmine.net.ID)) {
if (hitinfo.InitiatorPlayer == null || !hitinfo.InitiatorPlayer.IsRealPlayer()) return false;
else return true;
}
return null;
}
object CanEntityTakeDamage(ScientistNPC scientistNPC, HitInfo hitinfo) {
if (eventClass == null || scientistNPC == null || hitinfo == null || hitinfo.Initiator == null) return null;
NpcConfig npcConfig = _config.npcConfigs.FirstOrDefault(x => x.name == scientistNPC.displayName);
if (npcConfig == null) return null;
AutoTurret autoTurret = hitinfo.Initiator as AutoTurret;
if (autoTurret == null) return null;
if (eventClass.IsEventTurret(autoTurret.net.ID)) return false;
return null;
}
object CanEntityTakeDamage(BasePlayer victim, HitInfo hitinfo) {
if (eventClass == null || victim == null || hitinfo == null || !victim.userID.IsSteamId()) return null;
BasePlayer attacker = hitinfo.InitiatorPlayer;
if (attacker != null) {
SputnikClass sputnikClass = eventClass.GetSputnikClassFromPLayerInZoneUid(victim.userID);
if (sputnikClass != null && sputnikClass.sputnikDebrisConfig.zoneConfig.isCreateZonePVP && (attacker == null || (attacker != null && eventClass.GetSputnikClassFromPLayerInZoneUid(attacker.userID) != null))) return true;
}
else if (hitinfo.Initiator != null) {
AutoTurret autoTurret = hitinfo.Initiator as AutoTurret;
if (autoTurret != null) {
if (eventClass.IsEventTurret(autoTurret.net.ID)) return true;
return null;
}
BaseTrap baseTrap = hitinfo.Initiator as BaseTrap;
if (baseTrap != null) {
if (eventClass.IsEventMine(baseTrap.net.ID)) return true;
return null;
}
}
return null;
}
object CanEntityTrapTrigger(BaseTrap trap, BasePlayer player) {
if (eventClass == null || trap == null) return null;
if (eventClass.IsEventMine(trap.net.ID)) return true;
return null;
}
object CanEntityBeTargeted(BasePlayer player, BaseEntity turret) {
if (eventClass == null || turret == null || !player.IsRealPlayer()) return null;
if (eventClass.IsEventTurret(turret.net.ID)) return true;
return null;
}
#endregion OtherPlugins
#endregion Hooks
#region Commands
[ChatCommand("sputnikstart")]
void ChatStartCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
if (arg != null && arg.Length >= 1) StartEvent(arg[0], player);
else StartEvent(activator : player);
}
[ChatCommand("sputnikstop")]
void ChatStopCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
StopEvent();
}
[ConsoleCommand("sputnikstart")]
void ConsoleStartCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
if (arg.Args != null && arg.Args.Length > 0) StartEvent(arg.Args[0]);
StartEvent();
Puts("Event activated");
}
[ConsoleCommand("sputnikstop")]
void ConsoleStopCommand(ConsoleSystem.Arg arg) {
if (arg.Player() == null) StopEvent();
}
[ChatCommand("givespacecard")]
void GiveCustomItemChatCommand(BasePlayer player, string command, string[] arg) {
if (player == null || !player.IsAdmin || arg == null) return;
MoveItem(player, CreateCustomCardItem());
PrintToChat(player, GetMessage("GetSpaceCard", player.UserIDString, _config.prefix));
}
[ConsoleCommand("givespacecard")]
void GiveCustomItemCommand(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
BasePlayer target = null;
if (arg.Args.Length >= 1) target = BasePlayer.FindByID(Convert.ToUInt64(arg.Args[0]));
if (target == null) {
PrintToConsole(player, "Player not found");
return;
}
MoveItem(target, CreateCustomCardItem());
PrintToChat(target, GetMessage("GetSpaceCard", target.UserIDString, _config.prefix));
Puts($"A space card was given to {target.displayName}");
}
#endregion Commands
#region Methods
void PostLoadCheck() {
if (!plugins.Exists("NpcSpawn")) {
PrintError("NpcSpawn plugin doesn`t exist! Please read the file ReadMe.txt");
NextTick(() => Server.Command($"o.unload {Name}"));
return;
}
}
void UpdateConfig() {
if (_config.version == Version) return;
if (_config.version.Minor == 0) {
if (_config.version.Patch <= 2) {
_config.supportedPluginsConfig.zoneManager = new ZoneManagerConfig {
enable = false, blockFlags = new HashSet<string> {
"eject", "pvegod"
}
}
;
}
if (_config.version.Patch <= 3) {
_config.supportedPluginsConfig.raidableBases = new RaidableBasesConfig();
_config.spawnConfig.minTCDistance = 25;
_config.mainConfig.destroyAfterLootingTime = 300;
}
}
_config.version = Version;
SaveConfig();
}
void LoadData() {
saveData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, List<EntData>>>(ins.Title);
if (saveData == null || saveData.Count == 0) {
PrintError("Data file not found");
NextTick(() => Server.Command($"o.unload {Name}"));
}
}
void Unsubscribes() {
foreach (string hook in subscribeMethods) Unsubscribe(hook);
if (!_config.customCardConfig.enableSpawnInDefaultCrates) Unsubscribe("OnLootSpawn");
}
void Subscribes() {
foreach (string hook in subscribeMethods) Subscribe(hook);
}
void StartEvent(string presetName = "", BasePlayer activator = null) {
if (eventClass != null) {
SendErrorMessage(GetMessage("EventActive", activator != null ? activator.UserIDString : null, _config.prefix), activator);
return;
}
StopEvent();
EventConfig eventConfig = DefineEventConfig(presetName);
if (eventConfig == null) {
SendErrorMessage("Event preset not found!", activator);
return;
}
if (autoEventCorountine != null) ServerMgr.Instance.StopCoroutine(autoEventCorountine);
LocationDefiner.CacheBuildingPrivilegeLocations();
eventClass = new EventClass();
eventClass.StartEvent(eventConfig);
Interface.CallHook("OnSputnikEventStart");
}
void StopEvent() {
if (eventClass != null) {
if (autoEventCorountine != null) ServerMgr.Instance.StopCoroutine(autoEventCorountine);
if (_config.mainConfig.isAutoEvent) autoEventCorountine = ServerMgr.Instance.StartCoroutine(AutoEventCorountine());
eventClass.StopEvent();
eventClass = null;
FindNewEventPoints();
InformAllPlayers("EndEvent", _config.prefix);
Interface.CallHook("OnSputnikEventStop");
DefineEventWinner();
SendBalance();
Unsubscribes();
}
}
EventConfig DefineEventConfig(string presetName) {
if (presetName != "") {
return ins._config.eventConfigs.FirstOrDefault(x => x.presetName.Contains(presetName));
}
else if (ins._config.eventConfigs.Any(x => x.chance > 0)) {
while (true) {
foreach (EventConfig checkEventConfig in ins._config.eventConfigs) {
float chance = UnityEngine.Random.Range(0, 100);
if (chance <= checkEventConfig.chance) {
return checkEventConfig;
}
}
}
}
return null;
}
void FindNewEventPoints() {
if (findSpawnPointsCorountine != null) ServerMgr.Instance.StopCoroutine(findSpawnPointsCorountine);
findSpawnPointsCorountine = ServerMgr.Instance.StartCoroutine(LocationDefiner.FindSpawnPosition());
}
IEnumerator AutoEventCorountine() {
yield return CoroutineEx.waitForSeconds(UnityEngine.Random.Range(_config.mainConfig.minTimeBetweenEvent, _config.mainConfig.maxTimeBetweenEvent));
StartEvent();
}
void AddToContainerItem(ItemContainer container, LootTableConfig lootTableConfig, int typeOfLootTable) {
if (typeOfLootTable == 1) container.ClearItemsContainer();
int CountLootInContainer = 0;
int countLoot = UnityEngine.Random.Range(lootTableConfig.minAmount, lootTableConfig.maxAmount);
if (typeOfLootTable == 4) container.capacity += countLoot;
else container.capacity = countLoot;
for (; CountLootInContainer < countLoot;) {
foreach (ItemConfig item in lootTableConfig.itemsConfig) {
if (UnityEngine.Random.Range(0.0f, 100.0f) <= item.chance) {
int amount = UnityEngine.Random.Range(item.minAmount, item.maxAmount);
Item newItem = item.isBluePrint ? ItemManager.CreateByName("blueprintbase") : ItemManager.CreateByName(item.shortName, amount, item.skinID);
if (item.isBluePrint) newItem.blueprintTarget = ItemManager.FindItemDefinition(item.shortName).itemid;
if (item.name != "") newItem.name = item.name;
if (!newItem.MoveToContainer(container)) newItem.Remove();
if (CountLootInContainer == countLoot) return;
CountLootInContainer++;
}
}
}
}
#region MoveItem
void MoveItem(BasePlayer player, Item item) {
int spaceCountItem = GetSpaceCountItem(player, item.info.shortname, item.MaxStackable(), item.skin);
int inventoryItemCount;
if (spaceCountItem > item.amount) inventoryItemCount = item.amount;
else inventoryItemCount = spaceCountItem;
if (inventoryItemCount > 0) {
Item itemInventory = ItemManager.CreateByName(item.info.shortname, inventoryItemCount, item.skin);
if (item.skin != 0) itemInventory.name = item.name;
item.amount -= inventoryItemCount;
MoveInventoryItem(player, itemInventory);
}
if (item.amount > 0) MoveOutItem(player, item);
}
int GetSpaceCountItem(BasePlayer player, string shortname, int stack, ulong skinID) {
int slots = player.inventory.containerMain.capacity + player.inventory.containerBelt.capacity;
int taken = player.inventory.containerMain.itemList.Count + player.inventory.containerBelt.itemList.Count;
int result = (slots - taken) * stack;
foreach (Item item in player.inventory.AllItems()) if (item.info.shortname == shortname && item.skin == skinID && item.amount < stack) result += stack - item.amount;
return result;
}
void MoveInventoryItem(BasePlayer player, Item item) {
if (item.amount <= item.MaxStackable()) {
foreach (Item itemInv in player.inventory.AllItems()) {
if (itemInv.info.shortname == item.info.shortname && itemInv.skin == item.skin && itemInv.amount < itemInv.MaxStackable()) {
if (itemInv.amount + item.amount <= itemInv.MaxStackable()) {
itemInv.amount += item.amount;
itemInv.MarkDirty();
return;
}
else {
item.amount -= itemInv.MaxStackable() - itemInv.amount;
itemInv.amount = itemInv.MaxStackable();
}
}
}
if (item.amount > 0) player.inventory.GiveItem(item);
}
else {
while (item.amount > item.MaxStackable()) {
Item thisItem = ItemManager.CreateByName(item.info.shortname, item.MaxStackable(), item.skin);
if (item.skin != 0) thisItem.name = item.name;
player.inventory.GiveItem(thisItem);
item.amount -= item.MaxStackable();
}
if (item.amount > 0) player.inventory.GiveItem(item);
}
}
void MoveOutItem(BasePlayer player, Item item) {
if (item.amount <= item.MaxStackable()) item.Drop(player.transform.position, Vector3.up);
else {
while (item.amount > item.MaxStackable()) {
Item thisItem = ItemManager.CreateByName(item.info.shortname, item.MaxStackable(), item.skin);
if (item.skin != 0) thisItem.name = item.name;
thisItem.Drop(player.transform.position, Vector3.up);
item.amount -= item.MaxStackable();
}
if (item.amount > 0) item.Drop(player.transform.position, Vector3.up);
}
}
Item CreateCustomCardItem() {
Item item = ItemManager.CreateByName(_config.customCardConfig.shortName, 1, _config.customCardConfig.skinID);
if (_config.customCardConfig.name != "") item.name = _config.customCardConfig.name;
return item;
}
#endregion MoveItem
#region Notify
void SendErrorMessage(string message, BasePlayer player = null) {
if (player != null) PrintToChat(player, message);
else PrintError(message);
}
void InformAllPlayers(string langKey, params object[] args) {
foreach (BasePlayer player in BasePlayer.activePlayerList) if (player != null) InformPlayer(player, langKey, args);
SendDiscordMessage(langKey, args);
}
void InformPlayer(BasePlayer player, string langKey, params object[] args) {
if (_config.notifyConfig.chat) PrintToChat(player, GetMessage(langKey, player.UserIDString, args));
if (_config.supportedPluginsConfig.GUIAnnouncements.isGUIAnnouncements) GUIAnnouncements?.Call("CreateAnnouncement", ClearColorAndSize(GetMessage(langKey, player.UserIDString, args)), _config.supportedPluginsConfig.GUIAnnouncements.bannerColor, _config.supportedPluginsConfig.GUIAnnouncements.textColor, player, _config.supportedPluginsConfig.GUIAnnouncements.apiAdjustVPosition);
if (_config.supportedPluginsConfig.notify.isNotify) player.SendConsoleCommand($"notify.show {_config.supportedPluginsConfig.notify.type} {ClearColorAndSize(GetMessage(langKey, player.UserIDString, args))}");
}
void SendDiscordMessage(string langKey, params object[] args) {
if (CanSendDiscordMessage() && _config.supportedPluginsConfig.discord.keys.Contains(langKey)) {
object fields = new[] {
new {
name = Title, value = ClearColorAndSize(GetMessage(langKey, null, args)), inline = false
}
}
;
DiscordMessages?.Call("API_SendFancyMessage", _config.supportedPluginsConfig.discord.webhookUrl, "", _config.supportedPluginsConfig.discord.embedColor, JsonConvert.SerializeObject(fields), null, this);
}
}
string ClearColorAndSize(string message) {
message = message.Replace("</color>", string.Empty);
message = message.Replace("</size>", string.Empty);
while (message.Contains("<color=")) {
int index = message.IndexOf("<color=");
message = message.Remove(index, message.IndexOf(">", index) - index + 1);
}
while (message.Contains("<size=")) {
int index = message.IndexOf("<size=");
message = message.Remove(index, message.IndexOf(">", index) - index + 1);
}
return message;
}
private bool CanSendDiscordMessage() => _config.supportedPluginsConfig.discord.isDiscord && !string.IsNullOrEmpty(_config.supportedPluginsConfig.discord.webhookUrl) && _config.supportedPluginsConfig.discord.webhookUrl != "https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks";
string GetTimeMessage(string userIDString, int seconds) {
string message = "";
TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
if (timeSpan.Hours > 0) message += $" {timeSpan.Hours} {GetMessage("Hour", userIDString)}";
if (timeSpan.Minutes > 0) message += $" {timeSpan.Minutes} {GetMessage("Min", userIDString)}";
if (message == "") message += $" {timeSpan.Seconds} {GetMessage("Sec", userIDString)}";
return message;
}
#endregion Notify
#region Economy
[PluginReference]
readonly Plugin Economics, ServerRewards, IQEconomic;
readonly Dictionary<ulong, double> _playersBalance = new Dictionary<ulong, double>();
void ActionEconomy(ulong playerId, string type, string arg = "") {
switch (type) {
case "Crates" : double economyCrateData;
if (_config.supportedPluginsConfig.economy.crates.TryGetValue(arg, out economyCrateData)) AddBalance(playerId, economyCrateData);
break;
case "Npc" : AddBalance(playerId, _config.supportedPluginsConfig.economy.npcPoint);
break;
case "LockedCrate" : AddBalance(playerId, _config.supportedPluginsConfig.economy.lockedCratePoint);
break;
case "Turret" : AddBalance(playerId, _config.supportedPluginsConfig.economy.turretPoint);
break;
case "Heli" : AddBalance(playerId, _config.supportedPluginsConfig.economy.heliPoint);
break;
}
}
void AddBalance(ulong playerId, double balance) {
if (balance == 0) return;
if (_playersBalance.ContainsKey(playerId)) _playersBalance[playerId] += balance;
else _playersBalance.Add(playerId, balance);
}
void SendBalance() {
if (!_config.supportedPluginsConfig.economy.enable || _playersBalance.Count == 0) {
_playersBalance.Clear();
return;
}
foreach (KeyValuePair<ulong, double> dic in _playersBalance) {
if (dic.Value < _config.supportedPluginsConfig.economy.minEconomyPiont) continue;
int intCount = Convert.ToInt32(dic.Value);
if (_config.supportedPluginsConfig.economy.plugins.Contains("Economics") && plugins.Exists("Economics") && dic.Value > 0) Economics.Call("Deposit", dic.Key.ToString(), dic.Value);
if (_config.supportedPluginsConfig.economy.plugins.Contains("Server Rewards") && plugins.Exists("ServerRewards") && intCount > 0) ServerRewards.Call("AddPoints", dic.Key, intCount);
if (_config.supportedPluginsConfig.economy.plugins.Contains("IQEconomic") && plugins.Exists("IQEconomic") && intCount > 0) IQEconomic.Call("API_SET_BALANCE", dic.Key, intCount);
BasePlayer player = BasePlayer.FindByID(dic.Key);
if (player != null) InformPlayer(player, "SendEconomy", _config.prefix, dic.Value);
}
double max = 0;
ulong winnerId = 0;
foreach (var a in _playersBalance) {
if (a.Value > max) {
max = a.Value;
winnerId = a.Key;
}
}
if (max >= _config.supportedPluginsConfig.economy.minCommandPoint) foreach (string command in _config.supportedPluginsConfig.economy.commands) Server.Command(command.Replace("{steamid}", $"{winnerId}"));
_playersBalance.Clear();
}
void DefineEventWinner() {
var winnerPair = _playersBalance.Max(x => (float)x.Value);
if (winnerPair.Value > 0) Interface.CallHook("OnSputnikEventWin", winnerPair.Key);
}
#endregion Economy
#endregion Methods
#region Classes
class EventClass {
EventConfig eventConfig;
Coroutine startEventCorountine;
Coroutine eventCorountine;
HashSet<SputnikClass> sputnikClasses = new HashSet<SputnikClass>();
internal int eventTime;
internal SputnikClass GetSputnikClassFromPLayerInZoneUid(ulong userId) => sputnikClasses.FirstOrDefault(x => x != null && x.IsPlayerInZone(userId));
internal SputnikClass GetSputnikClassFromCrateUid(uint crateUID) => sputnikClasses.FirstOrDefault(x => x != null && (x.IsEventCrate(crateUID) || x.IsEventLockedCrate(crateUID)));
internal SputnikClass GetSputnikClassFromCardReaderUid(uint cardReaderUID) => sputnikClasses.FirstOrDefault(x => x != null && x.IsClassCardReader(cardReaderUID));
internal bool IsEventTurret(uint netID) => sputnikClasses.Any(x => x != null && x.IsDebrisTurret(netID));
internal bool IsEventMine(uint netID) => sputnikClasses.Any(x => x != null && x.IsDebrisMine(netID));
internal void StartEvent(EventConfig eventConfig) {
this.eventConfig = eventConfig;
eventTime = eventConfig.eventTime;
startEventCorountine = ServerMgr.Instance.StartCoroutine(StartEventCorountine());
}
internal void StopEvent() {
foreach (SputnikClass sputnikClass in sputnikClasses) {
if (sputnikClass != null && sputnikClass.gameObject != null) UnityEngine.Object.DestroyImmediate(sputnikClass.gameObject);
}
if (startEventCorountine != null) ServerMgr.Instance.StopCoroutine(startEventCorountine);
if (eventCorountine != null) ServerMgr.Instance.StopCoroutine(eventCorountine);
}
IEnumerator StartEventCorountine() {
if (ins._config.notifyConfig.chat) {
foreach (BasePlayer player in BasePlayer.activePlayerList) if (player != null) ins.InformPlayer(player, "PreStartEvent", ins._config.prefix, eventConfig.displayName, ins.GetTimeMessage(player.UserIDString, ins._config.notifyConfig.preStartTime));
}
ins.SendDiscordMessage("PreStartEvent", ins._config.prefix, eventConfig.displayName, ins.GetTimeMessage(null, ins._config.notifyConfig.preStartTime));
yield return CoroutineEx.waitForSeconds(ins._config.notifyConfig.preStartTime);
if (ins.autoEventCorountine != null) ServerMgr.Instance.StopCoroutine(ins.autoEventCorountine);
ins.InformAllPlayers("StartEvent", ins._config.prefix, eventConfig.displayName);
CreateNewSputnikClasses();
eventCorountine = ServerMgr.Instance.StartCoroutine(EventCorountine());
ins.Subscribes();
}
IEnumerator EventCorountine() {
while (eventTime > 0 && sputnikClasses.Any(x => x != null)) {
eventTime -= 1;
if (ins._config.notifyConfig.chat && ins._config.notifyConfig.timeNotifications.Contains(eventTime)) {
foreach (BasePlayer player in BasePlayer.activePlayerList) {
if (player != null) ins.PrintToChat(player, ins.GetMessage("RemainTime", player.UserIDString, ins._config.prefix, eventConfig.displayName, ins.GetTimeMessage(player.UserIDString, eventTime)));
}
}
foreach (SputnikClass sputnikClass in sputnikClasses) sputnikClass.UpdateZone();
yield return CoroutineEx.waitForSeconds(1);
}
ins.StopEvent();
}
void CreateNewSputnikClasses() {
if (eventConfig.fixedSputniksPresets != null && eventConfig.fixedSputniksPresets.Count > 0) {
foreach (string sputnikDebrisPresetName in eventConfig.fixedSputniksPresets) {
SputnikDebrisConfig sputnikDebrisConfig = ins._config.sputnikDebrisConfigs.FirstOrDefault(x => x.presetName == sputnikDebrisPresetName);
if (sputnikDebrisConfig == null) {
ins.PrintError("Sputnik debris preset not found!");
continue;
}
CreateNewSputnikClass(sputnikDebrisConfig);
}
}
if (sputnikClasses.Count == 0 || !sputnikClasses.Any(x => x != null)) ins.StopEvent();
}
void CreateNewSputnikClass(SputnikDebrisConfig sputnikDebrisConfig) {
GameObject gameObject = new GameObject();
gameObject.layer = (int)Layer.Reserved1;
SputnikClass sputnik = gameObject.AddComponent<SputnikClass>();
sputnik.Init(sputnikDebrisConfig);
sputnikClasses.Add(sputnik);
}
}
class SputnikClass : FacepunchBehaviour {
internal SputnikDebrisConfig sputnikDebrisConfig;
Coroutine crushEffectsCorountine;
Coroutine onSputnikFellCorountine;
Coroutine destroyCorountine;
FallSputnikClass fallSputnik;
MapMarkerGenericRadius mapmarker;
VendingMachineMapMarker vendingMarker;
HashSet<BaseEntity> decorEntities = new HashSet<BaseEntity>();
HashSet<AutoTurret> turrets = new HashSet<AutoTurret>();
HashSet<BaseEntity> mines = new HashSet<BaseEntity>();
ZoneClass zoneClass;
CardReader cardReader;
SputnikHeli sputnikHeli;
internal bool cardReaderOpen = true;
internal HashSet<ScientistNPC> npcs = new HashSet<ScientistNPC>();
internal HashSet<uint> openedCrates = new HashSet<uint>();
internal Dictionary<LootContainer, string> crates = new Dictionary<LootContainer, string>();
internal Dictionary<LootContainer, string> lockedCrates = new Dictionary<LootContainer, string>();
internal HashSet<uint> spaceCardCratesIDs = new HashSet<uint>();
internal int destroyTime = 0;
internal bool IsClassCardReader(uint netId) => cardReader != null && cardReader.net.ID == netId;
internal bool CanOpenCrate(uint netId) => !spaceCardCratesIDs.Contains(netId) || !cardReader.IsExists() || cardReaderOpen;
internal bool IsEventCrate(uint netId) => crates.Keys.Any(x => x.IsExists() && x.net.ID == netId);
internal bool IsEventLockedCrate(uint netId) => lockedCrates.Keys.Any(x => x.IsExists() && x.net.ID == netId);
internal bool IsPlayerInZone(ulong userId) => zoneClass != null && zoneClass.playersInZone.Any(x => x.userID == userId);
internal bool IsDebrisTurret(uint netId) => turrets.Any(x => x.IsExists() && x.net.ID == netId);
internal bool IsDebrisMine(uint netId) => mines.Any(x => x.IsExists() && x.net.ID == netId);
internal void RemovePlayerFromZone(BasePlayer player) {
if (zoneClass == null || !zoneClass.playersInZone.Any(x => x.userID == player.userID)) return;
zoneClass.playersInZone.Remove(player);
if (ins._config.guiConfig.IsGUI) CuiHelper.DestroyUi(player, "SputnikGui");
if (sputnikDebrisConfig.zoneConfig.isCreateZonePVP) ins.InformPlayer(player, "ExitPVP", ins._config.prefix);
}
internal void OnCratelooted(uint netId) {
if (destroyCorountine != null || openedCrates.Contains(netId) || ins._config.mainConfig.destroyAfterLootingTime > ins.eventClass.eventTime || ins._config.mainConfig.destroyAfterLootingTime == 0) return;
openedCrates.Add(netId);
if (crates.Keys.Any(x => x != null && !openedCrates.Contains(x.net.ID)) || lockedCrates.Keys.Any(x => x != null && !openedCrates.Contains(x.net.ID))) return;
destroyCorountine = ServerMgr.Instance.StartCoroutine(DestroyCorountine());
}
internal void Init(SputnikDebrisConfig sputnikDebrisConfig) {
this.sputnikDebrisConfig = sputnikDebrisConfig;
DefineEventPosition();
CreateFallSputnik();
}
internal void UpdateZone() {
UpdateMapMarker();
if (zoneClass != null) zoneClass.UpdateGui();
}
void DefineEventPosition() {
Vector3 position = Vector3.zero;
while (position == Vector3.zero && LocationDefiner.spawnPositions.Count > 0) {
Vector3 newPosition = LocationDefiner.spawnPositions.GetRandom();
if (LocationDefiner.PostChechPoint(newPosition)) {
position = newPosition;
break;
}
else LocationDefiner.spawnPositions.Remove(newPosition);
}
if (position != Vector3.zero) {
gameObject.transform.position = position;
LocationDefiner.spawnPositions.Remove(position);
}
else {
ins.PrintError("The event could not be started! Increase the number of cached spawn points!");
ins.NextTick(() => ins.StopEvent());
}
}
void CreateFallSputnik() {
fallSputnik = gameObject.AddComponent<FallSputnikClass>();
fallSputnik.Init(this, gameObject.transform.position);
}
internal void OnSputnikFell() => onSputnikFellCorountine = ServerMgr.Instance.StartCoroutine(OnSputnikFellCorountine());
IEnumerator OnSputnikFellCorountine() {
crushEffectsCorountine = ServerMgr.Instance.StartCoroutine(CrushEffectsCorountine());
yield return CoroutineEx.waitForSeconds(0.5f);
CreateGrounSputnik();
CreateCardReader();
CreateNPCs();
CreateCrates();
CreateMines();
SpawnMarkers();
CreateHeli();
CreateTurrets();
CreateZone();
yield return CoroutineEx.waitForSeconds(2f);
if (fallSputnik != null) Destroy(fallSputnik);
ins.InformAllPlayers("Crash", ins._config.prefix, PhoneController.PositionToGridCoord(gameObject.transform.position));
}
IEnumerator CrushEffectsCorountine() {
for (int i = 0; i < ins._config.fallindConfig.countEffects; i++) {
Effect.server.Run("assets/bundled/prefabs/fx/explosions/explosion_03.prefab", gameObject.transform.position + new Vector3(UnityEngine.Random.Range(-7.5f, 7.5f), 0, UnityEngine.Random.Range(-7.5f, 7.5f)));
Effect.server.Run("assets/bundled/prefabs/fx/explosions/explosion_02.prefab", gameObject.transform.position + new Vector3(UnityEngine.Random.Range(-7.5f, 7.5f), 0, UnityEngine.Random.Range(-7.5f, 7.5f)));
yield return CoroutineEx.waitForSeconds(0.1f);
}
}
IEnumerator DestroyCorountine() {
destroyTime = ins._config.mainConfig.destroyAfterLootingTime;
UpdateZone();
while (destroyTime > 1) {
destroyTime -= 1;
yield return CoroutineEx.waitForSeconds(1);
}
UnityEngine.Object.DestroyImmediate(this.gameObject);
}
void CreateZone() {
zoneClass = gameObject.AddComponent<ZoneClass>();
zoneClass.Init(this);
}
void SpawnMarkers() {
if (!sputnikDebrisConfig.markerConfig.enable) return;
SpawnMapMarker();
SpawnVendingMarker();
}
void SpawnMapMarker() {
mapmarker = GameManager.server.CreateEntity("assets/prefabs/tools/map/genericradiusmarker.prefab", gameObject.transform.position) as MapMarkerGenericRadius;
mapmarker.enableSaving = false;
mapmarker.Spawn();
mapmarker.radius = sputnikDebrisConfig.markerConfig.radius;
mapmarker.alpha = sputnikDebrisConfig.markerConfig.alpha;
mapmarker.color1 = new Color(sputnikDebrisConfig.markerConfig.color1.r, sputnikDebrisConfig.markerConfig.color1.g, sputnikDebrisConfig.markerConfig.color1.b);
mapmarker.color2 = new Color(sputnikDebrisConfig.markerConfig.color2.r, sputnikDebrisConfig.markerConfig.color2.g, sputnikDebrisConfig.markerConfig.color2.b);
}
void SpawnVendingMarker() {
vendingMarker = GameManager.server.CreateEntity("assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab", gameObject.transform.position) as VendingMachineMapMarker;
vendingMarker.enableSaving = false;
vendingMarker.markerShopName = $"{sputnikDebrisConfig.markerConfig.displayName} {ins.GetTimeMessage(null, ins.eventClass.eventTime)}";
vendingMarker.Spawn();
}
void UpdateMapMarker() {
if (vendingMarker != null) {
string text = destroyTime > 0 ? $"{sputnikDebrisConfig.markerConfig.displayName} {ins.GetTimeMessage(null, destroyTime)}" : $"{sputnikDebrisConfig.markerConfig.displayName} {ins.GetTimeMessage(null, ins.eventClass.eventTime)}";
vendingMarker.markerShopName = text;
vendingMarker.SendNetworkUpdate();
}
// ... [Code preview truncated due to length. Full source in attached file] ...