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

FREE AtlasVanish : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
//Reference: 0Harmony

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using HarmonyLib;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Ext.AtlasEx;
using Console = Oxide.Ext.AtlasEx.Console;

namespace Oxide.Plugins
{
    [Info("(Atlas) Vanish", "Ilovepatatos", "1.0.0")]
    public class AtlasVanish : CovalencePlugin
    {
        private const string CONFIGS_FILENAME = nameof(AtlasVanish);
        private const string WEBSITE_URL = "https://i.postimg.cc/2ynd0WPv/VANISH-4.png";

        private static AtlasVanish s_PluginInstance;
        private static string s_UserInterfaceCache;

        private static readonly HashSet<string> s_ToolsWhitelist = new HashSet<string>()
        {
            "assets/prefabs/weapons/hammer/hammer.entity.prefab"
        };

        private Configuration m_InternalConfigs;
        private DataFileSystem m_ConfigsFolder;

        private Harmony m_Harmony;

#pragma warning disable CS0649
        // ReSharper disable once InconsistentNaming
        [PluginReference] private Plugin ImageLibrary;
#pragma warning restore CS0649

#region Debug

        private static void Log(object msg, string color = Console.NORMAL)
        {
            Console.Log($"[(Atlas) Vanish] {msg}", color);
        }

        private static void Profile(object msg, string color = Console.NORMAL)
        {
            if (s_PluginInstance.Configs.EnableLogs)
                Console.Log($"[(Atlas) Vanish] {msg}", color);
        }

#endregion

#region Configs

        [Serializable]
        private class Configuration
        {
            public bool EnableLogs;

            public string UsePerms = "atlasvanish.use";
            public string StartVanishPerms = "atlasvanish.startvanish";
            public string HideUserInterfacePerms = "atlasvanish.hideui";

            public string IgnoreTrapsPerms = "atlasvanish.ignoretraps";
            public string IgnoreAIPerms = "atlasvanish.ignoreai";

            public string IgnoreLocksPerms = "atlasvanish.ignorelocks";

            [JsonProperty("Disable damage when invisible")]
            public bool DisableDamage = true;

            public string AppearSfx = "assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab";
            public string DisappearSfx = "assets/bundled/prefabs/fx/gestures/drink_vomit.prefab";

            public static Configuration GetTemplate()
            {
                var configs = new Configuration();
                return configs;
            }
        }

        private Configuration Configs
        {
            get
            {
                if (m_InternalConfigs == null)
                    LoadConfig();

                return m_InternalConfigs;
            }
            set { m_InternalConfigs = value; }
        }

        private static Configuration StaticConfigs => s_PluginInstance.Configs;

        private DataFileSystem ConfigsFolder => m_ConfigsFolder ?? (m_ConfigsFolder = new DataFileSystem($"{Interface.Oxide.ConfigDirectory}"));

        protected override void LoadConfig()
        {
            if (ConfigsFolder.ExistsDatafile(CONFIGS_FILENAME))
            {
                try
                {
                    Configs = ConfigsFolder.ReadObject<Configuration>(CONFIGS_FILENAME);
                    SaveConfig();
                }
                catch (Exception ex)
                {
                    Log($"The configuration file seems to be corrupted!\n{ex}");
                    LoadDefaultConfig();
                }
            }
            else
            {
                LoadDefaultConfig();
                SaveConfig();
            }
        }

        protected override void LoadDefaultConfig()
        {
            Configs = Configuration.GetTemplate();
        }

        protected override void SaveConfig()
        {
            ConfigsFolder.WriteObject(CONFIGS_FILENAME, Configs);
        }

#endregion

#region Localization

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["BECOMING_VISIBLE"] = "You are no longer vanished",
                ["BECOMING_INVISIBLE"] = "You are now vanished",
            }, this);
        }

        public static string Lang(IPlayer iPlayer, string key)
        {
            return s_PluginInstance.lang.GetMessage(key, s_PluginInstance, iPlayer?.Id);
        }

        public static string Lang(string key)
        {
            return Lang((IPlayer)null, key);
        }

        public static string Lang(BasePlayer player, string key)
        {
            IPlayer iPlayer = player != null ? player.IPlayer : null;
            return Lang(iPlayer, key);
        }

#endregion

#region Command

        [UsedImplicitly]
        [Command("vanish")]
        private void VanishCmd(IPlayer iPlayer, string cmd, string[] args)
        {
            if (!iPlayer.DoesPlayerHavePerms(Configs.UsePerms))
                return;

            var player = iPlayer.ToBasePlayer();
            if (player == null) return;

            if (player.limitNetworking)
            {
                Reappear(player);
            }
            else
            {
                Disappear(player);
            }
        }

#endregion

#region Hooks

        [UsedImplicitly]
        [HookMethod(nameof(Init))]
        public void Init()
        {
            Log($"Initializing {nameof(AtlasVanish)}...");
            s_PluginInstance = this;
            m_Harmony = new Harmony(Name + "Patches");
            SubscribeHooks();

            permission.RegisterPermission(Configs.UsePerms, this);
            permission.RegisterPermission(Configs.StartVanishPerms, this);
            permission.RegisterPermission(Configs.HideUserInterfacePerms, this);
            permission.RegisterPermission(Configs.IgnoreTrapsPerms, this);
            permission.RegisterPermission(Configs.IgnoreAIPerms, this);
            permission.RegisterPermission(Configs.IgnoreLocksPerms, this);
        }


        [UsedImplicitly]
        [HookMethod(nameof(OnServerInitialized))]
        private void OnServerInitialized(bool initial)
        {
            if (initial)
            {
                // Give time for image library to initialize...timer.Once(15f, () =>
                {
                    if (ImageLibrary == null)
                        Log($"THIS PLUGIN REQUIRES THE \"{nameof(ImageLibrary)}.cs\" PLUGIN FROM OXIDE", Console.RED);

                    ImageLibrary?.Call("AddImage", WEBSITE_URL + "atlas-vanish.png", "vanish (Image)", (ulong)0, new Action(InitializeUserInterface));
                });
            }
            else
            {
                if (ImageLibrary == null)
                    Log($"THIS PLUGIN REQUIRES THE \"{nameof(ImageLibrary)}.cs\" PLUGIN FROM OXIDE", Console.RED);

                ImageLibrary?.Call("AddImage", WEBSITE_URL + "atlas-vanish.png", "vanish (Image)", (ulong)0, new Action(InitializeUserInterface));
            }

            foreach (var player in BasePlayer.activePlayerList)
                OnPlayerConnected(player);
        }

// Define a custom ignore list to replace SimpleAIMemory
private static HashSet<BasePlayer> ignoredPlayers = new HashSet<BasePlayer>();

[UsedImplicitly]
[HookMethod(nameof(Unload))]
private void Unload()
{
    Log($"Unloading {nameof(AtlasVanish)}...");
    UnsubscribeHooks();
    ImageLibrary?.Call("RemoveImage", "vanish (Image)", (ulong)0);

    foreach (BasePlayer player in BasePlayer.activePlayerList)
    {
        if (player == null)
            continue;

        if (player.limitNetworking)
            Reappear(player);

        ignoredPlayers.Remove(player);
    }
}

[UsedImplicitly]
[HookMethod(nameof(OnPlayerConnected))]
private void OnPlayerConnected(BasePlayer player)
{
    if (player.DoesPlayerHavePerms(Configs.StartVanishPerms))
    {
        Disappear(player);
    }
    else if (player.limitNetworking)
    {
        Reappear(player);
    }

    if (!IsPlayerTargetableByAI(player))
        ignoredPlayers.Add(player);
}



[UsedImplicitly]
[HookMethod(nameof(OnPlayerDisconnected))]
private void OnPlayerDisconnected(BasePlayer player, string reason)
{
    if (player != null)
        ignoredPlayers.Remove(player);
}


        private void SubscribeHooks()
        {
            if (Configs.DisableDamage)
            {
                {
                    var initial = AccessTools.Method(typeof(BaseMelee), nameof(BaseMelee.PlayerAttack));
                    var patch = new HarmonyMethod(typeof(BaseMeleeHarmony), nameof(BaseMeleeHarmony.PlayerAttackTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }

                {
                    var initial = AccessTools.Method(typeof(BaseMelee), "CLProject");
                    var patch = new HarmonyMethod(typeof(BaseMeleeHarmony), nameof(BaseMeleeHarmony.CLProjectTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }

                {
                    var initial = AccessTools.Method(typeof(BaseProjectile), "CLProject");
                    var patch = new HarmonyMethod(typeof(BaseProjectileHarmony), nameof(BaseProjectileHarmony.CLProjectTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }

                {
                    var initial = AccessTools.Method(typeof(BaseLauncher), "SV_Launch");
                    var patch = new HarmonyMethod(typeof(BaseLauncherHarmony), nameof(BaseLauncherHarmony.SV_LaunchTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }

                {
                    var initial = AccessTools.Method(typeof(FlameThrower), nameof(FlameThrower.FlameTick));
                    var patch = new HarmonyMethod(typeof(FlameThrowerHarmony), nameof(FlameThrowerHarmony.FlameTickTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }

                {
                    var initial = AccessTools.Method(typeof(ThrownWeapon), "DoThrow");
                    var patch = new HarmonyMethod(typeof(ThrownWeaponHarmony), nameof(ThrownWeaponHarmony.DoThrowTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }

                {
                    var initial = AccessTools.Method(typeof(ThrownWeapon), "DoDrop");
                    var patch = new HarmonyMethod(typeof(ThrownWeaponHarmony), nameof(ThrownWeaponHarmony.DoDropTranspiler));
                    m_Harmony.Patch(initial, null, null, patch);
                }
            }

            {
                var initial = AccessTools.Method(typeof(TargetTrigger), nameof(TargetTrigger.InterestedInObject));
                var patch = new HarmonyMethod(typeof(TargetTriggerHarmony), nameof(TargetTriggerHarmony.InterestedInObjectPostfix));
                m_Harmony.Patch(initial, null, patch);
            }

            {
                var initial = AccessTools.Method(typeof(BaseTrapTrigger), nameof(BaseTrapTrigger.InterestedInObject));
                var patch = new HarmonyMethod(typeof(BearTrapTriggerHarmony), nameof(BearTrapTriggerHarmony.InterestedInObjectPostfix));
                m_Harmony.Patch(initial, null, patch);
            }

            {
                var initial = AccessTools.Method(typeof(ServerProjectile), "IsAValidHit");
                var patch = new HarmonyMethod(typeof(ServerProjectileHarmony), nameof(ServerProjectileHarmony.IsAValidHitPostfix));
                m_Harmony.Patch(initial, null, patch);
            }

            {
                var initial = AccessTools.Method(typeof(BradleyAPC), nameof(BradleyAPC.VisibilityTest));
                var patch = new HarmonyMethod(typeof(BradleyAPCHarmony), nameof(BradleyAPCHarmony.VisibilityTestTranspiler));
                m_Harmony.Patch(initial, null, null, patch);
            }

            {
                var initial = AccessTools.Method(typeof(PatrolHelicopterAI), nameof(PatrolHelicopterAI.UpdateTargetList));
                var patch = new HarmonyMethod(typeof(PatrolHelicopterHarmony), nameof(PatrolHelicopterHarmony.UpdateTargetListTranspiler));
                m_Harmony.Patch(initial, null, null, patch);
            }

            {
                var initial = AccessTools.Method(typeof(BaseVehicle), nameof(BaseVehicle.OnAttacked));
                var patch = new HarmonyMethod(typeof(BaseVehicleHarmony), nameof(BaseVehicleHarmony.OnAttackedPrefix));
                m_Harmony.Patch(initial, patch);
            }

            {
                var initial = AccessTools.Method(typeof(ScientistNPC), nameof(ScientistNPC.OnAttacked));
                var patch = new HarmonyMethod(typeof(ScientistNPCHarmony), nameof(ScientistNPCHarmony.OnAttackedPrefix));
                m_Harmony.Patch(initial, patch);
            }

            {
                var initial = AccessTools.Method(typeof(StorageContainer), nameof(StorageContainer.CanOpenLootPanel));
                var patch = new HarmonyMethod(typeof(StorageContainerHarmony), nameof(StorageContainerHarmony.CanOpenLootPanelPrefix));
                m_Harmony.Patch(initial, patch);
            }
        }

        private void UnsubscribeHooks()
        {
            m_Harmony.UnpatchAll(m_Harmony.Id);
        }

#endregion

#region Harmony

        /// <summary>
        /// Disable shooting server side while invisible
        /// </summary>
        private static class BaseMeleeHarmony
        {
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(BaseMelee), nameof(BaseMelee.PlayerAttack))]
            public static IEnumerable<CodeInstruction> PlayerAttackTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();
                int index = list.FindIndex(x => x.opcode == OpCodes.Stloc_0);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH {nameof(BaseMelee.PlayerAttack)}() TO PREVENT INVISIBLE PLAYERS FROM USING MELEE TOOL", Console.RED);
                    return list;
                }

                index += 1;

                // Load arguments for method
                list.Insert(index++, new CodeInstruction(OpCodes.Ldloc_0)); // BasePlayer
                list.Insert(index++, new CodeInstruction(OpCodes.Ldarg_0)); // this (BaseMelee)

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseMeleeTool), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));
                list[index].WithLabels(label);

                return list;
            }

            // ReSharper disable once InconsistentNaming
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(BaseMelee), "CLProject")]
            public static IEnumerable<CodeInstruction> CLProjectTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();
                int index = list.FindIndex(x => x.opcode == OpCodes.Stloc_0);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH BaseMelee.CLProject() TO PREVENT INVISIBLE PLAYERS FROM SHOOTING MELEE TOOL", Console.RED);
                    return list;
                }

                index += 1;

                // Load arguments for method
                list.Insert(index++, new CodeInstruction(OpCodes.Ldloc_0)); // BasePlayer

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseBaseProjectile), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));
                list[index].WithLabels(label);

                return list;
            }
        }

        /// <summary>
        /// Disable shooting server side while invisible
        /// </summary>
        private static class BaseProjectileHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(BaseProjectile), "CLProject")]
            public static IEnumerable<CodeInstruction> CLProjectTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();

                var target = typeof(BaseProjectile).GetMethod(nameof(BaseProjectile.ModifyAmmoCount));
                int index = list.FindIndex(x => x.opcode == OpCodes.Call && x.operand == target);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH BaseProjectile.CLProject() TO PREVENT INVISIBLE PLAYERS FROM SHOOTING WEAPON", Console.RED);
                    return list;
                }

                index -= 5;

                // Load arguments for method
                Label previous = list[index].labels[0];
                list.Insert(index++, new CodeInstruction(OpCodes.Ldloc_0).WithLabels(previous)); // BasePlayer

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseBaseProjectile), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));

                list[index].labels.Clear();
                list[index].WithLabels(label);

                return list;
            }
        }

        /// <summary>
        /// Disable shooting server side while invisible
        /// </summary>
        private static class BaseLauncherHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(BaseLauncher), "SV_Launch")]
            public static IEnumerable<CodeInstruction> SV_LaunchTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();

                var target = typeof(AttackEntity).GetProperty("UsingInfiniteAmmoCheat", ~(BindingFlags)0)?.GetGetMethod(true);
                int index = list.FindIndex(x => x.opcode == OpCodes.Call && x.operand == target);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH BaseLauncher.SV_Launch() TO PREVENT INVISIBLE PLAYERS FROM SHOOTING ROCKET LAUNCHERS", Console.RED);
                    return list;
                }

                index -= 1;

                // Load arguments for method
                list.Insert(index++, new CodeInstruction(OpCodes.Ldloc_0)); // BasePlayer

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseBaseProjectile), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));

                // Assign labels to next instruction
                list[index].WithLabels(label);

                return list;
            }
        }

        /// <summary>
        /// Disable shooting server side while invisible
        /// </summary>
        private static class FlameThrowerHarmony
        {
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(FlameThrower), nameof(FlameThrower.FlameTick))]
            public static IEnumerable<CodeInstruction> FlameTickTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();

                var target = typeof(FlameThrower).GetMethod(nameof(FlameThrower.ReduceAmmo));
                int index = list.FindIndex(x => x.opcode == OpCodes.Call && x.operand == target);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH {nameof(FlameThrower.FlameTick)}() TO PREVENT INVISIBLE PLAYERS FROM SHOOTING FLAME THROWER", Console.RED);
                    return list;
                }

                index -= 2;

                // Store labels
                var labels = list[index].labels.ToArray();
                list[index].labels.Clear();

                // Load arguments for method
                list.Insert(index++, new CodeInstruction(OpCodes.Ldloc_1).WithLabels(labels)); // BasePlayer

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseBaseProjectile), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));

                // Assign labels to next instruction
                list[index].WithLabels(label);

                return list;
            }
        }

        /// <summary>
        /// Disable shooting server side while invisible
        /// </summary>
        private static class ThrownWeaponHarmony
        {
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(ThrownWeapon), "DoThrow")]
            public static IEnumerable<CodeInstruction> DoThrowTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();

                int index = list.FindIndex(x => x.opcode == OpCodes.Ret);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH ThrownWeapon.DoThrow() TO PREVENT PLAYERS FROM SHOOTING ON ISLANDS", Console.RED);
                    return list;
                }

                index += 1;

                // Load arguments for method
                Label previous = list[index].labels[0];
                list.Insert(index++, new CodeInstruction(OpCodes.Ldarg_1).WithLabels(previous)); // RPCMessage

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseThrownWeapon), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));

                list[index].labels.Clear();
                list[index].WithLabels(label);

                return list;
            }

            [HarmonyTranspiler]
            [HarmonyPatch(typeof(ThrownWeapon), "DoDrop")]
            public static IEnumerable<CodeInstruction> DoDropTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();

                int index = list.FindIndex(x => x.opcode == OpCodes.Ret);

                if (index == -1)
                {
                    Log($"COULDN'T PATCH ThrownWeapon.DoDrop() TO PREVENT PLAYERS FROM SHOOTING ON ISLANDS", Console.RED);
                    return list;
                }

                index += 1;

                // Load arguments for method
                Label previous = list[index].labels[0];
                list.Insert(index++, new CodeInstruction(OpCodes.Ldarg_1).WithLabels(previous)); // RPCMessage

                // Call method
                MethodInfo canPlayerUseWeapon =
                    typeof(AtlasVanish).GetMethod(nameof(CanPlayerUseThrownWeapon), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canPlayerUseWeapon));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if false
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));

                list[index].labels.Clear();
                list[index].WithLabels(label);

                return list;
            }
        }

        /// <summary>
        /// Disable players with perm from entering trap colliders
        /// </summary>
        private static class TargetTriggerHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyPostfix]
            [HarmonyPatch(typeof(TargetTrigger), nameof(TargetTrigger.InterestedInObject))]
            public static void InterestedInObjectPostfix(GameObject obj, ref GameObject __result)
            {
                if (__result == null) return;

                BasePlayer player = obj.ToBaseEntity() as BasePlayer;
                if (player == null || player.IPlayer == null) return;

                if (player.IPlayer.HasPermission(StaticConfigs.IgnoreTrapsPerms))
                    __result = null;
            }
        }

        /// <summary>
        /// Disable players with perm from entering trap colliders
        /// </summary>
        private static class BearTrapTriggerHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyPostfix]
            [HarmonyPatch(typeof(BearTrapTrigger), nameof(BearTrapTrigger.InterestedInObject))]
            public static void InterestedInObjectPostfix(GameObject obj, ref GameObject __result)
            {
                if (__result == null) return;

                BasePlayer player = obj.ToBaseEntity() as BasePlayer;
                if (player == null || player.IPlayer == null) return;

                if (player.IPlayer.HasPermission(StaticConfigs.IgnoreTrapsPerms))
                    __result = null;
            }
        }

        private static class ServerProjectileHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyPostfix]
            [HarmonyPatch(typeof(ServerProjectile), "IsAValidHit")]
            public static void IsAValidHitPostfix(BaseEntity hitEnt, ref bool __result)
            {
                if (__result && hitEnt != null)
                    __result = !hitEnt.limitNetworking;
            }
        }

        /// <summary>
        /// Disable npc from targeting players with perm
        /// </summary>
        // ReSharper disable once InconsistentNaming
        private static class ScientistNPCHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyPrefix]
            [HarmonyPatch(typeof(ScientistNPC), nameof(ScientistNPC.OnAttacked))]
            public static bool OnAttackedPrefix(HitInfo info)
            {
                var initiator = info?.InitiatorPlayer;
                return initiator == null || !initiator.limitNetworking;
            }
        }

        /// <summary>
        /// Disable bradley from targeting players with perm
        /// </summary>
        // ReSharper disable once InconsistentNaming
        private static class BradleyAPCHarmony
        {
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(BradleyAPC), nameof(BradleyAPC.VisibilityTest))]
            public static IEnumerable<CodeInstruction> VisibilityTestTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
            {
                var list = instructions.ToList();

                int index = list.FindIndex(x => x.opcode == OpCodes.Stloc_1);

                if (index == -1)
                {
                    Log($"HARMONY EXCEPTION! COULDN'T PATCH {nameof(BradleyAPC.VisibilityTest)}() TO PREVENT BRADLEY FROM TARGETING PLAYERS", Console.RED);
                    return list;
                }

                index += 1;

                // Load arguments for method
                list.Insert(index++, new CodeInstruction(OpCodes.Ldloc_1));

                // Call method
                MethodInfo canTargetPlayer =
                    typeof(AtlasVanish).GetMethod(nameof(IsPlayerTargetableByAI), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(index++, new CodeInstruction(OpCodes.Call, canTargetPlayer));

                // Create new label to go to after if
                Label label = generator.DefineLabel();

                // Return if true
                list.Insert(index++, new CodeInstruction(OpCodes.Brtrue_S, label));
                list.Insert(index++, new CodeInstruction(OpCodes.Ldc_I4_0)); // Push false onto the stack
                list.Insert(index++, new CodeInstruction(OpCodes.Ret));

                list[index].WithLabels(label); // Add label to default instruction to go back to

                return list;
            }
        }

        /// <summary>
        /// Disable patrol helicopter from targeting players with perm
        /// </summary>
        private static class PatrolHelicopterHarmony
        {
            [HarmonyTranspiler]
            [HarmonyPatch(typeof(PatrolHelicopterAI), nameof(PatrolHelicopterAI.UpdateTargetList))]
            public static IEnumerable<CodeInstruction> UpdateTargetListTranspiler(IEnumerable<CodeInstruction> instructions)
            {
                var list = instructions.ToList();

                var targetMethod = typeof(Vector3Ex).GetMethod(nameof(Vector3Ex.Distance2D));
                int index = list.FindIndex(x => x.opcode == OpCodes.Call && (MethodInfo)x.operand == targetMethod);

                if (index == -1)
                {
                    Log($"HARMONY EXCEPTION! COULDN'T PATCH {nameof(PatrolHelicopterAI.UpdateTargetList)}() TO PREVENT HELI FROM TARGETING PLAYERS",
                        Console.RED);

                    return list;
                }

                index += 3;

                // Load arguments for method
                list.Insert(index, new CodeInstruction(OpCodes.Ldloc_S, 8));

                // Call method
                MethodInfo canTargetPlayer =
                    typeof(AtlasVanish).GetMethod(nameof(IsPlayerTargetableByAI), BindingFlags.Static | BindingFlags.NonPublic);

                list.Insert(++index, new CodeInstruction(OpCodes.Call, canTargetPlayer));

                // Return if false
                list.Insert(++index, new CodeInstruction(OpCodes.Brfalse_S, new Label().SetValue(25)));

                return list;
            }
        }

        /// <summary>
        /// Disable patrol helicopter from targeting players with perm on getting attacked
        /// </summary>
        private static class BaseVehicleHarmony
        {
            [HarmonyPrefix]
            [HarmonyPatch(typeof(BaseVehicle), nameof(BaseVehicle.OnAttacked))]
            public static bool OnAttackedPrefix(HitInfo info)
            {
                var initiator = info?.InitiatorPlayer;
                return initiator == null || !initiator.limitNetworking;
            }
        }

        private static class StorageContainerHarmony
        {
            // ReSharper disable once InconsistentNaming
            [HarmonyPrefix]
            [HarmonyPatch(typeof(StorageContainer), nameof(StorageContainer.CanOpenLootPanel))]
            public static bool CanOpenLootPanelPrefix(BasePlayer player, ref bool __result)
            {
                if (player != null && player.IPlayer.HasPermission(StaticConfigs.IgnoreLocksPerms))
                    __result = true;

                return !__result;
            }
        }

#endregion

#region Methods

        private void InitializeUserInterface()
        {
            Configuration configs = Configs;
            CreateVanishUI();

            foreach (var player in BasePlayer.activePlayerList)
            {
                if (!player.limitNetworking)
                    continue;

                if (!player.DoesPlayerHavePerms(configs.UsePerms))
                    continue;

                CuiHelper.DestroyUi(player, "VanishUI");

                bool hideUserInterface = player.IPlayer.HasPermission(configs.HideUserInterfacePerms);

                if (!hideUserInterface)
                    CuiHelper.AddUi(player, s_UserInterfaceCache);
            }
        }


        private void Disappear(BasePlayer player)
        {
            Log($"{player} is now invisible");
            Configuration configs = Configs;

            Effect effect = new Effect(configs.DisappearSfx, player, 0, Vector3.zero, Vector3.forward);
            EffectNetwork.Send(effect, player.Connection);

            player.PauseFlyHackDetection(float.MaxValue);
            player.limitNetworking = true;

            player.fallDamageEffect = new GameObjectRef();
            player.drownEffect = new GameObjectRef();

            if (!player.IsFlying && !player.isMounted)
                player.SendConsoleCommand("noclip");

            CuiHelper.DestroyUi(player, "VanishUI");

            bool hideUserInterface = player.IPlayer.HasPermission(configs.HideUserInterfacePerms);

            if (!hideUserInterface)
                CuiHelper.AddUi(player, s_UserInterfaceCache);

            string text = Lang(player, "BECOMING_INVISIBLE");
            player.ShowToast(GameTip.Styles.Red_Normal, text);
        }


        private void Reappear(BasePlayer player)
        {
            Log($"{player} is now visible");
            Configuration configs = Configs;

            Effect effect = new Effect(configs.AppearSfx, player, 0, Vector3.zero, Vector3.forward);
            EffectNetwork.Send(effect, player.Connection);

            player.ResetAntiHack();
            player.limitNetworking = false;

            player.drownEffect.guid = "28ad47c8e6d313742a7a2740674a25b5";
            player.fallDamageEffect.guid = "ca14ed027d5924003b1c5d9e523a5fce";

            CuiHelper.DestroyUi(player, "VanishUI");

            string text = Lang(player, "BECOMING_VISIBLE");
            player.ShowToast(GameTip.Styles.Red_Normal, text);
        }


#endregion

#region Utility

        private static bool IsPlayerTargetableByAI(BasePlayer player)
        {
            return player == null || player.IPlayer == null || !player.IPlayer.HasPermission(StaticConfigs.IgnoreAIPerms);
        }

        private static bool CanPlayerUseMeleeTool(BasePlayer player, BaseMelee melee)
        {
            return player == null || !player.limitNetworking || s_ToolsWhitelist.Contains(melee.PrefabName);
        }

        private static bool CanPlayerUseBaseProjectile(BasePlayer player)
        {
            return player == null || !player.limitNetworking;
        }

        private static bool CanPlayerUseThrownWeapon(BaseEntity.RPCMessage msg)
        {
            BasePlayer player = msg.player;
            return player == null || !player.limitNetworking;
        }

#endregion

#region UI

        private void CreateVanishUI()
        {
            Profile("Creating vanish ui...");
            var container = new CuiElementContainer();

            container.Add(new CuiElement
            {
                Name = "VanishUI",
                Parent = "Under",
                Components =
                {
                    new CuiRawImageComponent { Color = "1.000 1.000 1.000 1.000", Png = ImageLibrary?.Call<string>("GetImage", "vanish (Image)") },
                    new CuiRectTransformComponent { AnchorMin = "0.219 0.04", AnchorMax = "0.338 0.092", OffsetMin = "0 0", OffsetMax = "0 0" }
                }
            });

            s_UserInterfaceCache = container.ToJson();
        }

#endregion
    }
}

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