Иконка ресурса

FREE PersonalHeli : 1.1.4 1.1.4

Нет прав для скачивания
C#:
// #define DEBUG
using System.Collections.Generic;
using System;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using System.Text;
using System.Linq;
using Facepunch;
using Rust;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
	[Info("Personal Heli", "topplugin.ru", "1.1.4")]
	[Description("Calls heli to player and his team, with loot/damage and minig lock")]
	class PersonalHeli : RustPlugin
	{
		#region CONSTANTS
		const string permUse = "personalheli.use";
		const string permConsole = "personalheli.console";
		const float HelicopterEntitySpawnRadius = 10.0f;
		private static System.Random Rnd = new System.Random();

		private bool init;

		#endregion
		#region DEPENDENCIES
		[PluginReference]
		Plugin Friends, Clans;
		#endregion
		#region CONFIG
		public class PluginConfig
		{
			[JsonPropertyAttribute("Основные настройки", Order = 0)]
			public MainSettings MainBlock = new MainSettings();
			[JsonProperty("Настройки участников", Order = 1)]
			public TargetSettings TargetBlock = new TargetSettings();
			[JsonProperty("Настройки вертолета", Order = 2)]
			public Dictionary<string, HeliSettings> Heli = new Dictionary<string, HeliSettings>();

			public static PluginConfig GetNewConfig()
			{
				PluginConfig newConfig = new PluginConfig();
				newConfig.MainBlock = new MainSettings()
				{
					ChatCommand = "callheli",
					ChatLeaveCommand = "stopheli",
					MaxHeliCount = 1,
					Cooldowns = new Dictionary<string, int>(){
						{"personalheli.elite",300},
						{"personalheli.vip",600}
					},
					ResetCooldownsOnWipe = true,
					RetireOnAllTeamDead = true,
					LifeTimeMinutes = 15,
					BulletAccuracy = 2f
				};
				newConfig.TargetBlock = new TargetSettings()
				{
					UseFriends = true,
					UseTeams = true,
					UseClans = false
				};
				newConfig.Heli = new Dictionary<string, HeliSettings>();
				//EASY
				newConfig.Heli.Add("easy", new HeliSettings()
				{
					DifficultName = "<color=green>Легкая</color>",
					Speed = 30f,
					Health = new HeliSettings.HealthSettings()
					{
						HPBase = 10000f,
						HPFront = 900f,
						HPRear = 500f
					},
					Damage = new HeliSettings.DamageSettings()
					{
						Multiplier = 0.8f,
						ArmorMultiplier = 0.8f,
						Turrets = new HeliSettings.DamageSettings.TurretConfig()
						{
							BulletDamage = 11f,
							BulletSpeed = 350,
							FireSpeed = 0.07f,
							FireLenght = 2f,
							FireBetween = 4f,
							MaxDistance = 100f
						},
						Rockets = new HeliSettings.DamageSettings.RocketConfig()
						{
							MaxHeliRockets = 12,
							TimeBetweenRockets = 0.4f,
							BulletDamage = 175f,
							ExplosionDamage = 100f,
							ExplosionRadius = 6f
						}
					},
					Loot = new HeliSettings.LootSettings()
					{
						MaxLootCrates = 3,
						MemorizeTeamOnCall = true,
						RemoveFireFromCrates = true,
						DenyCratesLooting = true,
						DenyGibsMining = true,
						ProfileName = "easy"
					},
					ItemAction = new HeliSettings.HeliItem()
					{
						action = "unwrap",
						shortname = "xmas.present.large",
						skin = 2306487582,
						name = "Вызов легкой вертушки"
					}
				});
				//DEFAULT
				newConfig.Heli.Add("default", new HeliSettings()
				{
					DifficultName = "<color=yellow>Обычная</color>",
					Speed = 42f,
					Health = new HeliSettings.HealthSettings()
					{
						HPBase = 10000f,
						HPFront = 900f,
						HPRear = 500f
					},
					Damage = new HeliSettings.DamageSettings()
					{
						Multiplier = 1f,
						ArmorMultiplier = 1f,
						Turrets = new HeliSettings.DamageSettings.TurretConfig()
						{
							BulletDamage = 11f,
							BulletSpeed = 350,
							FireSpeed = 0.1f,
							FireLenght = 3f,
							FireBetween = 4f,
							MaxDistance = 150f
						},
						Rockets = new HeliSettings.DamageSettings.RocketConfig()
						{
							MaxHeliRockets = 12,
							TimeBetweenRockets = 0.3f,
							BulletDamage = 175f,
							ExplosionDamage = 100f,
							ExplosionRadius = 6f
						}
					},
					Loot = new HeliSettings.LootSettings()
					{
						MaxLootCrates = 4,
						MemorizeTeamOnCall = true,
						RemoveFireFromCrates = true,
						DenyCratesLooting = true,
						DenyGibsMining = true,
						ProfileName = "default"
					},
					ItemAction = new HeliSettings.HeliItem()
					{
						action = "unwrap",
						shortname = "xmas.present.large",
						skin = 2306496332,
						name = "Вызов обычной вертушки"
					}
				});
				//HARD
				newConfig.Heli.Add("hard", new HeliSettings()
				{
					DifficultName = "<color=red>Сложная</color>",
					Speed = 45f,
					Health = new HeliSettings.HealthSettings()
					{
						HPBase = 20000f,
						HPFront = 3000f,
						HPRear = 1500f
					},
					Damage = new HeliSettings.DamageSettings()
					{
						Multiplier = 1.3f,
						ArmorMultiplier = 0.8f,
						Turrets = new HeliSettings.DamageSettings.TurretConfig()
						{
							BulletDamage = 11f,
							BulletSpeed = 350,
							FireSpeed = 0.07f,
							FireLenght = 2f,
							FireBetween = 4f,
							MaxDistance = 100f
						},
						Rockets = new HeliSettings.DamageSettings.RocketConfig()
						{
							MaxHeliRockets = 12,
							TimeBetweenRockets = 0.4f,
							BulletDamage = 175f,
							ExplosionDamage = 100f,
							ExplosionRadius = 6f
						}
					},
					Loot = new HeliSettings.LootSettings()
					{
						MaxLootCrates = 5,
						MemorizeTeamOnCall = true,
						RemoveFireFromCrates = true,
						DenyCratesLooting = true,
						DenyGibsMining = true,
						ProfileName = "hard"
					},
					ItemAction = new HeliSettings.HeliItem()
					{
						action = "unwrap",
						shortname = "xmas.present.large",
						skin = 2306497849,
						name = "Вызов сложной вертушки"
					}
				});
				return newConfig;
			}

			public class HeliSettings
			{
				[JsonProperty("Наименование сложности", Order = 0)]
				public string DifficultName = "";
				[JsonProperty("Скорость полета", Order = 1)]
				public float Speed = 42f;
				
				[JsonProperty("Настройки прочности", Order = 2)]
				public HealthSettings Health = new HealthSettings();
				[JsonProperty("Настройки урона", Order = 3)]
				public DamageSettings Damage = new DamageSettings();
				[JsonProperty("Настройки лута", Order = 4)]
				public LootSettings Loot = new LootSettings();
				[JsonProperty("Настройки предмета для вызова вертушки", Order = 5)]
				public HeliItem ItemAction = new HeliItem();

				public class HeliItem
				{
					[JsonProperty("Вид события (unwrap|consume)", Order = 0)]
					public string action = "unwrap";
					[JsonProperty("Shortname предмета для вызова вертушки", Order = 1)]
					public string shortname = "xmas.present.large";
					[JsonProperty("Скин для предмета вызова вертушки", Order = 2)]
					public ulong skin = 2306487582;
					[JsonProperty("Наименование предмета", Order = 3)]
					public string name = "Вызов вертушки";
				}
				public class HealthSettings
				{
					[JsonProperty("Количество ХП корпуса", Order = 0)]
					public float HPBase = 10000f;
					[JsonProperty("Количество ХП переднего винта", Order = 1)]
					public float HPFront = 900f;
					[JsonProperty("Количество ХП заднего винта", Order = 2)]
					public float HPRear = 500f;
				}

				public class LootSettings
				{
					[JsonProperty("Количество ящиков с дропом", Order = 0)]
					public int MaxLootCrates = 4;
					[JsonProperty("Позволить вертолету запоминать кто его атаковал для последующего доступа к луту", Order = 1)]
					public bool MemorizeTeamOnCall = false;
					[JsonProperty("Убрать огонь с ящиков после падения вертолета", Order = 2)]
					public bool RemoveFireFromCrates = true;
					[JsonProperty("Ограничить доступ к луту тем кто не участвовал в сражении", Order = 3)]
					public bool DenyCratesLooting = true;
					[JsonProperty("Ограничить доступ к лутанию частей вертолета тем кто не участвовал в сражении", Order = 4)]
					public bool DenyGibsMining = true;
					[JsonProperty("Название файла профиля лута (в папке /Data/PersonalHeli/", Order = 5)]
					public string ProfileName = "default";

				}
				public class DamageSettings
				{
					[JsonProperty("Глобальный модификатор урона от вертолета", Order = 0)]
					public float Multiplier = 1f;
					[JsonProperty("Глобальный модификатор урона по вертолету", Order = 1)]
					public float ArmorMultiplier = 1f;
					[JsonProperty("Настройки пулемета", Order = 2)]
					public TurretConfig Turrets = new TurretConfig();
					[JsonProperty("Настройки ракетного залпа", Order = 3)]
					public RocketConfig Rockets = new RocketConfig();

					public class RocketConfig
					{
						[JsonProperty("Максимальное количество выпускаемых ракет", Order = 0)]
						public int MaxHeliRockets = 12;
						[JsonProperty("Интервал времени между запуском ракет", Order = 1)]
						public float TimeBetweenRockets = 0.2f;
						[JsonProperty("Урон при попадании ракеты", Order = 2)]
						public float BulletDamage = 175f;
						[JsonProperty("Урон от взрыва", Order = 3)]
						public float ExplosionDamage = 100f;
						[JsonProperty("Радиус распространения огня", Order = 4)]
						public float ExplosionRadius = 6f;
					}
					public class TurretConfig
					{
						[JsonProperty("Урон от пуль с пулемета", Order = 0)]
						public float BulletDamage = 11f;
						[JsonProperty("Скорость пули", Order = 1)]
						public int BulletSpeed = 350;
						[JsonProperty("Скорострельность пулемета", Order = 2)]
						public float FireSpeed = 0.1f;
						[JsonProperty("Длина пулеметной очереди", Order = 3)]
						public float FireLenght = 3f;
						[JsonProperty("Интервал между очередями", Order = 4)]
						public float FireBetween = 4f;
						[JsonProperty("Максимальная дистанция атаки", Order = 5)]
						public float MaxDistance = 150f;
					}
				}
			}

			public class MainSettings
			{
				[JsonProperty("Чат команда вызова вертолета на себя", Order = 0)]
				public string ChatCommand = "callheli";
				[JsonProperty("Чат команда отказа от запущенного вертолета", Order = 1)]
				public string ChatLeaveCommand = "helistop";
				[JsonProperty("Время ожидания до повторного вызова вертолета в секундах", Order = 2)]
				public Dictionary<string, int> Cooldowns = new Dictionary<string, int>();
				[JsonProperty("Максимальное количество активных вертолетов", Order = 3)]
				public int MaxHeliCount = 1;
				[JsonProperty("Максимальное время полета вертолетов в минутах (дефолт - 15)", Order = 4)]
				public int LifeTimeMinutes = 15;
				[JsonProperty("Точность вертолетов", Order = 5)]
				public float BulletAccuracy = 2f;
				[JsonProperty("Сбрасывать ожидания вызовов всех игроков при вайпе", Order = 6)]
				public bool ResetCooldownsOnWipe = true;
				[JsonProperty("В случае сметри всех атакующих вертолет улетает (иначе будет атаковать после возраждения)", Order = 7)]
				public bool RetireOnAllTeamDead = true;
			}

			public class TargetSettings
			{
				[JsonProperty("Позволять друзьям атаковать вертолет (использовать систему друзей)", Order = 0)]
				public bool UseFriends = true;
				[JsonProperty("Позволять тимейтам атаковать вертолет", Order = 1)]
				public bool UseTeams = true;
				[JsonProperty("Позволять соклановцам атаковать вертолет (использовать систему кланов)", Order = 2)]
				public bool UseClans = true;
			}
		}

		private PluginConfig config;

		public PluginConfig.HeliSettings GetHeliSettings(string difficult = "default")
		{
			if (string.IsNullOrEmpty(difficult)) return null;
			if (!config.Heli.ContainsKey(difficult)) return null;
			return config.Heli[difficult];
		}

		protected override void LoadConfig()
		{
			base.LoadConfig();
			try
			{
				config = Config.ReadObject<PluginConfig>();
				if ((config?.MainBlock == null) || (config?.TargetBlock == null) || (config?.Heli == null)) LoadDefaultConfig();
			}
			catch
			{
				LoadDefaultConfig();
			}
			NextTick(SaveConfig);
		}

		protected override void LoadDefaultConfig() => config = PluginConfig.GetNewConfig();
		protected override void SaveConfig() => Config.WriteObject(config);
		#endregion

		#region STORED DATA

		public Dictionary<string, LootProfile> LootProfiles = new Dictionary<string, LootProfile>();

		private LootProfile LoadProfileData(string ProfileName = "default")
		{
			LootProfile LP;// = new LootProfile(){};
			try
			{
				LP = Interface.Oxide.DataFileSystem.ReadObject<LootProfile>($"PersonalHeli/{ProfileName}");
				if (LP == null)
				{
					PrintWarning($"Loot profile `{ProfileName}` was created in oxide/data/personalheli/ with default parameters.Please check it!");
					LP = LP.GetDefaultLoot();
					Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject($"PersonalHeli/{ProfileName}", LP);
				}
				else if (LP.Loots == null || LP.Loots.Count == 0)
				{
					PrintWarning($"Loot profile `{ProfileName}` was created in oxide/data/personalheli/ with default parameters.Please check it!");
					LP = LP.GetDefaultLoot();
					Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject($"PersonalHeli/{ProfileName}", LP);
				}
				return LP;
			}
			catch
			{
				PrintError($"File oxide/data/personalheli/{ProfileName} is missing or contains errors");
				return null;
			}
			return null;
		}

		public class LootProfile
		{
			[JsonProperty("Минимум предметов в контейнере", Order = 5)]
			public int MinAmount;
			[JsonProperty("Максимум предметов в контейнере", Order = 6)]
			public int MaxAmount;
			[JsonProperty("Список лута для контейнера", Order = 7)]
			public List<LootPack> Loots = new List<LootPack>();

			public class LootPack
			{
				[JsonProperty("Название лута", Order = 0)]
				public string LootName;
				[JsonProperty("Минимальное количество", Order = 1)]
				public int MinAmount;
				[JsonProperty("Максимальное количество", Order = 2)]
				public int MaxAmount;
				[JsonProperty("Скин предмета (если не нужно то 0", Order = 3)]
				public ulong SkinID = 0;
				[JsonProperty("Уникальное имя (если не нужно то null", Order = 4)]
				public string AddName = null;
			}
			public LootProfile GetDefaultLoot()
			{
				return new LootProfile
				{
					MinAmount = 2,
					MaxAmount = 4,
					Loots = new List<LootProfile.LootPack>()
					{
						new LootProfile.LootPack() { LootName = "ammo.rifle", MinAmount = 64, MaxAmount = 128, SkinID=0,AddName=null},
						new LootProfile.LootPack() { LootName = "ammo.rifle.explosive", MinAmount = 16, MaxAmount = 64, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.rifle.incendiary", MinAmount = 64, MaxAmount = 128, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.rifle.hv", MinAmount = 64, MaxAmount = 128, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "weapon.mod.holosight", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "weapon.mod.silencer", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "weapon.mod.lasersight", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "weapon.mod.small.scope", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "weapon.mod.8x.scope", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "weapon.mod.flashlight", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "lmg.m249", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "explosive.timed", MinAmount = 1, MaxAmount = 2, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.rocket.basic", MinAmount = 1, MaxAmount = 3, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "targeting.computer", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.rocket.fire", MinAmount = 1, MaxAmount = 5, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.rocket.hv", MinAmount = 1, MaxAmount = 3, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.pistol", MinAmount = 128, MaxAmount = 256, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.pistol.hv", MinAmount = 64, MaxAmount = 128, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "ammo.pistol.fire", MinAmount = 64, MaxAmount = 128, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "wall.window.bars.toptier", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "shotgun.spas12", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "rifle.m39", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "rifle.lr300", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "door.hinged.toptier", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "floor.ladder.hatch", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "techparts", MinAmount = 5, MaxAmount = 12, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "door.double.hinged.toptier", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "rifle.l96", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "pistol.m92", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "smg.mp5", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "rifle.ak", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "explosives", MinAmount = 1, MaxAmount = 2, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "cctv.camera", MinAmount = 1, MaxAmount = 2, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "smg.2", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
						new LootProfile.LootPack() { LootName = "wall.frame.garagedoor", MinAmount = 1, MaxAmount = 1, SkinID=0,AddName=null },
					}
				};
			}
		}
		public class StoredData
		{
			public Dictionary<ulong, CallData> CallDatas = new Dictionary<ulong, CallData>();

			public class CallData
			{
				public DateTime LastCall = DateTime.MinValue;
				public bool CanCallNow(int cooldown)
				{
					return DateTime.Now.Subtract(LastCall).TotalSeconds > cooldown;
				}

				public int SecondsToWait(int cooldown)
				{
					return (int)Math.Round(cooldown - DateTime.Now.Subtract(LastCall).TotalSeconds);
				}

				public void OnCall()
				{
					LastCall = DateTime.Now;
				}
			}

			public CallData GetForPlayer(BasePlayer player)
			{
				if (!CallDatas.ContainsKey(player.userID))
				{
					CallDatas[player.userID] = new CallData();
				}

				return CallDatas[player.userID];
			}
		}
		private void SaveData()
		{
			if (storedData != null)
			{
				Interface.Oxide.DataFileSystem.WriteObject($"PersonalHeli/{Name}", storedData, true);
			}
		}
		private void LoadData()
		{
			storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>($"PersonalHeli/{Name}");
			if (storedData == null)
			{
				storedData = new StoredData();
				SaveData();
			}
		}
		private StoredData storedData;
		#endregion
		#region L10N
		protected override void LoadDefaultMessages()
		{
			lang.RegisterMessages(new Dictionary<string, string>
			{
				["NoPermission"] = "You have no permission to use this command",
				["Cooldown"] = "Helicopter call is on cooldown, time remaining: {0}",
				["LootDenied"] = "You are forbidden to loot this crate, it belongs to: {0}",
				["DamageDenied"] = "You are forbidden to damage this helicopter, it was called by: {0}",
				["MiningDenied"] = "You are forbidden to mine this debris, it belongs to: {0}",
				["Friends"] = "their friends",
				["Team"] = "their team",
				["Clan"] = "their clan",
				["CmdUsage"] = "Invalid format, usage: personalheli.call {{steamId}}",
				["InvalidSteamId"] = "{0} is invalid Steam ID",
				["PlayerNotFound"] = "Player with id {0} was not found",
				["PlayerCalled"] = "Personal helicopter is called for {0}\nDifficult is {1}",
				["PlayerCanceled"] = "Personal helicopter is stoped for {0}.Difficult is: {1}",
				["HeliNotFound"] = "No personal helicopter found.Perhaps you didn't call it",
				["LimitHeli"] = "You can't call a helicopter.Reached the maximum limit",
				["KillHeli"] = "Player {0} kill Helicopter with difficult {1}"
			}, this);

			lang.RegisterMessages(new Dictionary<string, string>
			{
				["NoPermission"] = "У Вас нет прав на использование этой команды",
				["Cooldown"] = "Вызов вертолета в кулдауне, ждать осталось: {0}",
				["HeliSuccess"] = "Вертолет был вызван",
				["LootDenied"] = "Вам запрещено лутать этот ящик, его могут лутать: {0}",
				["DamageDenied"] = "Вам запрещено наносить урон этому вертолету, его вызвал: {0}",
				["MiningDenied"] = "Вам запрещено добывать эти обломки, их могут добывать: {0}",
				["Friends"] = "его друзья",
				["Team"] = "его команда",
				["Clan"] = "его клан",
				["CmdUsage"] = "Неправильный формат, использование: personalheli.call {{steamId}}",
				["InvalidSteamId"] = "{0} не является Steam ID",
				["PlayerNotFound"] = "Игрок с ID {0} не найден",
				["PlayerCalled"] = "Вертолет был вызван для {0}\nСложность: {1}",
				["PlayerCanceled"] = "Вертолет был отозван игроком {0}.В ближайшее время вертолет улетит.\nСложность: {1}",
				["HeliNotFound"] = "Не найдено персонального вертолета.Возможно вы его не вызывали",
				["LimitHeli"] = "Вы не можете вызвать вертолет.Достигнут лимит.Попробуйте позднее.",
				["KillHeli"] = "Игрок {0} уничтожил вертолет\nСложность: {1}"
			}, this, "ru");
		}
		private string GetMsg(string key, string userId, params object[] args)
		{
			return string.Format(lang.GetMessage(key, this, userId), args);
		}
		#endregion
		#region HOOKS
		private void Init()
		{
			permission.RegisterPermission(permUse, this);
			permission.RegisterPermission(permConsole, this);
			foreach (string perms in config.MainBlock.Cooldowns.Keys)
			{
				permission.RegisterPermission(perms, this);
			}
			cmd.AddChatCommand(config.MainBlock.ChatCommand, this, CmdCallHeli);
			cmd.AddChatCommand(config.MainBlock.ChatLeaveCommand, this, CmdLeaveMeAlone);
			LoadData();
		}

		public int GetCooldown(string playerId)
		{
			int def = 2700;
			foreach (KeyValuePair<string, int> perms in config.MainBlock.Cooldowns)
			{
				if (permission.UserHasPermission(playerId, perms.Key)) return perms.Value;
			}
			return def;
		}

		private void OnServerInitialized()
		{
			ConVar.PatrolHelicopter.bulletAccuracy = config.MainBlock.BulletAccuracy;
			ConVar.PatrolHelicopter.lifetimeMinutes = config.MainBlock.LifeTimeMinutes;

			//ДОБАВЛЯЕМ ПАРАМЕТРЫ ЛУТА
			foreach (PluginConfig.HeliSettings HeliSets in config.Heli.Values)
			{
				if (!string.IsNullOrEmpty(HeliSets.Loot.ProfileName))
				{
					LootProfile profile = LoadProfileData(HeliSets.Loot.ProfileName);
					if (profile == null)
					{
						PrintError("Missing loot profile");
						return;
					}
					LootProfiles.Add(HeliSets.Loot.ProfileName, profile);
				}
			}
			init = true;
		}

		private void Unload()
		{
			foreach (var personal in UnityEngine.Object.FindObjectsOfType<PersonalComponent>())
			{
				UnityEngine.Object.Destroy(personal);
			}
			SaveData();
		}
		private void OnNewSave()
		{
			if (config.MainBlock.ResetCooldownsOnWipe)
			{
				storedData = new StoredData();
				SaveData();
			}
		}

		private void OnServerSave()
		{
			SaveData();
		}


		private void OnEntityKill(BaseEntity entity)
		{
			if (entity == null || entity.gameObject == null) return;
			if (!(entity is BaseHelicopter)) return;
			InvokePersonal<PersonalHeliComponent>(entity.gameObject, personalHeli => personalHeli.OnKill());
		}

		private object CanLootEntity(BasePlayer player, StorageContainer container)
		{
			return InvokePersonal<PersonalCrateComponent, object>(container?.gameObject, personalCrate => {
				var result = personalCrate.CanInterractWith(player);
				if (result == false)
				{
					SendReply(player, GetMsg("LootDenied", player.UserIDString, GetPlayerOwnerDescription(player, personalCrate.Player)));
					return false;
				}
				return null;
			});
		}

		public void BroadcastMessage(string Message)
		{
			foreach (var p in BasePlayer.activePlayerList)
			{
				SendReply(p, Message);
			}
			return;
		}

		private void OnEntitySpawned(BaseNetworkable entity)
		{
			if (!init || entity == null || entity.IsDestroyed || entity.gameObject == null) return;
			var prefabname = entity?.ShortPrefabName ?? string.Empty;
			var longprefabname = entity?.PrefabName ?? string.Empty;
			if (string.IsNullOrEmpty(prefabname) || string.IsNullOrEmpty(longprefabname)) return;
			if (prefabname.Contains("rocket_heli"))
			{
				TimedExplosive explosion = entity as TimedExplosive;
				PluginConfig.HeliSettings HeliSet = GetHeliSettings("default");
				//Не смог определить каким вертолетом выпущены ракеты
				if (explosion == null || explosion.IsDestroyed || explosion.gameObject == null) return; //super ultra extra safe null checking
				if (HeliSet.Damage.Rockets.MaxHeliRockets < 1) explosion.Kill();
				else
				{
					explosion.explosionRadius = HeliSet.Damage.Rockets.ExplosionRadius;


					var dmgTypes = explosion?.damageTypes ?? null;

					if (dmgTypes != null && dmgTypes.Count > 0)
					{
						for (int i = 0; i < dmgTypes.Count; i++)
						{
							var dmg = dmgTypes[i];
							if (dmg == null) continue;
							if (dmg.type == Rust.DamageType.Blunt) dmg.amount = HeliSet.Damage.Rockets.BulletDamage;
							if (dmg.type == Rust.DamageType.Explosion) dmg.amount = HeliSet.Damage.Rockets.ExplosionDamage;
						}
					}
				}
			}
		}

		private object OnHelicopterTarget(HelicopterTurret turret, BaseCombatEntity entity)
		{
			if (turret == null || entity == null) return null;
			return InvokePersonal<PersonalHeliComponent, object>(turret?._heliAI?.helicopterBase?.gameObject, personalHeli => {
				var result = personalHeli.CanInterractWith(entity);
				return result ? null : (object)false;
			});
		}

		private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
		{
			if (info == null || entity == null) return;

			if (entity is BaseHelicopter)
			{
				PersonalHeliComponent Heli = (entity as BaseHelicopter)?.GetComponent<PersonalHeliComponent>() ?? null;
				if (Heli == null) return;
				BroadcastMessage(GetMsg("KillHeli", Heli.Player.UserIDString, $"<color=#63ff64>{Heli.Player.displayName}</color>", Heli.HeliSets.DifficultName));
				InvokePersonal<PersonalHeliComponent>(entity.gameObject, personalHeli => personalHeli.OnDeath());

			}
			if (!config.MainBlock.RetireOnAllTeamDead)
			{
				return;
			}
			if (!(entity is BasePlayer))
			{
				return;
			}
			NextTick(() => {
				foreach (var heli in PersonalHeliComponent.ActiveHelis)
				{
					heli.OnPlayerDied(entity as BasePlayer);
				}
			});
		}
		object OnItemAction(Item item, string action, BasePlayer player)
		{
			if (item == null) return null;
			foreach (KeyValuePair<string, PluginConfig.HeliSettings> h in config.Heli)
			{
				PluginConfig.HeliSettings heli = h.Value;
				if (heli == null || heli.ItemAction == null) continue;
				if (action != heli.ItemAction.action || item.skin != heli.ItemAction.skin) continue;
				if (CallHeliForPlayer(player, h.Key, true, true))
				{
					item.UseItem(1);
				}
				else return false;
			}
			return null;
		}


		//Множитель урона вертолета
		private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
		{
			if (entity == null || info?.HitEntity == null) return;
			if (info.Initiator is BaseHelicopter && entity is BasePlayer)
			{
				BaseHelicopter Heli = info.Initiator as BaseHelicopter;
				if (Heli == null) return;
				//Пытаемся понять что за верт нас дамажет
				PersonalComponent HeliC = Heli?.GetComponent<PersonalComponent>() ?? null;
				if (HeliC == null) return;
				if (entity is NPCPlayer) return;
				float multiplier = HeliC.HeliSets.Damage.Multiplier;
				if (multiplier != 1f && multiplier >= 0)
				{
					info?.damageTypes?.ScaleAll(multiplier);
					return;
				}
			}
			if (info.Initiator is BasePlayer && entity is BaseHelicopter)
			{
				BaseHelicopter Heli = entity as BaseHelicopter;
				if (Heli == null) return;
				//Пытаемся понять по какому верту мы дамажем
				PersonalComponent HeliC = Heli?.GetComponent<PersonalComponent>() ?? null;
				if (HeliC == null) return;
				if (info.Initiator is NPCPlayer) return;
				
				float Armormultiplier = HeliC.HeliSets.Damage.ArmorMultiplier;
				if (Armormultiplier != 1f && Armormultiplier >= 0)
				{
					info?.damageTypes?.ScaleAll(Armormultiplier);
				}//Фиксируем ХП у вертолета  для защиты от регена
				if (Heli.health > HeliC.LastHealth) 
				{
					PrintWarning($"Regeniration is stoped! {Heli.health} > {HeliC.LastHealth}");
					Heli.Hurt(100000f);
					Heli.AdminKill();
					return;
					//Heli.SendNetworkUpdate();
					//Heli.SendNetworkUpdateImmediate(false);
				}
				HeliC.LastHealth = Heli.health;
			}
		}

		private object OnPlayerAttack(BasePlayer attacker, HitInfo info)
		{
			if (attacker == null || info?.HitEntity == null) return null;
			//При ударении по частям вертолета
			if (info.HitEntity is ServerGib && info.WeaponPrefab is BaseMelee)
			{
				return InvokePersonal<PersonalGibComponent, object>(info?.HitEntity?.gameObject, personalGib => {
					var result = personalGib.CanInterractWith(attacker);
					if (result == false)
					{
						SendReply(info.InitiatorPlayer, GetMsg("MiningDenied", info.InitiatorPlayer.UserIDString, GetPlayerOwnerDescription(info.InitiatorPlayer, personalGib.Player)));
						return false;
					}
					return null;
				});
			}

			return InvokePersonal<PersonalHeliComponent, object>(info?.HitEntity?.gameObject, personalHeli => {
				var result = personalHeli.CanInterractWith(attacker);
				if (result == false)
				{
					SendReply(info.InitiatorPlayer, GetMsg("DamageDenied", info.InitiatorPlayer.UserIDString, GetPlayerOwnerDescription(info.InitiatorPlayer, personalHeli.Player)));
					return false;
				}
				return null;
			});
		}

		private static bool IsHeliBox(LootContainer container)
		{
			if (container == null)
				return false;

			if (container.ShortPrefabName == "heli_crate")
				return true;

			return false;
		}

		private object CanHelicopterStrafeTarget(PatrolHelicopterAI heliAi, BasePlayer target)
		{
			if (heliAi == null) return null;
			if ((heliAi?._currentState ?? PatrolHelicopterAI.aiState.DEATH) == PatrolHelicopterAI.aiState.DEATH) return false;
			return InvokePersonal<PersonalHeliComponent, object>(heliAi?.helicopterBase?.gameObject, personalHeli => {
				return personalHeli.CanInterractWith(target) ? null : (object)false;
			});
		}

		private object CanHelicopterStrafe(PatrolHelicopterAI heliAi)
		{
			if (heliAi == null) return null;
			if ((heliAi?._currentState ?? PatrolHelicopterAI.aiState.DEATH) == PatrolHelicopterAI.aiState.DEATH) return false;
			return null;
		}

		private object CanHelicopterTarget(PatrolHelicopterAI heliAi, BasePlayer player)
		{
			if (heliAi == null) return null;
			if ((heliAi?._currentState ?? PatrolHelicopterAI.aiState.DEATH) == PatrolHelicopterAI.aiState.DEATH) return false;
			return InvokePersonal<PersonalHeliComponent, object>(heliAi?.helicopterBase?.gameObject, personalHeli => {
				return personalHeli.CanInterractWith(player) ? null : (object)false;
			});
		}

		#endregion

		private void UpdateHeli(BaseHelicopter heli, bool justCreated = false)
		{
			if (heli == null || heli.IsDestroyed || heli.IsDead()) return;
			PersonalComponent HeliC = heli?.GetComponent<PersonalComponent>() ?? null;
			if (HeliC == null) return;
			heli._maxHealth = HeliC.HeliSets.Health.HPBase;
			heli.startHealth = HeliC.HeliSets.Health.HPBase;
			heli.SetMaxHealth(heli.startHealth);
			if (justCreated) heli.InitializeHealth(HeliC.HeliSets.Health.HPBase, HeliC.HeliSets.Health.HPBase);
			heli.maxCratesToSpawn = HeliC.HeliSets.Loot.MaxLootCrates;
			heli.bulletDamage = HeliC.HeliSets.Damage.Turrets.BulletDamage;
			heli.bulletSpeed = HeliC.HeliSets.Damage.Turrets.BulletSpeed;
			var weakspots = heli.weakspots;
			
			if (weakspots != null && weakspots.Length > 1)
			{
				if (justCreated)
				{
					weakspots[0].health = HeliC.HeliSets.Health.HPFront;
					weakspots[1].health = HeliC.HeliSets.Health.HPRear;
				}
				weakspots[0].maxHealth = HeliC.HeliSets.Health.HPFront;
				weakspots[1].maxHealth = HeliC.HeliSets.Health.HPRear;
			}
			var heliAI = heli?.GetComponent<PatrolHelicopterAI>() ?? null;
			if (heliAI == null) return;
			heliAI.maxSpeed = Mathf.Clamp(HeliC.HeliSets.Speed, 0.1f, 125);
			heliAI.timeBetweenRockets = Mathf.Clamp(HeliC.HeliSets.Damage.Rockets.TimeBetweenRockets, 0.1f, 1f);
			heliAI.numRocketsLeft = Mathf.Clamp(HeliC.HeliSets.Damage.Rockets.MaxHeliRockets, 0, 48);
			UpdateTurrets(heliAI);
			heli.SendNetworkUpdateImmediate(justCreated);
		}

		private void UpdateTurrets(PatrolHelicopterAI helicopter)
		{
			if (helicopter == null || helicopter.leftGun == null || helicopter.rightGun == null) return;
			PersonalComponent HeliC = helicopter?.GetComponent<PersonalComponent>() ?? null;
			if (HeliC == null) return;
			helicopter.leftGun.fireRate = (helicopter.rightGun.fireRate = HeliC.HeliSets.Damage.Turrets.FireSpeed);
			helicopter.leftGun.timeBetweenBursts = (helicopter.rightGun.timeBetweenBursts = HeliC.HeliSets.Damage.Turrets.FireBetween);
			helicopter.leftGun.burstLength = (helicopter.rightGun.burstLength = HeliC.HeliSets.Damage.Turrets.FireLenght);
			helicopter.leftGun.maxTargetRange = (helicopter.rightGun.maxTargetRange = HeliC.HeliSets.Damage.Turrets.MaxDistance);
		}

		private bool CallHeliForPlayer(BasePlayer player, string difficult = "default", bool check = false, bool admin = false)
		{
			if (check)
			{

				if (!admin && !permission.UserHasPermission(player.UserIDString, permUse))
				{
					SendReply(player, GetMsg("NoPermission", player.UserIDString));
					return false;
				}
				if (!CheckHeli())
				{
					SendReply(player, GetMsg("LimitHeli", player.UserIDString));
					return false;
				}
				StoredData.CallData callData = storedData.GetForPlayer(player);
				if (!callData.CanCallNow(GetCooldown(player.UserIDString)))
				{
					SendReply(player, GetMsg("Cooldown", player.UserIDString, TimeSpan.FromSeconds(callData.SecondsToWait(GetCooldown(player.UserIDString)))));
					return false;
				}
			}
			var playerPos = player.transform.position;
			float mapWidth = (TerrainMeta.Size.x / 2) - 50f;
			var heliPos = new Vector3(
				playerPos.x < 0 ? -mapWidth : mapWidth,
				30,
				playerPos.z < 0 ? -mapWidth : mapWidth
			);

			if (!config.Heli.ContainsKey(difficult))
			{
				player.ChatMessage("Неверно указана сложность вертолета");
				return false;
			}
			BaseHelicopter heli = GameManager.server.CreateEntity("assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab", new Vector3(), new Quaternion(), true) as BaseHelicopter;
			if (!heli) return false;
			PatrolHelicopterAI heliAI = heli?.GetComponent<PatrolHelicopterAI>() ?? null;
			if (heliAI == null) return false;
			heli.Spawn();
			heli.transform.position = heliPos;
			heli.SendNetworkUpdate();
			var component = heli.gameObject.AddComponent<PersonalHeliComponent>();
			component.Init(this, heli, player, config.Heli[difficult]);
			UpdateHeli(heli, true);
			foreach (var p in BasePlayer.activePlayerList)
			{
				SendReply(p, GetMsg("PlayerCalled", p.UserIDString, $"<color=#63ff64>{player.displayName}</color>", config.Heli[difficult].DifficultName));
			}
			return true;
		}
		#region API
		private bool IsPersonal(BaseHelicopter heli) => InvokePersonal<PersonalHeliComponent, object>(heli?.gameObject, (comp) => true) == null ? false : true;

		#endregion
		private bool CheckHeli()
		{
			int count = BaseNetworkable.serverEntities.Count(x =>
			{
				var entity = x as BaseHelicopter;
				if (entity != null)
				{
					return true;
				}
				return false;
			}
			);
			if (count >= config.MainBlock.MaxHeliCount) return false;
			return true;
		}

		[ConsoleCommand("personalheli.call")]
		private void CmdCallHeliConsole(ConsoleSystem.Arg arg)
		{
			if (arg.Player() != null)
			{
				if (!permission.UserHasPermission(arg.Player().UserIDString, permConsole))
				{
					PrintToConsole(arg.Player(), GetMsg("NoPermission", arg.Player().UserIDString));
					return;
				}
			}
			Action<string> printToConsole;
			if (arg.Player() == null)
			{
				printToConsole = (str) => Puts(str);
			}
			else
			{
				printToConsole = (str) => PrintToConsole(arg.Player(), str);
			}

			string UserId = arg.Player() == null ? "" : arg.Player().UserIDString;
			if (!arg.HasArgs())
			{
				printToConsole(GetMsg("CmdUsage", UserId));
				return;
			}

			if (!arg.Args[0].IsSteamId())
			{
				printToConsole(GetMsg("InvalidSteamId", UserId, arg.Args[0]));
				return;
			}

			var player = BasePlayer.FindByID(ulong.Parse(arg.Args[0]));
			if (player == null)
			{
				player = BasePlayer.FindSleeping(ulong.Parse(arg.Args[0]));
			}

			if (player == null)
			{
				printToConsole(GetMsg("PlayerNotFound", UserId, arg.Args[0]));
				return;
			}
			string difficult = "default";
			if (arg.Args.Length > 1) difficult = arg.Args[1];
			if (CallHeliForPlayer(player, difficult, false, true))
			{
				printToConsole(GetMsg("PlayerCalled", UserId, player.displayName, difficult));
			}
		}


		[ConsoleCommand("giveCall")]
		void GiveHeliConsoleCommand(ConsoleSystem.Arg arg)
		{
			if (arg.Player() != null)
			{
				if (!(arg.Player().IsAdmin) && !permission.UserHasPermission(arg.Player().UserIDString, permConsole))
				{
					PrintToConsole(arg.Player(), GetMsg("NoPermission", arg.Player().UserIDString));
					return;
				}
			}
			if (arg == null || arg.Args?.Length < 2)
			{
				return;
			}
			BasePlayer player = BasePlayer.Find(arg.Args[0]);
			if (player == null)
			{
				PrintError($"[Error] Player {arg.Args[0]} not found");
				return;
			}
			string difficult = arg.Args[1];
			if (!config.Heli.ContainsKey(difficult))
			{
				PrintError("Difficult not found");
				return;
			}
			int count = 1;
			if (arg.Args?.Length > 2) if (!int.TryParse(arg.Args[2], out count)) count = 1;
			PluginConfig.HeliSettings.HeliItem act = config.Heli[difficult].ItemAction;
			if (act == null)
			{
				PrintError("ItemAction for this Difficult not found");
				return;
			}
			Item item = ItemManager.CreateByName(act.shortname, count, act.skin);
			item.name = act.name;
			GiveItem(item, player);
		}

		private static void GiveItem(Item item, Vector3 position)
		{
			if (item == null) return;
			item.Drop(position, Vector3.down);
		}

		private void GiveItem(Item item, BasePlayer player)
		{
			if (item == null) return;
			player.GiveItem(item);
			Puts($"Item was gave successfully to {player.displayName}");
		}
		
		private void CmdCallHeli(BasePlayer player, string cmd, string[] argv)
		{
			if (!permission.UserHasPermission(player.UserIDString, permUse))
			{
				SendReply(player, GetMsg("NoPermission", player.UserIDString));
				return;
			}
			if (!CheckHeli())
			{
				SendReply(player, GetMsg("LimitHeli", player.UserIDString));
				return;
			}
			StoredData.CallData callData = storedData.GetForPlayer(player);
			if (!callData.CanCallNow(GetCooldown(player.UserIDString)))
			{
				SendReply(player, GetMsg("Cooldown", player.UserIDString, TimeSpan.FromSeconds(callData.SecondsToWait(GetCooldown(player.UserIDString)))));
				return;
			}
			string difficult = "default";
			if (argv.Length > 0) difficult = argv[0];
			if (CallHeliForPlayer(player, difficult))
			{
				callData.OnCall();
			}
		}
		
		private void CmdLeaveMeAlone(BasePlayer player, string cmd, string[] argv)
		{
			if (!permission.UserHasPermission(player.UserIDString, permUse))
			{
				SendReply(player, GetMsg("NoPermission", player.UserIDString));
				return;
			}
			//Ищем вертолеты, который вы запустили
			foreach (PersonalHeliComponent personal in UnityEngine.Object.FindObjectsOfType<PersonalHeliComponent>())
			{
				if (player==personal.Player){		
					personal.LeaveMeAlone(); 
					return;
				}
			}
			SendReply(player, GetMsg("HeliNotFound", player.UserIDString));
		}
		private string GetPlayerOwnerDescription(BasePlayer player, BasePlayer playerOwner)
		{
			StringBuilder result = new StringBuilder($"<color=#63ff64>{playerOwner.displayName}</color>");
			if (config.TargetBlock.UseFriends && Friends != null)
			{
				result.Append($", {GetMsg("Friends", player.UserIDString)}");
			}
			if (config.TargetBlock.UseTeams)
			{
				result.Append($", {GetMsg("Team", player.UserIDString)}");
			}
			if (config.TargetBlock.UseClans)
			{
				result.Append($", {GetMsg("Clan", player.UserIDString)}");
			}
			return result.ToString();
		}

		private T InvokePersonal<C, T>(GameObject obj, Func<C, T> action) where C : PersonalComponent
		{
			var comp = obj?.GetComponent<C>();
			if (comp == null) return default(T);
			return action(comp);
		}
		private void InvokePersonal<C>(GameObject obj, Action<C> action) where C : PersonalComponent => InvokePersonal<C, object>(obj, comp => { action(comp); return null; });

		abstract class PersonalComponent : FacepunchBehaviour
		{
			protected PersonalHeli Plugin;
			protected string difficult;
			protected PluginConfig Config => Plugin.config;
			public PluginConfig.HeliSettings HeliSets;
			public List<BasePlayer> SavedTeam;
			public BasePlayer Player;
			public BaseHelicopter Heli;
			public float LastHealth  = 1000000f;

			public void Init(PersonalHeli plugin, BaseHelicopter heli, BasePlayer player, PluginConfig.HeliSettings HeliSet)
			{
				Player = player;
				Plugin = plugin;
				Heli = heli;
				HeliSets = HeliSet;
				OnInitChild();
			}

			protected virtual void OnInitChild() { }

			public virtual bool CanInterractWith(BaseEntity target)
			{
				if (HeliSets.Loot.MemorizeTeamOnCall && SavedTeam != null)
				{
					return SavedTeam.Contains(target as BasePlayer);
				}

				if (!(target is BasePlayer) || target is NPCPlayer)
				{
					return false;
				}

				if (target == Player)
				{
					return true;
				}

				if (Plugin.config.TargetBlock.UseFriends)
				{
					if (AreFriends(target as BasePlayer))
					{
						return true;
					}
				}

				if (Plugin.config.TargetBlock.UseTeams)
				{
					if (AreSameTeam(target as BasePlayer))
					{
						return true;
					}
				}

				if (Plugin.config.TargetBlock.UseClans)
				{
					if (AreSameClan(target as BasePlayer))
					{
						return true;
					}
				}

				return false;
			}

			protected bool AreSameClan(BasePlayer basePlayer)
			{
				if (Plugin.Clans == null)
				{
					return false;
				}
				var playerClan = Plugin.Clans.Call<string>("GetClanOf", Player);
				var otherPlayerClan = Plugin.Clans.Call<string>("GetClanOf", basePlayer);
				if (playerClan == null || otherPlayerClan == null)
				{
					return false;
				}

				return playerClan == otherPlayerClan;
			}

			protected bool AreSameTeam(BasePlayer otherPlayer)
			{
				if (Player.currentTeam == 0UL || otherPlayer.currentTeam == 0UL)
				{
					return false;
				}

				return Player.currentTeam == otherPlayer.currentTeam;
			}

			protected bool AreFriends(BasePlayer otherPlayer)
			{
				if (Plugin.Friends == null)
				{
					return false;
				}
				return Plugin.Friends.Call<bool>("AreFriends", Player.userID, otherPlayer.userID);
			}

			private void OnDestroy()
			{
				OnDestroyChild();
			}
			protected virtual void OnDestroyChild() { }
		}
		class PersonalCrateComponent : PersonalComponent
		{
			private LootContainer Crate;
			private void Awake()
			{
				Crate = GetComponent<LootContainer>();
				if (Crate == null)
				{
					return;
				}
			}

			public void FillLoot(PersonalHeli.LootProfile Loot)
			{

				Crate.inventory.Clear();
				ItemManager.DoRemoves();
				if (Loot == null) return;

				var amountLoots = Rnd.Next(Loot.MinAmount, Loot.MaxAmount + 1);

				for (int ii = 0; ii < amountLoots; ii++)
				{
					var itemCfg = Loot.Loots.OrderBy(x => Rnd.Next()).FirstOrDefault();
					var amount = Rnd.Next(itemCfg.MinAmount, itemCfg.MaxAmount + 1);
					if (amount <= 0) continue;

					var item = ItemManager.CreateByName(itemCfg.LootName, amount, itemCfg.SkinID);
					if (!string.IsNullOrEmpty(itemCfg.AddName)) item.name = itemCfg.AddName;
					if (item == null) continue;

					if (Crate.inventory.capacity < Crate.inventory.itemList.Count() + 1)
						Crate.inventory.capacity++;

					item.MoveToContainer(Crate.inventory, -1, true);
				}

				Crate.inventory.capacity = Crate.inventory.itemList.Count;
			}
			protected override void OnDestroyChild()
			{
				if (Crate != null && Crate.IsValid() && !Crate.IsDestroyed)
				{
					Crate.Kill();
				}
			}
		}
		class PersonalGibComponent : PersonalComponent
		{
			private HelicopterDebris Gib;
			private void Awake()
			{
				Gib = GetComponent<HelicopterDebris>();
			}
			protected override void OnDestroyChild()
			{
				if (Gib != null && Gib.IsValid() && !Gib.IsDestroyed)
				{
					Gib.Kill();
				}
			}
		}
		class PersonalHeliComponent : PersonalComponent
		{
			private const int MaxHeliDistanceToPlayer = 140;
			public bool isKilled = false;
			public static List<PersonalHeliComponent> ActiveHelis = new List<PersonalHeliComponent>();
			private BaseHelicopter Heli;
			private PatrolHelicopterAI HeliAi => Heli.GetComponent<PatrolHelicopterAI>();


			private void Awake()
			{
				Heli = this.GetComponent<BaseHelicopter>();
			}
			protected override void OnInitChild()
			{
				HeliAi.State_Move_Enter(Player.transform.position + new Vector3(UnityEngine.Random.Range(10f, 50f), 20f, UnityEngine.Random.Range(10f, 50f)));
				InvokeRepeating(new Action(UpdateTargets), 5.0f, 5.0f);
				if (HeliSets.Loot.MemorizeTeamOnCall)
				{
					SavedTeam = GetAllPlayersInTeam();
				}
				ActiveHelis.Add(this);
#if DEBUG
				InvokeRepeating(new Action(TraceState), 5.0f, 5.0f);
#endif
			}
#if DEBUG
			private void TraceState()
			{
				Plugin.Server.Broadcast($"helicopter: {Heli.transform.position}: {HeliAi._currentState.ToString()}");
				Plugin.Server.Broadcast(string.Join(", ", HeliAi._targetList.Select(tg => tg.ply.displayName)));
				Plugin.Server.Broadcast($"heli at destionation {Vector3.Distance(Heli.transform.position, HeliAi.destination)}");
			}
#endif
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Другие ресурсы пользователя 15FPS

Сверху