C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Plugin formatted by redBDGR's Plugin Formatting Tool
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins {
[Info("PilotEject", "redBDGR", "2.0.7")]
[Description("A special helicopter event")]
class PilotEject : RustPlugin {
[PluginReference]
Plugin GUIAnnouncements;
private bool useGUIAnnouncements;
private static PilotEject plugin;
private const string permissionName = "piloteject.admin";
private float arrowHeight = 200f;
private float arrowLength = 120f;
private float chanceOfOccuring = 0.20f;
private bool changed;
private bool inboundMessage = true;
private bool killMSG = true;
private float maxEventTime = 3600f;
private float maxTimeToEvent = 600.0f;
private float minEventTime = 1800f;
private float minimumSpawnHeight = 20f;
private bool minimumSpawnHeightEnabled;
private float minTimeToEvent = 300.0f;
private bool pilotArrow = true;
private float pilotLifeLength = 600f;
private int customCratesToDrop = 3;
private bool randomEventEnabled = true;
private int minHelicoptersBeforeNextEvent = 0;
private float pilotFallSpeed = 1;
private bool heliIsOnFire = true;
private Timer repeat;
private StoredData storedData;
private DynamicConfigFile InventoryData;
private float time;
private bool timedEventEnabled = true;
private bool truePVEPilotDamageable;
private int heliCount = 0;
private Dictionary<string, PilotInfo> pilotData = new Dictionary<string, PilotInfo>();
private List<BaseHelicopter> helis = new List<BaseHelicopter>();
private List<EjectedPlayer> pilots = new List<EjectedPlayer>();
private class StoredData {
public Dictionary<string, PilotInfo> pilotData = new Dictionary<string, PilotInfo>();
}
private class PilotInfo {
public string displayName;
public List<ItemInfo> beltItems;
public List<ItemInfo> clothingItems;
public List<ItemInfo> inventoryItems;
public float chance;
public float health;
public bool dropItems;
public bool wounded;
}
private class ItemInfo {
public int amount;
public float chance;
public string shortname;
public ulong skinId;
}
private void SaveData() {
storedData.pilotData = pilotData;
InventoryData.WriteObject(storedData);
}
private void LoadData() {
try {
storedData = InventoryData.ReadObject<StoredData>();
pilotData = storedData.pilotData;
}
catch {
Puts("Failed to load data, creating new file");
storedData = new StoredData();
}
}
private void LoadVariables() {
minTimeToEvent = Convert.ToSingle(GetConfig("Settings", "Min Time Until Pilot Eject", 300.0f));
maxTimeToEvent = Convert.ToSingle(GetConfig("Settings", "Max Time Until Pilot Eject", 600.0f));
killMSG = Convert.ToBoolean(GetConfig("Settings", "Pilot Death Message Enabled", true));
pilotLifeLength = Convert.ToSingle(GetConfig("Settings", "Pilot Life Length", 600f));
minimumSpawnHeight = Convert.ToSingle(GetConfig("Settings", "Pilot Minimum Spawn Height", 20f));
minimumSpawnHeightEnabled = Convert.ToBoolean(GetConfig("Settings", "Min Spawn Height Enabled", false));
inboundMessage = Convert.ToBoolean(GetConfig("Settings", "Inbound Message", true));
customCratesToDrop = Convert.ToInt32(GetConfig("Settings", "Number of Crates to Spawn", 3));
truePVEPilotDamageable = Convert.ToBoolean(GetConfig("Settings", "(TruePVP) Pilot Is Damageable", true));
useGUIAnnouncements = Convert.ToBoolean(GetConfig("Settings", "Use GUIAnnouncements", false));
pilotFallSpeed = Convert.ToSingle(GetConfig("Settings", "Pilot Fall Speed", 1f));
heliIsOnFire = Convert.ToBoolean(GetConfig("Settings", "Heli Is On Fire", true));
pilotArrow = Convert.ToBoolean(GetConfig("Arrow Settings", "Arrow Above Pilot", true));
arrowHeight = Convert.ToSingle(GetConfig("Arrow Settings", "Arrow Height", 200f));
arrowLength = Convert.ToSingle(GetConfig("Arrow Settings", "Arrow Length (seconds)", 120f));
timedEventEnabled = Convert.ToBoolean(GetConfig("Timed Event Settings", "Timed Helicopter Enabled", false));
minEventTime = Convert.ToSingle(GetConfig("Timed Event Settings", "Min Time Until Next Event", 1800f));
maxEventTime = Convert.ToSingle(GetConfig("Timed Event Settings", "Max Time Until Next Event", 3600f));
randomEventEnabled = Convert.ToBoolean(GetConfig("Random Event Settings", "Chance of helicopter being event heli (external helicopters only)", true));
chanceOfOccuring = Convert.ToSingle(GetConfig("Random Event Settings", "Chance Of Occuring", 0.20f));
minHelicoptersBeforeNextEvent = Convert.ToInt32(GetConfig("Random Event Settings", "Min Helicopters Between Random Event", 0));
if (!changed) return;
SaveConfig();
changed = false;
}
protected override void LoadDefaultConfig() {
Config.Clear();
LoadVariables();
}
private void Init() {
plugin = this;
LoadVariables();
InventoryData = Interface.Oxide.DataFileSystem.GetFile("PilotEject");
LoadData();
permission.RegisterPermission(permissionName, this);
if (timedEventEnabled) timer.Repeat(Random.Range(minEventTime, maxEventTime), 0, CallBrokenHeli);
lang.RegisterMessages(new Dictionary<string, string> {
["Heli Malfunctioned"]
= "The helicopter has malfunctioned! The pilot had to bail and is currently parachuting down.Go find him & steal his loot", ["No Permission"] = "You cannot use this command!", ["Pilot Killed"] = "The pilot has been killed by {0}", ["Pilot Inventory Set"] = "The pilots inventory has successfully been set!", ["Malfunction Timer Warning (Console)"] = "The helicopter will malfunction in {0} seconds", ["Broken Heli Inbound"] = "A badly damaged heli is inbound", ["setpilot Invalid Syntax"] = "Invalid Syntax! /setpilot <add/remove/set> <name>"
}
, this);
foreach (BasePlayer player in BasePlayer.activePlayerList) if (permission.UserHasPermission(player.UserIDString, "playerwake.notify")) player.ChatMessage("msg");
}
private void Unload() {
}
private void OnServerSave() {
SaveData();
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (!entity || info == null) return;
BaseHelicopter heli = entity.GetComponent<BaseHelicopter>();
if (heli) {
if (helis.Contains(heli)) helis.Remove(heli);
return;
}
EjectedPlayer pilot = entity.GetComponent<EjectedPlayer>();
if (pilot == null) return;
BasePlayer player = info.InitiatorPlayer;
if (player) if (killMSG) {
if (useGUIAnnouncements) SendGlobaGUIAnnouncement(string.Format(msg("Pilot Killed"), player.displayName));
else rust.BroadcastChat(null, string.Format(msg("Pilot Killed"), player.displayName));
}
}
private void OnEntitySpawned(BaseNetworkable entity) {
BaseHelicopter heli = entity.GetComponent<BaseHelicopter>();
if (!heli) {
PlayerCorpse corpse = entity.GetComponent<PlayerCorpse>();
if (!corpse) return;
if (corpse.playerSteamID.ToString().StartsWith("76561198")) return;
PilotInfo data = null;
try {
if (!pilotData.TryGetValue(corpse.playerName, out data)) return;
}
catch(Exception e) {
Puts($"Pilot {corpse.playerName} tried to spawn it's inventory but no inventory was found!");
return;
}
timer.Once(0.5f, () => GiveItems(corpse, data));
return;
}
if (heliCount != minHelicoptersBeforeNextEvent) {
heliCount++;
return;
}
timer.Once(0.1f, () => {
if (heli == null) return;
if (helis.Contains(heli)) return;
if (randomEventEnabled) {
float rng = Random.Range(0f, 1f);
if (rng > chanceOfOccuring) return;
TriggerEventStart(heli);
return;
}
else {
TriggerEventStart(heli);
}
}
);
}
private object CanEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (!truePVEPilotDamageable) return null;
EjectedPlayer player = entity.GetComponent<EjectedPlayer>();
if (player == null) return null;
info.damageTypes.Scale(Rust.DamageType.Heat, 0);
if (pilots.Contains(player)) return true;
return null;
}
object OnNpcPlayerResume(NPCPlayerApex player) {
EjectedPlayer pilot = player.GetComponent<EjectedPlayer>();
if (!pilot) return null;
if (pilot.isGrounded) return null;
return false;
}
private class EjectHelicopter : FacepunchBehaviour {
private BaseHelicopter heli;
private List<Scientist> pilots = new List<Scientist>();
private float eventTime;
private bool eventTriggered;
private bool isOverWater = true;
private bool spawnHeightEnabled = plugin.minimumSpawnHeightEnabled;
private float minSpawnHeight = plugin.minimumSpawnHeight;
private void Awake() {
heli = GetComponent<BaseHelicopter>();
eventTime = UnityEngine.Time.time + Random.Range(plugin.minTimeToEvent, plugin.maxTimeToEvent);
plugin.Puts(string.Format(plugin.msg("Malfunction Timer Warning (Console)"), eventTime - UnityEngine.Time.time));
if (plugin.inboundMessage) {
if (plugin.useGUIAnnouncements) plugin.SendGlobaGUIAnnouncement(plugin.msg("Broken Heli Inbound"));
else plugin.rust.BroadcastChat(null, plugin.msg("Broken Heli Inbound"));
}
InvokeRepeating(UpdateWaterCheck, 10f, 1f);
if (plugin.heliIsOnFire) foreach (BaseHelicopter.weakspot weakspot in heli.weakspots) {
weakspot.healthFractionOnDestroyed = 0f;
weakspot.Hurt(weakspot.health, null);
}
}
private void Update() {
if (eventTriggered == false) if (UnityEngine.Time.time >= eventTime) {
if (isOverWater) return;
StartEvent();
}
}
private void OnDestroy() {
CancelInvoke(UpdateWaterCheck);
foreach (Scientist pilot in pilots) pilot.GetComponent<EjectedPlayer>().heliCrashPos = new Vector3(transform.position.x + UnityEngine.Random.Range(-5f, 5f), TerrainMeta.HeightMap.GetHeight(transform.position), transform.position.z + UnityEngine.Random.Range(-5f, 5f));
}
private void StartEvent() {
eventTriggered = true;
if (heli) {
if (plugin.useGUIAnnouncements) plugin.SendGlobaGUIAnnouncement(plugin.msg("Heli Malfunctioned"));
else plugin.rust.BroadcastChat(null, plugin.msg("Heli Malfunctioned"));
PatrolHelicopterAI ai = heli.GetComponent<PatrolHelicopterAI>();
heli.maxCratesToSpawn = plugin.customCratesToDrop;
SpawnNPCs();
heli.Hurt(heli.health);
ai.CriticalDamage();
}
}
private void UpdateWaterCheck() {
bool x = WaterLevel.GetWaterInfo(new Vector3(transform.position.x, TerrainMeta.HeightMap.GetHeight(transform.position), transform.position.z)).isValid;
if (isOverWater == true && x == false) if (UnityEngine.Time.time >= eventTime) eventTime = UnityEngine.Time.time + 10f;
isOverWater = x;
}
private void SpawnNPCs() {
foreach (var entry in plugin.pilotData) CreatePilot(entry.Value);
}
private void CreatePilot(PilotInfo data) {
Vector3 pos = transform.position;
pos = new Vector3(pos.x + UnityEngine.Random.Range(-5f, 5f), pos.y, pos.z + UnityEngine.Random.Range(-5f, 5f));
if (spawnHeightEnabled) if (pos.y < minSpawnHeight) pos = new Vector3(pos.x, minSpawnHeight, pos.z);
Scientist pilot = GameManager.server.CreateEntity("assets/prefabs/npc/scientist/scientist.prefab", pos).GetComponent<Scientist>();
pilot.Pause();
pilot.CommunicationRadius = 0f;
pilot.Spawn();
pilot.GetComponent<NPCPlayer>().enabled = false;
pilots.Add(pilot);
pilot.displayName = data.displayName;
pilot._maxHealth = data.health;
pilot.InitializeHealth(data.health, data.health);
pilot.SendNetworkUpdateImmediate();
GiveItems(pilot.GetComponent<BasePlayer>(), data);
EjectedPlayer ep = pilot.gameObject.AddComponent<EjectedPlayer>();
ep.data = data;
}
private void GiveItems(BasePlayer player, PilotInfo data) {
foreach (var item in data.clothingItems) if (Random.Range(0f, 1f) < item.chance) {
var newitem = ItemManager.CreateByName(item.shortname, item.amount, item.skinId);
if (newitem == null) continue;
newitem.MoveToContainer(player.inventory.containerWear);
}
}
}
private class EjectedPlayer : FacepunchBehaviour {
private BasePlayer player;
public NPCPlayerApex npc;
public PilotInfo data;
public bool isGrounded;
public Vector3 groundPos;
private Vector3 startPos;
private BaseEntity chute;
private float deathTime;
public Vector3 heliCrashPos;
private bool doDraws = plugin.pilotArrow;
private float lifeLength = plugin.pilotLifeLength;
private void Awake() {
player = GetComponent<BasePlayer>();
npc = player.GetComponent<NPCPlayerApex>();
plugin.pilots.Add(this);
startPos = transform.position;
groundPos = FindGroundPosition();
deathTime = Time.time + lifeLength;
InitChute();
}
private Vector3 FindGroundPosition() {
RaycastHit raycastHit;
if (TransformUtil.GetGroundInfo(startPos, out raycastHit, 80f, 1101070337)) return raycastHit.point;
return new Vector3(transform.position.x, TerrainMeta.HeightMap.GetHeight(transform.position), transform.position.z);
}
private void FixedUpdate() {
if (isGrounded == false) {
transform.position = Vector3.MoveTowards(transform.position, groundPos, plugin.pilotFallSpeed * 0.25f);
npc?.SendNetworkUpdateImmediate();
if (Vector3.Distance(transform.position, groundPos) < 0.15f) {
OnLanded();
}
}
else {
if (heliCrashPos != null && heliCrashPos != Vector3.zero) {
if (Vector3.Distance(transform.position, heliCrashPos) < 0.5f) {
CancelInvoke(() => npc.SetDestination(heliCrashPos));
}
else if (Vector3.Distance(transform.position, heliCrashPos) > 10f) {
heliCrashPos = new Vector3(transform.position.x + UnityEngine.Random.Range(-5f, 5f), TerrainMeta.HeightMap.GetHeight(transform.position), transform.position.z + UnityEngine.Random.Range(-5f, 5f));
InvokeRepeating(() => npc.SetDestination(heliCrashPos), 0.2f, 5f);
}
}
if (UnityEngine.Time.time >= deathTime) {
KillPilot();
return;
}
}
}
private void OnDestroy() {
if (chute) chute.Kill();
if (plugin.pilots.Contains(this)) plugin.pilots.Remove(this);
if (npc) npc.displayName = data.displayName;
}
private void OnLanded() {
isGrounded = true;
npc.Resume();
transform.position = groundPos;
chute?.Kill();
if (data.wounded) npc.StartWounded();
else {
if (heliCrashPos != null && heliCrashPos != Vector3.zero) InvokeRepeating(() => npc.SetDestination(heliCrashPos), 0.05f, 5f);
}
if (doDraws) foreach (BasePlayer player in BasePlayer.activePlayerList) plugin.DoDraws(player, transform.position);
}
public void KillPilot() {
if (player) player.Kill();
}
private void InitChute() {
chute = GameManager.server.CreateEntity("assets/prefabs/misc/parachute/parachute.prefab", new Vector3(0, 0, 0));
chute.SetParent(player);
chute.Spawn();
}
}
[ChatCommand("callbrokenheli")]
private void CallBrokenHeliCMD(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, permissionName)) {
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
CallBrokenHeli();
}
[ConsoleCommand("callbrokenheli")]
private void CallBrokeHeliCONSOLECMD(ConsoleSystem.Arg args) {
if (args.Connection != null) return;
CallBrokenHeli();
Puts("Broken heli inbound");
}
[ChatCommand("setpilot")]
private void SetpilotinventoryCMD(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, permissionName)) {
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (args.Length != 2) {
player.ChatMessage(msg("setpilot Invalid Syntax", player.UserIDString));
return;
}
switch (args[0]) {
case "add" : if (pilotData.ContainsKey(args[1])) {
player.ChatMessage($"This pilot already exists.Use \"/setpilot set {args[1]}\" to change this pilots inventory");
break;
}
pilotData.Add(args[1], new PilotInfo() {
chance = 1f, displayName = args[1], health = 100f, dropItems = true, beltItems = new List<ItemInfo>(), clothingItems = new List<ItemInfo>(), inventoryItems = new List<ItemInfo>(), wounded = false
}
);
AddItemsToData(args[1], player);
player.ChatMessage($"{args[1]} has been added!");
break;
case "remove" : if (!pilotData.ContainsKey(args[1])) {
player.ChatMessage($"{args[1]} does not exist!");
break;
}
pilotData.Remove(args[1]);
player.ChatMessage($"{args[1]} has been removed!");
break;
case "set" : PilotInfo data;
if (!pilotData.TryGetValue(args[1], out data)) {
player.ChatMessage($"{args[1]} does not exist!");
break;
}
AddItemsToData(args[1], player);
player.ChatMessage($"{args[1]}'s inventory has been set!");
break;
default : player.ChatMessage(msg("setpilot Invalid Syntax", player.UserIDString));
break;
}
SaveData();
LoadData();
}
private void SendGlobaGUIAnnouncement(string msg) {
foreach(BasePlayer player in BasePlayer.activePlayerList) if (player.IsConnected) GUIAnnouncements?.Call("CreateAnnouncement", msg, "Grey", "White", player);
}
private void AddItemsToData(string pilotName, BasePlayer player) {
PilotInfo data;
if (!pilotData.TryGetValue(pilotName, out data)) return;
data.inventoryItems.Clear();
data.clothingItems.Clear();
data.beltItems.Clear();
foreach (var item in player.inventory.containerMain.itemList) data.inventoryItems.Add(new ItemInfo {
shortname = item.info.shortname, amount = item.amount, chance = 1f, skinId = item.skin
}
);
foreach (var item in player.inventory.containerBelt.itemList) data.beltItems.Add(new ItemInfo {
shortname = item.info.shortname, amount = item.amount, chance = 1f, skinId = item.skin
}
);
foreach (var item in player.inventory.containerWear.itemList) data.clothingItems.Add(new ItemInfo {
shortname = item.info.shortname, amount = item.amount, chance = 1f, skinId = item.skin
}
);
}
private void DoDraws(BasePlayer player, Vector3 startPos) {
if (player.IsAdmin) {
player.SendConsoleCommand("ddraw.arrow", arrowLength, Color.red, startPos + new Vector3(0f, 25f + arrowHeight, 0f), startPos + new Vector3(0f, 25f, 0f), 4.0f);
}
else {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendNetworkUpdateImmediate();
player.SendConsoleCommand("ddraw.arrow", arrowLength, Color.red, startPos + new Vector3(0f, 25f + arrowHeight, 0f), startPos + new Vector3(0f, 25f, 0f), 4.0f);
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
player.SendNetworkUpdateImmediate();
}
}
private void GiveItems(PlayerCorpse corpse, PilotInfo data) {
foreach (ItemContainer container in corpse.containers) container.Clear();
foreach (var item in data.inventoryItems) if (Random.Range(0f, 1f) < item.chance) {
var newitem = ItemManager.CreateByName(item.shortname, item.amount, item.skinId);
if (newitem == null) continue;
newitem.MoveToContainer(corpse.containers[0]);
}
foreach (var item in data.beltItems) if (Random.Range(0f, 1f) < item.chance) {
var newitem = ItemManager.CreateByName(item.shortname, item.amount, item.skinId);
if (newitem == null) continue;
newitem.MoveToContainer(corpse.containers[2]);
}
foreach (var item in data.clothingItems) if (Random.Range(0f, 1f) < item.chance) {
var newitem = ItemManager.CreateByName(item.shortname, item.amount, item.skinId);
if (newitem == null) continue;
newitem.MoveToContainer(corpse.containers[1]);
}
}
private void TriggerEventStart(BaseHelicopter heli) {
heli.gameObject.AddComponent<EjectHelicopter>();
helis.Add(heli);
heliCount = 0;
}
private void CallBrokenHeli() {
BaseEntity ent = GameManager.server.CreateEntity("assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab", new Vector3(0, 50f, 0));
ent.GetComponent<PatrolHelicopterAI>().enabled = false;
ent.transform.position = new Vector3(0, 50, 0);
ent.GetComponent<PatrolHelicopterAI>().enabled = true;
helis.Add((BaseHelicopter)ent);
ent.Spawn();
ent.gameObject.AddComponent<EjectHelicopter>();
}
private 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)) return value;
value = defaultValue;
data[datavalue] = value;
changed = true;
return value;
}
private string msg(string key, string id = null) {
return lang.GetMessage(key, this, id);
}
private bool IsDamagedHeli(BaseHelicopter heli) {
return helis.Contains(heli);
}
}
}
// Слив плагинов server-rust by Apolo YouGame
// If you wish to view this code in a formatted state, please contact redBDGR on discord @ redBDGR #0001