context: using UnityEngine;
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Xml.Serialization;
  using System.Reflection;
  using Pathfinding.RVO;
  using ExtensionMethods;
  using Frontiers;
  using Frontiers.Data;
  
  namespace Frontiers.World.WIScripts
  {
  	public class Creature : WIScript
  	{
  		static Creature ()
  		{
  			//add the tags we need to difficulty settings
  			DifficultySetting.AvailableTags.Add ("NoHostileCreatures");
  		}
  
  		public CreatureState State = new CreatureState ();
  		public CreatureTemplate Template {
  			get {
  				if (mTemplate == null) {
  					CheckTemplate ();
  				}
  				return mTemplate;
  			}
  			set {
  				mTemplate = value;
  			}
  		}
  		public CreatureBody Body = null;
  		public ICreatureDen Den = null;
  		public Damageable damageable;
  
  		protected CreatureTemplate mTemplate;
  
  		public override bool CanBeCarried {
  			get {
  				return false;
  			}
  		}
  
  		public override bool CanEnterInventory {
  			get {
  				return false;
  			}
  		}
  
  		public bool HasDen {
  			get {
  				return Den != null;
  			}
  		}
  
  		public bool IsInDen {
  			get {
  				return mIsInDen;
  			}
  			set {
  				if (!HasDen) {
  					mIsInDen = value;
  					return;
  				}
  
  				if (mIsInDen) {
  					//if we were in our den
  					if (!value) {
  						//we've left the den
  						mIsInDen = value;
  						//Debug.Log ("We've left the den!");
  						OnLeaveDen.SafeInvoke ();
  					}
  				} else {//if we weren't in our den
  					if (value) {
  						//we've entered our den
  						mIsInDen = value;
  						//Debug.Log ("Phew we're returning to the den");
  						OnVisitDen.SafeInvoke ();
  					}
  				}
  			}
  		}
  
  		public bool IsInDenInnerRadius {
  			get {
  				return mIsInDenInnerRadius;
  			}
  			set {
  				if (!HasDen) {
  					mIsInDenInnerRadius = value;
  					return;
  				}
  
  				if (mIsInDenInnerRadius) {
  					//if we were in our den
  					if (!value) {
  						//we've left the den
  						mIsInDenInnerRadius = value;
  						OnLeaveDenInnerRadius.SafeInvoke ();
  					}
  				} else {//if we weren't in our den
  					if (value) {
  						//we've entered our den
  						mIsInDenInnerRadius = value;
  						OnVisitDenInnerRadius.SafeInvoke ();
  					}
  				}
  			}
  		}
  		//behavior actions - behaviors subscribe to these
  		public Action OnDaytimeStart;
  		public Action OnNightTimeStart;
  		public Action OnHourStart;
  		public Action OnLeaveDen;
  		public Action OnVisitDen;
  		public Action OnLeaveDenInnerRadius;
  		public Action OnVisitDenInnerRadius;
  		public Action OnPlayerVisitDen;
  		public Action OnPlayerLeaveDen;
  		public Action OnPlayerVisitDenInnerRadius;
  		public Action OnPlayerLeaveDenInnerRadius;
  		public Action OnPlayerStayInDen;
  		public Action OnPackMemberIssueWarning;
  		//brain behavior
  		public Action OnRefreshBehavior;
  		public Action OnCollectiveThoughtStart;
  		public Action OnCollectiveThoughtEnd;
  		public CollectiveThought CurrentThought = new CollectiveThought ();
  		//stunned/revived
  		public Action OnStunned;
  		public Action OnRevived;
  		public Photosensitive photosensitive;
  
  		public override string FileNamer (int increment)
  		{
  			gFileNameBuilder.Clear ();
  			gFileNameBuilder.Append (State.TemplateName);
  			gFileNameBuilder.Append ("-");
  			gFileNameBuilder.Append (increment.ToString ());
  			return gFileNameBuilder.ToString ();
  		}
  
  		public override void OnEnable ()
  		{
  			Template = null;
  			base.OnEnable ();
  		}
  
  		public override void OnStartup ()
  		{
  			CheckTemplate ();
  			//create body for creature
  			CreatureBody body = null;
  			if (!Creatures.GetBody (Template.Props.BodyName, out body)) {
  				Debug.Log ("Couldn't get body in creature " + State.TemplateName);
  				return;
  			} else {
  				GameObject newBody = GameObject.Instantiate (body.gameObject, worlditem.tr.position, Quaternion.identity) as GameObject;
  				Body = newBody.GetComponent <CreatureBody> ();
  			}
  			//set the body's eye colors
  			Body.HostileEyeColor = Color.red;
  			Body.TimidEyeColor = Color.green;
  			Body.AggressiveEyeColor = Color.yellow;
  			Body.ScaredEyeColor = Color.white;
  			//don't set the body's parent or name
  			//let the body stay in the world to keep the heirarchy clean
  			//Body.transform.parent = worlditem.Group.transform;
  			//Body.name = worlditem.FileName + "-Body";
  			//if we're dead, we need to set the body to ragdoll right away
  		}
  
  		public override void OnInitializedFirstTime ()
  		{
  			CheckTemplate ();
  			//set the states of our looker, listener, motile etc. using our template
  			//this will only happen the first time the creature is created
  			//after that it will pull this info from its stack item state
  			Looker looker = null;
  			if (worlditem.Is <Looker> (out looker)) {
  				Reflection.CopyProperties (Template.LookerTemplate, looker.State);
  			}
  			Listener listener = null;
  			if (worlditem.Is <Listener> (out listener)) {
  				Reflection.CopyProperties (Template.ListenerTemplate, listener.State);
  			}
  			Motile motile = null;
  			if (worlditem.Is <Motile> (out motile)) {
  				Reflection.CopyProperties (Template.MotileTemplate, motile.State);
  			}
  			FillStackContainer fsc = null;
  			if (worlditem.Is <FillStackContainer> (out fsc)) {
  				if (string.IsNullOrEmpty (Template.Props.InventoryFillCategory)) {
  					Template.Props.InventoryFillCategory = Creatures.Get.DefaultInventoryFillCategory;
  				}
  				fsc.State.WICategoryName = Template.Props.InventoryFillCategory;
  			}
  			//all creatures are damageable
  			damageable = worlditem.Get <Damageable> ();
  			damageable.ApplyForceAutomatically = false;
  			if (!State.IsDead) {
  				Reflection.CopyProperties (Template.DamageableTemplate, damageable.State);
  			}
  			//add each of the custom scripts in the template
  			for (int i = 0; i < Template.Props.CustomWIScripts.Count; i++) {
  				worlditem.Add (Template.Props.CustomWIScripts [i]);
  			}
  			//and we're done!
  		}
  
  		public override void OnInitialized ()
  		{	
  			CheckTemplate ();
  
  			worlditem.OnActive += OnActive;
  			worlditem.OnVisible += OnVisible;
  			worlditem.OnInactive += OnInactive;
  			worlditem.OnPlayerEncounter += OnPlayerEncounter;
  			worlditem.OnAddedToGroup += OnAddedToGroup;
  
  			photosensitive = worlditem.GetOrAdd <Photosensitive> ();
  			photosensitive.OnExposureDecrease += RefreshEyes;
  			photosensitive.OnExposureDecrease += RefreshEyes;
  
  			Motile motile = null;
  			if (worlditem.Is <Motile> (out motile)) {
  				motile.SetBody (Body);
  				//always set the motile props even if we've saved the state
  				motile.State.MotileProps = Template.MotileTemplate.MotileProps;
  			}
  			Looker looker = null;
  			if (worlditem.Is <Looker> (out looker)) {
  				looker.OnSeeItemOfInterest += OnSeeItemOfInterest;
  			}
  			Listener listener = null;
  			if (worlditem.Is <Listener> (out listener)) {
  				listener.OnHearItemOfInterest += OnHearItemOfInterest;
  			}
  			damageable = worlditem.Get <Damageable> ();
  			damageable.OnTakeDamage += OnTakeDamage;
  			damageable.OnTakeCriticalDamage += OnTakeCriticalDamage;
  			damageable.OnTakeOverkillDamage += OnTakeOverkillDamage;
  			damageable.OnDie += OnDie;
  
  			Container container = worlditem.Get <Container> ();
  			container.CanOpen = false;
  			container.CanUseToOpen = false;
  
  			OnDaytimeStart += RefreshBehavior;
  			OnNightTimeStart += RefreshBehavior;
  			OnHourStart += RefreshBehavior;
  
  			//WanderAction ();
  		}
  
  		protected void CheckTemplate () {
  			if (mTemplate == null) {
  				if (!Creatures.GetTemplate (State.TemplateName, out mTemplate)) {
  					Debug.Log ("Couldn't get template in check template: " + State.TemplateName);
  					return;
  				}
  			}
  			State.TemplateName = mTemplate.Name;
  			State.AggressiveTOD = mTemplate.StateTemplate.AggressiveTOD;
  			State.Domestication = mTemplate.StateTemplate.Domestication;
  			State.FightOrFlightThreshold = mTemplate.StateTemplate.FightOrFlightThreshold;
  			State.MaxPursuitPastDen = mTemplate.StateTemplate.MaxPursuitPastDen;
  			State.OnReachFFThresholdAggressive = mTemplate.StateTemplate.OnReachFFThresholdAggressive;
  			State.OnReachFFThresholdTimid = mTemplate.StateTemplate.OnReachFFThresholdTimid;
  			State.OnTakeDamageAggressive = mTemplate.StateTemplate.OnTakeDamageAggressive;
  			State.OnTakeDamageTimid = mTemplate.StateTemplate.OnTakeDamageTimid;
  		}
  
  		public void OnActive ()
  		{
  			if (IsDead)
  				return;
  
  			Motile motile = null;
  			if (worlditem.Is <Motile> (out motile)) {
  				motile.StartMotileActions ();
  			}
  		}
  
  		public void OnVisible ()
  		{
  			if (IsDead)
  				return;
  
  			Motile motile = null;
  
gt: 			if (worlditem.Is <Motile> (out motile)) {