C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using CompanionServer.Handlers;
using UnityEngine;
using Network;
using Rust;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.SputnikExtensionMethods;
using Time = UnityEngine.Time;
using Epic.OnlineServices.Presence;
using ProtoBuf;
namespace Oxide.Plugins {
[Info("Sputnik", "Adem", "1.3.0")]
class Sputnik : RustPlugin {
#region Variables
const bool en = true;
static Sputnik ins;
HashSet<string> subscribeMethods = new HashSet<string> {
"OnCardSwipe", "CanHackCrate", "OnLootEntity", "CanLootEntity", "OnEntityTakeDamage", "OnEntityDeath", "OnPlayerSleep", "OnCorpsePopulate", "OnTrapTrigger", "OnTurretTarget", "CanHelicopterTarget", "OnCustomNpcTarget", "CanPopulateLoot", "OnCustomLootContainer", "CanEntityTakeDamage", "CanEntityTrapTrigger", "CanEntityBeTargeted", "OnRestoreUponDeath"
}
;
[PluginReference]
Plugin NpcSpawn, PveMode, GUIAnnouncements, DiscordMessages, ZoneManager, RaidableBases, Economics, ServerRewards, IQEconomic, Friends, Clans;
EventClass eventClass;
static Dictionary<string, List<EntData>> saveData;
Coroutine findSpawnPointsCorountine;
Coroutine autoEventCorountine;
#endregion Variables
#region Hooks
void Init() {
Unsubscribes();
}
void OnServerInitialized() {
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.Value);
if (sputnikClass != null) {
sputnikClass.OnCardSwipe(keycard, player);
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 CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
if (eventClass == null || player == null || crate == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(crate.net.ID.Value);
if (sputnikClass != null) {
if (!sputnikClass.IsSputnikAgressive()) {
sputnikClass.MakeSputnikAgressive();
return true;
}
if (!sputnikClass.CanOpenCrate(crate.net.ID.Value)) {
NotifyManager.SendMessageToPlayer(player, "NeedUseCard", _config.prefix);
return true;
}
else EconomyManager.ActionEconomy(player.userID, "LockedCrate");
}
return null;
}
object CanLootEntity(BasePlayer player, LootContainer container) {
if (eventClass == null || player == null || container == null || container.net == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(container.net.ID.Value);
if (sputnikClass != null) {
if (!sputnikClass.IsSputnikAgressive()) {
sputnikClass.MakeSputnikAgressive();
return true;
}
if (!sputnikClass.CanOpenCrate(container.net.ID.Value)) {
NotifyManager.SendMessageToPlayer(player, "NeedUseCard", _config.prefix);
return true;
}
}
return null;
}
void OnLootEntity(BasePlayer player, LootContainer container) {
if (eventClass == null || player == null || container == null) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(container.net.ID.Value);
if (sputnikClass != null) {
sputnikClass.MakeSputnikAgressive();
sputnikClass.OnCratelooted(container.net.ID.Value);
EconomyManager.ActionEconomy(player.userID, "Crates", container.PrefabName);
}
}
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;
SputnikClass sputnikClass = eventClass.GetSputnikClassByNpcUid(scientistNPC.net.ID.Value);
if (sputnikClass != null && info.InitiatorPlayer.IsRealPlayer()) sputnikClass.MakeSputnikAgressive();
AutoTurret autoTurret = info.Initiator as AutoTurret;
if (autoTurret != null && eventClass.GetSputnikClassByTurretUid(autoTurret.net.ID.Value) != null) return true;
return null;
}
object OnEntityTakeDamage(AutoTurret autoTurret, HitInfo info) {
if (eventClass == null || autoTurret == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassByTurretUid(autoTurret.net.ID.Value);
if (sputnikClass != null && info.InitiatorPlayer.IsRealPlayer()) sputnikClass.MakeSputnikAgressive();
return null;
}
void OnEntityTakeDamage(PatrolHelicopter patrolHelicopter, HitInfo info) {
if (eventClass == null || patrolHelicopter == null || patrolHelicopter.net == null) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassByHeliUid(patrolHelicopter.net.ID.Value);
if (sputnikClass != null && info.InitiatorPlayer.IsRealPlayer()) {
sputnikClass.MakeSputnikAgressive();
sputnikClass.sputnikHeli.OnPlayerAttacked(info.InitiatorPlayer.userID);
}
}
void OnEntityDeath(PatrolHelicopter patrolHelicopter, HitInfo info) {
if (patrolHelicopter == null || eventClass == null || patrolHelicopter.net == null) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassByHeliUid(patrolHelicopter.net.ID.Value);
if (sputnikClass != null) {
ulong lastHeliAttackerUserId = sputnikClass.sputnikHeli.lastAttackedPlayer;
if (lastHeliAttackerUserId != 0) EconomyManager.ActionEconomy(lastHeliAttackerUserId, "Heli");
}
}
void OnEntityDeath(BasePlayer player, HitInfo info) {
if (player == null) return;
ScientistNPC scientistNPC = player as ScientistNPC;
if (scientistNPC != null) {
if (eventClass == null || info == null) return;
else if (info.InitiatorPlayer.IsRealPlayer() && _config.npcConfigs.Any(x => x != null && x.name == scientistNPC.displayName)) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Npc");
}
else {
OnPlayerSleep(player);
}
}
void OnEntityDeath(AutoTurret autoTurret, HitInfo info) {
if (autoTurret == null || eventClass == null || autoTurret.net == null || !info.InitiatorPlayer.IsRealPlayer()) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassByTurretUid(autoTurret.net.ID.Value);
if (sputnikClass != null) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Turret");
}
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 (container == null) return;
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.IsExists()) corpse.Kill();
return;
}
if (npcConfig.typeLootTable == 2 || npcConfig.typeLootTable == 3) {
if (npcConfig.deleteCorpse && corpse.IsExists()) corpse.Kill();
return;
}
container.ClearItemsContainer();
if (npcConfig.typeLootTable == 1 && npcConfig.lootTable.minAmount > 0) AddToContainerItem(container, npcConfig.lootTable, npcConfig.typeLootTable);
if (npcConfig.deleteCorpse && corpse.IsExists()) 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 == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassByTurretUid(turret.net.ID.Value);
if (sputnikClass != null) {
if (!player.IsRealPlayer()) return true;
if (!sputnikClass.IsSputnikAgressive() && !_config.agressiveConfig.turretAgressiveMode) return true;
}
return null;
}
object CanHelicopterTarget(PatrolHelicopterAI heli, BasePlayer player) {
if (eventClass == null || heli == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassByHeliUid(heli.helicopterBase.net.ID.Value);
if (sputnikClass != null) {
if (!player.IsRealPlayer()) return false;
if (!sputnikClass.IsSputnikAgressive() && !_config.agressiveConfig.heliAgressiveMode) return false;
}
return null;
}
#region OtherPlugins
object OnCustomNpcTarget(ScientistNPC npc, BasePlayer player) {
if (eventClass == null || npc == null || npc.net == null) return null;
if (!_config.npcConfigs.Any(x => x.name == npc.displayName)) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassByNpcUid(npc.net.ID.Value);
if (sputnikClass != null) {
if (!sputnikClass.IsSputnikAgressive() && !_config.agressiveConfig.npcAgressiveMode) return false;
}
return null;
}
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;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(container.net.ID.Value);
if (sputnikClass == null) return null;
string cratePresetName = null;
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(NetworkableId netID) {
if (eventClass == null || netID == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassFromCrateUid(netID.Value);
if (sputnikClass == null) return null;
string cratePresetName = null;
if (sputnikClass.lockedCrates.Any(y => y.Key != null && y.Key.net.ID.Value == netID.Value)) cratePresetName = sputnikClass.lockedCrates.FirstOrDefault(y => y.Key != null && y.Key.net.ID.Value == netID.Value).Value;
else if (sputnikClass.crates.Any(y => y.Key != null && y.Key.net.ID.Value == netID.Value)) cratePresetName = sputnikClass.crates.FirstOrDefault(y => y.Key != null && y.Key.net.ID.Value == netID.Value).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;
SputnikClass sputnikClass = eventClass.GetSputnikClassByTurretUid(autoTurret.net.ID.Value);
if (sputnikClass != null) {
if (!hitinfo.InitiatorPlayer.IsRealPlayer()) return false;
if (hitinfo.InitiatorPlayer != null && !sputnikClass.pveModeController.IsPveModeBlockAction(hitinfo.InitiatorPlayer)) return true;
else return null;
}
return null;
}
object CanEntityTakeDamage(Landmine landmine, HitInfo hitinfo) {
if (eventClass == null || landmine == null || hitinfo == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassByMineUid(landmine.net.ID.Value);
if (sputnikClass != null) {
if (!hitinfo.InitiatorPlayer.IsRealPlayer()) return false;
if (hitinfo.InitiatorPlayer != null && !sputnikClass.pveModeController.IsPveModeBlockAction(hitinfo.InitiatorPlayer)) return true;
else return null;
}
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;
if (hitinfo.Initiator is AutoTurret && eventClass.GetSputnikClassByTurretUid(hitinfo.Initiator.net.ID.Value) != null) 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 && !_config.supportedPluginsConfig.pveMode.enable && (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) {
SputnikClass sputnikClass = eventClass.GetSputnikClassByTurretUid(autoTurret.net.ID.Value);
if (sputnikClass != null) {
if (victim != null && !sputnikClass.pveModeController.IsPveModeBlockAction(victim)) return true;
}
}
BaseTrap baseTrap = hitinfo.Initiator as BaseTrap;
if (baseTrap != null) {
SputnikClass sputnikClass = eventClass.GetSputnikClassByMineUid(baseTrap.net.ID.Value);
if (sputnikClass != null) {
if (victim != null && !sputnikClass.pveModeController.IsPveModeBlockAction(victim)) return true;
}
}
}
return null;
}
object CanEntityTrapTrigger(BaseTrap trap, BasePlayer player) {
if (eventClass == null || trap == null || !player.IsRealPlayer()) return null;
if (eventClass.GetSputnikClassByMineUid(trap.net.ID.Value) != null) return true;
return null;
}
object CanEntityBeTargeted(BasePlayer player, BaseEntity turret) {
if (eventClass == null || turret == null || turret.net == null) return null;
SputnikClass sputnikClass = eventClass.GetSputnikClassByTurretUid(turret.net.ID.Value);
if (sputnikClass != null) {
if (!player.IsRealPlayer()) return false;
else if (!sputnikClass.IsSputnikAgressive() && !_config.agressiveConfig.turretAgressiveMode) return false;
else if (player != null && !sputnikClass.pveModeController.IsPveModeBlockAction(player)) return true;
}
return null;
}
object OnRestoreUponDeath(BasePlayer player) {
if (player == null || eventClass == null) return null;
if (_config.supportedPluginsConfig.restoreUponDeath.disableRestore) {
SputnikClass sputnikClass = eventClass.GetSputnikClassFromPLayerInZoneUid(player.userID);
if (sputnikClass != null) return false;
}
return null;
}
void SetOwnerPveMode(string eventName, BasePlayer owner) {
if (eventClass == null) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassByShortName(eventName);
if (sputnikClass != null) sputnikClass.pveModeController.SetPveModeOwner(owner);
}
void ClearOwnerPveMode(string eventName) {
if (eventClass == null) return;
SputnikClass sputnikClass = eventClass.GetSputnikClassByShortName(eventName);
if (sputnikClass != null) sputnikClass.pveModeController.ClearPveModeOwner();
}
#endregion OtherPlugins
#endregion Hooks
#region Commands
[ChatCommand("sputnikstart")]
void ChatStartCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
string eventPresetName = "";
if (arg != null && arg.Length >= 1) eventPresetName = arg[0];
StartEvent(eventPresetName, 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;
string eventPresetName = "";
if (arg.Args != null && arg.Args.Length > 0) eventPresetName = arg.Args[0];
StartEvent(eventPresetName);
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) {
ulong userId = Convert.ToUInt64(arg.Args[0]);
target = BasePlayer.FindByID(userId);
}
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}");
}
[ChatCommand("sputnikspawnpoint")]
void SpawnPointCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
if (arg.Length <= 0) {
PrintToChat(player, _config.prefix + " Use the command: /sputnikspawnpoint <DebrisPresetName>");
return;
}
string sputnikPresetName = arg[0];
SputnikDebrisConfig sputnikDebrisConfig = _config.sputnikDebrisConfigs.FirstOrDefault(x => x.presetName == sputnikPresetName);
if (sputnikDebrisConfig == null) {
PrintToChat(player, _config.prefix + " <color=#ce3f27>Couldn't</color> find the preset");
return;
}
sputnikDebrisConfig.customSpawnPoints.Add(player.transform.position.ToString());
SaveConfig();
PrintToChat(player, _config.prefix + " New spawn point <color=#738d43>successfully</color> added");
}
#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;
}
if (_config.version.Patch <= 8) {
_config.supportedPluginsConfig.pveMode.scaleDamage.Add(new ScaleDamageConfig {
Type = "Helicopter", Scale = 1
}
);
}
_config.version = new VersionNumber(1, 1, 0);
}
if (_config.version.Minor == 1) {
if (_config.version.Patch <= 2) {
_config.agressiveConfig = new AgressiveConfig {
agressiveSecurityMode = true, agressiveTime = 120, npcAgressiveMode = true, turretAgressiveMode = true, heliAgressiveMode = false,
}
;
foreach (SputnikDebrisConfig sputnikDebrisConfig in _config.sputnikDebrisConfigs) {
sputnikDebrisConfig.useCustomSpawnPoints = false;
sputnikDebrisConfig.customSpawnPoints = new List<string>();
}
}
_config.version = new VersionNumber(1, 2, 0);
}
if (_config.version.Minor == 2) {
if (_config.version.Patch == 0) {
foreach (HeliConfig heliConfig in _config.heliConfigs) {
heliConfig.outsideTime = 60;
}
}
if (_config.version.Patch <= 1) {
foreach (SputnikDebrisConfig sputnikDebrisConfig in _config.sputnikDebrisConfigs) {
sputnikDebrisConfig.markerConfig.useRingMarker = true;
sputnikDebrisConfig.markerConfig.useShopMarker = true;
}
_config.supportedPluginsConfig.pveMode.showEventOwnerNameOnMap = true;
}
if (_config.version.Patch <= 5) {
_config.supportedPluginsConfig.zoneManager.blockIDs = new HashSet<string> {
"Example"
}
;
_config.supportedPluginsConfig.restoreUponDeath = new RestoreUponDeathConfig {
disableRestore = false
}
;
}
if (_config.version.Patch <= 9) {
if (_config.supportedPluginsConfig.pveMode.scaleDamage.Any(x => x.Type == "Turret")) {
ScaleDamageConfig scaleDamageConfig = new ScaleDamageConfig {
Type = "Turret", Scale = 1f
}
;
}
}
}
_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) {
NotifyManager.PrintError(activator, "EventActive_Exeption");
return;
}
StopEvent();
EventConfig eventConfig = DefineEventConfig(presetName);
if (eventConfig == null) {
NotifyManager.PrintError(activator, "PresetNotFound_Exeption", presetName);
return;
}
if (autoEventCorountine != null) ServerMgr.Instance.StopCoroutine(autoEventCorountine);
LocationDefiner.CacheBuildingPrivilegeLocations();
eventClass = new EventClass();
eventClass.StartEvent(eventConfig);
Interface.CallHook("OnSputnikEventStart");
if (ins._config.mainConfig.enableStartStopLogs) NotifyManager.PrintLogMessage("EventStart_Log", eventConfig.presetName);
}
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();
NotifyManager.SendMessageToAll("EndEvent", _config.prefix);
Interface.CallHook("OnSputnikEventStop");
EconomyManager.OnEventEnd();
Unsubscribes();
if (ins._config.mainConfig.enableStartStopLogs) NotifyManager.PrintLogMessage("EventStop_Log");
}
}
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 (container == null) return;
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
#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(ulong crateUID) => sputnikClasses.FirstOrDefault(x => x != null && (x.IsEventCrate(crateUID) || x.IsEventLockedCrate(crateUID)));
internal SputnikClass GetSputnikClassFromCardReaderUid(ulong cardReaderUID) => sputnikClasses.FirstOrDefault(x => x != null && x.IsClassCardReader(cardReaderUID));
internal SputnikClass GetSputnikClassByTurretUid(ulong netID) => sputnikClasses.FirstOrDefault(x => x != null && x.IsDebrisTurret(netID));
internal SputnikClass GetSputnikClassByMineUid(ulong netID) => sputnikClasses.FirstOrDefault(x => x != null && x.IsDebrisMine(netID));
internal SputnikClass GetSputnikClassByNpcUid(ulong netID) => sputnikClasses.FirstOrDefault(x => x != null && x.IsNpcMine(netID));
internal SputnikClass GetSputnikClassByHeliUid(ulong netID) => sputnikClasses.FirstOrDefault(x => x != null && x.IsHeliMine(netID));
internal SputnikClass GetSputnikClassByShortName(string shortname) => sputnikClasses.FirstOrDefault(x => x != null && shortname == x.sputnikDebrisConfig.presetName);
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.notificatonConfig.preStartTime > 0) {
NotifyManager.SendMessageToAll("PreStartEvent", ins._config.prefix, eventConfig.displayName, ins._config.notificatonConfig.preStartTime);
yield return CoroutineEx.waitForSeconds(ins._config.notificatonConfig.preStartTime);
}
if (ins.autoEventCorountine != null) ServerMgr.Instance.StopCoroutine(ins.autoEventCorountine);
NotifyManager.SendMessageToAll("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.notificatonConfig.timeNotifications.Contains(eventTime)) {
NotifyManager.SendMessageToAll("RemainTime", ins._config.prefix, eventConfig.displayName, 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;
Coroutine updateCorountine;
FallSputnikClass fallSputnik;
MapMarkerGenericRadius mapmarker;
VendingMachineMapMarker vendingMarker;
HashSet<BaseEntity> decorEntities = new HashSet<BaseEntity>();
internal HashSet<AutoTurret> turrets = new HashSet<AutoTurret>();
HashSet<BaseEntity> mines = new HashSet<BaseEntity>();
ZoneClass zoneClass;
CardReader cardReader;
internal SputnikHeli sputnikHeli;
internal bool cardReaderOpen = true;
internal HashSet<ScientistNPC> npcs = new HashSet<ScientistNPC>();
internal HashSet<ulong> openedCrates = new HashSet<ulong>();
internal Dictionary<LootContainer, string> crates = new Dictionary<LootContainer, string>();
internal Dictionary<LootContainer, string> lockedCrates = new Dictionary<LootContainer, string>();
internal HashSet<ulong> spaceCardCratesIDs = new HashSet<ulong>();
internal int destroyTime = 0;
internal int agressiveTime = 0;
internal PveModeController pveModeController;
float lastEventOvnerNameCheckTime = 0;
string eventOwnerName = "";
internal bool IsSputnikAgressive() {
return ins._config.agressiveConfig.agressiveSecurityMode || agressiveTime > 0;
}
internal void MakeSputnikAgressive() {
if (ins._config.agressiveConfig.agressiveSecurityMode) return;
agressiveTime = ins._config.agressiveConfig.agressiveTime;
}
internal bool IsClassCardReader(ulong netId) => cardReader != null && cardReader.net.ID.Value == netId;
internal bool CanOpenCrate(ulong netId) => !spaceCardCratesIDs.Contains(netId) || !cardReader.IsExists() || cardReaderOpen;
internal bool IsEventCrate(ulong netId) => crates.Keys.Any(x => x.IsExists() && x.net != null && x.net.ID.Value == netId);
internal bool IsEventLockedCrate(ulong netId) => lockedCrates.Keys.Any(x => x.IsExists() && x.net != null && x.net.ID.Value == netId);
internal bool IsPlayerInZone(ulong userId) => zoneClass != null && zoneClass.playersInZone.Any(x => x.userID == userId);
internal bool IsDebrisTurret(ulong netId) => turrets.Any(x => x.IsExists() && x.net.ID.Value == netId);
internal bool IsDebrisMine(ulong netId) => mines.Any(x => x.IsExists() && x.net.ID.Value == netId);
internal bool IsNpcMine(ulong netId) => npcs.Any(x => x.IsExists() && x.net.ID.Value == netId);
internal bool IsHeliMine(ulong netId) => sputnikHeli != null && sputnikHeli.patrolHelicopter.IsExists() && sputnikHeli.patrolHelicopter.net.ID.Value == 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) NotifyManager.SendMessageToPlayer(player, "ExitPVP", ins._config.prefix);
}
internal void OnCratelooted(ulong 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.Value)) || lockedCrates.Keys.Any(x => x != null && !openedCrates.Contains(x.net.ID.Value))) return;
destroyCorountine = ServerMgr.Instance.StartCoroutine(DestroyCorountine());
}
internal void Init(SputnikDebrisConfig sputnikDebrisConfig) {
this.sputnikDebrisConfig = sputnikDebrisConfig;
DefineEventPosition();
CreateFallSputnik();
updateCorountine = ServerMgr.Instance.StartCoroutine(UpdateCorountine());
pveModeController = new PveModeController();
}
internal void UpdateZone() {
UpdateMapMarker();
if (zoneClass != null) zoneClass.UpdateGui();
}
internal void OnCardSwipe(Keycard keycard, BasePlayer player) {
Item keyCardItem = keycard.GetCachedItem();
if (keyCardItem == null) return;
if (!IsSputnikAgressive()) {
MakeSputnikAgressive();
DeniedAcces();
return;
}
if (keyCardItem.info.shortname == ins._config.customCardConfig.shortName && keyCardItem.skin == ins._config.customCardConfig.skinID) {
keyCardItem.LoseCondition(ins._config.customCardConfig.helthLossScale);
cardReaderOpen = true;
}
else {
NotifyManager.SendMessageToPlayer(player, "NeedUseCard", ins._config.prefix);
DeniedAcces();
}
}
void DeniedAcces() {
Effect.server.Run(cardReader.accessDeniedEffect.resourcePath, cardReader.audioPosition.position, Vector3.up);
cardReader.CancelInvoke(cardReader.GrantCard);
}
void DefineEventPosition() {
Vector3 position = Vector3.zero;
if (sputnikDebrisConfig.useCustomSpawnPoints) {
string newPosition = sputnikDebrisConfig.customSpawnPoints.GetRandom();
if (newPosition == null) {
ins.PrintError("Couldn't find a custom position");
}
else position = newPosition.ToVector3();
// ... [Code preview truncated due to length. Full source in attached file] ...