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

FREE NpcMovingControl : 1.0.6 1.0.6

Нет прав для скачивания
C#:
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.AI;
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Plugins.NpcMovingControlExtensionMethods;

namespace Oxide.Plugins
{
    [Info("NpcMovingControl", "Adem", "1.0.6")]
    class NpcMovingControl : RustPlugin
    {
        #region Variables
        static NpcMovingControl ins;
        [PluginReference] private Plugin BotReSpawn;
        HashSet<string> subscribeMethods = new HashSet<string>
        {
            "OnEntitySpawned",
            "OnCorpsePopulate"
        };
        #endregion Variables

        #region Hooks
        void Init()
        {
            Unsubscribes();
        }

        void OnServerInitialized()
        {
            ins = this;
            UpdateConfig();
            Subscribes();
            UpdateAllNpc();
            LootManager.InitialLootManagerUpdate();
        }

        void Unload()
        {
            ins = null;
        }

        void OnEntitySpawned(ScarecrowNPC scarecrowNPC)
        {
            if (scarecrowNPC == null)
                return;

            UpdateScarecrow(scarecrowNPC);
        }

        void OnEntitySpawned(ScientistNPC scientistNPC)
        {
            if (scientistNPC != null)
                UpdateNpc(scientistNPC);
        }

        void OnCorpsePopulate(ScarecrowNPC scarecrowNPC, NPCPlayerCorpse corpse)
        {
            if (scarecrowNPC == null || corpse == null)
                return;

            if (ins._config.scareCrowLootPrefabName == "")
                return;

            ins.NextTick(() =>
            {
                if (corpse == null)
                    return;

                LootManager.UpdateScareCrowLoot(corpse.containers[0]);
            });
        }
        #endregion Hooks

        #region Methods

        void UpdateConfig()
        {
            if (_config.version != Version)
            {
                if (_config.version.Patch == 0)
                    _config.scareCrowLootPrefabName = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab";

                if (_config.version.Patch <= 3)
                {
                    _config.scareCrowHealthScale = 0.5f;

                    _config.scarecrowWearConfigs = new List<WearConfig>
                    {
                        new WearConfig
                        {
                            wearItems =  new HashSet<WearItemConfig>
                            {
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.01.head",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.01.torso",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.01.legs",
                                    skinID = 0,
                                }
                            }
                        },
                        new WearConfig
                        {
                            wearItems =  new HashSet<WearItemConfig>
                            {
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.02.head",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.02.torso",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.02.legs",
                                    skinID = 0,
                                }
                            }
                        },
                        new WearConfig
                        {
                            wearItems =  new HashSet<WearItemConfig>
                            {
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.03.head",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.03.torso",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.03.legs",
                                    skinID = 0,
                                }
                            }
                        }
                    };
                }

                if (_config.scareCrowLootPrefabName == null)
                    _config.scareCrowLootPrefabName = "";

                _config.version = Version;

                SaveConfig();
            }
        }

        void Unsubscribes()
        {
            foreach (string hook in subscribeMethods)
                Unsubscribe(hook);
        }

        void Subscribes()
        {
            foreach (string hook in subscribeMethods)
                Subscribe(hook);
        }

        void UpdateAllNpc()
        {
            foreach (ScientistNPC scientistNPC in BaseNetworkable.serverEntities.OfType<ScientistNPC>())
                if (scientistNPC != null)
                    UpdateNpc(scientistNPC);
        }

        void UpdateScarecrow(ScarecrowNPC scarecrowNPC)
        {
            float newHealth = scarecrowNPC.MaxHealth() * _config.scareCrowHealthScale;

            scarecrowNPC.startHealth = newHealth;
            scarecrowNPC.InitializeHealth(newHealth, newHealth);

            if (_config.scarecrowPatrolRadius > -1)
            {
                scarecrowNPC.RoamAroundHomePoint = true;

                if (_config.scarecrowPatrolRadius > 0)
                {
                    NextTick(() =>
                    {
                        if (scarecrowNPC != null && scarecrowNPC.Brain != null)
                            scarecrowNPC.Brain.Navigator.BestCoverPointMaxDistance = _config.scarecrowPatrolRadius;
                    });
                }
            }

            WearConfig wearConfig = _config.scarecrowWearConfigs.GetRandom();

            if (wearConfig != null)
                ApplyWearConfigToNpc(scarecrowNPC, wearConfig);
        }

        void UpdateNpc(ScientistNPC scientistNPC)
        {
            TryWearNpc(scientistNPC);

            if (scientistNPC.ShortPrefabName == "scientistnpc_roam" && _config.npcPatrolRadius > 0)
                timer.In(2f, () => TryModifyNpc(scientistNPC));
        }

        void TryWearNpc(ScientistNPC scientistNPC)
        {
            CustomNpcWearConfig customNpcWearConfig = _config.customNpcWearConfigs.FirstOrDefault(x => x.npcShortPrefabName == scientistNPC.ShortPrefabName);

            if (customNpcWearConfig != null)
            {
                WearConfig wearConfig = customNpcWearConfig.wearConfigs.GetRandom();

                if (wearConfig != null)
                    ApplyWearConfigToNpc(scientistNPC, wearConfig);
            }
        }

        void ApplyWearConfigToNpc(NPCPlayer npcPlayer, WearConfig wearConfig)
        {
            npcPlayer.inventory.containerWear.ClearItemsContainer();

            foreach (WearItemConfig wearItemConfig in wearConfig.wearItems)
            {
                Item item = ItemManager.CreateByName(wearItemConfig.shortName, skin: wearItemConfig.skinID);

                if (item != null)
                    item.MoveToContainer(npcPlayer.inventory.containerWear);
            }
        }

        void TryModifyNpc(ScientistNPC scientistNPC)
        {
            if (scientistNPC == null || scientistNPC.Brain == null || scientistNPC.isMounted)
                return;

            if (scientistNPC.GetType().ToString() != "ScientistNPC" || scientistNPC.Brain.GetType().ToString() != "ScientistBrain")
                return;

            if (plugins.Exists("BotReSpawn") && (bool)BotReSpawn?.Call("IsBotReSpawn", (ulong)scientistNPC.userID))
                return;

            if (scientistNPC.Brain.states.ContainsKey(AIState.FollowPath))
            {
                scientistNPC.Brain.states[AIState.Roam] = new RoamState(scientistNPC.transform.position, _config.npcPatrolRadius, scientistNPC);

                scientistNPC.Brain.CurrentState.StateLeave(scientistNPC.Brain, scientistNPC);
                scientistNPC.Brain.states.Remove(AIState.FollowPath);

                scientistNPC.Brain.CurrentState = scientistNPC.Brain.states[AIState.Roam];
                scientistNPC.Brain.CurrentState?.StateEnter(scientistNPC.Brain, scientistNPC);
            }
        }
        #endregion Methods

        #region Classes
        class RoamState : BaseAIBrain.BasicAIState
        {
            ScientistNPC scientistNPC;
            Vector3 roamPosition;
            float roamRadius;

            internal RoamState(Vector3 roamPosition, float roamRadius, ScientistNPC scientistNPC) : base(AIState.Roam)
            {
                this.roamPosition = roamPosition;
                this.roamRadius = roamRadius;
                this.scientistNPC = scientistNPC;
            }

            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
            {
                base.StateThink(delta, brain, entity);
                float distanceFromPatrolCenter = Vector3.Distance(scientistNPC.transform.position, roamPosition);

                if (distanceFromPatrolCenter > roamRadius)
                {
                    Vector3 roamPositionOnNavmesh = GetPositionOnNavmesh(roamPosition, 3);
                    NpcRoamToPosition(roamPositionOnNavmesh);
                }
                else if (!brain.Navigator.Moving)
                {
                    Vector3 randomRoamPosition = GetRandomRoamPosition(roamPosition);
                    randomRoamPosition = GetPositionOnNavmesh(randomRoamPosition, 3);
                    NpcRoamToPosition(randomRoamPosition);
                }

                return StateStatus.Running;
            }

            Vector3 GetRandomRoamPosition(Vector3 source)
            {
                Vector2 vector2 = UnityEngine.Random.insideUnitCircle * roamRadius;
                return source + new Vector3(vector2.x, 0f, vector2.y);
            }

            void NpcRoamToPosition(Vector3 position)
            {
                Vector3 currentDestination = scientistNPC.Brain.Navigator.Destination;

                if (Vector3.Distance(currentDestination, position) < 0.1f)
                    return;

                scientistNPC.Brain.Navigator.SetDestination(position, BaseNavigator.NavigationSpeed.Slow);
            }

            Vector3 GetPositionOnNavmesh(Vector3 position, float radius)
            {
                NavMeshHit navMeshHit;
                if (NavMesh.SamplePosition(position, out navMeshHit, radius, scientistNPC.NavAgent.areaMask))
                {
                    NavMeshPath path = new NavMeshPath();

                    if (NavMesh.CalculatePath(scientistNPC.transform.position, navMeshHit.position, scientistNPC.NavAgent.areaMask, path))
                    {
                        if (path.status == NavMeshPathStatus.PathComplete)
                            return navMeshHit.position;
                        else
                            return path.corners.Last();
                    }
                }
                return position;
            }
        }

        static class LootManager
        {
            internal static void InitialLootManagerUpdate()
            {
                LootPrefabController.FindPrefabs();
            }

            internal static void UpdateScareCrowLoot(ItemContainer itemContainer)
            {
                if (itemContainer == null)
                    return;

                ClearItemsContainer(itemContainer);
                LootPrefabController.TryAddLootToScareCrow(itemContainer);
                itemContainer.capacity = itemContainer.itemList.Count;
            }

            static void ClearItemsContainer(ItemContainer container)
            {
                for (int i = container.itemList.Count - 1; i >= 0; i--)
                {
                    Item item = container.itemList[i];
                    item.RemoveFromContainer();
                    item.Remove();
                }
            }

            class LootPrefabController
            {
                static LootPrefabController scareCrowLootController;

                string prefabName;
                LootContainer.LootSpawnSlot[] lootSpawnSlot;
                LootSpawn lootDefinition;
                int maxDefinitionsToSpawn;
                int scrapAmount;

                internal static void TryAddLootToScareCrow(ItemContainer itemContainer)
                {
                    if (scareCrowLootController == null)
                        return;

                    TryFillContainerByPrefab(itemContainer);
                }

                internal static void FindPrefabs()
                {
                    if (!string.IsNullOrEmpty(ins._config.scareCrowLootPrefabName))
                        TrySaveLootPrefab(ins._config.scareCrowLootPrefabName);
                }

                internal static void TrySaveLootPrefab(string prefabName)
                {
                    GameObject gameObject = GameManager.server.FindPrefab(prefabName);
                    LootContainer lootContainer = gameObject.GetComponent<LootContainer>();

                    if (lootContainer != null)
                    {
                        SaveLootPrefabData(prefabName, lootContainer.LootSpawnSlots, lootContainer.scrapAmount, lootContainer.lootDefinition, lootContainer.maxDefinitionsToSpawn);
                        return;
                    }

                    global::HumanNPC humanNPC = gameObject.GetComponent<global::HumanNPC>();

                    if (humanNPC != null && humanNPC.LootSpawnSlots.Length > 0)
                    {
                        SaveLootPrefabData(prefabName, humanNPC.LootSpawnSlots, 0);
                        return;
                    }

                    global::ScarecrowNPC scarecrowNPC = gameObject.GetComponent<global::ScarecrowNPC>();

                    if (scarecrowNPC != null && scarecrowNPC.LootSpawnSlots.Length > 0)
                    {
                        SaveLootPrefabData(prefabName, scarecrowNPC.LootSpawnSlots, 0);
                        return;
                    }
                }

                internal static void SaveLootPrefabData(string prefabName, LootContainer.LootSpawnSlot[] lootSpawnSlot, int scrapAmount, LootSpawn lootDefinition = null, int maxDefinitionsToSpawn = 0)
                {
                    LootPrefabController lootPrefabData = new LootPrefabController
                    {
                        prefabName = prefabName,
                        lootSpawnSlot = lootSpawnSlot,
                        lootDefinition = lootDefinition,
                        maxDefinitionsToSpawn = maxDefinitionsToSpawn,
                        scrapAmount = scrapAmount
                    };

                    scareCrowLootController = lootPrefabData;
                }

                internal static void TryFillContainerByPrefab(ItemContainer itemContainer)
                {
                    LootPrefabController lootPrefabData = scareCrowLootController;
                    lootPrefabData.SpawnPrefabLootInCrate(itemContainer);
                }

                void SpawnPrefabLootInCrate(ItemContainer itemContainer)
                {
                    if (lootSpawnSlot != null && lootSpawnSlot.Length > 0)
                    {
                        foreach (LootContainer.LootSpawnSlot lootSpawnSlot in lootSpawnSlot)
                            for (int j = 0; j < lootSpawnSlot.numberToSpawn; j++)
                                if (UnityEngine.Random.Range(0f, 1f) <= lootSpawnSlot.probability)
                                    lootSpawnSlot.definition.SpawnIntoContainer(itemContainer);
                    }
                    else if (lootDefinition != null)
                    {
                        for (int i = 0; i < maxDefinitionsToSpawn; i++)
                            lootDefinition.SpawnIntoContainer(itemContainer);
                    }

                    GenerateScrap(itemContainer);
                }

                void GenerateScrap(ItemContainer itemContainer)
                {
                    if (scrapAmount <= 0)
                        return;

                    Item item = ItemManager.CreateByName("scrap", scrapAmount, 0);

                    if (item == null)
                        return;

                    if (!item.MoveToContainer(itemContainer))
                        item.Remove();
                }
            }
        }
        #endregion Classes

        #region Config 
        private PluginConfig _config;

        protected override void LoadDefaultConfig()
        {
            _config = PluginConfig.DefaultConfig();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            _config = Config.ReadObject<PluginConfig>();
            Config.WriteObject(_config, true);
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(_config);
        }

        public class CustomNpcWearConfig
        {
            [JsonProperty("Npc ShortPrefabName")] public string npcShortPrefabName { get; set; }
            [JsonProperty("Replace clothes for this preset?")] public bool enable { get; set; }
            [JsonProperty("Random Clothing presets")] public List<WearConfig> wearConfigs { get; set; }
        }

        public class WearConfig
        {
            [JsonProperty("List of items:")] public HashSet<WearItemConfig> wearItems { get; set; }
        }

        public class WearItemConfig
        {
            [JsonProperty("ShortName")] public string shortName { get; set; }
            [JsonProperty("skin (0 - default)")] public ulong skinID { get; set; }
        }

        private class PluginConfig
        {
            [JsonProperty("Version")] public VersionNumber version { get; set; }
            [JsonProperty("NPC patrol Radius (-1 - Do not change the behavior; 0 - Do not change the radius)")] public float npcPatrolRadius { get; set; }
            [JsonProperty("Scarecrow patrol Radius (-1 - Do not change the behavior)")] public float scarecrowPatrolRadius { get; set; }
            [JsonProperty("Replace scarecrow loot with prefab (Empty - do not replace)")] public string scareCrowLootPrefabName { get; set; }
            [JsonProperty("Scarecrow Health Scale")] public float scareCrowHealthScale { get; set; }
            [JsonProperty("Configuring the replacement of NPC clothes")] public HashSet<CustomNpcWearConfig> customNpcWearConfigs { get; set; }
            [JsonProperty("Configuring the replacement of Scarecrow clothes")] public List<WearConfig> scarecrowWearConfigs { get; set; }


            public static PluginConfig DefaultConfig()
            {
                PluginConfig pluginConfig = new PluginConfig()
                {
                    version = new VersionNumber(1, 0, 6),
                    npcPatrolRadius = 20,
                    scarecrowPatrolRadius = 0,
                    scareCrowHealthScale = 0.5f,
                    scareCrowLootPrefabName = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab",
                    customNpcWearConfigs = new HashSet<CustomNpcWearConfig>
                    {
                        new CustomNpcWearConfig
                        {
                            npcShortPrefabName = "scientistnpc_roam",
                            enable = true,
                            wearConfigs = new List<WearConfig>
                            {
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "jumpsuit.suit.blue",
                                            skinID = 0,
                                        },
                                        new WearItemConfig
                                        {
                                            shortName = "shoes.boots",
                                            skinID = 0,
                                        },
                                        new WearItemConfig
                                        {
                                            shortName = "hat.beenie",
                                            skinID = 0,
                                        },
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "jumpsuit.suit",
                                            skinID = 0,
                                        },
                                        new WearItemConfig
                                        {
                                            shortName = "shoes.boots",
                                            skinID = 0,
                                        },
                                        new WearItemConfig
                                        {
                                            shortName = "mask.bandana",
                                            skinID = 0,
                                        },
                                        new WearItemConfig
                                        {
                                            shortName = "hat.cap",
                                            skinID = 0,
                                        },
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "halloween.surgeonsuit",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "halloween.surgeonsuit",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit.arcticsuit",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit_scientist_nvgm",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit_scientist_peacekeeper",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit_scientist_arctic",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "attire.banditguard",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit.nomadsuit",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit.lumberjack",
                                            skinID = 0,
                                        }
                                    }
                                },
                                new WearConfig
                                {
                                    wearItems =  new HashSet<WearItemConfig>
                                    {
                                        new WearItemConfig
                                        {
                                            shortName = "hazmatsuit.diver",
                                            skinID = 0,
                                        }
                                    }
                                }
                            }
                        }
                    },
                    scarecrowWearConfigs = new List<WearConfig>
                    {
                        new WearConfig
                        {
                            wearItems =  new HashSet<WearItemConfig>
                            {
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.01.head",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.01.torso",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.01.legs",
                                    skinID = 0,
                                }
                            }
                        },
                        new WearConfig
                        {
                            wearItems =  new HashSet<WearItemConfig>
                            {
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.02.head",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.02.torso",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.02.legs",
                                    skinID = 0,
                                }
                            }
                        },
                        new WearConfig
                        {
                            wearItems =  new HashSet<WearItemConfig>
                            {
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.03.head",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.03.torso",
                                    skinID = 0,
                                },
                                new WearItemConfig
                                {
                                    shortName = "frankensteins.monster.03.legs",
                                    skinID = 0,
                                }
                            }
                        }
                    }
                };
                return pluginConfig;
            }
        }
        #endregion Config
    }
}

namespace Oxide.Plugins.NpcMovingControlExtensionMethods
{
    public static class ExtensionMethods
    {
        public static TSource Last<TSource>(this IList<TSource> source) => source[source.Count - 1];

        public static void ClearItemsContainer(this ItemContainer container)
        {
            for (int i = container.itemList.Count - 1; i >= 0; i--)
            {
                Item item = container.itemList[i];
                item.RemoveFromContainer();
                item.Remove();
            }
        }

        public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            using (var enumerator = source.GetEnumerator()) while (enumerator.MoveNext()) if (predicate(enumerator.Current)) return enumerator.Current;
            return default(TSource);
        }

        public static HashSet<T> OfType<T>(this IEnumerable<BaseNetworkable> source)
        {
            HashSet<T> result = new HashSet<T>();
            using (var enumerator = source.GetEnumerator()) while (enumerator.MoveNext()) if (enumerator.Current is T) result.Add((T)(object)enumerator.Current);
            return result;
        }
    }
}

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