/// <summary> /// Gets properties for the specified AI and player /// and adds the properties if none exist /// </summary> public static vp_FPPlayerEventHandler GetPlayer(vp_AIEventHandler ai, Transform t) { vp_FPPlayerEventHandler player = null; // if the AI is not registered, return if (!Instance.AIs.ContainsKey(ai)) { return(null); } // if a dictionary hasn't been created for some reason, create it and then add the player Dictionary <Transform, vp_FPPlayerEventHandler> dict = null; if (!Instance.AIs.TryGetValue(ai, out dict)) { dict = new Dictionary <Transform, vp_FPPlayerEventHandler>(); goto Add; } // if the player doesn't exist, add it if (!dict.TryGetValue(t, out player)) { goto Add; } // if player was found, return the properties return(player); // add the player for this AI Add: return(Instance.AddPlayerForAI(ai, t)); }
/// <summary> /// this message sets up the component for damage /// and range and executes the TryFire event /// </summary> protected virtual void OnMessage_CauseDamage(Dictionary <string, object> data) { int attackType = (int)data["AttackType"]; if (attackType != (int)AttackType) { return; } if (m_AI == null) { m_AI = (vp_AIEventHandler)EventHandler; } if (m_AI.Target.Get() == null) { return; } m_Damage = (float)data["Damage"]; m_Range = (float)data["Range"]; Vector3 pos = (m_AI.Target.Get().collider != null ? m_AI.Target.Get().collider.bounds.center : m_AI.Target.Get().position) - m_Transform.position; m_Transform.rotation = Quaternion.LookRotation(pos); TryFire(); }
/// <summary> /// Unregister the specified AI from this manager /// </summary> public static void Unregister(vp_AIEventHandler ai) { if (Instance.AIs.ContainsKey(ai)) { Instance.AIs.Remove(ai); } }
/// <summary> /// Register the specified AI with this manager /// </summary> public static void Register(vp_AIEventHandler ai) { if (!Instance.AIs.ContainsKey(ai)) { Instance.AIs.Add(ai, new Dictionary <Transform, vp_FPPlayerEventHandler>()); } }
/// <summary> /// This is equivalent to Unity's Awake and will /// be called by the AI components Awake method. /// The AI component needs to be passed to this method. /// </summary> public virtual void Awake(vp_AI ai) { m_Enabled = Enabled; m_AI = ai; m_EventHandler = (vp_AIEventHandler)m_AI.EventHandler; m_Transform = ai.transform; m_GameObject = ai.gameObject; m_Rigidbody = ai.rigidbody; m_Audio = ai.audio; m_Controller = m_Transform.root.GetComponentInChildren <CharacterController>(); }
/// <summary> /// Alerts friendlies in the specified distance /// that this AI is attacking /// </summary> protected virtual void OnMessage_AlertFriendly() { if (m_EventHandler.HostileTarget.Get() == null) { return; } Collider[] colliders = Physics.OverlapSphere(m_Transform.position, m_AI.CombatAlertFriendlyDistance, 1 << m_Transform.gameObject.layer); foreach (Collider col in colliders) { vp_AIEventHandler ai = col.GetComponent <vp_AIEventHandler>(); if (ai != null) { ai.Attacking.TryStart(m_EventHandler.HostileTarget.Get()); } } }
/// <summary> /// try to add a player for the AI /// and the players properties /// </summary> public virtual vp_FPPlayerEventHandler AddPlayerForAI(vp_AIEventHandler ai, Transform t) { // if the AI is not registered, return if (!Instance.AIs.ContainsKey(ai)) { return(null); } // if the AI has cached this player, return the player if (Instance.AIs[ai].ContainsKey(t)) { return(Instance.AIs[ai][t]); } // add this player for this AI vp_FPPlayerEventHandler player = t.root.GetComponentInChildren <vp_FPPlayerEventHandler>(); Instance.AIs[ai].Add(t, player); return(player); }
protected static string m_ContainerName = "AI Container"; // empty gameobject that gets created to store all the AI /// <summary> /// in 'Awake' we do things that need to be run once at the /// very beginning. NOTE: as of Unity 4, gameobject hierarchy /// can not be altered in 'Awake' /// </summary> protected override void Awake() { base.Awake(); m_EventHandler = (vp_AIEventHandler)EventHandler; // use reflection to loop through fields in this class foreach (FieldInfo info in this.GetType().GetFields()) { // check if the field is a plugin if (info.FieldType.BaseType == typeof(vp_AIPlugin)) { // get the value of the plugin vp_AIPlugin plugin = (vp_AIPlugin)info.GetValue(this); if (plugin == null) { continue; } // check if the plugin is enabled if (plugin.Enabled) { // setup the AIStates in the plugins so they have the correct values foreach (FieldInfo stateInfo in plugin.GetType().GetFields()) { if (stateInfo.FieldType == typeof(vp_AIState)) { stateInfo.SetValue(plugin, RefreshState((vp_AIState)stateInfo.GetValue(plugin))); } } // add the plugin to the list m_Plugins.Add(plugin); } } // setup any AIStates in this class so they have the correct values if (info.FieldType == typeof(vp_AIState)) { info.SetValue(this, RefreshState((vp_AIState)info.GetValue(this))); } } // order the plugins by their sort order values m_Plugins = m_Plugins.OrderBy(p => p.SortOrder).ToList(); // run Awake on all the enabled plugins foreach (vp_AIPlugin plugin in m_Plugins) { plugin.Awake(this); if (!enabled) { plugin.OnDisable(); } } if (!enabled) { if (PlaceOnGround != null) { vp_Timer.In(0.1f, delegate { PlaceOnGround.PositionOnGround(true); }); } } }
/// <summary> /// Instantiates an spawn object by it's index /// and sets the new AI's properties /// </summary> protected virtual void InstantiateObject(int index) { if (index > AISpawnerObjects.Count) { return; } AISpawnerObject spawnerObject = AISpawnerObjects[index]; if (spawnerObject == null) { return; } if (spawnerObject.Prefab == null || !spawnerObject.Enabled) { return; } for (int i = 0; i < spawnerObject.AmountToSpawn; i++) { GameObject go = Object.Instantiate(spawnerObject.Prefab) as GameObject; vp_AIEventHandler ai = go.GetComponent <vp_AIEventHandler>(); if (ai != null) { Reroll: // get a random position within the spawners bounds Vector3 min = m_Collider.bounds.min; Vector3 max = m_Collider.bounds.max; Vector3 randPos = new Vector3(Random.Range(min.x, max.x), max.y, Random.Range(min.z, max.z)); // check to see if this is a good position to spawn, if not, reroll if (Physics.CheckSphere(randPos, spawnerObject.DamageHandlerRespawnCheckRadius, vp_Layer.Mask.PhysicsBlockers)) { goto Reroll; } // random rotation Quaternion randRot = Random.rotation; randRot.z = 0; randRot.x = 0; go.transform.position = randPos; go.transform.rotation = randRot; // set all the overridden properties to send to the various components Dictionary <string, object> dict = new Dictionary <string, object>(); foreach (FieldInfo info in spawnerObject.GetType().GetFields()) { AddSpawnProperty(spawnerObject, info, dict); } // send the spawner bounds with the other overrides dict.Add("AreaSpawnerBounds", m_Collider.bounds); // send the overridden properties to the various components ai.SetProperties.Send(dict); spawnerObject.CachedEventHandlers.Add(ai); if (!SpawnAtStart || (SpawnAtStart && !spawnerObject.SpawnAtStart)) { Renderer[] renderers = go.GetComponentsInChildren <Renderer>(); foreach (Renderer r in renderers) { r.enabled = false; } // the AI needs to be allowed to setup some stuff before being set to inactive vp_Timer.In(.1f, delegate { vp_Utility.Activate(go, false); foreach (Renderer r in renderers) { r.enabled = true; } }); } ai.Reset.Send(Vector3.zero); } } }