C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.ShipwreckExtensionMethods;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using CompanionServer.Handlers;
using UnityEngine;
using Rust;
using Time = UnityEngine.Time;
namespace Oxide.Plugins {
[Info("Shipwreck", "Adem", "1.1.2")]
class Shipwreck : RustPlugin {
#region Variables
const bool en = true;
static Shipwreck ins;
[PluginReference]
Plugin NpcSpawn, GUIAnnouncements, DiscordMessages, PveMode, Economics, ServerRewards, IQEconomic, DynamicPVP;
HashSet<string> subscribeMetods = new HashSet<string> {
"OnEntitySpawned", "OnCorpsePopulate", "OnEntityTakeDamage", "CanMountEntity", "OnEntityMounted", "CanExplosiveStick", "CanBuild", "CanAffordUpgrade", "OnStructureRotate", "OnDoorOpened", "OnCardSwipe", "OnEntityDeath", "CanHackCrate", "OnPlayerSleep", "CanEntityTakeDamage", "CanEntityTakeDamage", "OnRestoreUponDeath", "OnPlayerSleep"
}
;
EventController eventController;
#endregion Variables
#region Hooks
void Init() {
Unsubscribes();
}
void OnServerInitialized() {
ins = this;
UpdateConfig();
PostLoadCheck();
LoadDefaultMessages();
EventLauncher.AutoStartEvent();
}
void Unload() {
EventLauncher.StopEvent(isPluginUnloading : true);
}
void OnEntitySpawned(SimpleShark simpleShark) {
if (!simpleShark.IsExists()) return;
if (Vector3.Distance(eventController.transform.position, simpleShark.transform.position) < eventController.eventConfig.radius) {
timer.In(0.5f, () => {
if (simpleShark.IsExists()) simpleShark.Kill();
}
);
}
}
void OnEntitySpawned(DiveSite diveSite) {
if (!diveSite.IsExists()) return;
if (Vector3.Distance(eventController.transform.position, diveSite.transform.position) < eventController.eventConfig.radius) diveSite.Kill();
}
void OnEntitySpawned(DroppedItemContainer droppedItemContainer) {
if (ins._config.mainConfig.disableFloatingCorpse && droppedItemContainer.IsExists()) DisableCorpseFloating(droppedItemContainer);
}
void OnEntitySpawned(PlayerCorpse playerCorpse) {
if (ins._config.mainConfig.disableFloatingCorpse && playerCorpse.IsExists()) DisableCorpseFloating(playerCorpse);
}
void OnCorpsePopulate(BasePlayer entity, NPCPlayerCorpse corpse) {
if (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];
LootManager.UpdateLootContainerLootTable(container, npcConfig.lootTable, npcConfig.typeLootTable);
if (npcConfig.deleteCorpse && !corpse.IsDestroyed) corpse.Kill();
}
);
}
}
object OnEntityTakeDamage(BaseSubmarine baseSubmarine, HitInfo info) {
if (!baseSubmarine.IsExists() || info == null || baseSubmarine.net == null) return null;
PatrolSubmarine patrolSubmarine = PatrolSubmarine.GetPatrolSubmarineByNetID(baseSubmarine.net.ID.Value);
if (patrolSubmarine != null) {
if (info.InitiatorPlayer.IsRealPlayer()) patrolSubmarine.OnAttackedByPlayer(info.InitiatorPlayer);
else if (info.Initiator == null) return true;
}
if (info.Initiator == null && info.WeaponPrefab != null && info.WeaponPrefab.name == "TorpedoStraight") info.damageTypes.ScaleAll(_config.mainConfig.submarineDamageScale);
return null;
}
object OnEntityTakeDamage(SimpleShark shark, HitInfo info) {
if (!shark.IsExists() || info == null || shark.net == null) return null;
PatrolShark patrolShark = PatrolShark.GetPatrolSharkByNetId(shark.net.ID.Value);
if (patrolShark != null) {
if (info.Initiator == null) return true;
}
return null;
}
object OnEntityTakeDamage(ScientistNPC scientistNPC, HitInfo info) {
if (!scientistNPC.IsExists() || info == null) return null;
if (NpcSpawnManager.IsEventNpc(scientistNPC)) {
if (info.Initiator == null) return true;
}
return null;
}
void OnEntityTakeDamage(BasePlayer player, HitInfo info) {
if (player == null || info == null) return;
if (info.Initiator == null && info.WeaponPrefab != null && info.WeaponPrefab.name == "TorpedoStraight") {
info.damageTypes.ScaleAll(_config.mainConfig.submarineDamageScale);
return;
}
else if (info.Initiator != null) {
if (info.Initiator is SimpleShark) {
PatrolShark patrolShark = PatrolShark.GetPatrolSharkByNetId(info.Initiator.net.ID.Value);
if (patrolShark != null) info.damageTypes.ScaleAll(patrolShark.sharkConfig.damageScale);
return;
}
}
}
object CanMountEntity(BasePlayer player, BaseMountable seat) {
if (!player.IsRealPlayer() || seat == null) return null;
BaseVehicle vehicle = seat.VehicleParent();
if (vehicle == null || vehicle.net == null) return null;
PatrolSubmarine patrolSubmarine = PatrolSubmarine.GetPatrolSubmarineByNetID(vehicle.net.ID.Value);
if (patrolSubmarine != null) return true;
return null;
}
void OnEntityMounted(BaseMountable entity, BasePlayer player) {
if (entity == null || player == null) return;
BaseVehicle vehicle = entity.VehicleParent();
if (vehicle == null) return;
BaseSubmarine baseSubmarine = vehicle as BaseSubmarine;
if (baseSubmarine != null && baseSubmarine.buoyancy.rigidBody == null) {
baseSubmarine.buoyancy.rigidBody = baseSubmarine.rigidBody;
}
}
object CanExplosiveStick(TimedExplosive timedExplosive, BaseSubmarine baseSubmarine) {
if (!_config.mainConfig.allowStickC4 || baseSubmarine == null || baseSubmarine.net == null) return null;
PatrolSubmarine patrolSubmarine = PatrolSubmarine.GetPatrolSubmarineByNetID(baseSubmarine.net.ID.Value);
if (patrolSubmarine != null) return true;
return null;
}
object CanBuild(Planner planner, Construction prefab, Construction.Target target) {
BasePlayer player = planner.GetOwnerPlayer();
if (player != null && ZoneController.IsPlayerNearTheEventByDistance(player.transform.position)) return false;
return null;
}
object CanAffordUpgrade(BasePlayer player, BuildingBlock block, BuildingGrade.Enum grade) {
if (player == null) return null;
if (ZoneController.IsPlayerNearTheEventByDistance(player.transform.position)) return false;
return null;
}
object OnStructureRotate(BuildingBlock block, BasePlayer player) {
if (player == null) return null;
if (ZoneController.IsPlayerNearTheEventByDistance(player.transform.position)) return false;
return null;
}
void OnDoorOpened(Door door, BasePlayer player) {
if (door == null || player == null || door.OwnerID == 0) return;
ShipContainer shipContainer = ShipContainer.GetShipContainerByDoor(door);
if (shipContainer != null) {
shipContainer.OnPlayerOpenContainerDoor(player, door);
}
}
object OnCardSwipe(CardReader cardReader, Keycard card, BasePlayer player) {
if (cardReader == null || card == null || player == null) return null;
CardDoor cardDoor = CardDoor.GetCardDoorByCardReaderNetId(cardReader.net.ID.Value);
if (cardDoor != null) {
cardDoor.OnCardSwipe(card, player, cardReader);
return true;
}
return null;
}
void CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
if (player == null || crate == null || crate.net == null) return;
if (LootManager.IsEventCrate(crate.net.ID.Value)) {
EconomyManager.ActionEconomy(player.userID, "LockedCrate");
}
}
void OnEntityDeath(ScientistNPC scientistNPC, HitInfo info) {
if (scientistNPC == null || info == null) return;
if (info.InitiatorPlayer.IsRealPlayer() && NpcSpawnManager.IsEventNpc(scientistNPC)) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Npc");
}
void OnEntityDeath(SimpleShark shark, HitInfo info) {
if (shark == null || info == null || shark.net == null) return;
PatrolShark patrolShark = PatrolShark.GetPatrolSharkByNetId(shark.net.ID.Value);
if (info.InitiatorPlayer.IsRealPlayer() && patrolShark != null) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Shark");
}
void OnEntityDeath(BaseSubmarine baseSubmarine, HitInfo info) {
if (baseSubmarine == null || info == null || baseSubmarine.net == null) return;
PatrolSubmarine patrolSubmarine = PatrolSubmarine.GetPatrolSubmarineByNetID(baseSubmarine.net.ID.Value);
if (info.InitiatorPlayer.IsRealPlayer() && patrolSubmarine != null) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Submarine");
}
void OnEntityDeath(Door door, HitInfo info) {
if (door == null || info == null || door.net == null) return;
CardDoor cardDoor = CardDoor.GetCardDoorByDoorNetId(door.net.ID.Value);
if (info.InitiatorPlayer.IsRealPlayer() && cardDoor != null) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Door");
}
void OnPlayerDeath(BasePlayer player) {
if (player == null) return;
ZoneController.OnPlayerLeaveZone(player);
}
void OnPlayerSleep(BasePlayer player) {
if (player == null) return;
ZoneController.OnPlayerLeaveZone(player);
}
#region SupportedPLugins
object CanEntityTakeDamage(BasePlayer victim, HitInfo info) {
if (eventController == null) return null;
if (info == null || !victim.IsRealPlayer()) return null;
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_config.eventZone.isCreateZonePVP && ZoneController.IsPlayerInZone(victim.net.ID.Value) && ZoneController.IsPlayerInZone(info.InitiatorPlayer.net.ID.Value)) return true;
}
return null;
}
object CanEntityTakeDamage(BaseSubmarine baseSubmarine, HitInfo info) {
if (eventController == null) return null;
if (!baseSubmarine.IsExists() || info == null) return null;
PatrolSubmarine patrolSubmarine = PatrolSubmarine.GetPatrolSubmarineByNetID(baseSubmarine.net.ID.Value);
if (patrolSubmarine != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
patrolSubmarine.OnAttackedByPlayer(info.InitiatorPlayer);
return true;
}
else if (info.Initiator == null) return false;
}
else if (info.Initiator == null && ZoneController.IsPlayerNearTheEventByDistance(baseSubmarine.transform.position)) return true;
return null;
}
object CanEntityTakeDamage(SimpleShark shark, HitInfo info) {
if (!shark.IsExists() || info == null || shark.net == null) return null;
PatrolShark patrolShark = PatrolShark.GetPatrolSharkByNetId(shark.net.ID.Value);
if (patrolShark != null) {
if (info.Initiator == null) return false;
else if (info.InitiatorPlayer.IsRealPlayer()) return true;
}
return null;
}
object OnRestoreUponDeath(BasePlayer player) {
if (player == null) return null;
if (_config.eventZone.blockRestoreUponDeath && ZoneController.IsPlayerInZone(player.userID)) return false;
return null;
}
#endregion SupportedPLugins
#endregion Hooks
#region Commands
[ChatCommand("shipwreckstart")]
void ChatStartCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
if (arg != null && arg.Length >= 1) EventLauncher.StartEvent(player, arg[0]);
else EventLauncher.StartEvent(player);
}
[ChatCommand("shipwreckstartmyloc")]
void ChatStartMyPosCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
if (arg != null && arg.Length >= 1) EventLauncher.StartEvent(player, arg[0], true);
else EventLauncher.StartEvent(player, "", true);
}
[ChatCommand("shipwreckstop")]
void ChatStopCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
EventLauncher.StopEvent();
}
[ConsoleCommand("shipwreckstart")]
void ConsoleStartCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
if (arg.Args != null && arg.Args.Length > 0) EventLauncher.StartEvent(null, arg.Args[0]);
else EventLauncher.StartEvent();
}
[ConsoleCommand("shipwreckstop")]
void ConsoleStopCommand(ConsoleSystem.Arg arg) {
if (arg.Player() == null) EventLauncher.StopEvent();
}
[ChatCommand("screatepath")]
void ChatCreatePathCommand(BasePlayer player, string command, string[] arg) {
float step = 5;
if (arg.Length > 0) {
step = Convert.ToInt32(arg[0]);
if (step <= 0) step = 5;
}
if (eventController == null) {
NotifyManager.PrintError(player, "EventNoActive_Exeption", _config.prefix);
return;
}
PathRecorder.CreatePathRecorder(player, step);
NotifyManager.SendMessageToPlayer(player, "PathRecordStart", _config.prefix);
}
[ChatCommand("ssavepath")]
void ChatSavePathCommand(BasePlayer player, string command, string[] arg) {
if (eventController == null) {
NotifyManager.PrintError(player, "EventNoActive_Exeption", _config.prefix);
return;
}
PathRecorder pathRecorder = PathRecorder.GetPathRecorderByPlayerUID(player.userID);
if (pathRecorder == null) {
NotifyManager.PrintError(player, "PathSaveFailed", _config.prefix);
return;
}
pathRecorder.SaveRout(arg[0]);
NotifyManager.SendMessageToPlayer(player, "PathSaved", _config.prefix);
}
[ChatCommand("scancelpath")]
void ChatCancelPathCommand(BasePlayer player, string command, string[] arg) {
if (eventController == null) {
NotifyManager.PrintError(player, "EventNoActive_Exeption", _config.prefix);
return;
}
PathRecorder pathRecorder = PathRecorder.GetPathRecorderByPlayerUID(player.userID);
if (pathRecorder == null) return;
GameObject.Destroy(pathRecorder.gameObject);
NotifyManager.SendMessageToPlayer(player, "PathCancelled", _config.prefix);
}
#endregion Commands
#region Methods
void UpdateConfig() {
if (_config.version == null || _config.version == new VersionNumber(0, 0, 0)) {
ins.PrintError("The configuration file is corrupted!");
return;
}
if (_config.version != Version) {
if (_config.version.Minor == 0) {
if (_config.version.Patch <= 3) {
_config.mainConfig.disableRadiationFromRadioactivrBarrels = true;
_config.animationConfig = new AnimationConfig {
timeBeforeF15TakeOff = 60, enableExplosionsEffects = true
}
;
_config.supportedPluginsConfig.pveMode.showEventOwnerNameOnMap = true;
_config.supportedPluginsConfig.pveMode.damage = 25;
}
if (_config.version.Patch <= 5) {
_config.animationConfig.decorEntities = new HashSet<DataSkinnedEntityConfig> {
new DataSkinnedEntityConfig {
prefab = "assets/prefabs/building/wall.frame.garagedoor/wall.frame.garagedoor.prefab", skin = 1788350229, locations = new HashSet<LocationConfig> {
new LocationConfig {
position = "(-7.512, 6.5, 57.093)", rotation = "(0, 90, 0)"
}
, new LocationConfig {
position = "(7.550, 6.5, 57.093)", rotation = "(0, 90, 0)"
}
, new LocationConfig {
position = "(7.488, 6.430, -33.062)", rotation = "(0, 270, 0)"
}
, new LocationConfig {
position = "(-7.488, 6.430, -33.062)", rotation = "(0, 270, 0)"
}
}
}
}
;
}
if (_config.version.Patch <= 9) {
_config.supportedPluginsConfig.superCardConfig = new SuperCardConfig {
enable = false, skin = 1988408422
}
;
}
}
_config.version = Version;
SaveConfig();
}
}
void Unsubscribes() {
foreach (string hook in subscribeMetods) Unsubscribe(hook);
}
void Subscribes() {
foreach (string hook in subscribeMetods) Subscribe(hook);
}
void PostLoadCheck() {
if (!NpcSpawnManager.CheckNPCSpawn()) NextTick(() => Server.Command($"o.unload {Name}"));
foreach (EventConfig eventConfig in _config.eventConfigs) {
if (EventController.GetMonumentConfig(eventConfig) == null || EventController.LoadLocationDataFile(eventConfig) == null) {
NextTick(() => Server.Command($"o.unload {Name}"));
return;
}
}
GuiManager.LoadImages();
}
void DisableCorpseFloating(BaseEntity entity) {
if (entity.transform.position.y < 0) {
if (Vector3.Distance(entity.transform.position, eventController.GetEventPosition()) < eventController.eventConfig.radius + 10) {
Rigidbody rigidbody = entity.GetComponent<Rigidbody>();
if (rigidbody != null) rigidbody.mass = 100;
}
}
}
Vector3 GetPatrolInitiatePosition(PatrolCustomConfig patrolCustomConfig) {
Vector3 patrolInitiatePosition = Vector3.zero;
if (patrolCustomConfig != null) patrolInitiatePosition = PositionDefiner.GetGlobalPosition(ins.eventController.transform, patrolCustomConfig.patrolPathList[0].ToVector3());
return patrolInitiatePosition;
}
#endregion Methods
#region Classes
static class EventLauncher {
static Coroutine autoEventCoroutine;
internal static void AutoStartEvent() {
if (!ins._config.mainConfig.isAutoEvent) return;
if (autoEventCoroutine != null) ServerMgr.Instance.StopCoroutine(autoEventCoroutine);
autoEventCoroutine = ServerMgr.Instance.StartCoroutine(AutoEventCorountine());
}
static IEnumerator AutoEventCorountine() {
yield return CoroutineEx.waitForSeconds(UnityEngine.Random.Range(ins._config.mainConfig.minTimeBetweenEvents, ins._config.mainConfig.maxTimeBetweenEvents));
StartEvent();
}
internal static void StartEvent(BasePlayer initiator = null, string presetName = "", bool initiatorPosition = false) {
if (ins.eventController != null) {
NotifyManager.PrintError(initiator, "EventActive_Exeption");
return;
}
EventConfig eventConfig = DefineEventConfig(presetName);
if (eventConfig == null) {
NotifyManager.PrintError(initiator, "ConfigurationNotFound_Exeption");
StopEvent();
return;
}
Vector3 eventPosition = Vector3.zero;
Vector3 eventRotation = Vector3.zero;
if (initiatorPosition) {
eventPosition = PositionDefiner.GetGroundPositionInPoint(initiator.transform.position);
eventRotation = new Vector3(0, initiator.viewAngles.y, 0);
}
else eventPosition = PositionDefiner.DefineEventPosition();
if (eventPosition == Vector3.zero) {
NotifyManager.PrintError(initiator, "LocationNotFound_Exeption");
StopEvent();
return;
}
GameObject gameObject = new GameObject();
gameObject.transform.position = eventPosition;
if (eventRotation != Vector3.zero) {
gameObject.transform.rotation = Quaternion.Euler(eventRotation);
}
ins.eventController = gameObject.AddComponent<EventController>();
ins.eventController.Init(eventConfig);
}
static EventConfig DefineEventConfig(string eventPresetName) {
if (eventPresetName != "") {
return ins._config.eventConfigs.FirstOrDefault(x => x.presetName == eventPresetName);
}
else {
if (!ins._config.eventConfigs.Any(x => x.automatickStart && x.chance != 0)) return null;
float sumChance = 0;
foreach (EventConfig eventConfig in ins._config.eventConfigs) {
if (eventConfig.automatickStart) sumChance += eventConfig.chance;
}
float random = UnityEngine.Random.Range(0, sumChance);
foreach (EventConfig eventConfig in ins._config.eventConfigs) {
if (eventConfig.automatickStart) {
random -= eventConfig.chance;
if (random <= 0) return eventConfig;
}
}
return null;
}
}
internal static void StopEvent(bool isPluginUnloading = false) {
if (ins.eventController != null) {
ins.Unsubscribes();
ZoneController.DeleteZone();
GameObject.Destroy(ins.eventController.gameObject);
NotifyManager.SendMessageToAll("Finish", ins._config.prefix);
Interface.CallHook("OnShipwreckStop");
if (ins._config.mainConfig.enableStartStopLogs) NotifyManager.PrintLogMessage("EventStop_Log");
}
if (!isPluginUnloading) AutoStartEvent();
else if (autoEventCoroutine != null) ServerMgr.Instance.StopCoroutine(autoEventCoroutine);
}
}
sealed class EventController : FacepunchBehaviour {
internal EventConfig eventConfig {
get;
private set;
}
MapMarker mapMarker;
Coroutine eventCoroutine;
CargoSinkEffect cargoSinkEffect;
HashSet<PatrolNpc> patrolNpcs = new HashSet<PatrolNpc>();
HashSet<BaseEntity> decorEntities = new HashSet<BaseEntity>();
int eventTime;
internal int GetEventTime() {
return eventTime;
}
internal Vector3 GetEventPosition() {
return gameObject.transform.position;
}
internal void Init(EventConfig eventConfig) {
this.eventConfig = eventConfig;
eventTime = eventConfig.eventTime;
eventCoroutine = ServerMgr.Instance.StartCoroutine(EventCoroutine());
}
IEnumerator EventCoroutine() {
if (ins._config.mainConfig.preStartTime > 0) NotifyManager.SendMessageToAll("PreStart", ins._config.prefix, ins._config.mainConfig.preStartTime);
yield return CoroutineEx.waitForSeconds(ins._config.mainConfig.preStartTime);
if (ins._config.marker.useRingMarker || ins._config.marker.useShopMarker) mapMarker = MapMarker.CreateMarker(gameObject.transform.position);
if (eventConfig.enableCargoSinkEffect) {
if (ins._config.animationConfig.timeBeforeF15TakeOff > 0) NotifyManager.SendMessageToAll("Animation_Stage_1", ins._config.prefix, ins._config.animationConfig.timeBeforeF15TakeOff);
yield return CargoSinkCorountine();
}
yield return BuilderCorountine();
ins.Subscribes();
Interface.CallHook("OnShipwreckStart");
NotifyManager.SendMessageToAll("EventStart", ins._config.prefix, eventConfig.displayName, PhoneController.PositionToGridCoord(transform.position));
if (ins._config.mainConfig.enableStartStopLogs) NotifyManager.PrintLogMessage("EventStart_Log", eventConfig.presetName);
yield return TimeCounter();
EventLauncher.StopEvent();
}
IEnumerator CargoSinkCorountine() {
Vector3 cargoPosition = new Vector3(transform.position.x, 0, transform.position.z);
cargoSinkEffect = CargoSinkEffect.CreateCargoSinkControoler(cargoPosition, transform.rotation);
yield return CoroutineEx.waitForSeconds(ins._config.animationConfig.timeBeforeF15TakeOff);
if (cargoSinkEffect != null) {
cargoSinkEffect.StartAnimation();
NotifyManager.SendMessageToAll("Animation_Stage_2", ins._config.prefix);
}
while (cargoSinkEffect != null) {
yield return CoroutineEx.waitForSeconds(1f);
}
yield return null;
}
IEnumerator BuilderCorountine() {
DeleteEntitiesInEventArea();
HashSet<DataFileEntity> entitiesDataFile = LoadLocationDataFile(eventConfig);
if (entitiesDataFile != null) {
foreach (DataFileEntity dataFileEntity in entitiesDataFile) {
BaseEntity decorEntity = BuildManager.CreateDataFileEntity(dataFileEntity, gameObject.transform);
if (decorEntity != null) decorEntities.Add(decorEntity);
yield return null;
}
}
yield return null;
MonumentConfig monumentConfig = GetMonumentConfig(eventConfig);
if (monumentConfig != null && monumentConfig.shipContainerConfigs != null) {
foreach (LocationConfig locationConfig in monumentConfig.shipContainerConfigs.locations) {
Vector3 globalPosition = PositionDefiner.GetGlobalPosition(transform, locationConfig.position.ToVector3());
Quaternion globalRotation = PositionDefiner.GetGlobalRotation(transform, locationConfig.rotation.ToVector3());
string cratePrefab = DefineRandomPrefab(monumentConfig.shipContainerConfigs.probabilities);
if (cratePrefab != null) ShipContainer.BuildShipContainer(cratePrefab, globalPosition, globalRotation);
yield return null;
}
}
if (monumentConfig != null && monumentConfig.crates != null) {
foreach (DataEntityConfig crateData in monumentConfig.crates) {
foreach (LocationConfig locationConfig in crateData.locations) {
Vector3 globalPosition = PositionDefiner.GetGlobalPosition(transform, locationConfig.position.ToVector3());
Quaternion globalRotation = PositionDefiner.GetGlobalRotation(transform, locationConfig.rotation.ToVector3());
LootManager.CreateCrate(crateData.prefab, globalPosition, globalRotation);
}
}
}
if (monumentConfig != null && monumentConfig.raidDoorsConfigs != null) {
foreach (DataSkinnedEntityConfig doorData in monumentConfig.raidDoorsConfigs) {
foreach (LocationConfig locationConfig in doorData.locations) {
Vector3 globalPosition = PositionDefiner.GetGlobalPosition(transform, locationConfig.position.ToVector3());
Quaternion globalRotation = PositionDefiner.GetGlobalRotation(transform, locationConfig.rotation.ToVector3());
Door door = BuildManager.CreateStaticEntity(doorData.prefab, globalPosition, globalRotation, doorData.skin) as Door;
if (door != null) {
if (eventConfig.doorType != 2) door.canHandOpen = false;
decorEntities.Add(door);
}
yield return null;
}
}
}
if (monumentConfig != null && monumentConfig.cardReaderConfigs != null) {
foreach (DataCardDoorConfig dataCardDoorConfig in monumentConfig.cardReaderConfigs) {
CardDoor cardDoor = new CardDoor(dataCardDoorConfig, eventConfig.doorType);
yield return null;
}
}
if (monumentConfig != null && monumentConfig.resoursesConfigs != null) {
foreach (LocationConfig locationConfig in monumentConfig.resoursesConfigs.locations) {
string resoursePrefab = DefineRandomPrefab(monumentConfig.resoursesConfigs.probabilities);
BaseEntity baseEntity = BuildManager.CreateStaticEntityInLocalCoordinates(resoursePrefab, transform, locationConfig.position.ToVector3(), locationConfig.rotation.ToVector3());
decorEntities.Add(baseEntity);
yield return null;
}
}
CreatePatrolEntities();
ZoneController.CreateZone(gameObject.transform.position);
yield return null;
}
string DefineRandomPrefab(HashSet<ProbabilityConfig> probabilityConfigs) {
int counter = 0;
while (counter < 20) {
counter++;
foreach (ProbabilityConfig probabilityConfig in probabilityConfigs) {
if (UnityEngine.Random.Range(0.0f, 100.0f) <= probabilityConfig.probaility) {
return probabilityConfig.prefab;
}
}
}
return null;
}
IEnumerator TimeCounter() {
while (eventTime > 0 || (ins._config.mainConfig.dontStopEventIfPlayerInZone && ZoneController.AnyPlayerInZone())) {
if (eventTime > 0) eventTime--;
SendRemainTimeMessage();
GuiManager.UpdateCountdownGui(eventTime);
yield return CoroutineEx.waitForSeconds(1f);
}
}
internal static HashSet<DataFileEntity> LoadLocationDataFile(EventConfig eventConfig) {
string filePath = $"{ins.Name}/Prefabs/";
HashSet<DataFileEntity> locationsDataFile = Interface.Oxide.DataFileSystem.ReadObject<HashSet<DataFileEntity>>(filePath + eventConfig.dataFileName);
if (locationsDataFile == null || locationsDataFile.Count == 0) {
NotifyManager.PrintError(null, "FileNotFound_Exeption", eventConfig.presetName, filePath);
return null;
}
return locationsDataFile;
}
internal static MonumentConfig GetMonumentConfig(EventConfig eventConfig) {
string filePath = $"{ins.Name}/Configs/";
MonumentConfig monumentConfig = Interface.Oxide.DataFileSystem.ReadObject<MonumentConfig>(filePath + eventConfig.dataFileName);
if (monumentConfig == null || monumentConfig.crates == null) {
NotifyManager.PrintError(null, "FileNotFound_Exeption", eventConfig.presetName, filePath);
return null;
}
return monumentConfig;
}
void DeleteEntitiesInEventArea() {
foreach (Collider collider in UnityEngine.Physics.OverlapSphere(gameObject.transform.position, eventConfig.radius)) {
BaseEntity entity = collider.ToBaseEntity();
if (entity.IsExists() && (entity is SimpleShark || entity is DiveSite || entity is FreeableLootContainer || entity is SimpleShark)) entity.Kill();
}
}
void CreatePatrolEntities() {
foreach (PatrolCustomConfig patrolConfig in eventConfig.customPatrolRoutes) CreatePatrolEntity(patrolConfig);
}
void CreatePatrolEntity(PatrolCustomConfig patrolConfig) {
SharkConfig sharkConfig = ins._config.sharkConfigs.FirstOrDefault(x => x.presetName == patrolConfig.presetName);
if (sharkConfig != null) {
PatrolShark eventShark = PatrolShark.CreateShark(sharkConfig, patrolConfig);
return;
}
SubmarineConfig submarineConfig = ins._config.submarineConfigs.FirstOrDefault(x => x.presetName == patrolConfig.presetName);
if (submarineConfig != null) {
PatrolSubmarine patrolSubmarine = PatrolSubmarine.CreatePatrolCubmarine(submarineConfig, patrolConfig);
return;
}
NpcConfig npcConfig = ins._config.npcConfigs.FirstOrDefault(x => x.presetName == patrolConfig.presetName);
if (npcConfig != null) {
PatrolNpc patrolNpc = PatrolNpc.CreatePatrolNpc(npcConfig, patrolConfig);
patrolNpcs.Add(patrolNpc);
return;
}
}
void SendRemainTimeMessage() {
if (ins._config.mainConfig.timeNotifications.Contains(eventTime)) {
NotifyManager.SendMessageToAll("RemainTime", ins._config.prefix, eventConfig.displayName, eventTime);
}
}
void OnDestroy() {
if (eventCoroutine != null) ServerMgr.Instance.StopCoroutine(eventCoroutine);
if (mapMarker != null) mapMarker.DeleteMarker();
foreach (BaseEntity entity in decorEntities) {
if (!entity.IsExists()) continue;
BaseSubmarine baseSubmarine = entity as BaseSubmarine;
if (baseSubmarine != null && baseSubmarine.buoyancy != null && baseSubmarine.buoyancy.rigidBody != null) continue;
entity.Kill();
}
PatrolNpc.KillAllPatrolNpcs();
PatrolShark.KillAllSharks();
PatrolSubmarine.KillAllSubmarines();
ShipContainer.KillAllShipContainers();
PathRecorder.KillAllPathRecorders();
LootManager.DestroyEventCrates();
CardDoor.KillAllCardDoors();
if (cargoSinkEffect != null) cargoSinkEffect.Destroy();
EconomyManager.OnEventEnd();
GuiManager.DestroyGuiForAllPLayers();
}
}
sealed class CargoSinkEffect : FacepunchBehaviour {
BaseEntity cargoShip;
HashSet<BaseEntity> decorEntities = new HashSet<BaseEntity>();
PlanesController planesController;
Coroutine cargoSinkCorountine;
GameObject positionGameObject;
static List<string> effects = new List<string> {
"assets/bundled/prefabs/fx/explosions/explosion_01.prefab", "assets/bundled/prefabs/fx/explosions/explosion_02.prefab", "assets/bundled/prefabs/fx/explosions/explosion_03.prefab", "assets/bundled/prefabs/fx/gas_explosion_small.prefab", "assets/bundled/prefabs/fx/survey_explosion.prefab", "assets/bundled/prefabs/fx/weapons/landmine/landmine_explosion.prefab"
}
;
static List<AnimationPosition> animationData = new List<AnimationPosition> {
new AnimationPosition {
moveTime = 10, position = new Vector3(0, 0, 0), rotation = new Vector3(0, 0, 30),
}
, new AnimationPosition {
moveTime = 10, position = new Vector3(0, -5, 0), rotation = new Vector3(350, 0, 30),
}
, new AnimationPosition {
moveTime = 40, position = new Vector3(0, -35, 0), rotation = new Vector3(0, 10, 30), speed = 0.22f
}
, new AnimationPosition {
moveTime = 50, position = new Vector3(0, -60, 0), rotation = new Vector3(0, 10, 30), speed = 0.25f
}
}
;
internal static CargoSinkEffect CreateCargoSinkControoler(Vector3 position, Quaternion rotation) {
BaseEntity cargoShip = BuildManager.CreateDecorEntity("assets/content/vehicles/boats/cargoship/cargoshiptest.prefab", position, rotation);
CargoSinkEffect cargoSinkEffect = cargoShip.gameObject.AddComponent<CargoSinkEffect>();
cargoSinkEffect.Init(cargoShip);
return cargoSinkEffect;
}
void Init(BaseEntity cargoShip) {
this.cargoShip = cargoShip;
positionGameObject = new GameObject();
positionGameObject.transform.position = cargoShip.transform.position;
positionGameObject.transform.rotation = cargoShip.transform.rotation;
SpawnDecorEntities();
}
void SpawnDecorEntities() {
foreach (DataSkinnedEntityConfig dataSkinnedEntityConfig in ins._config.animationConfig.decorEntities) {
foreach (LocationConfig locationConfig in dataSkinnedEntityConfig.locations) {
BaseEntity entity = BuildManager.CreateChildEntity(cargoShip, dataSkinnedEntityConfig.prefab, locationConfig.position.ToVector3(), locationConfig.rotation.ToVector3(), dataSkinnedEntityConfig.skin);
decorEntities.Add(entity);
}
}
}
internal void StartAnimation() {
planesController = PlanesController.CreatePlaneController(this);
}
internal void StartcargoSinkAnimation() {
cargoSinkCorountine = ServerMgr.Instance.StartCoroutine(CargoSinkCorountine());
}
IEnumerator CargoSinkCorountine() {
float animationStartTime = 0;
int currentPointIndex = 0;
float lastExplodeTime = 0;
AnimationPosition animationPosition = null;
while (cargoShip.IsExists()) {
if (currentPointIndex >= animationData.Count) break;
AnimationPosition newAnimation = animationData[currentPointIndex];
if (newAnimation != animationPosition) {
animationPosition = newAnimation;
animationStartTime = Time.realtimeSinceStartup;
}
if (Time.realtimeSinceStartup - animationStartTime >= animationPosition.moveTime) currentPointIndex++;
if (animationPosition == null) break;
if (ins._config.animationConfig.enableExplosionsEffects && Time.realtimeSinceStartup - lastExplodeTime >= 0.15f) {
ExplodeEffect();
lastExplodeTime = Time.realtimeSinceStartup;
}
MoveCargo(animationPosition);
yield return null;
}
Destroy();
}
void ExplodeEffect() {
Vector3 randomLocalPosition = new Vector3(UnityEngine.Random.Range(-12, 12), UnityEngine.Random.Range(7, 11), UnityEngine.Random.Range(-60, 80));
Vector3 randomGlobalPosition = PositionDefiner.GetGlobalPosition(cargoShip.transform, randomLocalPosition);
if (randomGlobalPosition.y < 0) return;
string randomEffect = effects.GetRandom();
Effect.server.Run(randomEffect, randomGlobalPosition);
}
void MoveCargo(AnimationPosition animationPosition) {
Vector3 globalPosition = PositionDefiner.GetGlobalPosition(positionGameObject.transform, animationPosition.position);
Quaternion globalRotation = PositionDefiner.GetGlobalRotation(positionGameObject.transform, animationPosition.rotation);
cargoShip.transform.position = Vector3.Lerp(cargoShip.transform.position, globalPosition, 0.001f * animationPosition.speed);
cargoShip.transform.rotation = Quaternion.Lerp(cargoShip.transform.rotation, globalRotation, 0.001f * animationPosition.speed);
}
internal void Destroy() {
if (cargoShip.IsExists()) cargoShip.Kill();
}
void OnDestroy() {
if (cargoSinkCorountine != null) ServerMgr.Instance.StopCoroutine(cargoSinkCorountine);
if (planesController != null) {
planesController.StopPlaneAnimation();
planesController = null;
}
}
class AnimationPosition {
internal float moveTime;
internal float speed = 1;
internal Vector3 position;
internal Vector3 rotation;
}
class PlanesController : FacepunchBehaviour {
CargoSinkEffect cargoSinkEffect;
StorageContainer ammoContainer;
BaseMountable baseMountableForFiring;
Vector3 direction;
List<F15> planes = new List<F15>();
Coroutine planeAnimationCorountine;
int animationStage;
static internal PlanesController CreatePlaneController(CargoSinkEffect cargoSinkEffect) {
PlanesController planesController = cargoSinkEffect.gameObject.AddComponent<PlanesController>();
planesController.Init(cargoSinkEffect);
return planesController;
}
void Init(CargoSinkEffect cargoSinkEffect) {
this.cargoSinkEffect = cargoSinkEffect;
Vector3 centerPlaneSpawnPosition = -cargoSinkEffect.transform.position;
direction = Vector3Ex.Direction(cargoSinkEffect.transform.position, centerPlaneSpawnPosition);
F15 centralPlain = CreatePlane(centerPlaneSpawnPosition, direction);
if (centralPlain == null) return;
Vector3 rightPlanePosition = centerPlaneSpawnPosition - direction * 25 + centralPlain.transform.right * 25;
CreatePlane(rightPlanePosition, direction);
Vector3 leftPlanePosition = centerPlaneSpawnPosition - direction * 25 - centralPlain.transform.right * 25;
CreatePlane(leftPlanePosition, direction);
CreateBaseMountable(transform.position);
CreateAndFillAmmoStorageContainer(transform.position);
planeAnimationCorountine = ServerMgr.Instance.StartCoroutine(PlaneAnimationCorountine());
}
F15 CreatePlane(Vector3 position, Vector3 direction) {
F15 plane = BuildManager.CreateRegularEntity("assets/scripts/entity/misc/f15/f15e.prefab", position, Quaternion.LookRotation(direction)) as F15;
plane.enabled = false;
planes.Add(plane);
return plane;
}
void CreateBaseMountable(Vector3 shipPosition) {
Vector3 spawnPosition = shipPosition - new Vector3(0, 200, 0);
baseMountableForFiring = BuildManager.CreateStaticEntity("assets/prefabs/vehicle/seats/testseat.prefab", spawnPosition, Quaternion.identity) as BaseMountable;
}
void CreateAndFillAmmoStorageContainer(Vector3 shipPosition) {
Vector3 spawnPosition = shipPosition - new Vector3(0, 200, 0);
ammoContainer = BuildManager.CreateStaticEntity("assets/prefabs/deployable/woodenbox/woodbox_deployed.prefab", spawnPosition, Quaternion.identity) as StorageContainer;
Item item = ItemManager.CreateByName("ammo.rocket.mlrs", 10);
item.MoveToContainer(ammoContainer.inventory);
ammoContainer.limitNetworking = true;
}
internal bool CheckPlanes() {
return !planes.Any(x => !x.IsExists()) && ammoContainer.IsExists() && baseMountableForFiring.IsExists();
}
IEnumerator PlaneAnimationCorountine() {
while (CheckPlanes() && animationStage != 4) {
// ... [Code preview truncated due to length. Full source in attached file] ...