C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using IEnumerator = System.Collections.IEnumerator;
using UnityEngine;
using Newtonsoft.Json;
namespace Oxide.Plugins {
[Info("FancyDrop", "Fujikura", "2.7.1", ResourceId = 1934)]
[Description("The Next Level of a fancy airdrop-toolset")]
class FancyDrop : RustPlugin {
[PluginReference]
Plugin BetterLoot;
[PluginReference]
Plugin GUIAnnouncements;
[PluginReference]
Plugin AlphaLoot;
static FancyDrop fd = null;
bool Changed = false;
bool initialized = false;
Vector3 lastDropPos;
float lastDropRadius = 0;
Vector3 lastLootPos;
int lastMinute;
double lastHour;
string msgConsoleDropSpawn;
static string msgConsoleDropLanded;
List<CargoPlane> CargoPlanes = new List<CargoPlane>();
List<SupplyDrop> SupplyDrops = new List<SupplyDrop>();
List<SupplyDrop> LootedDrops = new List<SupplyDrop>();
List<BaseEntity> activeSignals = new List<BaseEntity>();
Dictionary<BasePlayer, Timer> timers = new Dictionary<BasePlayer, Timer>();
static Dictionary<string, object> defaultRealTimers() {
var dp = new Dictionary<string, object>();
dp.Add("16:00", "massdrop 3");
dp.Add("18:00", "toplayer *");
return dp;
}
static Dictionary<string, object> defaultServerTimers() {
var dp = new Dictionary<string, object>();
dp.Add("6", "massdrop 3");
dp.Add("18", "massdropto 0 0 5 100");
return dp;
}
static Dictionary<string, object> defaultDrop() {
var dp = new Dictionary<string, object>();
dp.Add("minItems", 6);
dp.Add("maxItems", 6);
dp.Add("minCrates", 1);
dp.Add("maxCrates", 1);
dp.Add("cratesGap", 50);
dp.Add("useCustomLootTable", false);
dp.Add("additionalheight", 0);
dp.Add("despawnMinutes", 15);
dp.Add("crateAirResistance", 2.0);
dp.Add("includeStaticItemList", false);
dp.Add("includeStaticItemListName", "regular");
dp.Add("includeStaticItemListOnly", false);
dp.Add("planeSpeed", 75);
dp.Add("itemDivider", 2);
return dp;
}
static Dictionary<string, object> defaultDropTypes() {
var dp = new Dictionary<string, object>();
var dp0 = new Dictionary<string, object>();
dp0.Add("minItems", 6);
dp0.Add("maxItems", 6);
dp0.Add("minCrates", 1);
dp0.Add("maxCrates", 1);
dp0.Add("cratesGap", 50);
dp0.Add("useCustomLootTable", false);
dp0.Add("additionalheight", 0);
dp0.Add("despawnMinutes", 15);
dp0.Add("crateAirResistance", 2.0);
dp0.Add("includeStaticItemList", false);
dp0.Add("includeStaticItemListName", "regular");
dp0.Add("includeStaticItemListOnly", false);
dp0.Add("planeSpeed", 75);
dp0.Add("itemDivider", 2);
dp.Add("regular", dp0);
var dp1 = new Dictionary<string, object>();
dp1.Add("minItems", 6);
dp1.Add("maxItems", 6);
dp1.Add("minCrates", 1);
dp1.Add("maxCrates", 1);
dp1.Add("cratesGap", 50);
dp1.Add("useCustomLootTable", false);
dp1.Add("additionalheight", 0);
dp1.Add("despawnMinutes", 15);
dp1.Add("crateAirResistance", 2.0);
dp1.Add("includeStaticItemList", false);
dp1.Add("includeStaticItemListName", "supplysignal");
dp1.Add("includeStaticItemListOnly", false);
dp1.Add("planeSpeed", 75);
dp1.Add("itemDivider", 2);
dp.Add("supplysignal", dp1);
var dp2 = new Dictionary<string, object>();
dp2.Add("minItems", 6);
dp2.Add("maxItems", 6);
dp2.Add("minCrates", 1);
dp2.Add("maxCrates", 1);
dp2.Add("cratesGap", 50);
dp2.Add("useCustomLootTable", false);
dp2.Add("additionalheight", 0);
dp2.Add("despawnMinutes", 15);
dp2.Add("crateAirResistance", 2.0);
dp2.Add("includeStaticItemList", false);
dp2.Add("includeStaticItemListName", "massdrop");
dp2.Add("includeStaticItemListOnly", false);
dp2.Add("planeSpeed", 75);
dp2.Add("itemDivider", 2);
dp.Add("massdrop", dp2);
var dp3 = new Dictionary<string, object>();
dp3.Add("minItems", 6);
dp3.Add("maxItems", 6);
dp3.Add("minCrates", 1);
dp3.Add("maxCrates", 1);
dp3.Add("cratesGap", 50);
dp3.Add("useCustomLootTable", false);
dp3.Add("additionalheight", 0);
dp3.Add("despawnMinutes", 15);
dp3.Add("crateAirResistance", 2.0);
dp3.Add("includeStaticItemList", false);
dp3.Add("includeStaticItemListName", "dropdirect");
dp3.Add("includeStaticItemListOnly", false);
dp3.Add("planeSpeed", 75);
dp3.Add("itemDivider", 2);
dp.Add("dropdirect", dp3);
var dp4 = new Dictionary<string, object>();
dp4.Add("minItems", 6);
dp4.Add("maxItems", 6);
dp4.Add("minCrates", 1);
dp4.Add("maxCrates", 1);
dp4.Add("cratesGap", 50);
dp4.Add("useCustomLootTable", false);
dp4.Add("additionalheight", 0);
dp4.Add("despawnMinutes", 15);
dp4.Add("crateAirResistance", 2.0);
dp4.Add("includeStaticItemList", false);
dp4.Add("includeStaticItemListName", "custom_event");
dp4.Add("includeStaticItemListOnly", false);
dp4.Add("planeSpeed", 75);
dp4.Add("notificationInfo", "Custom Stuff");
dp4.Add("itemDivider", 2);
dp.Add("custom_event", dp4);
return dp;
}
static Dictionary<string, object> defaultItemList() {
var dp0_0 = new Dictionary<string, object>();
dp0_0.Add("targeting.computer", 2);
dp0_0.Add("cctv.camera", 2);
var dp0 = new Dictionary<string, object>();
dp0.Add("itemList", dp0_0);
dp0.Add("itemDivider", 2);
var dp1_0 = new Dictionary<string, object>();
dp1_0.Add("explosive.timed", 4);
dp1_0.Add("metal.refined", 100);
var dp1 = new Dictionary<string, object>();
dp1.Add("itemList", dp1_0);
dp1.Add("itemDivider", 2);
var dp2_0 = new Dictionary<string, object>();
dp2_0.Add("explosive.timed", 4);
dp2_0.Add("grenade.f1", 10);
var dp2 = new Dictionary<string, object>();
dp2.Add("itemList", dp2_0);
dp2.Add("itemDivider", 2);
var dp3_0 = new Dictionary<string, object>();
dp3_0.Add("explosive.timed", 4);
dp3_0.Add("surveycharge", 10);
var dp3 = new Dictionary<string, object>();
dp3.Add("itemList", dp3_0);
dp3.Add("itemDivider", 2);
var dp4_0 = new Dictionary<string, object>();
dp4_0.Add("explosive.timed", 10);
dp4_0.Add("grenade.f1", 10);
var dp4 = new Dictionary<string, object>();
dp4.Add("itemList", dp4_0);
dp4.Add("itemDivider", 2);
var dp = new Dictionary<string, object>();
dp.Add("regular", dp0);
dp.Add("supplysignal", dp1);
dp.Add("massdrop", dp2);
dp.Add("dropdirect", dp3);
dp.Add("custom_event", dp4);
return dp;
}
FieldInfo dropPlanestartPos = typeof(CargoPlane).GetField("startPos", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo dropPlaneendPos = typeof(CargoPlane).GetField("endPos", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo dropPlanesecondsToTake = typeof(CargoPlane).GetField("secondsToTake", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo dropPlanesecondsTaken = typeof(CargoPlane).GetField("secondsTaken", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo dropPlanedropped = typeof(CargoPlane).GetField("dropped", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo _isSpawned = typeof(BaseNetworkable).GetField("isSpawned", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo _creationFrame = typeof(BaseNetworkable).GetField("creationFrame", (BindingFlags.Instance | BindingFlags.NonPublic));
static FieldInfo _parachute = typeof(SupplyDrop).GetField("parachute", (BindingFlags.Instance | BindingFlags.NonPublic));
List<Regex> regexTags = new List<Regex> {
new Regex(@"<color=.+?>", RegexOptions.Compiled), new Regex(@"<size=.+?>", RegexOptions.Compiled)
}
;
List<string> tags = new List<string> {
"</color>", "</size>", "<i>", "</i>", "<b>", "</b>"
}
;
#region Config
Dictionary<string, object> setupDropTypes;
Dictionary<string, object> setupDropDefault;
Dictionary<string, object> setupItemList;
float planeOffSetXMultiply;
float planeOffSetYMultiply;
bool airdropTimerEnabled;
bool airdropRemoveInBuilt;
bool airdropTimerResetAfterRandom;
bool airdropCleanupAtStart;
int airdropTimerMinPlayers;
int airdropTimerWaitMinutesMin;
int airdropTimerWaitMinutesMax;
int airdropMassdropDefault;
float airdropMassdropRadiusDefault;
float airdropMassdropDelay;
Timer _aidropTimer;
Timer _massDropTimer;
static bool useSupplyDropEffectLanded;
static string supplyDropEffect;
bool disableRandomSupplyPos;
bool shootDownDrops;
int shootDownCount;
bool supplyDropLight;
float dropLightFrequency;
float dropLightOffTime;
bool removeDropLightOnLanded;
float signalRocketSpeed;
float signalRocketExplosionTime;
string Prefix;
string Color;
string colorAdmMsg;
string colorTextMsg;
string Format;
string guiCommand;
float supplySignalSmokeTime;
int neededAuthLvl;
bool lockDirectDrop;
bool lockSignalDrop;
bool unlockDropAfterLoot;
string version;
bool useRealtimeTimers;
bool useGametimeTimers;
bool logTimersToConsole;
int timersMinPlayers;
Dictionary<string, object> realTimers = new Dictionary<string, object>();
Dictionary<string, object> serverTimers = new Dictionary<string, object>();
bool notifyByChatAdminCalls;
bool notifyDropGUI;
bool notifyDropServerSignal;
bool notifyDropServerSignalCoords;
bool notifyDropSignalByPlayer;
bool notifyDropSignalByPlayerCoords;
bool notifyDropAdminSignal;
bool notifyDropConsoleSignal;
bool notifyDropServerRegular;
bool notifyDropServerRegularCoords;
bool notifyDropConsoleRegular;
bool notifyDropServerCustom;
bool notifyDropServerCustomCoords;
bool notifyDropServerMass;
bool notifyDropPlayer;
bool notifyDropDirect;
static bool notifyDropPlayersOnLanded;
float supplyDropNotifyDistance;
float supplyLootNotifyDistance;
bool notifyDropServerLooted;
bool notifyDropServerLootedCoords;
bool notifyDropConsoleLooted;
static bool notifyDropConsoleOnLanded;
bool notifyDropConsoleSpawned;
bool notifyDropConsoleFirstOnly;
bool SimpleUI_Enable;
int SimpleUI_FontSize;
float SimpleUI_Top;
float SimpleUI_Left;
float SimpleUI_MaxWidth;
float SimpleUI_MaxHeight;
float SimpleUI_HideTimer;
string SimpleUI_NoticeColor;
string SimpleUI_ShadowColor;
object GetConfig(string menu, string datavalue, object defaultValue) {
var data = Config[menu] as Dictionary<string, object>;
if (data == null) {
data = new Dictionary<string, object>();
Config[menu] = data;
Changed = true;
}
object value;
if (!data.TryGetValue(datavalue, out value)) {
value = defaultValue;
data[datavalue] = value;
Changed = true;
}
return value;
}
void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
{
"msgDropSignal", "Someone ordered an Airdrop"
}
, {
"msgDropSignalCoords", "Someone ordered an Airdrop to position <color=yellow>X:{0} Z:{1}</color>"
}
, {
"msgDropSignalAdmin", "Signal thrown by '{0}' at: {1}"
}
, {
"msgDropSignalByPlayer", "Signal thrown by <color=yellow>{0}</color>"
}
, {
"msgDropSignalByPlayerCoords", "Signal thrown by <color=yellow>{0}</color> at position <color=yellow>X:{1} Z:{2}</color>"
}
, {
"msgDropRegular", "Cargoplane will deliver the daily AirDrop in a few moments"
}
, {
"msgDropRegularCoords", "Cargoplane will deliver the daily AirDrop at <color=yellow>X:{0} | Z:{1}</color> in a few moments"
}
, {
"msgDropMass", "Massdrop incoming"
}
, {
"msgDropCustom", "Eventdrop <color=orange>{0}</color> is on his way"
}
, {
"msgDropCustomCoords", "Eventdrop <color=orange>{0}</color> is on his way to <color=yellow>X:{1} | Z:{2}</color>"
}
, {
"msgDropPlayer", "<color=yellow>Incoming Drop</color> to your current location"
}
, {
"msgDropDirect", "<color=yellow>Drop</color> spawned above your <color=yellow>current</color> location"
}
, {
"msgDropLanded", "Supplydrop has landed <color=yellow>{0:F0}m</color> away from you at direction <color=yellow>{1}</color>"
}
, {
"msgDropLootet", "<color=yellow>{0}</color> was looting the AirDrop"
}
, {
"msgDropLootetCoords", "<color=yellow>{0}</color> was looting the AirDrop at (<color=yellow>X:{1} | Z:{2}</color>)"
}
, {
"msgNoAccess", "You are not allowed to use this command"
}
, {
"msgConsoleDropSpawn", "SupplyDrop spawned at (X:{0} Y:{1} Z:{2})"
}
, {
"msgConsoleDropLanded", "SupplyDrop landed at (X:{0} Y:{1} Z:{2})"
}
, {
"msgCrateLocked", "This crate is locked until being looted by the owner"
}
, {
"msgNorth", "North"
}
, {
"msgNorthEast", "NorthEast"
}
, {
"msgEast", "East"
}
, {
"msgSouthEast", "SouthEast"
}
, {
"msgSouth", "South"
}
, {
"msgSouthWest", "SouthWest"
}
, {
"msgWest", "West"
}
, {
"msgNorthWest", "NorthWest"
}
,
}
, this);
}
void LoadVariables() {
setupDropTypes = (Dictionary<string, object>)GetConfig("DropSettings", "DropTypes", defaultDropTypes());
setupDropDefault = (Dictionary<string, object>)GetConfig("DropSettings", "DropDefault", defaultDrop());
setupItemList = (Dictionary<string, object>)GetConfig("StaticItems", "DropTypes", defaultItemList());
useSupplyDropEffectLanded = Convert.ToBoolean(GetConfig("Airdrop", "Use special effect at reaching ground position", true));
supplyDropEffect = Convert.ToString(GetConfig("Airdrop", "Prefab effect to use", "assets/bundled/prefabs/fx/survey_explosion.prefab"));
airdropMassdropDefault = Convert.ToInt32(GetConfig("Airdrop", "Massdrop default plane amount", 5));
airdropMassdropDelay = Convert.ToSingle(GetConfig("Airdrop", "Delay between Massdrop plane spawns", 0.33));
airdropMassdropRadiusDefault = Convert.ToSingle(GetConfig("Airdrop", "Default radius for location based massdrop", 100));
signalRocketSpeed = Convert.ToSingle(GetConfig("Airdrop", "signal rocket speed", 15));
signalRocketExplosionTime = Convert.ToSingle(GetConfig("Airdrop", "signal rocket explosion timer", 15));
shootDownDrops = Convert.ToBoolean(GetConfig("Airdrop", "Players can shoot down the drop", false));
shootDownCount = Convert.ToInt32(GetConfig("Airdrop", "Players can shoot down the drop - needed hits", 5));
airdropTimerEnabled = Convert.ToBoolean(GetConfig("Timer", "Use Airdrop timer", true));
airdropRemoveInBuilt = Convert.ToBoolean(GetConfig("Timer", "Remove builtIn Airdrop", true));
airdropCleanupAtStart = Convert.ToBoolean(GetConfig("Timer", "Cleanup old Drops at serverstart", true));
airdropTimerMinPlayers = Convert.ToInt32(GetConfig("Timer", "Minimum players for timed Drop", 2));
airdropTimerWaitMinutesMin = Convert.ToInt32(GetConfig("Timer", "Minimum minutes for random timer delay ", 30));
airdropTimerWaitMinutesMax = Convert.ToInt32(GetConfig("Timer", "Maximum minutes for random timer delay ", 50));
airdropTimerResetAfterRandom = Convert.ToBoolean(GetConfig("Timer", "Reset Timer after manual random drop", false));
planeOffSetXMultiply = Convert.ToSingle(GetConfig("Airdrop", "Multiplier for overall flight distance; lower means faster at map", 1.25));
planeOffSetYMultiply = Convert.ToSingle(GetConfig("Airdrop", "Multiplier for (plane height * highest point on Map); Default 1.0", 1.0));
disableRandomSupplyPos = Convert.ToBoolean(GetConfig("Airdrop", "Disable SupplySignal randomization", false));
Prefix = Convert.ToString(GetConfig("Generic", "Chat/Message prefix", "Air Drop"));
Color = Convert.ToString(GetConfig("Generic", "Prefix color", "cyan"));
Format = Convert.ToString(GetConfig("Generic", "Prefix format", "<color={0}>{1}</color>: "));
guiCommand = Convert.ToString(GetConfig("Generic", "GUI Announce command", "announce.announce"));
neededAuthLvl = Convert.ToInt32(GetConfig("Generic", "AuthLevel needed for console commands", 1));
supplySignalSmokeTime = Convert.ToSingle(GetConfig("Generic", "Time for active smoke of SupplySignal", 210.0));
colorAdmMsg = Convert.ToString(GetConfig("Generic", "Admin messages color", "silver"));
notifyByChatAdminCalls = Convert.ToBoolean(GetConfig("Generic", "Show message to admin after command usage", true));
colorTextMsg = Convert.ToString(GetConfig("Generic", "Broadcast messages color", "white"));
lockDirectDrop = Convert.ToBoolean(GetConfig("Generic", "Lock DirectDrop to be looted only by target player", true));
lockSignalDrop = Convert.ToBoolean(GetConfig("Generic", "Lock SignalDrop to be looted only by target player", false));
unlockDropAfterLoot = Convert.ToBoolean(GetConfig("Generic", "Unlock crates only after player stopped looting", false));
version = Convert.ToString(GetConfig("Generic", "version", this.Version.ToString()));
if (version != this.Version.ToString()) {
Config["Generic", "version"] = this.Version.ToString();
Changed = true;
}
useRealtimeTimers = Convert.ToBoolean(GetConfig("Timers", "use RealTime", false));
useGametimeTimers = Convert.ToBoolean(GetConfig("Timers", "use ServerTime", false));
logTimersToConsole = Convert.ToBoolean(GetConfig("Timers", "log to console", true));
realTimers = (Dictionary<string, object>)GetConfig("Timers", "RealTime", defaultRealTimers());
serverTimers = (Dictionary<string, object>)GetConfig("Timers", "ServerTime", defaultServerTimers());
timersMinPlayers = Convert.ToInt32(GetConfig("Timers", "Minimum players for running Timers", 0));
supplyDropLight = Convert.ToBoolean(GetConfig("DropLight", "use SupplyDrop Light", true));
dropLightFrequency = Convert.ToSingle(GetConfig("DropLight", "Frequency for blinking", 0.25));
dropLightOffTime = Convert.ToSingle(GetConfig("DropLight", "Time for pause between blinking", 3.0));
removeDropLightOnLanded = Convert.ToBoolean(GetConfig("DropLight", "remove Light once landed", false));
notifyDropGUI = Convert.ToBoolean(GetConfig("Notification", "use GUI Announcements for any Drop notification", false));
notifyDropServerSignal = Convert.ToBoolean(GetConfig("Notification", "Notify players at Drop by SupplySignal", true));
notifyDropServerSignalCoords = Convert.ToBoolean(GetConfig("Notification", "Notify players at Drop by SupplySignal including Coords ", false));
notifyDropConsoleSignal = Convert.ToBoolean(GetConfig("Notification", "Notify console at Drop by SupplySignal", true));
notifyDropServerRegular = Convert.ToBoolean(GetConfig("Notification", "Notify players at Random/Timed Drop", true));
notifyDropServerRegularCoords = Convert.ToBoolean(GetConfig("Notification", "Notify players at Random/Timed Drop including Coords", false));
notifyDropConsoleRegular = Convert.ToBoolean(GetConfig("Notification", "Notify console at timed-regular Drop", true));
notifyDropServerCustom = Convert.ToBoolean(GetConfig("Notification", "Notify players at custom/event Drop", true));
notifyDropServerCustomCoords = Convert.ToBoolean(GetConfig("Notification", "Notify players at custom/event Drop including Coords", false));
notifyDropServerMass = Convert.ToBoolean(GetConfig("Notification", "Notify players at Massdrop", true));
notifyDropPlayer = Convert.ToBoolean(GetConfig("Notification", "Notify a player about incoming Drop to his location", true));
notifyDropDirect = Convert.ToBoolean(GetConfig("Notification", "Notify a player about spawned Drop at his location", true));
notifyDropPlayersOnLanded = Convert.ToBoolean(GetConfig("Notification", "Notify players when Drop is landed about distance", true));
notifyDropConsoleOnLanded = Convert.ToBoolean(GetConfig("Notification", "Notify console when Drop is landed", false));
notifyDropConsoleSpawned = Convert.ToBoolean(GetConfig("Notification", "Notify console when Drop is spawned", false));
notifyDropConsoleFirstOnly = Convert.ToBoolean(GetConfig("Notification", "Notify console when Drop landed/spawned only at the first", true));
supplyDropNotifyDistance = Convert.ToSingle(GetConfig("Notification", "Maximum distance in meters to get notified about landed Drop", 1000));
supplyLootNotifyDistance = Convert.ToSingle(GetConfig("Notification", "Maximum distance in meters to get notified about looted Drop", 1000));
notifyDropServerLooted = Convert.ToBoolean(GetConfig("Notification", "Notify players when a Drop is being looted", true));
notifyDropServerLootedCoords = Convert.ToBoolean(GetConfig("Notification", "Notify players when a Drop is being looted including coords", false));
notifyDropConsoleLooted = Convert.ToBoolean(GetConfig("Notification", "Notify console when a Drop is being looted", true));
notifyDropSignalByPlayer = Convert.ToBoolean(GetConfig("Notification", "Notify Players who has thrown a SupplySignal", false));
notifyDropSignalByPlayerCoords = Convert.ToBoolean(GetConfig("Notification", "Notify Players who has thrown a SupplySignal including coords", false));
notifyDropAdminSignal = Convert.ToBoolean(GetConfig("Notification", "Notify admins per chat about player who has thrown SupplySignal ", false));
SimpleUI_Enable = Convert.ToBoolean(GetConfig("SimpleUI", "SimpleUI_Enable", false));
SimpleUI_FontSize = Convert.ToInt32(GetConfig("SimpleUI", "SimpleUI_FontSize", 25));
SimpleUI_Top = Convert.ToSingle(GetConfig("SimpleUI", "SimpleUI_Top", 0.05));
SimpleUI_Left = Convert.ToSingle(GetConfig("SimpleUI", "SimpleUI_Left", 0.1));
SimpleUI_MaxWidth = Convert.ToSingle(GetConfig("SimpleUI", "SimpleUI_MaxWidth", 0.8));
SimpleUI_MaxHeight = Convert.ToSingle(GetConfig("SimpleUI", "SimpleUI_MaxHeight", 0.1));
SimpleUI_HideTimer = Convert.ToSingle(GetConfig("SimpleUI", "SimpleUI_HideTimer", 10));
SimpleUI_NoticeColor = Convert.ToString(GetConfig("SimpleUI", "SimpleUI_NoticeColor", "1 1 1 0.9"));
SimpleUI_ShadowColor = Convert.ToString(GetConfig("SimpleUI", "SimpleUI_ShadowColor", "0.1 0.1 0.1 0.5"));
if (!Changed) return;
SaveConfig();
Changed = false;
}
protected override void LoadDefaultConfig() {
Config.Clear();
LoadVariables();
}
#endregion Config
#region ColliderCheck
void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (!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 < shootDownCount) {
col.hitCounter++;
return;
}
parachute.Kill();
parachute = null;
drop.GetComponent<Rigidbody>().drag = 0.6f;
col.wasHit = true;
}
}
sealed class ColliderCheck : MonoBehaviour {
public bool notifyEnabled = true;
public bool notifyConsole;
public Dictionary<string, object> cratesettings;
public bool landed = false;
public int hitCounter = 0;
public bool wasHit;
private void Awake() {
fd.NextTick(() => {
if (cratesettings.ContainsKey("maxItems")) fd.SetupContainer(GetComponent<StorageContainer>(), cratesettings);
else Awake();
}
);
}
void PlayerStoppedLooting(BasePlayer player) {
if (!fd.unlockDropAfterLoot || GetComponent<BaseEntity>().OwnerID == 0uL || player.userID != GetComponent<BaseEntity>().OwnerID) return;
GetComponent<BaseEntity>().OwnerID = 0uL;
fd.LootedDrops.Add(GetComponent<BaseEntity>() as SupplyDrop);
}
void OnCollisionEnter(Collision col) {
if (!landed) {
landed = true;
if (wasHit) {
if (useSupplyDropEffectLanded) Effect.server.Run(supplyDropEffect, GetComponent<BaseEntity>().transform.position);
StartCoroutine(HitRemove() );
return;
}
if (cratesettings.ContainsKey("fireSignalRocket") && (bool)cratesettings["fireSignalRocket"]) fd.CreateRocket(GetComponent<BaseEntity>().transform.position);
if (notifyEnabled && notifyDropPlayersOnLanded && (string)cratesettings["droptype"] != "dropdirect" && (((fd.lastDropRadius*2)*1.2) - Vector3.Distance(fd.lastDropPos, GetComponent<BaseEntity>().transform.position) <= 0 && !(UnityEngine.CollisionEx.GetEntity(col) is SupplyDrop))) fd.NotifyOnDropLanded(GetComponent<BaseEntity>());
fd.lastDropPos = GetComponent<BaseEntity>().transform.position;
StartCoroutine(DeSpawn() );
if (useSupplyDropEffectLanded) Effect.server.Run(supplyDropEffect, GetComponent<BaseEntity>().transform.position);
if(notifyConsole && notifyDropConsoleOnLanded) fd.Puts(string.Format(fd.lang.GetMessage(msgConsoleDropLanded, fd), GetComponent<BaseEntity>().transform.position.x.ToString("0"), GetComponent<BaseEntity>().transform.position.y.ToString("0"), GetComponent<BaseEntity>().transform.position.z.ToString("0")));
}
}
IEnumerator HitRemove() {
yield return new WaitForSeconds(0.1f );
DropUtil.DropItems(GetComponent<StorageContainer>().inventory, GetComponent<BaseEntity>().transform.position, 1f);
fd.SupplyDrops.Remove(GetComponent<SupplyDrop>());
cratesettings.Clear();
GetComponent<BaseEntity>().Kill(BaseNetworkable.DestroyMode.Gib);
}
IEnumerator DeSpawn() {
yield return new WaitForSeconds((int)cratesettings["despawnMinutes"] * 60 );
yield return new WaitWhile(() => GetComponent<BaseEntity>().IsOpen());
cratesettings.Clear();
GetComponent<BaseEntity>().Kill();
}
void OnDestroy() {
cratesettings.Clear();
fd.SupplyDrops.Remove(GetComponent<SupplyDrop>());
fd.LootedDrops.Remove(GetComponent<SupplyDrop>());
}
public ColliderCheck() {
}
}
#endregion ColliderCheck
#region DropTiming
private sealed class DropTiming : MonoBehaviour {
private int dropCount;
private float updatedTime;
public Vector3 startPos;
public Vector3 endPos;
public bool notify = true;
private bool notifyConsole = true;
private int cratesToDrop;
public Dictionary<string, object> dropsettings;
private float gapTimeToTake = 0f;
private float halfTimeToTake = 0f;
private float offsetTimeToTake = 0f;
public 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);
}
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)fd.dropPlanesecondsTaken.GetValue(GetComponent<CargoPlane>()) > updatedTime && dropCount < cratesToDrop) {
updatedTime += gapTimeToTake;
dropCount++;
fd.createSupplyDrop(GetComponent<CargoPlane>().transform.position, new Dictionary<string, object>(dropsettings), notify, notifyConsole, startPos, endPos);
if(fd.notifyDropConsoleSpawned && notifyConsole) fd.Puts(string.Format(fd.lang.GetMessage(fd.msgConsoleDropSpawn, fd), 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 && fd.notifyDropConsoleFirstOnly) notifyConsole = false;
}
private void OnDestroy() {
dropsettings.Clear();
fd.CargoPlanes.Remove(GetComponent<CargoPlane>());
Destroy(this);
}
public DropTiming() {
}
}
#endregion DropTiming
#region DropLight
private sealed class DropLight : MonoBehaviour {
bool isRunning = false;
public void Awake() {
if (TOD_Sky.Instance.IsNight) {
if(!(bool)fd._isSpawned.GetValue(GetComponent<BaseEntity>())) GetComponent<BaseEntity>().Spawn();
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.Locked, true);
isRunning = true;
StartCoroutine(Light() );
}
}
public void Update() {
if (TOD_Sky.Instance.IsNight && !isRunning) {
if(!(bool)fd._isSpawned.GetValue(GetComponent<BaseEntity>())) GetComponent<BaseEntity>().Spawn();
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.Locked, true);
isRunning = true;
StartCoroutine(Light() );
}
if((fd.removeDropLightOnLanded && GetComponent<BaseEntity>().GetParentEntity().GetComponent<ColliderCheck>().landed) || GetComponent<BaseEntity>().ParentHasFlag(BaseEntity.Flags.Open)) DoDestroy();
}
private IEnumerator Light() {
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.On, true);
yield return new WaitForSeconds(fd.dropLightFrequency );
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.On, false);
yield return new WaitForSeconds(fd.dropLightFrequency );
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.On, true);
yield return new WaitForSeconds(fd.dropLightFrequency );
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.On, false);
yield return new WaitForSeconds(fd.dropLightFrequency );
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.On, true);
yield return new WaitForSeconds(fd.dropLightFrequency );
GetComponent<BaseEntity>().SetFlag(BaseEntity.Flags.On, false);
yield return new WaitForSeconds(fd.dropLightOffTime );
if(TOD_Sky.Instance.IsNight) StartCoroutine(Light() );
else {
isRunning = false;
DoDestroy();
}
}
public void DoDestroy() {
if (!GetComponent<BaseEntity>().IsDestroyed) GetComponent<BaseEntity>().KillMessage();
Destroy(this);
}
public DropLight() {
}
}
#endregion DropLight
#region ObjectsCreation
private CargoPlane createCargoPlane(Vector3 pos = new Vector3()) {
var newPlane = GameManager.server.CreateEntity("assets/prefabs/npc/cargo plane/cargo_plane.prefab", pos, new Quaternion(), true) as CargoPlane;
return newPlane;
}
void createSupplyDrop(Vector3 pos, Dictionary<string, object> cratesettings, bool notify = true, bool notifyConsole = true, Vector3 start = new Vector3(), Vector3 end = new Vector3()) {
SupplyDrop newDrop;
object value;
if(cratesettings.TryGetValue("userID", out value)) {
newDrop = GameManager.server.CreateEntity("assets/prefabs/misc/supply drop/supply_drop.prefab", pos, new Quaternion(), true) as SupplyDrop;
(newDrop as BaseEntity).OwnerID = (ulong)value;
}
else newDrop = GameManager.server.CreateEntity("assets/prefabs/misc/supply drop/supply_drop.prefab", pos, Quaternion.LookRotation(end - start), true) as SupplyDrop;
(newDrop as BaseNetworkable).gameObject.AddComponent<ColliderCheck>();
newDrop.GetComponent<ColliderCheck>().cratesettings = cratesettings;
newDrop.GetComponent<ColliderCheck>().notifyEnabled = notify;
newDrop.GetComponent<ColliderCheck>().notifyConsole = notifyConsole;
newDrop.GetComponent<Rigidbody>().drag = Convert.ToSingle(cratesettings["crateAirResistance"]);
if ((bool)cratesettings["betterloot"]) newDrop.GetComponent<LootContainer>().initialLootSpawn = false;
object obj = Interface.CallHook("OnFancyDropCrate", cratesettings );
if (obj != null) {
newDrop.GetComponent<ColliderCheck>().cratesettings["AlCustom"] = true;
newDrop.GetComponent<ColliderCheck>().cratesettings["AlCustomList"] = (List<Item>)obj;
SpawnNetworkable(newDrop as BaseNetworkable);
}
else newDrop.Spawn();
Interface.CallHook("OnLootSpawn", new object[] {
newDrop.GetComponent<LootContainer>()
}
);
SupplyDrops.Add(newDrop);
if (supplyDropLight) createLantern(newDrop as BaseEntity);
}
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.PreInitShared();
ent.InitShared();
ent.ServerInit();
ent.PostInitShared();
ent.UpdateNetworkGroup();
_isSpawned.SetValue(ent, true);
Interface.CallHook("OnEntitySpawned", ent );
ent.SendNetworkUpdateImmediate(true);
}
private static void createLantern(BaseEntity entity) {
var lantern = (BaseOven)GameManager.server.CreateEntity("assets/prefabs/deployable/lantern/lantern.deployed.prefab", default(Vector3), default(Quaternion), true);
lantern.gameObject.AddComponent<DropLight>();
lantern.gameObject.Identity();
lantern.SetParent(entity as LootContainer, "parachute_attach");
lantern.GetComponent<DropLight>().Awake();
}
void CreateRocket(Vector3 startPoint) {
BaseEntity entity = null;
if (TOD_Sky.Instance.IsNight) entity = GameManager.server.CreateEntity("assets/prefabs/npc/patrol helicopter/rocket_heli_airburst.prefab", startPoint + new Vector3(0, 10, 0), new Quaternion(), true);
else entity = GameManager.server.CreateEntity("assets/prefabs/ammo/rocket/rocket_smoke.prefab", startPoint + new Vector3(0, 10, 0), new Quaternion(), true);
entity.GetComponent<TimedExplosive>().timerAmountMin = signalRocketExplosionTime;
entity.GetComponent<TimedExplosive>().timerAmountMax = signalRocketExplosionTime;
entity.GetComponent<ServerProjectile>().gravityModifier = 0f;
entity.GetComponent<ServerProjectile>().speed = 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();
}
protected 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;
if (setupDropTypes.ContainsKey(dropType)) {
dropsettings = new Dictionary<string, object>((Dictionary<string, object>)setupDropTypes[dropType]);
object value;
foreach(var pair in setupDropDefault) if (!dropsettings.TryGetValue(pair.Key, out value)) dropsettings.Add(pair.Key, setupDropDefault[pair.Key]);
}
else dropsettings = new Dictionary<string, object>((Dictionary<string, object>)setupDropDefault);
if (userID != 0uL) dropsettings.Add("userID", userID);
dropsettings.Add("droptype", dropType);
if(staticList != "") dropsettings["includeStaticItemListName"] = 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["minItems"]) < 1) dropsettings["minItems"] = 1;
if (Convert.ToInt32(dropsettings["maxItems"]) < 1) dropsettings["maxItems"] = 1;
if (Convert.ToInt32(dropsettings["minCrates"]) < 1) dropsettings["minCrates"] = 1;
if (Convert.ToInt32(dropsettings["maxCrates"]) < 1) dropsettings["maxCrates"] = 1;
if (BetterLoot && BetterLoot.Call("isSupplyDropActive") != null && (bool)BetterLoot.Call("isSupplyDropActive")) dropsettings["betterloot"] = true;
else dropsettings["betterloot"] = false;
if (AlphaLoot && AlphaLoot.Call("isSupplyDropActive") != null && (bool)AlphaLoot.Call("isSupplyDropActive")) dropsettings["betterloot"] = true;
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 * planeOffSetYMultiply) + (int)dropsettings["additionalheight"];
Vector3 startPos = Vector3Ex.Range(-1f, 1f);
startPos.y = 0f;
startPos.Normalize();
startPos *= x * planeOffSetXMultiply;
startPos.y = y;
Vector3 endPos = startPos * -1f;
endPos.y = startPos.y;
startPos += dropToPos;
endPos += dropToPos;
float secondsToTake = Vector3.Distance(startPos, endPos) / (int)dropsettings["planeSpeed"];
plane.gameObject.AddComponent<DropTiming>();
plane.GetComponent<DropTiming>().GetSettings(new Dictionary<string, object>(dropsettings), startPos, endPos, secondsToTake);
dropsettings.Clear();
dropPlanedropped.SetValue(plane, 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) plane.Spawn();
plane.transform.position = startPos;
plane.transform.rotation = Quaternion.LookRotation(endPos - startPos);
dropPlanestartPos.SetValue(plane, startPos);
dropPlaneendPos.SetValue(plane, endPos);
dropPlanesecondsToTake.SetValue(plane, secondsToTake);
(plane as BaseNetworkable).limitNetworking = false;
if (showinfo) DropNotifier(dropToPos, dropType, staticList, notificationInfo);
}
private void DropNotifier(Vector3 dropToPos, string dropType, string staticList, string notificationInfo) {
if (dropType == "dropdirect") return;
else if (dropType == "supplysignal") {
if(notifyDropServerSignal) if(notifyDropGUI && SimpleUI_Enable) if (notifyDropServerSignalCoords) foreach(var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(lang.GetMessage("msgDropSignalCoords", this, player.UserIDString), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else foreach(var player in BasePlayer.activePlayerList) MessageToPlayerUI(player, string.Format(lang.GetMessage("msgDropSignal", this, player.UserIDString)));
else if(notifyDropGUI && GUIAnnouncements) if (notifyDropServerSignalCoords) MessageToAllGui(string.Format(lang.GetMessage("msgDropSignalCoords", this), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else MessageToAllGui(lang.GetMessage("msgDropSignal", this));
else if (notifyDropServerSignalCoords) foreach(var player in BasePlayer.activePlayerList) MessageToPlayer(player, string.Format(lang.GetMessage("msgDropSignalCoords", this, player.UserIDString), dropToPos.x.ToString("0"), dropToPos.z.ToString("0")));
else foreach(var player in Base
// ... [Code preview truncated due to length. Full source in attached file] ...