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

FREE StateImprovement : 0.0.1 0.0.1

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Requires: Cordyceps
using Convert = System.Convert;
using Network;
using Oxide.Core.Plugins;
using Oxide.Core;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Rust.Ai;
using System;
using UnityEngine; 
using UnityEngine.AI; 
using  UnityEditor; 
using Oxide.Core.Libraries.Covalence;
using Oxide.Plugins;
	using Oxide.Core.Plugins;
using System.Threading;
	using Oxide.Core;
	using Newtonsoft.Json;//

namespace Oxide.Plugins
{
	[Info("StateImprovement", "obsol", "0.0.1")]
	[Description("For breaking monuments")]
	public class StateImprovement : CovalencePlugin
	{
		
		#region config
		public ConfigData config;
		public static float findNextZone = 300;
		public class ConfigData
		{
			
			[JsonProperty("findNextZone", ObjectCreationHandling = ObjectCreationHandling.Replace)]			
			public float findNextZone = 300;
			
			[JsonProperty("version", ObjectCreationHandling = ObjectCreationHandling.Replace)]
			public Oxide.Core.VersionNumber Version = default(VersionNumber);
		}
		protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<ConfigData>();
                if (config == null)
                {
                    LoadDefaultConfig();
                }
                else
                {
                    UpdateConfigValues();
                }
            }
            catch (Exception ex)
            {
                PrintError($"The configuration file is corrupted or missing.\n{ex}");
                LoadDefaultConfig();
            }
			StateImprovement.findNextZone=config.findNextZone;
            SaveConfig();
        }

        protected override void LoadDefaultConfig()
        {
			Puts("Version mismatch for config");
            config = new ConfigData();
            config.Version = Version;
        }

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

        private void UpdateConfigValues()
        {
            if (config.Version < Version)
            {
                if (config.Version <= default(VersionNumber))
                {
					Puts("Version mismatch for config");
                }
                config.Version = Version;
            }
        }

        private bool GetConfigValue<T>(out T value, params string[] path)
        {
            var configValue = Config.Get(path);
            if (configValue == null)
            {
                value = default(T);
                return false;
            }
            value = Config.ConvertValue<T>(configValue);
            return true;
        }

		#endregion
		
		[PluginReference]
		private Plugin MonuNet;
		public static StateImprovement _instance= null;
		public static AssociationAIZ getNextZone(AIInformationZone aiz){
			return StateImprovement._instance.getNextZone_local(aiz);
		}
			
		public AssociationAIZ getNextZone_local(AIInformationZone aiz){
			if (MonuNet != null) // check if plugin is loaded
			{
				return new AssociationAIZ(MonuNet.Call<List<System.Object>>("Find_Adjacent_Simplified", aiz));
			}
			return new AssociationAIZ();
		}
			
		public struct AssociationAIZ{
			public int a_path=-1;
			public int b_path=-1;
			public int a_idx=-1;
			public int b_idx=-1;
			public AIInformationZone a=null;
			public AIInformationZone b=null;	
			public AssociationAIZ(){
			}
			public AssociationAIZ(List<System.Object> packed){
				if(packed.Count()==3&&((List<int>)packed[2]).Count()==4&&packed[0] is AIInformationZone){
					a=(AIInformationZone)packed[0];
					b=(AIInformationZone)packed[1];
					a_path=(int)((List<int>)packed[2])[0];
					a_idx=(int)((List<int>)packed[2])[1];
					b_path=(int)((List<int>)packed[2])[2];
					b_idx=(int)((List<int>)packed[2])[3];
				}
			}
		}
		
		#region States
		public class CustomFollowPathState : BaseAIBrain.BaseFollowPathState
		{
			float TimeOnPath = 0f;
			public static float TimeLimit = 300;
			public static float TimeLimitMax = 600;
			HumanNPC self = null;
			public Vector3 lastPosition= new Vector3(0,0,0);
			public float timeAtPoint = 0;
			public static float stuckLimit = 5;
			public AIMovePointPath path;
			public StateStatus status;
			public AIMovePoint currentTargetPoint;
			public float currentWaitTime;
			private float currentLookTime = 0;
			private float next_zone = 0;
			private AIMovePointPath.PathDirection pathDirection;
			public int currentNodeIndex;
			public AIInformationZone current_zone;
			
			public static bool debugMode = false;
			public static BaseAIBrain debugEntity = null;
			
			public void debugState(string text, BaseAIBrain entity){
				if(debugMode){
					if(debugEntity==null){
						debugEntity=entity;
					}
					if(debugEntity!=entity) return;
					System.Console.ForegroundColor = ConsoleColor.Red;
					System.Console.WriteLine(text);
					System.Console.ResetColor();
					
				}
			}
		
			public CustomFollowPathState(){
			}
			
			public void setNextPath(BaseAIBrain brain, BaseEntity entity){
				
				// Get zone
				AIInformationZone forPoint = self.GetInformationZone(entity.transform.position);
				AIMovePointPath best = brain.Navigator.Path;
				
				// If there's a zone and paths, check for best path
				if(forPoint!=null||forPoint.paths.Count()>=0){					
					
					
					// Find best path you can reach
					foreach (AIMovePointPath aizPath in forPoint.paths)
					{
						if(best== brain.Navigator.Path || Vector3.Distance(aizPath.transform.position,entity.transform.position) < Vector3.Distance(best.transform.position,entity.transform.position))
						{
							NavMeshPath navMeshPath = new NavMeshPath();
							if(NavMesh.CalculatePath(entity.transform.position, aizPath.transform.position, 25, navMeshPath)){
								if(navMeshPath.status == NavMeshPathStatus.PathComplete)
								{
									best=aizPath;
								}
							}
							else{
								brain.Navigator.Agent.Warp(entity.transform.position);
							}
						}
					}
				}
				// If same path just flip
				if(best==brain.Navigator.Path){
					this.pathDirection = (this.pathDirection==AIMovePointPath.PathDirection.Forwards?AIMovePointPath.PathDirection.Backwards:AIMovePointPath.PathDirection.Forwards);
					//System.Console.ForegroundColor = ConsoleColor.Cyan;
					//System.Console.WriteLine("Flipping path");
					//System.Console.ResetColor();
				}else{
					//System.Console.ForegroundColor = ConsoleColor.Cyan;
					//System.Console.WriteLine("Changing path");
					//System.Console.ResetColor();
				}
				
				brain.Navigator.Path = best;
				
				
			
			}
			
			public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
			{
				base.StateLeave(brain, entity);
				//If we've been on path too long, find best path
				if(TimeOnPath >  TimeLimit){
					TimeOnPath=0f;
					setNextPath(brain,entity);
				}
				if(currentTargetPoint!=null){
					currentTargetPoint.ClearIfUsedBy(entity);
				}
				pathDirection = UnityEngine.Random.Range(0f,1f)>0.5f?AIMovePointPath.PathDirection.Forwards:AIMovePointPath.PathDirection.Backwards;
			}

			public void NextZoneProcessing(BaseAIBrain brain, BaseEntity entity){
				if(next_zone>StateImprovement.findNextZone){
					next_zone=0;
					//AIInformationZone source, out AIInformationZone target, out int path, out int idx
					AIInformationZone target = null;
					int path = -1;
					int idx = -1;
					StateImprovement.AssociationAIZ result = new AssociationAIZ();
					MonumentInfo mi = null;
					try{
						result = StateImprovement.getNextZone(current_zone);
						if(result.a==null&&result.b==null){
							if(StateImprovement._instance.MonuNet!=null){
								mi = StateImprovement._instance.MonuNet.Call<MonumentInfo>("Find_Associated_Monument", current_zone);
								if(mi==null){
									System.Console.ForegroundColor= System.ConsoleColor.Red;
									System.Console.WriteLine(" No monument at "+entity.transform.position+" | "+entity.transform.name);
									System.Console.ResetColor();								
								}
								else{
									System.Console.ForegroundColor= System.ConsoleColor.Red;
									System.Console.WriteLine(" Failing monument: "+mi.displayPhrase.english+" | "+entity.transform.name);
									System.Console.ResetColor();
								}
							}
							return ;
						}else{		
							if(StateImprovement._instance.MonuNet!=null){
								mi = StateImprovement._instance.MonuNet.Call<MonumentInfo>("Find_Associated_Monument", current_zone);	
								if(mi==null){			
									System.Console.ForegroundColor= System.ConsoleColor.Green;
									System.Console.WriteLine(" No monument at "+entity.transform.position+" | "+entity.transform.name);									
									System.Console.ResetColor();								
								}
								else{
									System.Console.ForegroundColor= System.ConsoleColor.Green;
									System.Console.WriteLine(" Found monument:"+mi.displayPhrase.english+" | "+entity.transform.name);
								}
									if(result.b!=null){
										current_zone=result.b;
										brain.Navigator.Path=null;
										this.path = null;
									}
									System.Console.ResetColor();	
							}
						
						}
					}
					catch(Exception e){
						System.Console.ForegroundColor= System.ConsoleColor.DarkRed;
						System.Console.WriteLine(" ERROR FOR "+entity.transform.position+" | "+entity.transform.name);
						System.Console.WriteLine("CZ : "+(current_zone==null?"N":"Y")+" | A: "+(result.a==null?"N":"Y")+" | B: "+(result.b==null?"N":"Y")+" | MonInf :"+(mi==null?"N":"Y")+"["+(mi==null?"---":mi.displayPhrase.english)+"]");
						
						System.Console.ResetColor();	
						
					}
				}
			}
			public bool SetFirstZone(BaseAIBrain brain, BaseEntity entity)
			{
				if(current_zone==null){
					current_zone = AIInformationZone.GetForPoint(entity.ServerPosition, true);
					if (current_zone == null)
					{
						return false;
					}
				}
				return true;
			}
			public bool SetPath(BaseAIBrain brain, BaseEntity entity)
			{
				this.path = brain.Navigator.Path;
				if (this.path == null)
				{
					this.path = brain.Navigator.Path = current_zone.GetNearestPath(entity.ServerPosition);
					if (this.path == null)
					{
						if(current_zone.movePoints.Count>0){
							AIMovePointPath aimpp =  current_zone.gameObject.GetComponent<AIMovePointPath>();
							if(aimpp==null){
								aimpp = current_zone.gameObject.AddComponent<AIMovePointPath>();
							}
							aimpp.Points = new List<AIMovePoint>(current_zone.movePoints.ToArray());
							this.path = brain.Navigator.Path = aimpp;
						}
						if (this.path == null)
						{
							return false;
						}
					}
				}
				try{
					//Find a point
					this.currentNodeIndex = this.path.FindNearestPointIndex(entity.ServerPosition);
					this.currentTargetPoint = this.path.FindNearestPoint(entity.ServerPosition);
				}catch(Exception e){
					if(StateImprovement._instance.MonuNet!=null){
						MonumentInfo mi = StateImprovement._instance.MonuNet.Call<MonumentInfo>("Find_Associated_Monument", current_zone);	
						if(mi==null){			
							System.Console.ForegroundColor= System.ConsoleColor.DarkCyan;
							System.Console.WriteLine(" No monument at "+entity.transform.position+" for "+entity.transform.name+"| ");
							
							System.Console.ResetColor();								
						}
						else{		
							System.Console.ForegroundColor= System.ConsoleColor.DarkCyan;
							System.Console.WriteLine(" Found monument:"+mi.displayPhrase.english+" for "+entity.transform.name+"| ");
							
							System.Console.ResetColor();									
						}
					}
					System.Console.WriteLine("IDX: "+currentNodeIndex+" | LEN: "+this.path.Points.Count);//			
				}
				if (this.currentTargetPoint == null)
				{
					return false;
				}
				//Get next index
				currentTargetPoint.ClearIfUsedBy(entity);
				
				int i = 0;
				//While next point is busy, pick next next point (up to path length)
				do{
					//Get next index
					
					this.currentNodeIndex = this.path.GetNextPointIndex(this.currentNodeIndex, ref this.pathDirection);
					this.currentTargetPoint = this.path.GetPointAtIndex(this.currentNodeIndex);
					i++;
				}while(i<this.path.Points.Count() && this.currentTargetPoint.InUse());
				
				currentTargetPoint.SetUsedBy(entity,20f);
				return true;
			}
			public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
			{
				NextZoneProcessing(brain,entity);
				debugState("Start Follow Path",brain);
				if(self==null) 
					self= entity as HumanNPC;
					
				timeAtPoint=0;
				lastPosition = entity.transform.position;
				
				this.status = StateStatus.Error;
				brain.Navigator.SetBrakingEnabled(false);
				if(!SetFirstZone(brain,entity)){
					return;
				}
				//Set the path
				if(!SetPath(brain,entity)){
					return;
				}
				
				this.status = StateStatus.Running;
				
				// figure out necessary speed
				this.currentWaitTime = 0f;
				float distance = Vector3.Distance(this.currentTargetPoint.transform.position,entity.ServerPosition);
				BaseNavigator.NavigationSpeed speed = BaseNavigator.NavigationSpeed.Slowest;
				if(distance < 25){
					speed = BaseNavigator.NavigationSpeed.Slow;
				}
				else if(distance < 50){
					speed = BaseNavigator.NavigationSpeed.Normal;
				}
				else{
					speed = BaseNavigator.NavigationSpeed.Fast;
				}
				
				// Lock for self and head to point
				currentTargetPoint.SetUsedBy(entity,20f);
				brain.Navigator.SetDestination(this.currentTargetPoint.transform.position, speed, 0f, 0f);
			}
			
			public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
			{
				next_zone+=delta;
				/*
				debugState("Thinking",brain);				
				if (this.status == global::StateStatus.Error)
				{
					debugState("  Error return",brain);
					return this.status;
				}
				if (!brain.Navigator.Moving)
				{
					debugState("  Stuck or moving",brain);
					if (this.currentWaitTime <= 0f && this.currentTargetPoint.HasLookAtPoints())
					{
						debugState("    Look At Point",brain);
						global::UnityEngine.Transform randomLookAtPoint = this.currentTargetPoint.GetRandomLookAtPoint();
						if (randomLookAtPoint != null)
						{
							brain.Navigator.SetFacingDirectionOverride(global::UnityEngine.Vector3Ex.Direction2D(randomLookAtPoint.transform.position, entity.ServerPosition));
						}
					}
					if (this.currentTargetPoint.WaitTime > 0f)
					{
						this.currentWaitTime += delta;
					}
					if (this.currentTargetPoint.WaitTime <= 0f || this.currentWaitTime >= this.currentTargetPoint.WaitTime)
					{
						debugState("    Done waiting at point",brain);
						brain.Navigator.ClearFacingDirectionOverride();
						this.currentWaitTime = 0f;
						int num = this.currentNodeIndex;
						this.currentNodeIndex = this.path.GetNextPointIndex(this.currentNodeIndex, ref this.pathDirection);
						this.currentTargetPoint = this.path.GetPointAtIndex(this.currentNodeIndex);
						if ((!(this.currentTargetPoint != null) || this.currentNodeIndex != num) && (this.currentTargetPoint == null || !brain.Navigator.SetDestination(this.currentTargetPoint.transform.position, global::BaseNavigator.NavigationSpeed.Slow, 0f, 0f)))
						{
							debugState("      Error pathing in think - Target point: "+(this.currentTargetPoint == null).ToString()+" \n      Target Index and old : "+this.currentNodeIndex.ToString()+":"+num.ToString(), brain);
							return global::StateStatus.Error;
						}
					}
				}
				else if (this.currentTargetPoint != null)
				{
					debugState("  Goto point",brain);
					brain.Navigator.SetDestination(this.currentTargetPoint.transform.position, global::BaseNavigator.NavigationSpeed.Slow, 1f, 0f);
				}
				return global::StateStatus.Running;
				/*/
				
				debugState("Thinking",brain);
				TimeOnPath+=delta;
				currentLookTime+=delta;
				
				// If position changed, reset stuck time, otherwise increment
				if(entity.transform.position!=lastPosition){
					timeAtPoint=0;
				}
				else{
					timeAtPoint+=delta;
				}
				if (this.status == StateStatus.Error)
				{
					this.currentWaitTime = 0f;
					return this.status;
				}
				
				// If we're over the stuck limit we're stuck
				bool isStuck=timeAtPoint>stuckLimit;
				
				// If we're done moving or we're stuck
				if (!brain.Navigator.Moving||isStuck)
				{
					debugState("Stuck or not moving",brain);
					//If we're stuck flip direction
					if(isStuck){
						debugState("We're stuck",brain);
						pathDirection = UnityEngine.Random.Range(0f,1f)>0.5f?AIMovePointPath.PathDirection.Forwards:AIMovePointPath.PathDirection.Backwards;
						//Reset wait time
						this.currentWaitTime = 0f;
						return StateStatus.Error;
					}
					
					// If the point has lookat points, look at them
					if (this.currentWaitTime <= 0f && this.currentTargetPoint.HasLookAtPoints())
					{
						debugState("Look At Point",brain);
						UnityEngine.Transform randomLookAtPoint = this.currentTargetPoint.GetRandomLookAtPoint();
						if (randomLookAtPoint != null)
						{
							brain.Navigator.SetFacingDirectionOverride(UnityEngine.Vector3Ex.Direction2D(randomLookAtPoint.transform.position, entity.ServerPosition));
						}
					} 
					
					// If not, look at a sorta forward location
					else if(currentLookTime>10){
						
						debugState("Random look",brain);
						currentLookTime=0;
						float x=UnityEngine.Random.Range(-1.5f,1.5f);
						float y=UnityEngine.Random.Range(-1.5f,1.5f);
						brain.Navigator.SetFacingDirectionOverride(UnityEngine.Vector3Ex.Direction2D(entity.transform.position+entity.transform.forward+new Vector3(x,0,y), entity.ServerPosition));
					}
					
					//  Increment wait time
					this.currentWaitTime += delta;
					
					// If it`s time to change path, return finished
					if(TimeOnPath >  TimeLimit){
						debugState("Done with path, finishing",brain);
						brain.Navigator.ClearFacingDirectionOverride();
						return StateStatus.Finished;
					}
					
					// If point has no wait time or we're over the wait time
					if (this.currentTargetPoint.WaitTime <= 0f || this.currentWaitTime >= this.currentTargetPoint.WaitTime)
					{
						debugState("Done waiting at point",brain);
						//Allow freelook
						brain.Navigator.ClearFacingDirectionOverride();
						
						//Reset wait time
						this.currentWaitTime = 0f;
						
						//Take note of current index
						int num = this.currentNodeIndex;
						
						currentTargetPoint.ClearIfUsedBy(entity);
						
						return StateStatus.Finished;
					}else{
						currentTargetPoint.SetUsedBy(entity,20f);						
					}
				}
				// If still moving and there's a point, move to point
				else if (this.currentTargetPoint != null)
				{
					currentTargetPoint.SetUsedBy(entity,20f);
					debugState("Continuing Path",brain);
				}
				// Note last positino and keep running
				
				debugState("Still running at "+entity.transform.position.ToString(),brain);
				lastPosition=entity.transform.position;
				return StateStatus.Running;
				//*/
			}
				


		}
		public class CustomRoamState : BaseAIBrain.BaseRoamState
		{
			float TimeOnPath = 0f;
			public static float TimeLimit = 300;
			public static float TimeLimitMax = 600;
			HumanNPC self = null;
			public Vector3 lastPosition= new Vector3(0,0,0);
			public float timeAtPoint = 0;
			public static float stuckLimit = 5;
			public AIMovePointPath path;
			public StateStatus status;
			public AIMovePoint currentTargetPoint;
			public float currentWaitTime;
			private float currentLookTime = 0;
			private float next_zone = 3000;
			private AIMovePointPath.PathDirection pathDirection;
			public int currentNodeIndex;
			public AIInformationZone current_zone;
			
			public static bool debugMode = false;
			public static BaseAIBrain debugEntity = null;
			
			public void debugState(string text, BaseAIBrain entity){
				if(debugMode){
					if(debugEntity==null){
						debugEntity=entity;
					}
					if(debugEntity!=entity) return;
					System.Console.ForegroundColor = ConsoleColor.Red;
					System.Console.WriteLine(text);
					System.Console.ResetColor();
					
				}
			}
			
			public CustomRoamState(){
			}
			
			public void setNextPath(BaseAIBrain brain, BaseEntity entity){
				
				// Get zone
				AIInformationZone forPoint = self.GetInformationZone(entity.transform.position);
				AIMovePointPath best = brain.Navigator.Path;
				
				// If there's a zone and paths, check for best path
				if(forPoint!=null||forPoint.paths.Count()>=0){					
					
					
					// Find best path you can reach
					foreach (AIMovePointPath aizPath in forPoint.paths)
					{
						if(best== brain.Navigator.Path || Vector3.Distance(aizPath.transform.position,entity.transform.position) < Vector3.Distance(best.transform.position,entity.transform.position))
						{
							NavMeshPath navMeshPath = new NavMeshPath();
							if(NavMesh.CalculatePath(entity.transform.position, aizPath.transform.position, 25, navMeshPath)){
								if(navMeshPath.status == NavMeshPathStatus.PathComplete)
								{
									best=aizPath;
								}
							}
							else{
								brain.Navigator.Agent.Warp(entity.transform.position);
							}
						}
					}
				}
				// If same path just flip
				if(best==brain.Navigator.Path){
					this.pathDirection = (this.pathDirection==AIMovePointPath.PathDirection.Forwards?AIMovePointPath.PathDirection.Backwards:AIMovePointPath.PathDirection.Forwards);
					System.Console.ForegroundColor = ConsoleColor.Cyan;
					///System.Console.WriteLine("Flipping path");
					System.Console.ResetColor();
				}else{
					System.Console.ForegroundColor = ConsoleColor.Cyan;
					//System.Console.WriteLine("Changing path");
					System.Console.ResetColor();
				}
				
				brain.Navigator.Path = best;
				
				
			
			}
			
			public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
			{
				base.StateLeave(brain, entity);
				//If we've been on path too long, find best path
				if(TimeOnPath >  TimeLimit){
					TimeOnPath=0f;
					setNextPath(brain,entity);
				}
				if(currentTargetPoint!=null){
					currentTargetPoint.ClearIfUsedBy(entity);
				}
				pathDirection = UnityEngine.Random.Range(0f,1f)>0.5f?AIMovePointPath.PathDirection.Forwards:AIMovePointPath.PathDirection.Backwards;
			}

			public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
			{
				if(next_zone>StateImprovement.findNextZone && current_zone!=null){
					next_zone=0;
					//AIInformationZone source, out AIInformationZone target, out int path, out int idx
					AIInformationZone target = null;
					int path = -1;
					int idx = -1;
					StateImprovement.AssociationAIZ result = StateImprovement.getNextZone(current_zone);
					if(result.a==null&&result.b==null){
						if(StateImprovement._instance.MonuNet!=null){
							MonumentInfo mi = StateImprovement._instance.MonuNet.Call<MonumentInfo>("Find_Associated_Monument", current_zone);
							if(mi==null){
								System.Console.ForegroundColor= System.ConsoleColor.Red;
								System.Console.WriteLine(" No monument at "+entity.transform.position+" | "+entity.transform.name);
								System.Console.ResetColor();								
							}
							else{
								System.Console.ForegroundColor= System.ConsoleColor.Red;
								System.Console.WriteLine(" Failing monument: "+mi.displayPhrase.english+" | "+entity.transform.name);
								System.Console.ResetColor();
							}
						}
						return ;
					}else{		
						if(StateImprovement._instance.MonuNet!=null){
								MonumentInfo mi = StateImprovement._instance.MonuNet.Call<MonumentInfo>("Find_Associated_Monument", current_zone);	
							if(mi==null){			
								System.Console.ForegroundColor= System.ConsoleColor.Green;
								System.Console.WriteLine(" No monument at "+entity.transform.position+" | "+entity.transform.name);		
								
							}							
							else{
								System.Console.ForegroundColor= System.ConsoleColor.Green;
								System.Console.WriteLine(" Found monument:"+mi.displayPhrase.english+" | "+entity.transform.name);
							}
							if(result.b!=null&&current_zone!=result.b){
								System.Console.ForegroundColor= System.ConsoleColor.Green;
								System.Console.WriteLine(" CHANGED ZONED FOR "+entity.transform.name);
								current_zone=result.b;
								brain.Navigator.Path=null;
								this.path = null;
							}
							System.Console.ResetColor();	
						}
					
					}
				}
				debugState("Start Follow Path",brain);
				if(self==null) 
					self= entity as HumanNPC;
					
				timeAtPoint=0;
				lastPosition = entity.transform.position;
				
				this.status = StateStatus.Error;
				brain.Navigator.SetBrakingEnabled(false);
				
				//Set the path
				this.path = brain.Navigator.Path;
				if (this.path == null)
				{
					current_zone = AIInformationZone.GetForPoint(entity.ServerPosition, true);
					if (current_zone == null)
					{
						return;
					}
					this.path = brain.Navigator.Path = current_zone.GetNearestPath(entity.ServerPosition);
					if (this.path == null)
					{
						return;
					}
				}
				try{
					//Find a point
					this.currentNodeIndex = this.path.FindNearestPointIndex(entity.ServerPosition);
					this.currentTargetPoint = this.path.FindNearestPoint(entity.ServerPosition);
				}catch(Exception e){
					if(StateImprovement._instance.MonuNet!=null){
						MonumentInfo mi = StateImprovement._instance.MonuNet.Call<MonumentInfo>("Find_Associated_Monument", current_zone);	
						if(mi==null){			
							System.Console.ForegroundColor= System.ConsoleColor.DarkCyan;
							System.Console.Write(" No monument at "+entity.transform.position+" for "+entity.transform.name+"| ");
							
							System.Console.ResetColor();								
						}
						else{		
							System.Console.ForegroundColor= System.ConsoleColor.DarkCyan;
							System.Console.Write(" Found monument:"+mi.displayPhrase.english+" for "+entity.transform.name+"| ");
							
							System.Console.ResetColor();									
						}
					}
					System.Console.WriteLine("IDX: "+currentNodeIndex+" | LEN: "+this.path.Points.Count);//
				}
				if (this.currentTargetPoint == null)
				{
					return;
				}
				//Get next index
				currentTargetPoint.ClearIfUsedBy(entity);
				
				int i = 0;
				//While next point is busy, pick next next point (up to path length)
				do{
					//Get next index
					
					this.currentNodeIndex = this.path.GetNextPointIndex(this.currentNodeIndex, ref this.pathDirection);
					this.currentTargetPoint = this.path.GetPointAtIndex(this.currentNodeIndex);
					i++;
				}while(i<this.path.Points.Count() && this.currentTargetPoint.InUse());
				
				currentTargetPoint.SetUsedBy(entity,20f);
				this.status = StateStatus.Running;
				
				// figure out necessary speed
				this.currentWaitTime = 0f;
				float distance = Vector3.Distance(this.currentTargetPoint.transform.position,entity.ServerPosition);
				BaseNavigator.NavigationSpeed speed = BaseNavigator.NavigationSpeed.Slowest;
				if(distance < 25){
					speed = BaseNavigator.NavigationSpeed.Slow;
				}
				else if(distance < 50){
					speed = BaseNavigator.NavigationSpeed.Normal;
				}
				else{
					speed = BaseNavigator.NavigationSpeed.Fast;
				}
				
				// Lock for self and head to point
				currentTargetPoint.SetUsedBy(entity,20f);
				brain.Navigator.SetDestination(this.currentTargetPoint.transform.position, speed, 0f, 0f);
			}
			
			public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
			{
				next_zone+=delta;
				/*
				debugState("Thinking",brain);				
				if (this.status == global::StateStatus.Error)
				{
					debugState("  Error return",brain);
					return this.status;
				}
				if (!brain.Navigator.Moving)
				{
					debugState("  Stuck or moving",brain);
					if (this.currentWaitTime <= 0f && this.currentTargetPoint.HasLookAtPoints())
					{
						debugState("    Look At Point",brain);
						global::UnityEngine.Transform randomLookAtPoint = this.currentTargetPoint.GetRandomLookAtPoint();
						if (randomLookAtPoint != null)
						{
							brain.Navigator.SetFacingDirectionOverride(global::UnityEngine.Vector3Ex.Direction2D(randomLookAtPoint.transform.position, entity.ServerPosition));
						}
					}
					if (this.currentTargetPoint.WaitTime > 0f)
					{
						this.currentWaitTime += delta;
					}
					if (this.currentTargetPoint.WaitTime <= 0f || this.currentWaitTime >= this.currentTargetPoint.WaitTime)
					{
						debugState("    Done waiting at point",brain);
						brain.Navigator.ClearFacingDirectionOverride();
						this.currentWaitTime = 0f;
						int num = this.currentNodeIndex;
						this.currentNodeIndex = this.path.GetNextPointIndex(this.currentNodeIndex, ref this.pathDirection);
						this.currentTargetPoint = this.path.GetPointAtIndex(this.currentNodeIndex);
						if ((!(this.currentTargetPoint != null) || this.currentNodeIndex != num) && (this.currentTargetPoint == null || !brain.Navigator.SetDestination(this.currentTargetPoint.transform.position, global::BaseNavigator.NavigationSpeed.Slow, 0f, 0f)))
						{
							debugState("      Error pathing in think - Target point: "+(this.currentTargetPoint == null).ToString()+" \n      Target Index and old : "+this.currentNodeIndex.ToString()+":"+num.ToString(), brain);
							return global::StateStatus.Error;
						}
					}
				}
				else if (this.currentTargetPoint != null)
				{
					debugState("  Goto point",brain);
					brain.Navigator.SetDestination(this.currentTargetPoint.transform.position, global::BaseNavigator.NavigationSpeed.Slow, 1f, 0f);
				}
				return global::StateStatus.Running;
				/*/
				
				debugState("Thinking",brain);
				TimeOnPath+=delta;
				currentLookTime+=delta;
				
				// If position changed, reset stuck time, otherwise increment
				if(entity.transform.position!=lastPosition){
					timeAtPoint=0;
				}
				else{
					timeAtPoint+=delta;
				}
				if (this.status == StateStatus.Error)
				{
					this.currentWaitTime = 0f;
					return this.status;
				}
				
				// If we're over the stuck limit we're stuck
				bool isStuck=timeAtPoint>stuckLimit;
				
				// If we're done moving or we're stuck
				if (!brain.Navigator.Moving||isStuck)
				{
					debugState("Stuck or not moving",brain);
					//If we're stuck flip direction
					if(isStuck){
						debugState("We're stuck",brain);
						pathDirection = UnityEngine.Random.Range(0f,1f)>0.5f?AIMovePointPath.PathDirection.Forwards:AIMovePointPath.PathDirection.Backwards;
						//Reset wait time
						this.currentWaitTime = 0f;
						return StateStatus.Error;
					}
					
					// If the point has lookat points, look at them
					if (this.currentWaitTime <= 0f && this.currentTargetPoint.HasLookAtPoints())
					{
						debugState("Look At Point",brain);
						UnityEngine.Transform randomLookAtPoint = this.currentTargetPoint.GetRandomLookAtPoint();
						if (randomLookAtPoint != null)
						{
							brain.Navigator.SetFacingDirectionOverride(UnityEngine.Vector3Ex.Direction2D(randomLookAtPoint.transform.position, entity.ServerPosition));
						}
					} 
					
					// If not, look at a sorta forward location
					else if(currentLookTime>10){
						
						debugState("Random look",brain);
						currentLookTime=0;
						float x=UnityEngine.Random.Range(-1.5f,1.5f);
						float y=UnityEngine.Random.Range(-1.5f,1.5f);
						brain.Navigator.SetFacingDirectionOverride(UnityEngine.Vector3Ex.Direction2D(entity.transform.position+entity.transform.forward+new Vector3(x,0,y), entity.ServerPosition));
					}
					
					//  Increment wait time
					this.currentWaitTime += delta;
					
					// If it`s time to change path, return finished
					if(TimeOnPath >  TimeLimit){
						debugState("Done with path, finishing",brain);
						brain.Navigator.ClearFacingDirectionOverride();
						return StateStatus.Finished;
					}
					
					// If point has no wait time or we're over the wait time
					if (this.currentTargetPoint.WaitTime <= 0f || this.currentWaitTime >= this.currentTargetPoint.WaitTime)
					{
						debugState("Done waiting at point",brain);
						//Allow freelook
						brain.Navigator.ClearFacingDirectionOverride();
						
						//Reset wait time
						this.currentWaitTime = 0f;
						
						//Take note of current index
						int num = this.currentNodeIndex;
						
						currentTargetPoint.ClearIfUsedBy(entity);
						
						return StateStatus.Finished;
					}else{
						currentTargetPoint.SetUsedBy(entity,20f);						
					}
				}
				// If still moving and there's a point, move to point
				else if (this.currentTargetPoint != null)
				{
					currentTargetPoint.SetUsedBy(entity,20f);
					debugState("Continuing Path",brain);
				}
				// Note last positino and keep running
				
				debugState("Still running at "+entity.transform.position.ToString(),brain);
				lastPosition=entity.transform.position;
				return StateStatus.Running;
				//*/
			}
				


		}

		public class CustomTakeCoverState : ScientistBrain.TakeCoverState{
			
			public Vector3 lastPosition= new Vector3(0,0,0);
			public float timeAtPoint = 0;
			public static float stuckLimit = 5;
			
			public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
			{
				lastPosition=entity.transform.position;
				timeAtPoint = 0;	
				this.status = StateStatus.Running;
				if (!this.StartMovingToCover(entity as HumanNPC))
				{
					this.status = StateStatus.Error;
				}
				
			}
			public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
			{
				if(lastPosition==entity.transform.position){
					timeAtPoint+=delta;
					if(timeAtPoint>stuckLimit){
						return StateStatus.Finished;
					}
				}
				lastPosition=entity.transform.position;
				timeAtPoint = 0;
				
				if (brain.Navigator.Moving)
				{
					FaceTarget();
					return StateStatus.Running;
				}
				return StateStatus.Finished;
			}
			private void FaceCoverFromEntity()
			{
				this.coverFromEntity = this.brain.Events.Memory.Entity.Get(this.brain.Events.CurrentInputMemorySlot);
				if (this.coverFromEntity == null)
				{
					this.brain.Navigator.ClearFacingDirectionOverride();
					return;
				}
				this.brain.Navigator.SetFacingDirectionEntity(this.coverFromEntity);
			}
			private void FaceTarget()
			{
				BaseEntity baseEntity = this.brain.Events.Memory.Entity.Get(this.brain.Events.CurrentInputMemorySlot);
				if (baseEntity == null)
				{
					FaceCoverFromEntity();
					return;
				}
				this.brain.Navigator.SetFacingDirectionEntity(baseEntity);
			}
			private bool StartMovingToCover(HumanNPC entity)
			{
				this.coverFromEntity = this.brain.Events.Memory.Entity.Get(this.brain.Events.CurrentInputMemorySlot);
				if (this.coverFromEntity == null)
				{
					return false;
				}
				UnityEngine.Vector3 vector = (this.coverFromEntity ? this.coverFromEntity.transform.position : (entity.transform.position + entity.LastAttackedDir * 30f));
				AIInformationZone informationZone = entity.GetInformationZone(entity.transform.position);
				if (informationZone == null)
				{
					return false;
				}
				float num = ((entity.SecondsSinceAttacked < 2f) ? 2f : 0f);
				float bestCoverPointMaxDistance = this.brain.Navigator.BestCoverPointMaxDistance;
				AICoverPoint bestCoverPoint = informationZone.GetBestCoverPoint(entity.transform.position, vector, num, bestCoverPointMaxDistance, entity, true);
				if (bestCoverPoint == null)
				{
					return false;
				}
				UnityEngine.Vector3 position = bestCoverPoint.transform.position;
				if (!this.brain.Navigator.SetDestination(position, BaseNavigator.NavigationSpeed.Normal, 0f, 0f))
				{
					return false;
				}
				this.FaceCoverFromEntity();
				this.brain.Events.Memory.AIPoint.Set(bestCoverPoint, 4);
				bestCoverPoint.SetUsedBy(entity);
				return true;
			}
			private StateStatus status = StateStatus.Error;
			private BaseEntity coverFromEntity;
	
		}	
		#endregion
		
		#region Load
		
		Cordyceps cordy;

		public static string[] targets= new string[]{"assets/rust.ai/agents/npcplayer/humannpc/banditguard/npc_bandit_guard.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_lr300.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_mp5.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_pistol.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_shotgun.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_heavy.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_junkpile_pistol.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_peacekeeper.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_excavator.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_oilrig.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roamtethered.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_patrol.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/tunneldweller/npc_tunneldweller.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_oilrig.prefab",
            "assets/rust.ai/agents/npcplayer/humannpc/underwaterdweller/npc_underwaterdweller.prefab"};

		void OnEntitySpawned(HumanNPC hn){
			if(hn.Brain==null) return;
			if(hn.Brain.AIDesign==null) return;
			hn.Brain.SwitchToState(AIState.Idle,hn.Brain.AIDesign.GetFirstStateContainerOfType(AIState.Idle).ID);
		}
		
        void Loaded(){
			
			cordy = (Cordyceps)Manager.GetPlugin("Cordyceps");
			loadStates();
			StateImprovement._instance=this;
		}
		void loadStates(){
			foreach(string s in targets){
				CustomTakeCoverState tcs= new CustomTakeCoverState();
				cordy.AssignHumanState(s, tcs.StateType, tcs);
				CustomFollowPathState fps= new CustomFollowPathState();
				cordy.AssignHumanState(s, fps.StateType, fps);
				CustomRoamState frs= new CustomRoamState();
				cordy.AssignHumanState(s, frs.StateType, frs);
			}			
		}
		
		#endregion
		
	}
}

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