using System.Collections; using System.Collections.Generic; using Invector; using Invector.vCharacterController.AI; using PixelCrushers; using UnityEngine; using UnityEngine.Events; namespace Beyond { public class EnemySpawner : Saver { public GameObject m_prefab; public Transform m_distanceFrom; //public bool m_distanceFromMainCam; public float m_spawnCheckInterval = .5f; public float m_distance = 20f; public int m_numToSpawn = -1; public bool m_respawnOnPlayersDeath = true; public LayerMask raycastMask = 1; //default private SaveData m_spawnData; //private bool m_spawned; private vControlAI m_spawnedAI; public UnityEvent m_OnDead; public UnityEvent m_onReceivedDamage; class SaveData { public int numSpawned; public bool spawned; } public override void Awake() { base.Awake(); //m_spawned = false; m_spawnData = new SaveData(); m_spawnData.numSpawned = 0; m_spawnData.spawned = false; } void OnDestroy() { if (m_respawnOnPlayersDeath && Player.Instance != null) { var respawner = Player.Instance.GetComponent(); respawner.m_onRespawned.RemoveListener(OnPlayerRespawned); } if (m_spawnedAI) { m_spawnedAI.onDead.RemoveListener(OnDead); } } public override void Start() { base.Start(); if (Player.Instance != null) m_distanceFrom = Player.Instance.transform; else { m_distanceFrom = Camera.main.transform; } if (m_respawnOnPlayersDeath) { var respawner = Player.Instance.GetComponent(); respawner.m_onRespawned.AddListener(OnPlayerRespawned); } InvokeRepeating("CheckSpawn", m_spawnCheckInterval + (Random.value * m_spawnCheckInterval), m_spawnCheckInterval); } void CheckRespawnCondition() { if ((m_numToSpawn < 0 || m_numToSpawn > m_spawnData.numSpawned) && m_spawnedAI == null ) m_spawnData.spawned = false; } private void OnPlayerRespawned() { CheckRespawnCondition(); } public override string RecordData() { return SaveSystem.Serialize(m_spawnData); } public override void ApplyData(string s) { var data = SaveSystem.Deserialize(s); if (data != null) { m_spawnData = data; //m_spawned = true; CheckRespawnCondition(); } } public bool SpawnedAndLive() { return m_spawnedAI != null; } public bool SpawnedAndDead() { return m_spawnData.spawned && m_spawnedAI == null; } public void Spawn() { if (m_prefab == null) return; Vector3 pos; const float RAY_OFFSET = 30f; const float Y_OFFSET = .1f; pos = transform.position; pos.y += RAY_OFFSET; RaycastHit hit = new RaycastHit(); if (Physics.Raycast(pos, Vector3.down, out hit, 100f, raycastMask)) { pos.y -= RAY_OFFSET; if (pos.y < hit.point.y + Y_OFFSET) { pos.y = hit.point.y + Y_OFFSET; } } else { Debug.LogError("EnemySpawner error: raycast failed"); return; } //m_spawned = true; m_spawnData.spawned = true; m_spawnData.numSpawned++; var enemy = Instantiate(m_prefab, pos, transform.rotation, transform); m_spawnedAI = enemy.GetComponent(); if (m_spawnedAI) { m_spawnedAI.onDead.AddListener(OnDead); m_spawnedAI.onReceiveDamage.AddListener(OnReceiveDamage); } } private void OnReceiveDamage(vDamage arg0) { m_onReceivedDamage?.Invoke(this); } private void OnDead(GameObject arg0) { m_spawnedAI = null; m_OnDead?.Invoke(this); } public void CheckSpawn(){ if (!m_spawnData.spawned && gameObject.activeInHierarchy && (transform.position - m_distanceFrom.position).sqrMagnitude < m_distance * m_distance){ Spawn(); } } } }