C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Oxide.Core;
using Oxide.Core.Plugins;
using IEnumerator = System.Collections.IEnumerator;
using UnityEngine;
using Newtonsoft.Json;
namespace Oxide.Plugins {
[Info("FancyDrop", "FastBurst", "3.2.7")]
[Description("The Next Level of a fancy airdrop-toolset")]
class FancyDrop : RustPlugin {
[PluginReference]
Plugin AlphaLoot, GUIAnnouncements, MagicLoot;
#region Vars
private static FancyDrop Instance = null;
bool Changed = false;
bool initialized = false;
Vector3 lastDropPos;
float lastDropRadius = 0;
Vector3 lastLootPos;
int lastMinute;
double lastHour;
string msgConsoleDropSpawn;
static string msgConsoleDropLanded;
Timer _aidropTimer;
Timer _massDropTimer;
private const string SMOKE_EFFECT = "assets/bundled/prefabs/fx/smoke_signal_full.prefab";
private const string SIRENLIGHT_EFFECT = "assets/prefabs/io/electric/lights/sirenlightorange.prefab";
private const string SIRENALARM_EFFECT = "assets/prefabs/deployable/playerioents/alarms/audioalarm.prefab";
private const string PLANE_PREFAB = "assets/prefabs/npc/cargo plane/cargo_plane.prefab";
private const string SUPPLY_PREFAB = "assets/prefabs/misc/supply drop/supply_drop.prefab";
private const string HELIBURST_PREFAB = "assets/prefabs/npc/patrol helicopter/rocket_heli_airburst.prefab";
private const string ROCKETSMOKE_PREFAB = "assets/prefabs/ammo/rocket/rocket_smoke.prefab";
private const string EXPLOSION_PREFAB = "assets/bundled/prefabs/fx/survey_explosion.prefab";
private const string HELIEXPLOSION_EFFECT = "assets/prefabs/npc/patrol helicopter/effects/heli_explosion.prefab";
private const string BRADLEY_CANNON_EFFECT = "assets/prefabs/npc/m2bradley/effects/maincannonattack.prefab";
private const string PARACHUTE_PREFAB = "assets/prefabs/misc/parachute/parachute.prefab";
private static RaycastHit rayCastHit;
private const int CAST_LAYERS = 1 << 0 | 1 << 4 | 1 << 8 | 1 << 10 | 1 << 16 | 1 << 21 | 1 << 23 | 1 << 25 | 1 << 26;
List<CargoPlane> CargoPlanes = new List<CargoPlane>();
List<SupplyDrop> SupplyDrops = new List<SupplyDrop>();
private bool IsFancySupplyDrop(SupplyDrop drop) => SupplyDrops.Contains(drop);
List<SupplyDrop> LootedDrops = new List<SupplyDrop>();
List<BaseEntity> activeSignals = new List<BaseEntity>();
Dictionary<BasePlayer, Timer> timers = new Dictionary<BasePlayer, Timer>();
private Dictionary<string, int> itemNameToId = new Dictionary<string, int>();
private ConfigData.StaticOptions.LootOptions lootTable;
#endregion
#region Oxide Hooks
private void Init() {
Instance = this;
initialized = false;
msgConsoleDropSpawn = msg("msgConsoleDropSpawn");
msgConsoleDropLanded = msg("msgConsoleDropLanded");
Interface.CallHook("OnFancyDropTypes", configData.DropSettings.setupDropTypes);
}
private void Unload() {
airdropTimerStop();
foreach (var obj in UnityEngine.Object.FindObjectsOfType<ColliderCheck>().ToList()) GameObject.Destroy(obj);
foreach (var obj in UnityEngine.Object.FindObjectsOfType<DropTiming>().ToList()) GameObject.Destroy(obj);
if (_massDropTimer != null && !_massDropTimer.Destroyed) _massDropTimer.Destroy();
var drops = UnityEngine.Object.FindObjectsOfType<SupplyDrop>().ToList();
foreach (var drop in drops) drop.Kill();
CargoPlanes.Clear();
SupplyDrops.Clear();
LootedDrops.Clear();
ItemManager.DoRemoves();
Instance = null;
}
private void OnServerInitialized() {
referencePlane = GameManager.server.FindPrefab(PLANE_PREFAB).GetComponent<CargoPlane>();
spawnFilter = GameManager.server.FindPrefab(PLANE_PREFAB).GetComponent<CargoPlane>().filter;
Puts($"Map Highest Point: ({TerrainMeta.HighestPoint.y}m) | Plane flying height: (~{TerrainMeta.HighestPoint.y * configData.AirdropSettings.planeOffSetYMultiply}m)");
if (configData.TimerSettings.airdropTimerEnabled) Puts($"Timed Airdrop activated with '{configData.TimerSettings.airdropTimerMinPlayers}' players between '{configData.TimerSettings.airdropTimerWaitMinutesMin}' and '{configData.TimerSettings.airdropTimerWaitMinutesMax}' minutes");
if ((configData.TimerSettings.airdropCleanupAtStart && UnityEngine.Time.realtimeSinceStartup < 60) || BasePlayer.activePlayerList.Count == 1) airdropCleanUp();
if (configData.TimerSettings.airdropRemoveInBuilt) removeBuiltInAirdrop();
if (configData.TimerSettings.airdropTimerEnabled) airdropTimerNext();
object value;
var checkdefaults = defaultDrop();
foreach (var pair in checkdefaults) if (!setupDropDefault.TryGetValue(pair.Key, out value)) setupDropDefault.Add(pair.Key, checkdefaults[pair.Key]);
lang.RegisterMessages(Messages, this);
initialized = true;
}
private void OnExplosiveThrown(BasePlayer player, BaseEntity entity) {
NextTick(() => {
if (!initialized || entity == null || !(entity is SupplySignal)) return;
if (entity.net == null) entity.net = Network.Net.sv.CreateNetworkable();
if (Interface.CallHook("ShouldFancyDrop", entity.net.ID) != null) return;
if (activeSignals.Contains(entity)) return;
activeSignals.Add(entity);
SupplyThrown(player, entity);
}
);
}
private void OnExplosiveDropped(BasePlayer player, BaseEntity entity, ThrownWeapon thrown) {
NextTick(() => {
if (!initialized || entity == null || !(entity is SupplySignal)) return;
if (Interface.CallHook("ShouldFancyDrop", entity.net.ID) != null) return;
if (activeSignals.Contains(entity)) return;
activeSignals.Add(entity);
SupplyThrown(player, entity);
}
);
}
private void SupplyThrown(BasePlayer player, BaseEntity entity) {
Vector3 playerposition = player.transform.position;
timer.Once(3.0f, () => {
if (entity == null) {
activeSignals.Remove(entity);
return;
}
InvokeHandler.CancelInvoke(entity.GetComponent<MonoBehaviour>(), new Action((entity as SupplySignal).Explode));
}
);
timer.Once(3.3f, () => {
if (entity == null) return;
activeSignals.Remove(entity);
Vector3 position = new Vector3();
string gridPos = GetGridString(position);
if (!configData.AirdropSettings.disableRandomSupplyPos) position = entity.transform.position + new Vector3(UnityEngine.Random.Range(-20f, 20f), 0f, UnityEngine.Random.Range(-20f, 20f));
else position = entity.transform.position;
InvokeHandler.Invoke(entity.GetComponent<MonoBehaviour>(), new Action((entity as SupplySignal).FinishUp), configData.GenericSettings.supplySignalSmokeTime);
entity.SetFlag(BaseEntity.Flags.On, true, false);
entity.SendNetworkUpdateImmediate(false);
if (configData.GenericSettings.lockSignalDrop) startCargoPlane(position, false, null, "supplysignal", "", true, player.userID);
else startCargoPlane(position, false, null, "supplysignal");
if (configData.Notifications.notifyDropConsoleSignal) Puts($"SupplySignal thrown by '{player.displayName}' at: {playerposition}");
if (configData.Notifications.notifyDropAdminSignal) {
foreach (var admin in BasePlayer.activePlayerList.Where(p => p.IsAdmin).ToList()) SendReply(admin, $"<color={configData.GenericSettings.colorAdmMsg}>" + string.Format(msg("msgDropSignalAdmin", player.UserIDString), player.displayName, playerposition) + "</color>");
}
if (configData.Notifications.notifyDropSignalByPlayer) if (configData.Notifications.notifyDropSignalByPlayerCoords) PrintToChat(string.Format(configData.GenericSettings.Format, configData.GenericSettings.Color, configData.GenericSettings.Prefix) + $"<color={configData.GenericSettings.colorTextMsg}>" + string.Format(msg("msgDropSignalByPlayerCoords", player.UserIDString), player.displayName, position.x.ToString("0"), position.z.ToString("0")) + "</color>");
else if (configData.Notifications.notifyDropSignalByPlayerGrid) PrintToChat(string.Format(configData.GenericSettings.Format, configData.GenericSettings.Color, configData.GenericSettings.Prefix) + $"<color={configData.GenericSettings.colorTextMsg}>" + string.Format(msg("msgDropSignalByPlayerGrid", player.UserIDString), player.displayName, gridPos) + "</color>");
else PrintToChat(string.Format(configData.GenericSettings.Format, configData.GenericSettings.Color, configData.GenericSettings.Prefix) + $"<color={configData.GenericSettings.colorTextMsg}>" + string.Format(msg("msgDropSignalByPlayer", player.UserIDString), player.displayName) + "</color>");
}
);
}
private void OnLootEntity(BasePlayer player, BaseEntity entity) {
if (!initialized || entity == null || !(entity is SupplyDrop) || LootedDrops.Contains(entity as SupplyDrop)) return;
if ((configData.GenericSettings.lockSignalDrop || configData.GenericSettings.lockDirectDrop) && entity.OwnerID != 0uL && entity.OwnerID != player.userID) {
NextTick(() => player.EndLooting());
MessageToPlayer(player, msg("msgCrateLocked", player.UserIDString));
if (configData.DebugSettings.useDebug) Puts($"Drop is locked to {entity.OwnerID.ToString()}");
return;
}
if (entity.OwnerID == player.userID) {
string gridPos = GetGridString(entity.transform.position);
if (configData.Notifications.notifyDropConsoleLooted) Puts($"{player.displayName} ({player.UserIDString}) looted his Drop at: {entity.transform.position.ToString("0")} grid area: {gridPos}");
if (!configData.GenericSettings.unlockDropAfterLoot) {
entity.OwnerID = 0uL;
LootedDrops.Add(entity as SupplyDrop);
}
return;
}
if (Vector3.Distance(lastLootPos, entity.transform.position) > ((lastDropRadius * 2) * 1.2)) {
string gridPos = GetGridString(entity.transform.position);
if (configData.Notifications.notifyDropServerLooted) NotifyOnDropLooted(entity, player);
if (configData.Notifications.notifyDropConsoleLooted) Puts($"{player.displayName} ({player.UserIDString}) looted the Drop at: {entity.transform.position.ToString("0")} grid area: {gridPos}");
LootedDrops.Add(entity as SupplyDrop);
lastLootPos = entity.transform.position;
return;
}
}
private object getFancyDropTypes() {
if (setupDropTypes != null) return setupDropTypes;
else return null;
}
private void OnTick() {
if (configData.TimersSettings.useRealtimeTimers) OnTickReal();
if (configData.TimersSettings.useGametimeTimers) OnTickServer();
}
private void OnTickReal() {
if (lastMinute == DateTime.UtcNow.Minute) return;
lastMinute = DateTime.UtcNow.Minute;
if (BasePlayer.activePlayerList.Count >= configData.TimersSettings.timersMinPlayers && configData.TimersSettings.realTimers.ContainsKey(DateTime.Now.ToString("HH:mm"))) {
string runCmd = (string)configData.TimersSettings.realTimers[DateTime.Now.ToString("HH:mm")];
if (configData.TimersSettings.logTimersToConsole) Puts($"Run real timer: ({DateTime.Now.ToString("HH : mm")}) {runCmd}");
ConsoleSystem.Run(ConsoleSystem.Option.Server.Quiet(), "ad." + runCmd);
}
}
private void OnTickServer() {
if (lastHour == Math.Floor(TOD_Sky.Instance.Cycle.Hour)) return;
lastHour = Math.Floor(TOD_Sky.Instance.Cycle.Hour);
if (BasePlayer.activePlayerList.Count >= configData.TimersSettings.timersMinPlayers && configData.TimersSettings.serverTimers.ContainsKey(lastHour.ToString())) {
string runCmd = (string)configData.TimersSettings.serverTimers[lastHour.ToString()];
if (configData.TimersSettings.logTimersToConsole) Puts($"Run server timer: ({lastHour}) {runCmd}");
ConsoleSystem.Run(ConsoleSystem.Option.Server.Quiet(), "ad." + runCmd);
}
}
#endregion Oxide Hooks
#region Plugin Hooks
private bool IsFancyDrop(CargoPlane plane) => plane == null ? false : plane.GetComponent<DropTiming>();
private object IsFancyDropType(CargoPlane plane) {
if (plane == null || !plane.GetComponent<DropTiming>()) return false;
return (string)plane.GetComponent<DropTiming>().dropsettings["droptype"];
}
private void OverrideDropTime(CargoPlane plane, float seconds) {
var dropTiming = plane.GetComponent<DropTiming>();
if (dropTiming != null) {
dropTiming.TimeOverride(seconds);
}
}
#endregion
#region ColliderCheck
// Removing from being active until proper fix
//private void OnEntityTakeDamage(SupplyDrop entity, HitInfo info)
//{
// if (!configData.DamageSettings.shootDownDrops || info == null)
// return;
// if (entity is SupplyDrop)
// {
// var drop = entity as SupplyDrop;
// if (drop == null || drop.IsDestroyed)
// return;
// BaseEntity parachute = _parachute.GetValue(drop) as BaseEntity;
// if (parachute == null || parachute.IsDestroyed)
// return;
// var col = drop.GetComponent<ColliderCheck>();
// if (col == null)
// return;
// if (col.hitCounter < configData.DamageSettings.shootDownCount)
// {
// col.hitCounter++;
// return;
// }
// parachute.Kill();
// parachute = null;
// drop.GetComponent<Rigidbody>().drag = configData.DamageSettings.dropDragsetting;
// drop.GetComponent<Rigidbody>().mass = configData.DamageSettings.dropMassSetting;
// drop.GetComponent<Rigidbody>().useGravity = true;
// drop.GetComponent<Rigidbody>().isKinematic = false;
// drop.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
// drop.GetComponent<Rigidbody>().angularDrag = configData.DamageSettings.dropAngularDragSetting;
// drop.GetComponent<Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Continuous;
// col.wasHit = true;
// }
//}
sealed class ColliderCheck : FacepunchBehaviour {
public bool notifyEnabled = true;
public bool notifyConsole;
public Dictionary<string, object> cratesettings;
public bool landed = false;
public int hitCounter = 0;
public bool wasHit;
public string dropType;
private BaseEntity parachute;
private void Awake() {
Instance.NextTick(() => {
if (dropType != null) {
if (Convert.ToBoolean(cratesettings["useCustomLootTable"])) Instance.SetupContainer(GetComponent<StorageContainer>(), dropType, true);
else Instance.SetupContainer(GetComponent<StorageContainer>(), dropType);
}
else Awake();
}
);
}
private void PlayerStoppedLooting(BasePlayer player) {
if (!configData.GenericSettings.unlockDropAfterLoot || GetComponent<BaseEntity>().OwnerID == 0uL || player.userID != GetComponent<BaseEntity>().OwnerID) return;
GetComponent<BaseEntity>().OwnerID = 0uL;
Instance.LootedDrops.Add(GetComponent<BaseEntity>() as SupplyDrop);
}
private void OnCollisionEnter(Collision col) {
if (!landed) {
landed = true;
if (wasHit) {
if (configData.AirdropSettings.EffectsSettings.useSupplyDropEffectLanded) Effect.server.Run(EXPLOSION_PREFAB, GetComponent<BaseEntity>().transform.position);
if (configData.DamageSettings.explodeImpact) {
if (UnityEngine.Random.Range(0, 100) <= configData.DamageSettings.explodeChance) {
StartCoroutine(HitRemove(true));
return;
}
}
else {
StartCoroutine(DeSpawn());
return;
}
}
if (configData.AirdropSettings.EffectsSettings.useSupplyDropRocket) Instance.CreateRocket(GetComponent<BaseEntity>().transform.position);
if (notifyEnabled && configData.Notifications.notifyDropPlayersOnLanded && dropType != "dropdirect" && (((Instance.lastDropRadius * 2) * 1.2) - Vector3.Distance(Instance.lastDropPos, GetComponent<BaseEntity>().transform.position) <= 0 && !(UnityEngine.CollisionEx.GetEntity(col) is SupplyDrop))) Instance.NotifyOnDropLanded(GetComponent<BaseEntity>());
Instance.lastDropPos = GetComponent<BaseEntity>().transform.position;
StartCoroutine(DeSpawn());
if (configData.DebugSettings.useDebug) Instance.Puts("Debug Info: Drop has landed on the ground.");
if (configData.AirdropSettings.EffectsSettings.useSupplyDropEffectLanded) Effect.server.Run(EXPLOSION_PREFAB, GetComponent<BaseEntity>().transform.position);
if (notifyConsole && configData.Notifications.notifyDropConsoleOnLanded) Instance.Puts(string.Format(Instance.lang.GetMessage(msgConsoleDropLanded, Instance), GetComponent<BaseEntity>().transform.position.x.ToString("0"), GetComponent<BaseEntity>().transform.position.y.ToString("0"), GetComponent<BaseEntity>().transform.position.z.ToString("0")));
}
}
private IEnumerator HitRemove(bool explode) {
if (explode) {
yield return new WaitForEndOfFrame();
Effect.server.Run("assets/bundled/prefabs/fx/item_break.prefab", GetComponent<BaseEntity>().transform.position);
(GetComponent<BaseEntity>() as StorageContainer).DropItems();
Instance.SupplyDrops.Remove(GetComponent<SupplyDrop>());
cratesettings.Clear();
GetComponent<BaseEntity>().Kill();
}
else {
yield return new WaitForEndOfFrame();
Instance.SupplyDrops.Remove(GetComponent<SupplyDrop>());
}
}
private IEnumerator DeSpawn() {
yield return new WaitForSeconds(Convert.ToSingle(cratesettings["despawnMinutes"]) * 60.0f);
yield return new WaitWhile(() => GetComponent<BaseEntity>().IsOpen());
cratesettings.Clear();
GetComponent<BaseEntity>().Kill();
}
private void OnDestroy() {
cratesettings.Clear();
//Instance.SupplyDrops.Remove(GetComponent<SupplyDrop>());
//Instance.LootedDrops.Remove(GetComponent<SupplyDrop>());
}
internal void OnGroundCollision() {
parachute.Kill(BaseNetworkable.DestroyMode.None);
}
public ColliderCheck() {
}
}
#endregion ColliderCheck
#region Drop Timing
class DropTiming : FacepunchBehaviour {
private int dropCount;
private float updatedTime;
public Vector3 startPos;
public Vector3 endPos;
public bool notify = true;
private bool notifyConsole = true;
private int cratesToDrop;
public string dropType;
public Dictionary<string, object> dropsettings;
public ulong userID;
private float gapTimeToTake = 0f;
private float halfTimeToTake = 0f;
private float offsetTimeToTake = 0f;
private void Awake() {
dropCount = 0;
notifyConsole = true;
}
public void GetSettings(Dictionary<string, object> drop, Vector3 start, Vector3 end, float seconds) {
dropsettings = new Dictionary<string, object>(drop);
startPos = start;
endPos = end;
gapTimeToTake = Convert.ToSingle(dropsettings["cratesGap"]) / Convert.ToSingle(dropsettings["planeSpeed"]);
halfTimeToTake = seconds / 2;
offsetTimeToTake = gapTimeToTake / 2;
cratesToDrop = Mathf.RoundToInt(UnityEngine.Random.Range(Convert.ToSingle(dropsettings["minCrates"]) * 100f, Convert.ToSingle(dropsettings["maxCrates"]) * 100f) / 100f);
if ((cratesToDrop % 2) == 0) updatedTime = halfTimeToTake - offsetTimeToTake - ((cratesToDrop - 1) / 2 * gapTimeToTake);
else updatedTime = halfTimeToTake - ((cratesToDrop - 1) / 2 * gapTimeToTake);
if (userID != 0ul) userID = Convert.ToUInt64(dropsettings["userID"]);
}
public void TimeOverride(float seconds) {
halfTimeToTake = seconds / 2;
offsetTimeToTake = gapTimeToTake / 2;
cratesToDrop = Mathf.RoundToInt(UnityEngine.Random.Range(Convert.ToSingle(dropsettings["minCrates"]) * 100f, Convert.ToSingle(dropsettings["maxCrates"]) * 100f) / 100f);
if ((cratesToDrop % 2) == 0) updatedTime = halfTimeToTake - offsetTimeToTake - ((cratesToDrop - 1) / 2 * gapTimeToTake);
else updatedTime = halfTimeToTake - ((cratesToDrop - 1) / 2 * gapTimeToTake);
}
private void Update() {
//if ((float)Instance.dropPlanesecondsTaken.GetValue(GetComponent<CargoPlane>()) > updatedTime && dropCount < cratesToDrop)
if ((float)GetComponent<CargoPlane>().secondsTaken > updatedTime && dropCount < cratesToDrop) {
dropsettings = new Dictionary<string, object>();
dropsettings = getObjects(dropType);
updatedTime += gapTimeToTake;
dropCount++;
//Instance.Puts("We Got a UserID? " + dropsettings["userID"].ToString());
Instance.createSupplyDrop(GetComponent<CargoPlane>().transform.position, dropsettings, notify, notifyConsole, startPos, endPos, dropType, userID);
if (configData.Notifications.notifyDropConsoleSpawned && notifyConsole) Instance.Puts(string.Format(Instance.lang.GetMessage(Instance.msgConsoleDropSpawn, Instance), GetComponent<BaseEntity>().transform.position.x.ToString("0"), GetComponent<BaseEntity>().transform.position.y.ToString("0"), GetComponent<BaseEntity>().transform.position.z.ToString("0")));
}
if (dropCount == 1 && notify) notify = false;
if (dropCount == 1 && configData.Notifications.notifyDropConsoleFirstOnly) notifyConsole = false;
}
private void OnDestroy() {
dropsettings.Clear();
Instance.CargoPlanes.Remove(GetComponent<CargoPlane>());
Destroy(this);
}
public DropTiming() {
}
}
#endregion Drop Timing
#region Objects Creation
CargoPlane createCargoPlane(Vector3 pos = new Vector3()) => (CargoPlane)GameManager.server.CreateEntity(PLANE_PREFAB, new Vector3(), new Quaternion(), true);
private static void RunEffect(string name, BaseEntity entity = null, Vector3 position = new Vector3(), Vector3 offset = new Vector3()) {
if (entity != null) Effect.server.Run(name, entity, 0, offset, position, null, true);
else Effect.server.Run(name, position, Vector3.up, null, true);
}
private static void CreateSirenLights(BaseEntity entity) {
var SirenLight = GameManager.server.CreateEntity(SIRENLIGHT_EFFECT, default(Vector3), default(Quaternion), true);
SirenLight.gameObject.Identity();
SirenLight.SetParent(entity as LootContainer, "parachute_attach");
SirenLight.Spawn();
SirenLight.SetFlag(BaseEntity.Flags.Reserved8, true);
}
private static void CreateSirenAlarms(BaseEntity entity) {
var SirenAlarm = GameManager.server.CreateEntity(SIRENALARM_EFFECT, new Vector3(0f, 0f, 0f), default(Quaternion), true);
SirenAlarm.gameObject.Identity();
SirenAlarm.SetParent(entity);
SirenAlarm.Spawn();
SirenAlarm.SetFlag(BaseEntity.Flags.Reserved8, true);
}
private void CreateDropEffects(BaseEntity entity) {
if (entity == null) return;
if (configData.AirdropSettings.EffectsSettings.useSirenAlarmOnDrop && configData.AirdropSettings.EffectsSettings.useSirenAlarmAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenAlarms(entity);
else if (configData.AirdropSettings.EffectsSettings.useSirenAlarmAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenAlarms(entity);
else if (configData.AirdropSettings.EffectsSettings.useSirenAlarmOnDrop) CreateSirenAlarms(entity);
else return;
if (configData.AirdropSettings.EffectsSettings.useSirenLightOnDrop && configData.AirdropSettings.EffectsSettings.useSirenLightAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenLights(entity);
else if (configData.AirdropSettings.EffectsSettings.useSirenLightAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenLights(entity);
else if (configData.AirdropSettings.EffectsSettings.useSirenLightOnDrop) CreateSirenLights(entity);
else return;
}
private void createSupplyDrop(Vector3 pos, Dictionary<string, object> cratesettings, bool notify = true, bool notifyConsole = true, Vector3 start = new Vector3(), Vector3 end = new Vector3(), string dropType = "regular", ulong userID = 0uL) {
SupplyDrop newDrop;
object value;
if (configData.DropSettings.setupDropTypes.ContainsKey(dropType)) {
cratesettings = getObjects(dropType);
if (configData.DebugSettings.useDebug) Puts("Debug Info: Yes we have current settings");
}
else {
cratesettings = new Dictionary<string, object>((Dictionary<string, object>)setupDropDefault);
if (configData.DebugSettings.useDebug) Puts("Debug Info: We are using new settings");
}
if (userID != 0uL) {
if (configData.DebugSettings.useDebug) Puts("Debug Info: We got userID and set and locked to " + userID.ToString());
newDrop = GameManager.server.CreateEntity(SUPPLY_PREFAB, pos, new Quaternion(), true) as SupplyDrop;
(newDrop as BaseEntity).OwnerID = userID;
}
else {
newDrop = GameManager.server.CreateEntity(SUPPLY_PREFAB, pos, Quaternion.LookRotation(end - start), true) as SupplyDrop;
if (configData.DebugSettings.useDebug) Puts("Debug Info: Drop is currently not locked to any players");
}
(newDrop as BaseNetworkable).gameObject.AddComponent<ColliderCheck>();
newDrop.GetComponent<ColliderCheck>().cratesettings = cratesettings;
newDrop.GetComponent<ColliderCheck>().notifyEnabled = notify;
newDrop.GetComponent<ColliderCheck>().notifyConsole = notifyConsole;
newDrop.GetComponent<ColliderCheck>().dropType = dropType;
newDrop.GetComponent<Rigidbody>().drag = Convert.ToSingle(cratesettings["crateAirResistance"]);
if (configData.DebugSettings.useDebug) {
Puts("Debug Info: Supply Drop (after spawning) Resistance Now " + Convert.ToDouble(cratesettings["crateAirResistance"]).ToString());
Puts("Debug Info: Supply Drop (after spawning) Despawn Time " + cratesettings["despawnMinutes"].ToString());
}
newDrop.Spawn();
int slots = 36;
newDrop.inventory.capacity = 36;
newDrop.panelName = "generic";
newDrop.inventory.ServerInitialize(null, slots);
newDrop.inventory.MarkDirty();
//Interface.CallHook("OnLootSpawn", new object[] { newDrop.GetComponent<LootContainer>() });
SupplyDrops.Add(newDrop);
if (configData.AirdropSettings.EffectsSettings.useSmokeEffectOnDrop) RunEffect(SMOKE_EFFECT, newDrop);
if (configData.AirdropSettings.EffectsSettings.useSirenAlarmOnDrop || configData.AirdropSettings.EffectsSettings.useSirenLightOnDrop && newDrop != null) {
if (newDrop == null) return;
CreateDropEffects(newDrop);
}
}
private void createSupplyDropSpace(Vector3 pos, Dictionary<string, object> cratesettings, bool notify = true, bool notifyConsole = true, Vector3 start = new Vector3(), Vector3 end = new Vector3(), string dropType = "regular", ulong userID = 0uL) {
SupplyDrop newDrop;
object value;
pos.y = 350f;
if (configData.DropSettings.setupDropTypes.ContainsKey(dropType)) {
cratesettings = getObjects(dropType);
if (configData.DebugSettings.useDebug) Puts("Debug Info: Yes we have current settings");
}
else {
cratesettings = new Dictionary<string, object>((Dictionary<string, object>)setupDropDefault);
if (configData.DebugSettings.useDebug) Puts("Debug Info: We are using new settings");
}
if (userID != 0uL) {
if (configData.DebugSettings.useDebug) Puts("Debug Info: We got userID and set and locked to " + userID.ToString());
newDrop = GameManager.server.CreateEntity(SUPPLY_PREFAB, pos, new Quaternion(), true) as SupplyDrop;
(newDrop as BaseEntity).OwnerID = userID;
}
else {
newDrop = GameManager.server.CreateEntity(SUPPLY_PREFAB, pos, Quaternion.LookRotation(end - start), true) as SupplyDrop;
if (configData.DebugSettings.useDebug) Puts("Debug Info: Drop is currently not locked to any players");
}
(newDrop as BaseNetworkable).gameObject.AddComponent<ColliderCheck>();
newDrop.GetComponent<ColliderCheck>().cratesettings = cratesettings;
newDrop.GetComponent<ColliderCheck>().notifyEnabled = notify;
newDrop.GetComponent<ColliderCheck>().notifyConsole = notifyConsole;
newDrop.GetComponent<ColliderCheck>().dropType = dropType;
(newDrop as BaseNetworkable).gameObject.AddComponent<DropBehaviour>();
Effect.server.Run(BRADLEY_CANNON_EFFECT, newDrop.transform.position, Vector3.zero, null, true);
newDrop.Invoke(() => Effect.server.Run(HELIEXPLOSION_EFFECT, newDrop.transform.position, Vector3.zero, null, true), 0.5f);
newDrop.Invoke(() => Effect.server.Run(HELIEXPLOSION_EFFECT, newDrop.transform.position, Vector3.zero, null, true), 0.6f);
if (configData.DebugSettings.useDebug) {
Puts("Debug Info: Supply Drop (after spawning) Resistance Now " + Convert.ToDouble(cratesettings["crateAirResistance"]).ToString());
Puts("Debug Info: Supply Drop (after spawning) Despawn Time " + cratesettings["despawnMinutes"].ToString());
}
newDrop.Spawn();
int slots = 36;
newDrop.inventory.capacity = 36;
newDrop.panelName = "generic";
newDrop.inventory.ServerInitialize(null, slots);
newDrop.inventory.MarkDirty();
//Interface.CallHook("OnLootSpawn", new object[] { newDrop.GetComponent<LootContainer>() });
SupplyDrops.Add(newDrop);
if (configData.AirdropSettings.EffectsSettings.useSmokeEffectOnDrop) RunEffect(SMOKE_EFFECT, newDrop);
if (configData.AirdropSettings.EffectsSettings.useSirenAlarmOnDrop || configData.AirdropSettings.EffectsSettings.useSirenLightOnDrop && newDrop != null) {
if (newDrop == null) return;
CreateDropEffects(newDrop);
}
}
private void SpawnNetworkable(BaseNetworkable ent) {
if (ent.GetComponent<UnityEngine.Component>().transform.root != ent.GetComponent<UnityEngine.Component>().transform) ent.GetComponent<UnityEngine.Component>().transform.parent = null;
Rust.Registry.Entity.Register(ent.GetComponent<UnityEngine.Component>().gameObject, ent);
if (ent.net == null) ent.net = Network.Net.sv.CreateNetworkable();
ent.net.handler = ent;
//_creationFrame.SetValue(ent, Time.frameCount);
ent.creationFrame = Time.frameCount;
ent.PreInitShared();
ent.InitShared();
ent.ServerInit();
ent.PostInitShared();
ent.UpdateNetworkGroup();
//_isSpawned.SetValue(ent, true);
ent.isSpawned = true;
Interface.CallHook("OnEntitySpawned", ent);
ent.SendNetworkUpdateImmediate(true);
}
private void CreateRocket(Vector3 startPoint) {
BaseEntity entity = null;
if (TOD_Sky.Instance.IsNight) entity = GameManager.server.CreateEntity(HELIBURST_PREFAB, startPoint + new Vector3(0, 10, 0), new Quaternion(), true);
else entity = GameManager.server.CreateEntity(ROCKETSMOKE_PREFAB, startPoint + new Vector3(0, 10, 0), new Quaternion(), true);
entity.GetComponent<TimedExplosive>().timerAmountMin = configData.AirdropSettings.EffectsSettings.signalRocketExplosionTime;
entity.GetComponent<TimedExplosive>().timerAmountMax = configData.AirdropSettings.EffectsSettings.signalRocketExplosionTime;
entity.GetComponent<ServerProjectile>().gravityModifier = 0f;
entity.GetComponent<ServerProjectile>().speed = configData.AirdropSettings.EffectsSettings.signalRocketSpeed;
for (int i = 0; i < entity.GetComponent<TimedExplosive>().damageTypes.Count;
i++) {
entity.GetComponent<TimedExplosive>().damageTypes[i].amount *= 0f;
}
entity.SendMessage("InitializeVelocity", Vector3.up * 2f);
entity.Spawn();
}
private static Dictionary<string, object> getObjects(string name) {
Dictionary<string, object> dropsettings = new Dictionary<string, object>();
if (configData.DropSettings.setupDropTypes.ContainsKey(name)) {
var json = JsonConvert.SerializeObject(configData.DropSettings.setupDropTypes[name]);
dropsettings = JsonConvert.DeserializeObject<Dictionary<string, object>>(json) as Dictionary<string, object>;
}
return dropsettings;
}
public static Dictionary<string, TValue> ToDictionary<TValue>(object obj) {
var json = JsonConvert.SerializeObject(obj);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, TValue>>(json);
return dictionary;
}
private void startCargoPlane(Vector3 dropToPos = new Vector3(), bool randomDrop = true, CargoPlane plane = null, string dropType = "regular", string staticList = "", bool showinfo = true, ulong userID = 0uL) {
Dictionary<string, object> dropsettings = new Dictionary<string, object>();
int speed = 35;
int additionalheight = 0;
if (configData.DropSettings.setupDropTypes.ContainsKey(dropType)) {
dropsettings = getObjects(dropType);
}
else dropsettings = new Dictionary<string, object>((Dictionary<string, object>)setupDropDefault);
if (userID != 0uL) {
if (configData.DebugSettings.useDebug) Puts("Debug Info: UserID received and set as " + userID.ToString());
dropsettings.Add("userID", userID);
}
if (!dropsettings.ContainsKey("droptype")) dropsettings.Add("droptype", dropType);
if (staticList != "") dropsettings["CustomLootListName"] = staticList;
if (Convert.ToInt32(dropsettings["planeSpeed"]) < 20) dropsettings["planeSpeed"] = 20;
if (Convert.ToSingle(dropsettings["crateAirResistance"]) < 0.6) dropsettings["crateAirResistance"] = 0.6;
if (Convert.ToInt32(dropsettings["despawnMinutes"]) < 1) dropsettings["despawnMinutes"] = 1;
if (Convert.ToInt32(dropsettings["cratesGap"]) < 5) dropsettings["cratesGap"] = 5;
if (Convert.ToInt32(dropsettings["minCrates"]) < 1) dropsettings["minCrates"] = 1;
if (Convert.ToInt32(dropsettings["maxCrates"]) < 1) dropsettings["maxCrates"] = 1;
speed = Convert.ToInt32(dropsettings["planeSpeed"]);
additionalheight = Convert.ToInt32(dropsettings["additionalheight"]);
object isSupplyDropActive = Interface.Oxide.CallHook("isSupplyDropActive");
if (dropsettings.ContainsKey("betterloot")) dropsettings["betterloot"] = isSupplyDropActive != null && (bool)isSupplyDropActive ? true : false;
string notificationInfo = "";
if (dropsettings.ContainsKey("notificationInfo")) notificationInfo = (string)dropsettings["notificationInfo"];
if (plane == null) plane = createCargoPlane();
if (randomDrop) dropToPos = plane.RandomDropPosition();
float x = TerrainMeta.Size.x;
float y;
y = (TerrainMeta.HighestPoint.y * configData.AirdropSettings.planeOffSetYMultiply) + additionalheight;
Vector3 startPos = Vector3Ex.Range(-1f, 1f);
startPos.y = 0f;
startPos.Normalize();
startPos *= x * configData.AirdropSettings.planeOffSetXMultiply;
startPos.y = y;
Vector3 endPos = startPos * -1f;
endPos.y = startPos.y;
startPos += dropToPos;
endPos += dropToPos;
float secondsToTake = Vector3.Distance(startPos, endPos) / speed;
plane.gameObject.AddComponent<DropTiming>();
plane.GetComponent<DropTiming>().dropType = dropType;
plane.GetComponent<DropTiming>().userID = userID;
plane.GetComponent<DropTiming>().GetSettings(dropsettings, startPos, endPos, secondsToTake);
if (configData.DebugSettings.useDebug) {
Puts("Debug Info: Plane Height Setting " + dropsettings["additionalheight"].ToString());
Puts("Debug Info: Plane Speed Setting " + dropsettings["planeSpeed"].ToString());
Puts("Debug Info: Supply Drop Despawn Setting " + dropsettings["despawnMinutes"].ToString());
Puts("Debug Info: Supply Drop Resistance Setting " + dropsettings["crateAirResistance"].ToString());
Puts("Debug Info: Notification Info " + notificationInfo);
if (userID != 0uL) Puts("Debug Info: UserID Set to " + dropsettings["userID"].ToString());
}
dropsettings.Clear();
//dropPlanedropped.SetValue(plane, true);
plane.dropped = true;
plane.InitDropPosition(dropToPos);
if (!CargoPlanes.Contains(plane)) {
if ((plane as BaseNetworkable).net == null) (plane as BaseNetworkable).net = Network.Net.sv.CreateNetworkable();
CargoPlanes.Add(plane);
}
(plane as BaseNetworkable).limitNetworking = true;
//if ((int)_creationFrame.GetValue(plane) == 0)
if ((int)plane.creationFrame == 0) plane.Spawn();
plane.transform.position = startPos;
plane.transform.rotation = Quaternion.LookRotation(endPos - startPos);
//dropPlanestartPos.SetValue(plane, startPos);
plane.startPos = startPos;
//dropPlaneendPos.SetValue(plane, endPos);
plane.endPos = endPos;
//dropPlanesecondsToTake.SetValue(plane, secondsToTake);
plane.secondsToTake = secondsToTake;
(plane as BaseNetworkable).limitNetworking = false;
if (showinfo) DropNotifier(dropToPos, dropType, staticList, notificationInfo);
}
private static string GetGridString(Vector3 position) => MapHelper.PositionToString(position);
private void DropNotifier(Vector3 dropToPos, string dropType, string staticList, string notificationInfo) {
string gridPos = GetGridString(dropToPos);
if (dropType == "dropdirect") return;
else if (dropType == "supplysignal") {
if (configData.Notifications.notifyDropServerSignal) if (configData.Notifications.notifyDropGUI && configData.UISettings.SimpleUI_Enable) if (configData.Notifications.notifyDropServerSignalCoords) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropSignalCoords", player.UserIDString), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerSignalGrid) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropSignalGrid", player.UserIDString), gridPos));
else foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropSignal", player.UserIDString)));
else if (configData.Notifications.notifyDropGUI && GUIAnnouncements) if (configData.Notifications.notifyDropServerSignalCoords) MessageToAllGui(string.Format(msg("msgDropSignalCoords"), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerSignalGrid) MessageToAllGui(string.Format(msg("msgDropSignalGrid"), gridPos));
else MessageToAllGui(msg("msgDropSignal"));
else if (configData.Notifications.notifyDropServerSignalCoords) foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, string.Format(msg("msgDropSignalCoords", player.UserIDString), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerSignalGrid) foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, string.Format(msg("msgDropSignalGrid", player.UserIDString), gridPos));
else foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, msg("msgDropSignal", player.UserIDString));
return;
}
else if (dropType == "regular") {
if (configData.Notifications.notifyDropServerRegular) if (configData.Notifications.notifyDropGUI && configData.UISettings.SimpleUI_Enable) if (configData.Notifications.notifyDropServerRegularCoords) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropRegularCoords", player.UserIDString), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerRegularGrid) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropRegularGrid", player.UserIDString), gridPos));
else foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, msg("msgDropRegular", player.UserIDString));
else if (configData.Notifications.notifyDropGUI && GUIAnnouncements) if (configData.Notifications.notifyDropServerRegularCoords) MessageToAllGui(string.Format(msg("msgDropRegularCoords"), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerRegularGrid) MessageToAllGui(string.Format(msg("msgDropRegularGrid"), gridPos));
else MessageToAllGui(msg("msgDropRegular"));
else if (configData.Notifications.notifyDropServerRegularCoords) foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, string.Format(msg("msgDropRegularCoords", player.UserIDString), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerRegularGrid) foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, string.Format(msg("msgDropRegularGrid", player.UserIDString), gridPos));
else foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, msg("msgDropRegular", player.UserIDString));
return;
}
else if (dropType == "massdrop") {
if (configData.Notifications.notifyDropServerMass) if (configData.Notifications.notifyDropGUI && configData.UISettings.SimpleUI_Enable) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, msg("msgDropMass", player.UserIDString));
else if (configData.Notifications.notifyDropGUI && GUIAnnouncements) MessageToAllGui(msg("msgDropMass"));
else foreach (var player in BasePlayer.activePlayerList) MessageToPlayer(player, msg("msgDropMass", player.UserIDString));
return;
}
else {
if (configData.Notifications.notifyDropServerCustom) if (configData.Notifications.notifyDropGUI && configData.UISettings.SimpleUI_Enable) if (configData.Notifications.notifyDropServerCustomCoords && _massDropTimer != null && _massDropTimer.Repetitions == 0) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropCustomCoords", player.UserIDString), notificationInfo, dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else if (configData.Notifications.notifyDropServerCustomGrid && _massDropTimer != null && _massDropTimer.Repetitions == 0) foreach (var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(msg("msgDropCustomGrid", player.UserIDString), notificationInfo, gridPos));
// ... [Code preview truncated due to length. Full source in attached file] ...