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

FREE HumanNPC : 0.1.7 0.1.7

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Reference: Oxide.Ext.Rust
// Reference: RustBuild
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Data;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using Rust;
namespace Oxide.Plugins {
    [Info("HumanNPC", "Reneb", "0.1.7", ResourceId = 856)]
    class HumanNPC : RustPlugin {
        //////////////////////////////////////////////////////
        ///  Fields
        //////////////////////////////////////////////////////
        private static FieldInfo serverinput;
        private static FieldInfo viewangles;
        private static int playerLayer;
        private DamageTypeList emptyDamage;
        private List<Oxide.Plugins.Timer> TimersList;
        private static Vector3 Vector3Down;
        private static Vector3 Vector3Forward;
        private static Vector3 jumpPosition;
        private static int groundLayer;
        private static int blockshootLayer;
        StoredData storedData;
        static Hash<string, Waypoint> waypoints = new Hash<string, Waypoint>();
        Hash<string, HumanNPCInfo> humannpcs = new Hash<string, HumanNPCInfo>();
        [PluginReference]
        Plugin Kits;
        [PluginReference]
        public static Plugin PathFinding;
        //////////////////////////////////////////////////////
        ///  Cached Fields
        //////////////////////////////////////////////////////
        private Quaternion currentRot;
        private Vector3 closestHitpoint;
        private static Vector3 eyesPosition;
        private static RaycastHit hitinfo;
        private object closestEnt;
        //////////////////////////////////////////////////////
        ///  class WaypointInfo
        ///  Waypoint information, position & speed
        ///  public => will be saved in the data file
        ///  non public => won't be saved in the data file
        //////////////////////////////////////////////////////
        class WaypointInfo {
            public string x;
            public string y;
            public string z;
            public string s;
            Vector3 position;
            float speed;
            public WaypointInfo(Vector3 position, float speed) {
                x = position.x.ToString();
                y = position.y.ToString();
                z = position.z.ToString();
                s = speed.ToString();
                this.position = position;
                this.speed = speed;
            }
            public Vector3 GetPosition() {
                if (position == Vector3.zero) position = new Vector3(float.Parse(x), float.Parse(y), float.Parse(z));
                return position;
            }
            public float GetSpeed() {
                speed = Convert.ToSingle(s);
                return speed;
            }
        }
        //////////////////////////////////////////////////////
        ///  class SpawnInfo
        ///  Spawn information, position & rotation
        ///  public => will be saved in the data file
        ///  non public => won't be saved in the data file
        //////////////////////////////////////////////////////
        class SpawnInfo {
            public string x;
            public string y;
            public string z;
            public string rx;
            public string ry;
            public string rz;
            public string rw;
            Vector3 position;
            Quaternion rotation;
            public SpawnInfo(Vector3 position, Quaternion rotation) {
                x = position.x.ToString();
                y = position.y.ToString();
                z = position.z.ToString();
                rx = rotation.x.ToString();
                ry = rotation.y.ToString();
                rz = rotation.z.ToString();
                rw = rotation.w.ToString();
                this.position = position;
                this.rotation = rotation;
            }
            public Vector3 GetPosition() {
                if (position == Vector3.zero) position = new Vector3(float.Parse(x), float.Parse(y), float.Parse(z));
                return position;
            }
            public Quaternion GetRotation() {
                if (rotation.x == 0f) rotation = new Quaternion(Convert.ToSingle(rx), Convert.ToSingle(ry), Convert.ToSingle(rz), Convert.ToSingle(rw));
                return rotation;
            }
            public string String() {
                return string.Format("Pos({0},{1},{2}) - Rot({3},{4},{5},{6})", x, y, z, rx, ry, rz, rw);
            }
            public string ShortString() {
                return string.Format("Pos({0},{1},{2})", Math.Ceiling(position.x).ToString(), Math.Ceiling(position.y).ToString(), Math.Ceiling(position.z).ToString());
            }
            public SpawnInfo Clone() {
                var clone = (SpawnInfo)MemberwiseClone();
                return clone;
            }
        }
        //////////////////////////////////////////////////////
        ///  class Waypoint
        ///  Waypoint List information
        //////////////////////////////////////////////////////
        class Waypoint {
            public string Name;
            public List<WaypointInfo> Waypoints;
            public Waypoint() {
                Waypoints = new List<WaypointInfo>();
            }
            public void AddWaypoint(Vector3 position, float speed) {
                Waypoints.Add(new WaypointInfo(position, speed));
            }
        }
        //////////////////////////////////////////////////////
        ///  class HumanTrigger
        /// MonoBehaviour: managed by UnityEngine
        ///  This takes care of all collisions and area management of humanNPCs
        //////////////////////////////////////////////////////
        class HumanTrigger : MonoBehaviour {
            HumanPlayer npc;
            Collider[] colliderArray;
            List<BasePlayer> collidePlayers = new List<BasePlayer>();
            List<BasePlayer> triggerPlayers = new List<BasePlayer>();
            List<BasePlayer> removePlayers = new List<BasePlayer>();
            BasePlayer cachedPlayer;
            public float collisionRadius;
            void Awake() {
                npc = GetComponent<HumanPlayer>();
                collisionRadius = float.Parse(npc.info.collisionRadius);
                InvokeRepeating("UpdateTriggerArea", 2, 2);
            }
            void UpdateTriggerArea() {
                colliderArray = Physics.OverlapSphere(npc.player.transform.position, collisionRadius, playerLayer);
                foreach (Collider collider in colliderArray) {
                    cachedPlayer = collider.GetComponentInParent<BasePlayer>();
                    if (cachedPlayer == null) continue;
                    if (cachedPlayer == npc.player) continue;
                    collidePlayers.Add(cachedPlayer);
                    if (!triggerPlayers.Contains(cachedPlayer)) OnEnterCollision(cachedPlayer);
                }
                foreach (BasePlayer player in triggerPlayers) {
                    if (!collidePlayers.Contains(player)) removePlayers.Add(player);
                }
                foreach (BasePlayer player in removePlayers) {
                    OnLeaveCollision(player);
                }
                collidePlayers.Clear();
                removePlayers.Clear();
            }
            void OnEnterCollision(BasePlayer targetplayer) {
                triggerPlayers.Add(targetplayer);
                Interface.CallHook("OnEnterNPC", npc.player, targetplayer);
            }
            void OnLeaveCollision(BasePlayer targetplayer) {
                triggerPlayers.Remove(targetplayer);
                Interface.CallHook("OnLeaveNPC", npc.player, targetplayer);
            }
        }
        //////////////////////////////////////////////////////
        ///  class HumanLocomotion
        /// MonoBehaviour: managed by UnityEngine
        ///  This takes care of all movements and attacks of HumanNPCs
        //////////////////////////////////////////////////////
        class HumanLocomotion : MonoBehaviour {
            public HumanPlayer npc;
            public Vector3 StartPos = new Vector3(0f, 0f, 0f);
            public Vector3 EndPos = new Vector3(0f, 0f, 0f);
            public Vector3 LastPos = new Vector3(0f, 0f, 0f);
            public Vector3 nextPos = new Vector3(0f, 0f, 0f);
            public float waypointDone = 0f;
            public float secondsTaken = 0f;
            public float secondsToTake = 0f;
            public List<WaypointInfo> cachedWaypoints;
            public int currentWaypoint = -1;
            public float c_attackDistance = 0f;
            public float attackDistance = 0f;
            public float maxDistance = 0f;
            public float damageDistance = 0f;
            public float damageInterval = 0f;
            public float damageAmount = 0f;
            public float lastHit = 0f;
            public float speed = 4f;
            public int noPath = 0;
            public bool shouldMove = true;
            public BaseEntity attackEntity = null;
            public List<Vector3> pathFinding;
            public List<Vector3> temppathFinding;
            void Awake() {
                npc = GetComponent<HumanPlayer>();
                cachedWaypoints = GetWayPoints(npc.info.waypoint);
                attackDistance = float.Parse(npc.info.attackDistance);
                maxDistance = float.Parse(npc.info.maxDistance);
                damageDistance = float.Parse(npc.info.damageDistance);
                damageInterval = float.Parse(npc.info.damageInterval);
                damageAmount = float.Parse(npc.info.damageAmount);
                speed = float.Parse(npc.info.speed);
            }
            void FixedUpdate() {
                TryToMove();
            }
            void TryToMove() {
                if (npc.player.IsWounded()) return;
                if(attackEntity != null) MoveOrAttack(attackEntity);
                else if (secondsTaken == 0f) GetNextPath();
                if (StartPos != EndPos) Execute_Move();
                if (waypointDone >= 1f) secondsTaken = 0f;
            }
            void Execute_Move() {
                if (!shouldMove) return;
                secondsTaken += Time.deltaTime;
                waypointDone = Mathf.InverseLerp(0f, secondsToTake, secondsTaken);
                nextPos = Vector3.Lerp(StartPos, EndPos, waypointDone);
                npc.player.transform.position = nextPos;
                npc.player.TransformChanged();
            }
            void GetNextPath() {
                if (npc == null) npc = GetComponent<HumanPlayer>();
                LastPos = Vector3.zero;
                shouldMove = true;
                if (cachedWaypoints == null) {
                    shouldMove = false;
                    return;
                }
                Interface.CallHook("OnNPCPosition", npc.player, npc.player.transform.position);
                if (currentWaypoint +1 >= cachedWaypoints.Count) currentWaypoint = -1;
                currentWaypoint++;
                SetMovementPoint(npc.player.transform.position, cachedWaypoints[currentWaypoint].GetPosition(), cachedWaypoints[currentWaypoint].GetSpeed());
                if (npc.player.transform.position == cachedWaypoints[currentWaypoint].GetPosition()) {
                    npc.DisableMove();
                    npc.Invoke("AllowMove", cachedWaypoints[currentWaypoint].GetSpeed());
                    return;
                }
            }
            public void SetMovementPoint(Vector3 startpos, Vector3 endpos, float s) {
                StartPos = startpos;
                EndPos = endpos;
                if (StartPos != EndPos) secondsToTake = Vector3.Distance(EndPos, StartPos) / s;
                LookTowards(npc.player, EndPos);
                secondsTaken = 0f;
                waypointDone = 0f;
            }
            void MoveOrAttack(BaseEntity entity) {
                c_attackDistance = Vector3.Distance(entity.transform.position, npc.player.transform.position);
                shouldMove = false;
                if (((BaseCombatEntity)entity).IsAlive() && c_attackDistance < attackDistance && Vector3.Distance(LastPos, npc.player.transform.position) < maxDistance && noPath < 5) {
                    if (waypointDone >= 1f) {
                        if (pathFinding != null && pathFinding.Count > 0) pathFinding.RemoveAt(0);
                        waypointDone = 0f;
                    }
                    if (c_attackDistance < damageDistance && CanSee(npc.player, entity)) {
                        if (Time.realtimeSinceStartup > lastHit + damageInterval) DoHit(this, (BaseCombatEntity)entity);
                        return;
                    }
                    if (pathFinding == null || pathFinding.Count < 1) return;
                    shouldMove = true;
                    if (waypointDone == 0f) SetMovementPoint(npc.player.transform.position, pathFinding[0], speed*2);
                }
                else npc.EndAttackingEntity();
            }
            public void PathFinding() {
                if (IsInvoking("PathFinding")) {
                    CancelInvoke("PathFinding");
                }
                temppathFinding = (List<Vector3>)Interface.CallHook("FindBestPath", npc.player.transform.position, attackEntity.transform.position);
                if (temppathFinding == null) {
                    if (pathFinding == null || pathFinding.Count == 0) noPath++;
                    else noPath = 0;
                    Invoke("PathFinding", 2);
                }
                else {
                    noPath = 0;
                    pathFinding = temppathFinding;
                    waypointDone = 0f;
                    Invoke("PathFinding", pathFinding.Count/speed);
                }
            }
            public void GetBackToLastPos() {
                if (npc.player.transform.position != LastPos) {
                    SetMovementPoint(npc.player.transform.position, LastPos, 7f);
                    secondsTaken = 0.01f;
                }
            }
            public void Enable() {
                this.enabled = true;
            }
            public void Disable() {
                this.enabled = false;
            }
        }
        //////////////////////////////////////////////////////
        ///  class HumanPlayer : MonoBehaviour
        ///  MonoBehaviour: managed by UnityEngine
        /// Takes care of all the sub categories of the HumanNPCs
        //////////////////////////////////////////////////////
        class HumanPlayer : MonoBehaviour {
            public HumanNPCInfo info;
            public HumanLocomotion locomotion;
            public HumanTrigger trigger;
            public BasePlayer player;
            public bool hostile;
            public bool invulnerability;
            public bool stopandtalk;
            public float stopandtalkSeconds;
            public float lastMessage;
            void Awake() {
                player = GetComponent<BasePlayer>();
            }
            public void SetInfo(HumanNPCInfo info) {
                this.info = info;
                if (info == null) return;
                player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
                player.userID = ulong.Parse(info.userid);
                player.displayName = info.displayName;
                invulnerability = bool.Parse(info.invulnerability);
                stopandtalk = bool.Parse(info.stopandtalk);
                hostile = bool.Parse(info.hostile);
                stopandtalkSeconds = float.Parse(info.stopandtalkSeconds);
                player.InitializeHealth(float.Parse(info.health), float.Parse(info.health));
                player.syncPosition = true;
                player.transform.position = info.spawnInfo.GetPosition();
                player.TransformChanged();
                SetViewAngle(player, info.spawnInfo.GetRotation());
                player.EndSleeping();
                player.UpdateNetworkGroup();
                Interface.CallHook("OnNPCRespawn", player);
                locomotion = player.gameObject.AddComponent<HumanLocomotion>();
                trigger = player.gameObject.AddComponent<HumanTrigger>();
                enabled = true;
                lastMessage = Time.realtimeSinceStartup;
            }
            public void AllowMove() {
                locomotion.Enable();
            }
            public void DisableMove() {
                locomotion.Disable();
            }
            public void TemporaryDisableMove(float thetime = -1f) {
                if (thetime == -1f) thetime = stopandtalkSeconds;
                DisableMove();
                if (IsInvoking("AllowMove")) CancelInvoke("AllowMove");
                Invoke("AllowMove", thetime);
            }
            public void EndAttackingEntity() {
                if (locomotion.IsInvoking("PathFinding")) locomotion.CancelInvoke("PathFinding");
                locomotion.noPath = 0;
                locomotion.shouldMove = true;
                Debug.Log("end");
                Interface.CallHook("OnNPCStopTarget", player, locomotion.attackEntity);
                locomotion.attackEntity = null;
                player.health = float.Parse(info.health);
                locomotion.GetBackToLastPos();
            }
            public void StartAttackingEntity(BaseEntity entity) {
                if (Interface.CallHook("OnNPCStartTarget", player, entity) == null) {
                    locomotion.attackEntity = entity;
                    locomotion.pathFinding = null;
                    locomotion.temppathFinding = null;
                    if (locomotion.LastPos == Vector3.zero) locomotion.LastPos = player.transform.position;
                    if(IsInvoking("AllowMove")) {
                        CancelInvoke("AllowMove");
                        AllowMove();
                    }
                    locomotion.Invoke("PathFinding", 0);
                }
            }
            void OnDestroy() {
                GameObject.Destroy(locomotion);
                GameObject.Destroy(trigger);
            }
        }
        //////////////////////////////////////////////////////
        ///  class HumanNPCInfo
        ///  NPC information that will be saved inside the datafile
        ///  public => will be saved in the data file
        ///  non public => won't be saved in the data file
        //////////////////////////////////////////////////////
        class HumanNPCInfo {
            public string userid;
            public string displayName;
            public string invulnerability;
            public string health;
            public string respawn;
            public string respawnSeconds;
            public SpawnInfo spawnInfo;
            public string waypoint;
            public string collisionRadius;
            public string spawnkit;
            public string damageAmount;
            public string damageDistance;
            public string damageInterval;
            public string attackDistance;
            public string maxDistance;
            public string hostile;
            public string speed;
            public string stopandtalk;
            public string stopandtalkSeconds;
            public string enable;
            public string lootable;
            public List<string> message_hello;
            public List<string> message_bye;
            public List<string> message_use;
            public List<string> message_hurt;
            public List<string> message_kill;
            public HumanNPCInfo(ulong userid, Vector3 position, Quaternion rotation) {
                this.userid = userid.ToString();
                displayName = "NPC";
                invulnerability = "true";
                health = "50";
                hostile = "false";
                respawn = "true";
                respawnSeconds = "60";
                spawnInfo = new SpawnInfo(position, rotation);
                collisionRadius = "10";
                damageDistance = "3";
                damageAmount = "10";
                attackDistance = "100";
                maxDistance = "200";
                speed = "3";
                stopandtalk = "true";
                stopandtalkSeconds = "3";
                enable = "true";
                lootable = "true";
                damageInterval = "2";
            }
            public HumanNPCInfo Clone(ulong userid) {
                var clone = new HumanNPCInfo(userid, this.spawnInfo.GetPosition(), this.spawnInfo.GetRotation());
                clone.userid = userid.ToString();
                clone.displayName = this.displayName;
                clone.invulnerability = this.invulnerability;
                clone.health = this.health;
                clone.respawn = this.respawn;
                clone.respawnSeconds = this.respawnSeconds;
                clone.waypoint = this.waypoint;
                clone.collisionRadius = this.collisionRadius;
                clone.spawnkit = this.spawnkit;
                clone.damageAmount = this.damageAmount;
                clone.damageDistance = this.damageDistance;
                clone.attackDistance = this.attackDistance;
                clone.maxDistance = this.maxDistance;
                clone.hostile = this.hostile;
                clone.speed = this.speed;
                clone.stopandtalk = this.stopandtalk;
                clone.stopandtalkSeconds = this.stopandtalkSeconds;
                clone.lootable = this.lootable;
                clone.damageInterval = this.damageInterval;
                clone.message_hello = this.message_hello;
                clone.message_bye = this.message_bye;
                clone.message_use = this.message_use;
                clone.message_hurt = this.message_hurt;
                clone.message_kill = this.message_kill;
                return clone;
            }
        }
        class WaypointEditor : MonoBehaviour {
            public Waypoint targetWaypoint;
            void Awake() {
            }
        }
        class NPCEditor : MonoBehaviour {
            public BasePlayer player;
            public HumanPlayer targetNPC;
            void Awake() {
                player = GetComponent<BasePlayer>();
            }
        }
        class StoredData {
            public HashSet<Waypoint> WayPoints = new HashSet<Waypoint>();
            public HashSet<HumanNPCInfo> HumanNPCs = new HashSet<HumanNPCInfo>();
            public StoredData() {
            }
        }
        static float GetGroundY(Vector3 position) {
            position = position + jumpPosition;
            if (Physics.Raycast(position, Vector3Down, out hitinfo, 1.5f, groundLayer)) {
                return hitinfo.point.y;
            }
            return position.y - 1.5f;
        }
        void Loaded() {
            LoadData();
            serverinput = typeof(BasePlayer).GetField("serverInput", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
            viewangles = typeof(BasePlayer).GetField("viewAngles", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
            TimersList = new List<Oxide.Plugins.Timer>();
            eyesPosition = new Vector3(0f, 0.5f, 0f);
            jumpPosition = new Vector3(0f, 1f, 0f);
            Vector3Down = new Vector3(0f, -1f, 0f);
            Vector3Forward = new Vector3(0f, 0f, 1f);
        }
        void Unloaded() {
            SaveData();
        }
        void Unload() {
            var objects = GameObject.FindObjectsOfType(typeof(WaypointEditor));
            if (objects != null) foreach (var gameObj in objects) GameObject.Destroy(gameObj);
            objects = GameObject.FindObjectsOfType(typeof(HumanPlayer));
            if (objects != null) foreach (var gameObj in objects) GameObject.Destroy(gameObj);
            objects = GameObject.FindObjectsOfType(typeof(NPCEditor));
            if (objects != null) foreach (var gameObj in objects) GameObject.Destroy(gameObj);
            foreach (Oxide.Plugins.Timer timers in TimersList) timers.Destroy();
            TimersList.Clear();
        }
        void SaveData() {
            Interface.GetMod().DataFileSystem.WriteObject("HumanNPC", storedData);
        }
        void LoadData() {
            waypoints.Clear();
            try {
                storedData = Interface.GetMod().DataFileSystem.ReadObject<StoredData>("HumanNPC");
            }
            catch {
                storedData = new StoredData();
            }
            foreach (var thewaypoint in storedData.WayPoints) waypoints[thewaypoint.Name] = thewaypoint;
            foreach (var thenpc in storedData.HumanNPCs) humannpcs[thenpc.userid] = thenpc;
        }
        //////////////////////////////////////////////////////
        ///  Oxide Hooks
        //////////////////////////////////////////////////////
        //////////////////////////////////////////////////////
        ///  OnServerInitialized()
        ///  called when the server is done being initialized
        //////////////////////////////////////////////////////
        void OnServerInitialized() {
            playerLayer = LayerMask.GetMask(new string[] {
                "Player (Server)"
            }
            );
            groundLayer = LayerMask.GetMask(new string[] {
                "Construction", "Terrain", "World"
            }
            );
            blockshootLayer = LayerMask.GetMask(new string[] {
                "Construction", "Terrain", "World"
            }
            );
            RefreshAllNPC();
            emptyDamage = new DamageTypeList();
        }
        //////////////////////////////////////////////////////
        ///  OnServerSave()
        ///  called when a server performs a save
        //////////////////////////////////////////////////////
        void OnServerSave() {
            SaveData();
        }
        //////////////////////////////////////////////////////
        /// OnPlayerInput(BasePlayer player, InputState input)
        /// Called when a plugin presses a button
        //////////////////////////////////////////////////////
        void OnPlayerInput(BasePlayer player, InputState input) {
            if (input.WasJustPressed(BUTTON.USE)) {
                TryGetPlayerView(player, out currentRot);
                if (Physics.Raycast(new Ray(player.transform.position + eyesPosition, currentRot * Vector3.forward), out hitinfo, 5f, playerLayer)) if (hitinfo.collider.GetComponentInParent<HumanPlayer>() != null) Interface.CallHook("OnUseNPC", hitinfo.collider.GetComponentInParent<BasePlayer>(), player);
            }
        }
        //////////////////////////////////////////////////////
        /// OnEntityAttacked(BaseCombatEntity entity, HitInfo hitinfo)
        /// Called when an entity gets attacked (can be anything, building, animal, player..)
        //////////////////////////////////////////////////////
        void OnEntityAttacked(BaseCombatEntity entity, HitInfo hitinfo) {
            if (entity.GetComponent<HumanPlayer>() != null) {
                Interface.CallHook("OnHitNPC", entity.GetComponent<BaseCombatEntity>(), hitinfo);
                if (entity.GetComponent<HumanPlayer>().invulnerability) {
                    hitinfo.damageTypes = emptyDamage;
                    hitinfo.HitMaterial = 0;
                }
            }
        }
        //////////////////////////////////////////////////////
        /// OnEntityDeath(BaseEntity entity, HitInfo hitinfo)
        /// Called when an entity gets killed (can be anything, building, animal, player..)
        //////////////////////////////////////////////////////
        void OnEntityDeath(BaseEntity entity, HitInfo hitinfo) {
            if (entity.GetComponent<HumanPlayer>() != null) {
                Interface.CallHook("OnKillNPC", entity.GetComponent<BasePlayer>(), hitinfo);
                if (entity.GetComponent<HumanPlayer>().info.respawn == "true") {
                    var userid = entity.GetComponent<HumanPlayer>().info.userid;
                    TimersList.Add(timer.Once(float.Parse(entity.GetComponent<HumanPlayer>().info.respawnSeconds), () => SpawnNPC(userid, false)));
                }
            }
        }
        void OnPlayerLoot(PlayerLoot loot, BaseEntity target) {
            var userid = GetIDFromLoot(target);
            if (userid != 0L && humannpcs[userid.ToString()] != null) {
                Interface.CallHook("OnLootNPC", loot, target, userid.ToString());
            }
        }
        //////////////////////////////////////////////////////
        /// End of Oxide Hooks
        //////////////////////////////////////////////////////
        ulong GetIDFromLoot(BaseEntity target) {
            if (target is PlayerCorpse) return (target as PlayerCorpse).playerSteamID;
            if (target is BasePlayer) return (target as BasePlayer).userID;
            return 0L;
        }
        HumanPlayer FindHumanPlayerByID(ulong userid) {
            var allBasePlayer = UnityEngine.Resources.FindObjectsOfTypeAll<HumanPlayer>();
            foreach (HumanPlayer humanplayer in allBasePlayer) {
                if (humanplayer.player.userID == userid) return humanplayer;
            }
            return null;
        }
        BasePlayer FindPlayerByID(ulong userid) {
            var allBasePlayer = UnityEngine.Resources.FindObjectsOfTypeAll<BasePlayer>();
            foreach (BasePlayer player in allBasePlayer) {
                if (player.userID == userid) return player;
            }
            return null;
        }
        static void DoHit(HumanLocomotion loc, BaseCombatEntity target) {
            loc.lastHit = Time.realtimeSinceStartup;
            HitInfo info = new HitInfo(loc.npc.player, DamageType.Stab, loc.damageAmount, target.transform.position) {
                PointStart = loc.npc.player.transform.position, PointEnd = target.transform.position
            }
            ;
            target.SendMessage("OnAttacked", info, SendMessageOptions.DontRequireReceiver);
            loc.npc.player.SignalBroadcast(BaseEntity.Signal.Attack, null);
        }
        static void SetViewAngle(BasePlayer player, Quaternion ViewAngles) {
            viewangles.SetValue(player, ViewAngles);
            player.SendNetworkUpdate(BasePlayer.NetworkQueue.Positional);
        }
        void RefreshAllNPC() {
            List<string> npcspawned = new List<string>();
            foreach (KeyValuePair<string, HumanNPCInfo> pair in humannpcs) {
                if (pair.Value.enable == "true") {
                    BasePlayer findplayer = FindPlayerByID(Convert.ToUInt64(pair.Key));
                    npcspawned.Add(pair.Key);
                    if (findplayer == null) SpawnNPC(pair.Key, false);
                    else RefreshNPC(findplayer, false);
                }
            }
            foreach (BasePlayer player in UnityEngine.Resources.FindObjectsOfTypeAll<BasePlayer>()) {
                if (player.userID < 76560000000000000L && player.userID > 0L) if (!npcspawned.Contains(player.userID.ToString())) {
                    player.KillMessage();
                    Puts(string.Format("Detected a HumanNPC with no data or disabled, deleting him: {0} {1}", player.userID.ToString(), player.displayName));
                }
            }
        }
        void SpawnNPC(string userid, bool isediting) {
            if (humannpcs[userid] == null) return;
            if (!isediting && humannpcs[userid].enable == "false") return;
            var newplayer = GameManager.server.CreateEntity("player/player", humannpcs[userid].spawnInfo.GetPosition(), humannpcs[userid].spawnInfo.GetRotation()).ToPlayer();
            newplayer.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
            newplayer.userID = Convert.ToUInt64(userid);
            var humanplayer = newplayer.gameObject.AddComponent<HumanPlayer>();
            newplayer.displayName = (humannpcs[userid]).displayName;
            newplayer.Spawn(true);
            humanplayer.SetInfo(humannpcs[userid]);
            Puts("Spawned NPC: " + userid);
        }
        void RefreshNPC(BasePlayer player, bool isediting) {
            if (player.GetComponent<HumanPlayer>() != null) GameObject.Destroy(player.GetComponent<HumanPlayer>());
            var humanplayer = player.gameObject.AddComponent<HumanPlayer>();
            humanplayer.SetInfo(humannpcs[player.userID.ToString()]);
            if (humannpcs[player.userID.ToString()].enable == "false" && !isediting) {
                player.KillMessage();
                Puts("NPC was refreshed and Killed because he is disabled: " + player.userID.ToString());
                return;
            }
            Puts("Refreshed NPC: " + player.userID.ToString());
        }
        bool hasAccess(BasePlayer player) {
            if (player.net.connection.authLevel < 1) {
                SendReply(player, "You don't have access to this command");
                return false;
            }
            return true;
        }
        bool isEditingWP(BasePlayer player, int ttype) {
            if (player.GetComponent<WaypointEditor>() != null) {
                if (ttype == 0) SendReply(player, string.Format("You are already editing {0}", player.GetComponent<WaypointEditor>().targetWaypoint.Name.ToString()));
                return true;
            }
            else {
                if (ttype == 1) SendReply(player, string.Format("You are not editing any waypoints, say /waypoints_new or /waypoints_edit NAME"));
                return false;
            }
        }
        bool hasNoArguments(BasePlayer player, string[] args, int Number) {
            if (args.Length < Number) {
                SendReply(player, "Not enough Arguments");
                return true;
            }
            return false;
        }
        bool TryGetPlayerView(BasePlayer player, out Quaternion viewAngle) {
            viewAngle = new Quaternion(0f, 0f, 0f, 0f);
            var input = serverinput.GetValue(player) as InputState;
            if (input == null) return false;
            if (input.current == null) return false;
            viewAngle = Quaternion.Euler(input.current.aimAngles);
            return true;
        }
        bool TryGetClosestRayPoint(Vector3 sourcePos, Quaternion sourceDir, out object closestEnt, out Vector3 closestHitpoint) {
            Vector3 sourceEye = sourcePos + new Vector3(0f, 1.5f, 0f);
            UnityEngine.Ray ray = new UnityEngine.Ray(sourceEye, sourceDir * Vector3.forward);
            var hits = UnityEngine.Physics.RaycastAll(ray);
            float closestdist = 999999f;
            closestHitpoint = sourcePos;
            closestEnt = false;
            foreach (var hit in hits) if (hit.collider.GetComponentInParent<TriggerBase>() == null) if (hit.distance < closestdist) {
                closestdist = hit.distance;
                closestEnt = hit.collider;
                closestHitpoint = hit.point;
            }
            if (closestEnt is bool) return false;
            return true;
        }
        static bool CanSee(BasePlayer source, BaseEntity target) {
            if (UnityEngine.Physics.Linecast(source.transform.position + jumpPosition, target.transform.position + jumpPosition, blockshootLayer)) return false;
            return true;
        }
        string GetRandomMessage(List<string> messagelist) {
            return messagelist[GetRandom(0, messagelist.Count)];
        }
        int GetRandom(int min, int max) {
            return UnityEngine.Random.Range(min, max);
        }
        static List<WaypointInfo> GetWayPoints(string name) => waypoints[name]?.Waypoints;
        List<string> ListFromArgs(string[] args, int from) {
            var newlist = new List<string>();
            for (var i = from; i < args.Length; i++) {
                newlist.Add(args[i]);
            }
            return newlist;
        }
        public static void LookTowards(BasePlayer player, Vector3 pos) {
            if (pos != player.transform.position) SetViewAngle(player, Quaternion.LookRotation(pos - player.transform.position));
        }
        //////////////////////////////////////////////////////////////////////////////
        /// Chat Commands
        //////////////////////////////////////////////////////////////////////////////
        [ChatCommand("npc_add")]
        void cmdChatNPCAdd(BasePlayer player, string command, string[] args) {
            if (!hasAccess(player)) return;
            if (player.GetComponent<NPCEditor>() != null) {
                SendReply(player, "NPC Editor: Already editing an NPC, say /npc_end first");
                return;
            }
            if (!TryGetPlayerView(player, out currentRot)) return;
            var newplayer = GameManager.server.CreateEntity("player/player", player.transform.position, currentRot).ToPlayer();
            newplayer.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
            newplayer.displayName = "NPC";
            newplayer.Spawn(true);
            var humannpcinfo = new HumanNPCInfo(newplayer.userID, player.transform.position, currentRot);
            var humanplayer = newplayer.gameObject.AddComponent<HumanPlayer>();
            if (args.Length > 0) {
                if (humannpcs[args[0]] != null) {
                    humannpcinfo = humannpcs[args[0]].Clone(newplayer.userID);
                    humannpcinfo.userid = newplayer.userID.ToString();
                    humannpcinfo.spawnInfo = new SpawnInfo(player.transform.position, currentRot);
                    humanplayer.SetInfo(humannpcinfo);
                }
            }
            else {
                humanplayer.SetInfo(humannpcinfo);
            }
            var npceditor = player.gameObject.AddComponent<NPCEditor>();
            npceditor.targetNPC = humanplayer;
            if (humannpcs[newplayer.userID.ToString()] != null) storedData.HumanNPCs.Remove(humannpcs[newplayer.userID.ToString()]);
            humannpcs[newplayer.userID.ToString()] = humannpcinfo;
            storedData.HumanNPCs.Add(humannpcs[newplayer.userID.ToString()]);
            SaveData();
        }
        [ChatCommand("npc_edit")]
        void cmdChatNPCEdit(BasePlayer player, string command, string[] args) {
            if (!hasAccess(player)) return;
            if (player.GetComponent<NPCEditor>() != null) {
                SendReply(player, "NPC Editor: Already editing an NPC, say /npc_end first");
                return;
            }
            HumanPlayer targetnpc;
            ulong userid;
            if (args.Length == 0) {
                if (!TryGetPlayerView(player, out currentRot)) return;
                if (!TryGetClosestRayPoint(player.transform.position, currentRot, out closestEnt, out closestHitpoint)) return;
                if (((Collider)closestEnt).GetComponentInParent<HumanPlayer>() == null) {
                    SendReply(player, "This is not an NPC");
                    return;
                }
                targetnpc = ((Collider)closestEnt).GetComponentInParent<HumanPlayer>();
            }
            else if (humannpcs[args[0]] != null) {
                if (!ulong.TryParse(args[0], out userid)) {
                    SendReply(player, "/npc_edit TARGETID");
                    return;
                }
                targetnpc = FindHumanPlayerByID(userid);
                if (targetnpc == null) {
                    SpawnNPC(args[0], true);
                }
                targetnpc = FindHumanPlayerByID(userid);
                if (targetnpc == null) {
                    SendReply(player, "Couldn't Spawn the NPC");
                    return;
                }
            }
            else {
                SendReply(player, "You are not looking at an NPC or this userid doesn't exist");
                return;
            }
            var npceditor = player.gameObject.AddComponent<NPCEditor>();
            npceditor.targetNPC = targetnpc;
            SendReply(player, string.Format("NPC Editor: Start Editing {0} - {1}", npceditor.targetNPC.player.displayName, npceditor.targetNPC.player.userID.ToString()));
        }
        [ChatCommand("npc_list")]
        void cmdChatNPCList(BasePlayer player, string command, string[] args) {
            if (!hasAccess(player)) return;
            if (humannpcs.Count == 0) {
                SendReply(player, "No NPC created yet");
                return;
            }
            SendReply(player, "==== NPCs ====");
            foreach (KeyValuePair<string, HumanNPCInfo> pair in humannpcs) SendReply(player, string.Format("{0} - {1} - {2} {3}", pair.Key, pair.Value.displayName, pair.Value.spawnInfo.ShortString(), pair.Value.enable == "true" ? "" : "- Disabled"));
        }
        [ChatCommand("npc")]
        void cmdChatNPC(BasePlayer player, string command, string[] args) {
            if (!hasAccess(player)) return;
            if (player.GetComponent<NPCEditor>() == null) {
                SendReply(player, "NPC Editor: You need to be editing an NPC, say /npc_add or /npc_edit");
                return;
            }
            var npceditor = player.GetComponent<NPCEditor>();
            if (args.Length == 0) {
                SendReply(player, "<color=#81F781>/npc attackdistance</color><color=#F2F5A9> XXX </color>=> <color=#D8D8D8>Distance between him and the target needed for the NPC to ignore the target and go back to spawn</color>");
                SendReply(player, "<color=#81F781>/npc bye</color> reset/<color=#F2F5A9>\"TEXT\" \"TEXT2\" \"TEXT3\" </color>=><color=#D8D8D8> Dont forgot the \", this is what NPC with say when a player gets away, multiple texts are possible</color>");
                SendReply(player, "<color=#81F781>/npc damageamount</color> <color=#F2F5A9>XXX </color>=> <color=#D8D8D8>Damage done by that NPC when he hits a player</color>");
                SendReply(player, "<color=#81F781>/npc damagedistance</color> <color=#F2F5A9>XXX </color>=> <color=#D8D8D8>Min distance for the NPC to hit a player (3 is default, maybe 20-30 needed for snipers?)</color>");
                SendReply(player, "<color=#81F781>/npc damageinterval</color> <color=#F2F5A9>XXX </color>=> <color=#D8D8D8>Time to wait before attacking again (2 seconds is default)</color>");
                SendReply(player, "<color=#81F781>/npc enable</color> <color=#F2F5A9>true</color>/<color=#F6CECE>false</color><color=#D8D8D8>Enable/Disable the NPC, maybe save it for later?</color>");
                SendReply(player, "<color=#81F781>/npc health</color> <color=#F2F5A9>XXX </color>=> <color=#D8D8D8>To set the Health of the NPC</color>");
                SendReply(player, "<color=#81F781>/npc hello</color> <color=#F6CECE>reset</color>/<color=#F2F5A9>\"TEXT\" \"TEXT2\" \"TEXT3\" </color>=> <color=#D8D8D8>Dont forgot the \", this what will be said when the player gets close to the NPC</color>");
                SendReply(player, "<color=#81F781>/npc hostile</color> <color=#F2F5A9>true</color>/<color=#F6CECE>false</color> <color=#F2F5A9>XX </color>=> <color=#D8D8D8>To set it if the NPC is Hostile</color>");
                SendReply(player, "<color=#81F781>/npc hurt</color> <color=#F6CECE>reset</color>/<color=#F2F5A9>\"TEXT\" \"TEXT2\" \"TEXT3\"</color> => <color=#D8D8D8>Dont forgot the \", set a message to tell the player when he hurts the NPC</color>");
                SendReply(player, "<color=#81F781>/npc invulnerable</color> <color=#F2F5A9>true</color>/<color=#F6CECE>false </color>=> <color=#D8D8D8>To set the NPC invulnerable or not</color>");
                SendReply(player, "<color=#81F781>/npc kill</color> <color=#F6CECE>reset</color>/<color=#F2F5A9>\"TEXT\" \"TEXT2\" \"TEXT3\" </color>=> <color=#D8D8D8>Dont forgot the \", set a message to tell the player when he kills the NPC</color>");
                SendReply(player, "<color=#81F781>/npc kit</color> <color=#F6CECE>reset</color>/<color=#F2F5A9>\"KitName\" </color>=> <color=#D8D8D8>To set the kit of this NPC, requires the Kit plugin</color>");
                SendReply(player, "<color=#81F781>/npc lootable</color> <color=#F2F5A9>true</color>/<color=#F6CECE>false</color> <color=#F2F5A9>XX </color>=> <color=#D8D8D8>To set it if the NPC corpse is lootable or not</color>");
                SendReply(player, "<color=#81F781>/npc maxdistance</color> <color=#F2F5A9>XXX </color>=><color=#D8D8D8> Max distance from the spawn point that the NPC can run from (while attacking a player)</color>");
                SendReply(player, "<color=#81F781>/npc name</color> <color=#F2F5A9>\"THE NAME\"</color> =><color=#D8D8D8> To set a name to the NPC</color>");
                SendReply(player, "<color=#81F781>/npc radius</color> <color=#F2F5A9>XXX</color> =><color=#D8D8D8> Radius of which the NPC will detect the player</color>");
                SendReply(player, "<color=#81F781>/npc respawn</color> <color=#F2F5A9>true</color>/<color=#F6CECE>false</color> <color=#F2F5A9>XX </color>=> <color=#D8D8D8>To set it to respawn on death after XX seconds, default is instant respawn</color>");
                SendReply(player, "<color=#81F781>/npc spawn</color> <color=#F2F5A9>\"new\" </color>=> <color=#D8D8D8>To set the new spawn location</color>");
                SendReply(player, "<color=#81F781>/npc speed</color><color=#F2F5A9> XXX </color>=> <color=#D8D8D8>To set the NPC running speed (while chasing a player)</color>");
                SendReply(player, "<color=#81F781>/npc stopandtalk</color> <color=#F2F5A9>true</color>/<color=#F6CECE>false</color> XX <color=#F2F5A9>XX </color>=> <color=#D8D8D8>To choose if the NPC should stop & look at the player that is talking to him</color>");
                SendReply(player, "<color=#81F781>/npc use</color> <color=#F6CECE>reset</color>/<color=#F2F5A9>\"TEXT\" \"TEXT2\" \"TEXT3\"</color> => <color=#D8D8D8>Dont forgot the \", this what will be said when the player presses USE on the NPC</color>");
                SendReply(player, "<color=#81F781>/npc waypoints</color> <color=#F6CECE>reset</color>/<color=#F2F5A9>\"Waypoint list Name\" </color>=> <color=#D8D8D8>To set waypoints of an NPC, /npc_help for more informations</color>");
                return;
            }
            switch (args[0].ToLower()) {
                case "name" : if (args.Length == 1) {
                    SendReply(player, string.Format("This NPC name is: {0}", npceditor.targetNPC.info.displayName));
                    return;
                }
                npceditor.targetNPC.info.displayName = args[1];
                break;
                case "enable" : case "enabled" : if (args.Length == 1) {
                    SendReply(player, string.Format("This NPC Respawn enabled: {0}", npceditor.targetNPC.info.enable));
                    return;
                }
                if (args[1] == "true" || args[1] == "1") npceditor.targetNPC.info.enable = "true";
                else npceditor.targetNPC.info.enable = "false";
                br
// ... [Code preview truncated due to length. Full source in attached file] ...

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