using Oxide.Core.Plugins; using Oxide.Game.Rust.Cui; using System; using System.Collections.Generic; using UnityEngine; namespace Oxide.Plugins { [Info("Heli Ride", "ColonBlow", "1.1.17")] [Description("Allows players to fly the Patrol Helicopter")] public class HeliRide : RustPlugin { //Rust update fixes #region Loadup [PluginReference] private Plugin Chute, Vanish; public bool CockpitOverlay => Config.Get("Show Custom Cockpit Overlay"); public bool CrossHair => Config.Get("Show Custom Crosshair"); private static Dictionary HeliFlying = new Dictionary(); private static Dictionary DamagedHeli = new Dictionary(); private static Dictionary AddParachute = new Dictionary(); public class HeliData { public BasePlayer player; } public class HeliDamage { public BasePlayer player; } public class HasParachute { public BasePlayer player; } private void Loaded() { if (Chute == null) { PrintWarning("Chute plugin not found. To enable player parachutes when there helicopter dies, install Chute plugin!"); } if (Vanish == null) { PrintWarning("Vanish plugin not found. Player will be visable and UseAutoVanish will be turned off"); UseAutoVanish = false; } LoadVariables(); permission.RegisterPermission("heliride.allowed", this); } #endregion #region Configuration private bool Changed; private static bool ShowCockpitOverlay = true; private static bool ShowCrosshair = true; private static bool UseParachutes = true; private static bool SpawnCrates = false; private static bool UseAutoVanish = false; private static double RocketDelay = 0.2; private static float RocketMax = 36f; private static float NapalmMax = 36f; private static double RocketNapalmReloadTime = 20; private static float BulletDamage = 50f; private static string RocketPrefab = "assets/prefabs/npc/patrol helicopter/rocket_heli.prefab"; private static string NapalmPrefab = "assets/prefabs/npc/patrol helicopter/rocket_heli_napalm.prefab"; private void LoadConfigVariables() { CheckCfg("ShowCockpitOverlay", ref ShowCockpitOverlay); CheckCfg("ShowCrosshair", ref ShowCrosshair); CheckCfg("UseParachutes", ref UseParachutes); CheckCfg("SpawnCrates", ref SpawnCrates); CheckCfg("UseAutoVanish", ref UseAutoVanish); CheckCfg("RocketDelay", ref RocketDelay); CheckCfg("RocketNapalmReloadTime", ref RocketNapalmReloadTime); CheckCfgFloat("BulletDamage", ref BulletDamage); CheckCfgFloat("Max Rockets Loaded", ref RocketMax); CheckCfgFloat("Max Napalm Loaded", ref NapalmMax); CheckCfg("Heli Rocket prefab : ", ref RocketPrefab); CheckCfg("Heli Napam prefab : ", ref NapalmPrefab); } protected override void LoadDefaultConfig() { Puts("Creating a new config file"); Config.Clear(); LoadVariables(); } private void LoadVariables() { LoadConfigVariables(); SaveConfig(); } private void CheckCfg(string Key, ref T var) { if (Config[Key] is T) var = (T)Config[Key]; else Config[Key] = var; } private void CheckCfgFloat(string Key, ref float var) { if (Config[Key] != null) var = Convert.ToSingle(Config[Key]); else Config[Key] = var; } private object GetConfig(string menu, string datavalue, object defaultValue) { var data = Config[menu] as Dictionary; if (data == null) { data = new Dictionary(); Config[menu] = data; Changed = true; } object value; if (!data.TryGetValue(datavalue, out value)) { value = defaultValue; data[datavalue] = value; Changed = true; } return value; } #endregion #region Localization private new void LoadDefaultMessages() { lang.RegisterMessages(new Dictionary { {"noheli", "You are not flying a helicopter."}, {"notallowed", "You are not allowed to access that command."}, {"notflying", "You must be noclipping to activate Helicopter."} }, this); } #endregion #region Commands [ChatCommand("flyheli")] private void chatFlyHeli(BasePlayer player, string command, string[] args) { string SteamID = player.userID.ToString(); if (isAllowed(player, "heliride.allowed")) { var playerheli = player.GetComponent(); if (HeliFlying.ContainsKey(player.userID)) { GameObject.Destroy(playerheli); if (Vanish != null && UseAutoVanish) { Vanish.Call("Reappear", player); } HeliFlying.Remove(player.userID); return; } if (playerheli != null) { GameObject.Destroy(playerheli); if (Vanish != null && UseAutoVanish) { Vanish.Call("Reappear", player); } HeliFlying.Remove(player.userID); return; } if (playerheli == null) { if (!player.IsFlying) { SendReply(player, lang.GetMessage("notflying", this, SteamID)); return; } if (Vanish != null && UseAutoVanish) { Vanish.Call("Disappear", player); } timer.Once(1f, () => AddHeli(player)); return; } } if (!isAllowed(player, "heliride.allowed")) { SendReply(player, lang.GetMessage("notallowed", this, SteamID)); } } [ConsoleCommand("flyheli")] private void cmdConsoleFlyHeli(ConsoleSystem.Arg arg) { BasePlayer player = arg.Player(); string SteamID = player.userID.ToString(); if (isAllowed(player, "heliride.allowed")) { var playerheli = player.GetComponent(); if (HeliFlying.ContainsKey(player.userID)) { GameObject.Destroy(playerheli); HeliFlying.Remove(player.userID); if (Vanish != null && UseAutoVanish) { Vanish.Call("Reappear", player); } return; } if (playerheli != null) { GameObject.Destroy(playerheli); if (Vanish != null && UseAutoVanish) { Vanish.Call("Reappear", player); } HeliFlying.Remove(player.userID); return; } if (playerheli == null) { if (!player.IsFlying) { SendReply(player, lang.GetMessage("notflying", this, SteamID)); return; } if (Vanish != null && UseAutoVanish) { Vanish.Call("Disappear", player); } timer.Once(1f, () => AddHeli(player)); return; } } if (!isAllowed(player, "heliride.allowed")) { SendReply(player, lang.GetMessage("notallowed", this, SteamID)); } } [ConsoleCommand("showcockpit")] private void cmdConsoleShowCockpit(ConsoleSystem.Arg arg) { BasePlayer player = arg.Player(); var playerheli = player.GetComponent(); if (!playerheli) { string SteamID = player.userID.ToString(); SendReply(player, lang.GetMessage("noheli", this, SteamID)); return; } if (playerheli) { playerheli.CockpitOverlay(player); playerheli.CrosshairOverlay(player); } } [ConsoleCommand("hidecockpit")] private void cmdConsoleHideCockpit(ConsoleSystem.Arg arg) { BasePlayer player = arg.Player(); var playerheli = player.GetComponent(); if (!playerheli) { string SteamID = player.userID.ToString(); SendReply(player, lang.GetMessage("noheli", this, SteamID)); return; } if (playerheli) { CuiHelper.DestroyUi(player, "CockpitGuiOverlay"); CuiHelper.DestroyUi(player, "CrosshairGuiOverlay"); CuiHelper.DestroyUi(player, "DamageGuiOverlay"); } } #endregion #region Hooks private void OnEntityTakeDamage(BasePlayer player, HitInfo hitInfo) { if (player == null || hitInfo == null) return; if (HeliFlying.ContainsKey(player.userID)) { hitInfo.damageTypes.ScaleAll(0); } } private void OnPlayerTick(BasePlayer player) { if (!UseParachutes) return; if (UseParachutes) { if (!AddParachute.ContainsKey(player.userID)) return; if (AddParachute.ContainsKey(player.userID)) { if (Chute != null) { AddParachute.Remove(player.userID); timer.Once(0.5f, () => Chute.Call("ExternalAddPlayerChute", player)); if (Vanish != null && UseAutoVanish) { timer.Once(0.5f, () => Vanish.Call("Reappear", player)); } } if (Chute == null) { AddParachute.Remove(player.userID); } } } } private void AddHeli(BasePlayer player) { if (player.IsFlying) { player.gameObject.AddComponent(); HeliFlying.Add(player.userID, new HeliData { player = player }); return; } if (!player.IsFlying) { string SteamID = player.userID.ToString(); SendReply(player, lang.GetMessage("notflying", this, SteamID)); } } private void Unload() { DestroyAll(); foreach (var player in BasePlayer.activePlayerList) { RemoveHeliComponents(player); } } private static void DestroyAll() { var objects = GameObject.FindObjectsOfType(typeof(T)); if (objects != null) { foreach (var gameObj in objects) { GameObject.Destroy(gameObj); } } } private void RemoveHeliComponents(BasePlayer player) { var playerheli = player.GetComponent(); if (playerheli != null) { playerheli.DestroyCui(player); GameObject.Destroy(playerheli); } } private void OnPlayerDisconnected(BasePlayer player) { RemoveHeliComponents(player); } private void OnPlayerRespawned(BasePlayer player) { RemoveHeliComponents(player); } private bool isAllowed(BasePlayer player, string perm) => permission.UserHasPermission(player.UserIDString, perm); #endregion #region HeliRide Entity private class FlyHelicopter : MonoBehaviour { public BasePlayer player; public BaseEntity helicopterBase; private BaseEntity rockets; public PatrolHelicopterAI heliAI; public PatrolHelicopter heli; public HelicopterTurret heliturret; public InputState input; private RaycastHit hitInfo; public Vector3 PlayerPOS; public Vector3 target; public Vector3 CurrentPOS; private Vector3 direction; private float bulletDamage; private float rocketMax; private bool hasRockets; private float napalmMax; private bool hasNapalm; private double rocketcycletimer; private double reloadtimer; private double rocketDelay; private bool rocketcycle; private bool leftTubeFiredLast; private bool isReloading; private double rocketNapalmReploadTime; private void Awake() { player = GetComponent(); if (player == null) { OnDestroy(); return; } input = player.serverInput; rocketcycletimer = 0.0; reloadtimer = 0.0; isReloading = false; rocketNapalmReploadTime = RocketNapalmReloadTime; rocketMax = RocketMax; hasRockets = true; napalmMax = NapalmMax; hasNapalm = true; rocketDelay = RocketDelay; bulletDamage = BulletDamage; rocketcycle = false; PlayerPOS = player.transform.position + player.eyes.BodyForward() * 3f; string prefab = "assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab"; helicopterBase = GameManager.server.CreateEntity(prefab); heliAI = helicopterBase.GetComponent(); heliAI.enabled = false; heliturret = helicopterBase.GetComponent(); heli = helicopterBase.GetComponent(); heli.OwnerID = player.userID; heli.InitalizeWeakspots(); if (!SpawnCrates) heli.maxCratesToSpawn = 0; heli.bulletDamage = bulletDamage; heli.spotlightTarget = FindTarget(target); helicopterBase.Spawn(); if (ShowCockpitOverlay) CockpitOverlay(player); if (ShowCrosshair) CrosshairOverlay(player); helicopterBase.transform.localPosition = PlayerPOS; helicopterBase.transform.rotation = player.eyes.rotation; } ////////////////////////////////////////////////////////////////////////////////////// public void CockpitOverlay(BasePlayer player) { var cockpitcui = new CuiElementContainer(); cockpitcui.Add(new CuiElement { Name = "CockpitGuiOverlay", Components = { new CuiRawImageComponent { Color = "1 1 1 1", Url = "http://i.imgur.com/6O0hMC5.png", Sprite = "assets/content/textures/generic/fulltransparent.tga" }, new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1"} } }); CuiHelper.AddUi(player, cockpitcui); } public void CrosshairOverlay(BasePlayer player) { var crosshaircui = new CuiElementContainer(); crosshaircui.Add(new CuiElement { Name = "CrosshairGuiOverlay", Components = { new CuiRawImageComponent { Color = "1 1 1 1", Url = "http://i.imgur.com/yweKHFT.png", Sprite = "assets/content/textures/generic/fulltransparent.tga" }, new CuiRectTransformComponent { AnchorMin = "0.450 0.450", AnchorMax = "0.540 0.550"} } }); CuiHelper.AddUi(player, crosshaircui); } public void DamageOverlay(BasePlayer player) { var damageoverlay = new CuiElementContainer(); damageoverlay.Add(new CuiElement { Name = "DamageGuiOverlay", Components = { new CuiRawImageComponent { Color = "1 1 1 1", Url = "http://i.imgur.com/XrpqTdP.png", Sprite = "assets/content/textures/generic/fulltransparent.tga" }, new CuiRectTransformComponent { AnchorMin = "0.35 0.25", AnchorMax = "0.60 0.70"} } }); CuiHelper.AddUi(player, damageoverlay); } public void HealthIndicator(BasePlayer player, float health) { CuiHelper.DestroyUi(player, "HealthGui"); var healthstr = health.ToString(); var rocketstr = isReloading ? "R" : rocketMax.ToString(); var napalmstr = isReloading ? "R" : napalmMax.ToString(); var dispalystr = isReloading ? "Reloading " + healthstr + " Reloading" : "N: " + napalmstr + " " + healthstr + " R: " + rocketstr; var healthindicator = new CuiElementContainer(); healthindicator.Add(new CuiButton { Button = { Command = "", Color = "0.0 0.0 0.0 1.0" }, RectTransform = { AnchorMin = "0.40 0.15", AnchorMax = "0.60 0.18" }, Text = { Text = dispalystr, FontSize = 18, Color = "1.0 0.0 0.0 0.2", Align = TextAnchor.MiddleCenter } }, "Overall", "HealthGui"); CuiHelper.AddUi(player, healthindicator); } ////////////////////////////////////////////////////////////////////////////////////// private void FixedUpdate() { player = GetComponent(); if (player.IsDead() || !player.IsFlying) { heliAI._currentState = PatrolHelicopterAI.aiState.DEATH; } if (heliAI._currentState == PatrolHelicopterAI.aiState.DEATH) { heliAI.enabled = true; DestroyCui(player); GameObject.Destroy(this); return; } if (rocketMax <= 0) hasRockets = false; if (napalmMax <= 0) hasNapalm = false; Vector3 PlayerPOS = player.transform.position - player.eyes.BodyForward() * 5 + Vector3.down * 0.45f; CurrentPOS = helicopterBase.transform.position; Vector3 direction = Quaternion.Euler(input.current.aimAngles) * Vector3.fwd; heli.spotlightTarget = FindTarget(target); helicopterBase.transform.localPosition = PlayerPOS; helicopterBase.transform.rotation = Quaternion.Lerp(helicopterBase.transform.rotation, player.eyes.rotation, 2f * Time.deltaTime); helicopterBase.transform.eulerAngles = new Vector3(0, helicopterBase.transform.eulerAngles.y, 0); BaseCombatEntity helientity = helicopterBase.GetComponent(); float health = helientity.Health(); HealthIndicator(player, health); if (health <= 3000f && ShowCockpitOverlay) { if (!DamagedHeli.ContainsKey(player.userID)) { if (ShowCockpitOverlay) { DamageOverlay(player); DamagedHeli.Add(player.userID, new HeliDamage { player = player }); } } } if (isReloading) { reloadtimer += Time.deltaTime; if (reloadtimer >= rocketNapalmReploadTime) { isReloading = false; rocketMax = RocketMax; hasRockets = true; napalmMax = NapalmMax; hasNapalm = true; reloadtimer = 0.0; } } if (rocketcycle) { rocketcycletimer += Time.deltaTime; if (rocketcycletimer >= rocketDelay) { rocketcycle = false; rocketcycletimer = 0.0; } } if (health > 3000f && ShowCockpitOverlay) { if (DamagedHeli.ContainsKey(player.userID)) { CuiHelper.DestroyUi(player, "DamageGuiOverlay"); DamagedHeli.Remove(player.userID); } } if (input.IsDown(BUTTON.RELOAD)) { isReloading = true; } if (input.IsDown(BUTTON.DUCK)) { Vector3 downPos = player.transform.position + Vector3.down * (UnityEngine.Time.deltaTime * 3f); player.ClientRPCPlayer(null, player, "ForcePositionTo", downPos); player.SendNetworkUpdate(); } if (input.IsDown(BUTTON.FIRE_PRIMARY)) { target = FindTarget(target); FireGuns(target); } if (input.IsDown(BUTTON.FIRE_SECONDARY)) { if (!hasRockets || isReloading) return; if (!rocketcycle) { leftTubeFiredLast = !leftTubeFiredLast; FireRocket(leftTubeFiredLast, direction, PlayerPOS, true); } rocketcycle = true; } if (input.IsDown(BUTTON.FIRE_THIRD)) { if (!hasNapalm || isReloading) return; if (!rocketcycle) { leftTubeFiredLast = !leftTubeFiredLast; FireRocket(leftTubeFiredLast, direction, PlayerPOS, false); } rocketcycle = true; } } private void FireGuns(Vector3 target) { heliAI.FireGun(target, ConVar.PatrolHelicopter.bulletAccuracy, true); heliAI.FireGun(target, ConVar.PatrolHelicopter.bulletAccuracy, false); } private void FireRocket(bool leftTubeFiredLast, Vector3 direction, Vector3 PlayerPOS, bool isrocket) { RaycastHit hit; string projectile; if (isrocket) { rocketMax = rocketMax - 1f; } if (!isrocket) { napalmMax = napalmMax - 1f; } float num = 4f; projectile = isrocket ? RocketPrefab : NapalmPrefab; Vector3 origin = PlayerPOS + Vector3.down; if (num > 0f) { direction = (Vector3)(Quaternion.Euler(UnityEngine.Random.Range((float)(-num * 0.5f), (float)(num * 0.5f)), UnityEngine.Random.Range((float)(-num * 0.5f), (float)(num * 0.5f)), UnityEngine.Random.Range((float)(-num * 0.5f), (float)(num * 0.5f))) * direction); } float maxDistance = 1f; if (Physics.Raycast(origin, direction, out hit, maxDistance, -1063040255)) { maxDistance = hit.distance - 0.1f; } Transform transform = !leftTubeFiredLast ? heliAI.helicopterBase.rocket_tube_right.transform : heliAI.helicopterBase.rocket_tube_left.transform; Effect.server.Run(heliAI.helicopterBase.rocket_fire_effect.resourcePath, heliAI.helicopterBase, StringPool.Get(!leftTubeFiredLast ? "rocket_tube_right" : "rocket_tube_left"), Vector3.zero, Vector3.forward, null, true); Vector3 rocketPos = !leftTubeFiredLast ? heliAI.helicopterBase.rocket_tube_right.transform.position : heliAI.helicopterBase.rocket_tube_left.transform.position; rockets = GameManager.server.CreateEntity(projectile, rocketPos); rockets.creatorEntity = player; if (rockets != null) { rockets.SendMessage("InitializeVelocity", (Vector3)(direction * 50f)); rockets.Spawn(); } } private Vector3 FindTarget(Vector3 target) { if (!UnityEngine.Physics.Raycast(player.eyes.HeadRay(), out hitInfo, Mathf.Infinity, -1063040255)) { } Vector3 hitpoint = hitInfo.point; return hitpoint; } public void DestroyCui(BasePlayer player) { CuiHelper.DestroyUi(player, "CockpitGuiOverlay"); CuiHelper.DestroyUi(player, "CrosshairGuiOverlay"); CuiHelper.DestroyUi(player, "DamageGuiOverlay"); CuiHelper.DestroyUi(player, "HealthGui"); DamagedHeli.Remove(player.userID); } private void addplayerchute() { if (!UseParachutes) return; AddParachute.Add(player.userID, new HasParachute { player = player }); } public void OnDestroy() { player = GetComponent(); DestroyCui(player); DamagedHeli.Remove(player.userID); HeliFlying.Remove(player.userID); if (helicopterBase == null) return; if (heliAI._currentState == PatrolHelicopterAI.aiState.DEATH) { heliAI.enabled = true; heli.bulletDamage = 0f; GameObject.Destroy(this); addplayerchute(); return; } helicopterBase.Kill(); GameObject.Destroy(this); } } #endregion } }