Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.14 KB | None | 0 0
  1. using UnityEngine;
  2. using UnityEngine.AI;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using BaseAssets.AI;
  6. using BaseAssets.Events;
  7. using BaseAssets.Debugger;
  8. using Sirenix.OdinInspector;
  9.  
  10. namespace BaseAssets.Tools
  11. {
  12. [RequireComponent(typeof(AIDataHolder))]
  13. [RequireComponent(typeof(AIVisualDebugger))]
  14. public class SpawnManager : MonoBehaviour
  15. {
  16. [FoldoutGroup("Tool Settings"), PropertyOrder(0)]
  17. public bool showGizmoOnSelect = false;
  18. [FoldoutGroup("Tool Settings"), PropertyOrder(0)]
  19. public float gizmoScale = 1f;
  20. [HideInInspector] public bool gizmoInEditMode = false;
  21. [HideInInspector] public bool gizmoInPlayMode = false;
  22.  
  23. [BoxGroup("SETUP"), PropertyOrder(1)]
  24. public Transform spawnTroopContainer = null;
  25. [BoxGroup("SETUP"), Required, PropertyOrder(1)]
  26. public GameObject troopPrefab = null;
  27. [BoxGroup("SETUP"), PropertyOrder(1)]
  28. public bool inheritFightingMode = true;
  29. [BoxGroup("SETUP"), PropertyOrder(2)]
  30. public List<FormationPlanner> formations = new List<FormationPlanner>();
  31.  
  32. [FoldoutGroup("Overwrite"), PropertyOrder(1)]
  33. public bool OverwriteAIDataHolder = false;
  34. [FoldoutGroup("Overwrite"), ShowIf("OverwriteAIDataHolder"), PropertyOrder(1)]
  35. public List<SpawnManager> prioritizationData = new List<SpawnManager>();
  36.  
  37. [FoldoutGroup("General Spawn Settings"), PropertyOrder(3)]
  38. public bool spawnOnStart = true;
  39. [FoldoutGroup("General Spawn Settings"), PropertyOrder(3)]
  40. public bool spawnAtTheSpot = false;
  41. [FoldoutGroup("General Spawn Settings"), PropertyOrder(3)]
  42. public bool updateWaypointHeight = false;
  43. [FoldoutGroup("General Spawn Settings"), ShowIf("@ (updateWaypointHeight) || (spawnAtTheSpot)"), PropertyOrder(3)]
  44. public LayerMask waypointHeightLayerMask;
  45.  
  46. [FoldoutGroup("Enums"), PropertyOrder(4)]
  47. public SpawnType spawnType = SpawnType.SpawnAllAtOnce;
  48. [FoldoutGroup("Enums"), PropertyOrder(4)]
  49. public SpawnLocationType spawnLocationType = SpawnLocationType.SpecificLocations;
  50. [FoldoutGroup("Enums"), PropertyOrder(4)]
  51. public TargetingType targetingType = TargetingType.SphereCast;
  52. [FoldoutGroup("Enums"), PropertyOrder(4)]
  53. public EndlessTargetAxis endlessTargetAxis = EndlessTargetAxis.X_Axis;
  54.  
  55. public enum SpawnType { SpawnAllAtOnce, SpawnInBurst, SpawnWithTimer, SpawnEndless }
  56. public enum SpawnLocationType { SpecificLocations, RandomArea }
  57. public enum TargetingType { SphereCast, BoxCast }
  58. public enum EndlessTargetAxis { X_Axis, Z_Axis }
  59.  
  60. [TabGroup("Spawns", "Endless Spawn"), ShowIf("spawnType", SpawnType.SpawnEndless), PropertyOrder(5)]
  61. public int endlessTroopCountPerBurst = 1;
  62. [TabGroup("Spawns", "Endless Spawn"), ShowIf("spawnType", SpawnType.SpawnEndless), PropertyOrder(5)]
  63. public float endlessBurstDelay = 1;
  64. [TabGroup("Spawns", "Endless Spawn"), ShowIf("spawnType", SpawnType.SpawnEndless), PropertyOrder(5)]
  65. public float endlessBurstDelayInitial = 1;
  66. [TabGroup("Spawns", "Endless Spawn"), ShowIf("spawnType", SpawnType.SpawnEndless), PropertyOrder(5)]
  67. public float endlessDestroyTime = 0f;
  68.  
  69. [TabGroup("Spawns", "Burst Spawn"), ShowIf("spawnType", SpawnType.SpawnInBurst), PropertyOrder(5)]
  70. public int burstCount = 1;
  71. [TabGroup("Spawns", "Burst Spawn"), ShowIf("spawnType", SpawnType.SpawnInBurst), PropertyOrder(5)]
  72. public float burstDelay = 1f;
  73. [TabGroup("Spawns", "Burst Spawn"), ShowIf("spawnType", SpawnType.SpawnInBurst), PropertyOrder(5)]
  74. public float burstSpawnDelayInitial = 0f;
  75.  
  76. [TabGroup("Spawns", "Timer Spawn"), ShowIf("spawnType", SpawnType.SpawnWithTimer), PropertyOrder(5)]
  77. public float spawnDelayInitial = 0f;
  78. [TabGroup("Spawns", "Timer Spawn"), ShowIf("spawnType", SpawnType.SpawnWithTimer), PropertyOrder(5)]
  79. public float spawnDelayPerTroop = 0f;
  80.  
  81. [TabGroup("Areas", "Endless Target Area"), ShowIf("spawnType", SpawnType.SpawnEndless), PropertyOrder(6)]
  82. public Vector3 endlessTargetAreaPosition = new Vector3();
  83. [TabGroup("Areas", "Endless Target Area"), ShowIf("spawnType", SpawnType.SpawnEndless), PropertyOrder(6)]
  84. public Vector3 endlessTargetAreaDimension = new Vector3();
  85.  
  86. [TabGroup("Areas", "Spawn Area"), ShowIf("spawnLocationType", SpawnLocationType.RandomArea), PropertyOrder(6)]
  87. public Vector3 spawnAreaPosition = new Vector3();
  88. [TabGroup("Areas", "Spawn Area"), ShowIf("spawnLocationType", SpawnLocationType.RandomArea), PropertyOrder(6)]
  89. public Vector3 spawnAreaDimension = new Vector3();
  90. [TabGroup("Areas", "Spawn Area"), ShowIf("spawnLocationType", SpawnLocationType.SpecificLocations), PropertyOrder(6)]
  91. public List<GameObject> spawnLocations = new List<GameObject>();
  92.  
  93. [TabGroup("Areas", "Box Cast Area"), ShowIf("targetingType", TargetingType.BoxCast), PropertyOrder(6)]
  94. public Vector3 attackTargetAreaPosition = new Vector3();
  95. [TabGroup("Areas", "Box Cast Area"), ShowIf("targetingType", TargetingType.BoxCast), PropertyOrder(6)]
  96. public Vector3 attackTargetAreaDimension = new Vector3();
  97.  
  98. [FoldoutGroup("Automated Formation Settings"), PropertyOrder(7)]
  99. public bool automateFormationSwitch = false;
  100. [FoldoutGroup("Automated Formation Settings"), PropertyOrder(7)]
  101. public bool loopAutomation = false;
  102. [FoldoutGroup("Automated Formation Settings"), PropertyOrder(7)]
  103. public float automatedTime = 0f;
  104.  
  105. [FoldoutGroup("Optional Compute Shaders"), PropertyOrder(8)]
  106. public ComputeShader findClosestCompute = null;
  107.  
  108. [HideInInspector] public Transform endlessWaypointContainer = null;
  109.  
  110. private Transform waypointContainer = null;
  111.  
  112. private int formationIndex = 0;
  113. private int activeSpawnLocation = 0;
  114. private Coroutine BurstCoroutine = null;
  115. private Coroutine TimerCoroutine = null;
  116. private Coroutine BurstEndlessCoroutine = null;
  117. private Coroutine AutomatedFormationSwitchCoroutine = null;
  118.  
  119. private void Start()
  120. {
  121. if (spawnTroopContainer == null)
  122. {
  123. spawnTroopContainer = new GameObject($"{transform.name}'s Troop Container").transform;
  124. DebugManager.SpawnContainerEmpty(gameObject);
  125. }
  126.  
  127. if (spawnType == SpawnManager.SpawnType.SpawnEndless && endlessWaypointContainer == null)
  128. {
  129. endlessWaypointContainer = new GameObject($"{transform.name}'s Waypoint Container").transform;
  130. DebugManager.WaypointContainerEmpty(gameObject);
  131. }
  132.  
  133. if (spawnOnStart)
  134. {
  135. Spawn();
  136. }
  137.  
  138. if (automateFormationSwitch)
  139. {
  140. AutomatedFormationSwitchCoroutine = StartCoroutine(AutomatedFormationSwitch());
  141. }
  142. }
  143.  
  144. public void CheckIfAllAtOrigin()
  145. {
  146. if (!inheritFightingMode) return;
  147.  
  148. AIDataHolder[] datas = new AIDataHolder[spawnTroopContainer.childCount];
  149.  
  150. for (int i = 0; i < spawnTroopContainer.childCount; i++)
  151. {
  152. AIDataHolder data = spawnTroopContainer.GetChild(i).GetComponent<AIDataHolder>();
  153.  
  154. if (data && data.CurrentHealth > 0f)
  155. {
  156. datas[i] = data;
  157. }
  158. }
  159.  
  160. bool isAllAtOrigin = true;
  161.  
  162. for (int i = 0; i < datas.Length; i++)
  163. {
  164. if (datas[i] && datas[i].AtOrigin == false)
  165. {
  166. isAllAtOrigin = false;
  167. break;
  168. }
  169. }
  170.  
  171. if (isAllAtOrigin)
  172. {
  173. if (!formations[formationIndex].isFormationMoverActive)
  174. {
  175. SetFightingMode(formations[formationIndex].fightingModeArrival);
  176. }
  177. }
  178. }
  179.  
  180. public void Update()
  181. {
  182. if (updateWaypointHeight) UpdateWaypointHeightByRaycast();
  183. }
  184.  
  185. // GIZMO ========================================================================================================================================================
  186. private void OnDrawGizmos()
  187. {
  188. if (DebugManager.DISABLE_GIZMOS) return;
  189.  
  190. if (Application.isPlaying && !gizmoInPlayMode) return;
  191. if (!Application.isPlaying && !gizmoInEditMode) return;
  192.  
  193. if (showGizmoOnSelect) return;
  194. DrawGizmo();
  195. }
  196.  
  197. private void OnDrawGizmosSelected()
  198. {
  199. if (DebugManager.DISABLE_GIZMOS) return;
  200.  
  201. if (Application.isPlaying && !gizmoInPlayMode) return;
  202. if (!Application.isPlaying && !gizmoInEditMode) return;
  203.  
  204. if (!showGizmoOnSelect) return;
  205. DrawGizmo();
  206. }
  207.  
  208. private void DrawGizmo()
  209. {
  210. if (spawnLocationType == SpawnLocationType.RandomArea)
  211. {
  212. Gizmos.color = Color.cyan;
  213. Gizmos.DrawWireCube(transform.position + spawnAreaPosition, spawnAreaDimension);
  214.  
  215. if (spawnType == SpawnType.SpawnEndless)
  216. {
  217. Gizmos.color = Color.red;
  218. Gizmos.DrawWireCube(transform.position + endlessTargetAreaPosition, endlessTargetAreaDimension);
  219. }
  220. }
  221. else
  222. {
  223. if (spawnLocations != null && spawnLocations.Count > 0)
  224. {
  225. Gizmos.color = Color.cyan;
  226. for (int i = 0; i < spawnLocations.Count; i++)
  227. {
  228. Gizmos.DrawWireSphere(spawnLocations[i].transform.position, gizmoScale);
  229. }
  230.  
  231. if (spawnType == SpawnType.SpawnEndless)
  232. {
  233. Gizmos.color = Color.red;
  234. Gizmos.DrawWireCube(transform.position + endlessTargetAreaPosition, endlessTargetAreaDimension);
  235. }
  236. }
  237. else
  238. {
  239. DebugManager.SpawnLocationsEmpty(gameObject);
  240. }
  241. }
  242.  
  243. if (targetingType == TargetingType.BoxCast)
  244. {
  245. Gizmos.color = Color.blue;
  246. Gizmos.DrawWireCube(transform.position + attackTargetAreaPosition, attackTargetAreaDimension);
  247. }
  248. }
  249. // GIZMO ========================================================================================================================================================
  250.  
  251. // FORMATION SWITCH =============================================================================================================================================
  252. private IEnumerator AutomatedFormationSwitch()
  253. {
  254. while (automateFormationSwitch)
  255. {
  256. yield return new WaitForSeconds(automatedTime);
  257.  
  258. if (formationIndex + 1 >= formations.Count && loopAutomation)
  259. {
  260. SwitchToNextFormation();
  261. }
  262. else if (formationIndex + 1 < formations.Count)
  263. {
  264. SwitchToNextFormation();
  265. }
  266. }
  267. }
  268.  
  269. public void SwitchFormation(int _formationIndex)
  270. {
  271. if (formations.Count <= 1)
  272. {
  273. DebugManager.NoFormationToSwitchTo(gameObject);
  274. return;
  275. }
  276.  
  277. if (troopPrefab == null)
  278. {
  279. DebugManager.NoTroopPrefabSet(gameObject);
  280. return;
  281. }
  282.  
  283. if (spawnTroopContainer == null)
  284. {
  285. DebugManager.NoTroopParentSet(gameObject);
  286. return;
  287. }
  288.  
  289. DestroyAllWaypoints();
  290.  
  291. List<Vector3> spawnPositions = formations[_formationIndex].GetActiveList();
  292. List<Transform> waypoints = CreateWaypoints(spawnPositions);
  293.  
  294. for (int i = 0; i < spawnPositions.Count; i++)
  295. {
  296. if (i < spawnTroopContainer.childCount)
  297. {
  298. AIDataHolder troop = spawnTroopContainer.GetChild(i).GetComponent<AIDataHolder>();
  299.  
  300. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  301. if (inheritFightingMode) troop.fightingMode = formations[_formationIndex].fightingModeTransition;
  302. }
  303. else
  304. {
  305. AIDataHolder troop = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  306.  
  307. SetPosition(troop, spawnTroopContainer.GetChild(0).position);
  308.  
  309. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  310.  
  311. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  312. if (inheritFightingMode) troop.fightingMode = formations[_formationIndex].fightingModeTransition;
  313. }
  314. }
  315.  
  316. if (EventHandler.onFormationSwitch != null) EventHandler.onFormationSwitch(this, formations[_formationIndex]);
  317. }
  318.  
  319. private void SwitchToNextFormation()
  320. {
  321. if (formations.Count <= 1)
  322. {
  323. DebugManager.NoFormationToSwitchTo(gameObject);
  324. return;
  325. }
  326.  
  327. if (troopPrefab == null)
  328. {
  329. DebugManager.NoTroopPrefabSet(gameObject);
  330. return;
  331. }
  332.  
  333. if (spawnTroopContainer == null)
  334. {
  335. DebugManager.NoTroopParentSet(gameObject);
  336. return;
  337. }
  338.  
  339. DestroyAllWaypoints();
  340.  
  341. formationIndex++;
  342.  
  343. if (formationIndex >= formations.Count)
  344. {
  345. formationIndex = 0;
  346. }
  347.  
  348. List<Vector3> spawnPositions = formations[formationIndex].GetActiveList();
  349. List<Transform> waypoints = CreateWaypoints(spawnPositions);
  350.  
  351. for (int i = 0; i < spawnPositions.Count; i++)
  352. {
  353. if (i < spawnTroopContainer.childCount)
  354. {
  355. AIDataHolder troop = spawnTroopContainer.GetChild(i).GetComponent<AIDataHolder>();
  356.  
  357. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  358. if (inheritFightingMode) troop.fightingMode = formations[formationIndex].fightingModeTransition;
  359. }
  360. else
  361. {
  362. AIDataHolder troop = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  363.  
  364. SetPosition(troop, spawnTroopContainer.GetChild(0).position);
  365.  
  366. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  367.  
  368. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  369. if (inheritFightingMode) troop.fightingMode = formations[formationIndex].fightingModeTransition;
  370. }
  371. }
  372.  
  373. if (formations[formationIndex].pathCreator)
  374. {
  375. formations[formationIndex].isFormationMoverActive = true;
  376. }
  377.  
  378. if (EventHandler.onFormationSwitch != null) EventHandler.onFormationSwitch(this, formations[formationIndex]);
  379. }
  380. // FORMATION SWITCH =============================================================================================================================================
  381.  
  382. // SPAWN TYPES ==================================================================================================================================================
  383. private void SpawnAllAtOnce()
  384. {
  385. if (formations.Count == 0)
  386. {
  387. DebugManager.NoFormationAtAll(gameObject);
  388. return;
  389. }
  390.  
  391. if (formations[formationIndex] == null)
  392. {
  393. DebugManager.MissingFormation(gameObject);
  394. return;
  395. }
  396.  
  397. if (troopPrefab == null)
  398. {
  399. DebugManager.NoTroopPrefabSet(gameObject);
  400. return;
  401. }
  402.  
  403. if (spawnTroopContainer == null)
  404. {
  405. DebugManager.NoTroopParentSet(gameObject);
  406. return;
  407. }
  408.  
  409. List<Transform> waypoints = CreateWaypoints(formations[formationIndex].GetActiveList());
  410.  
  411. for (int i = 0; i < formations[formationIndex].GetActiveList().Count; i++)
  412. {
  413. AIDataHolder troop = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  414.  
  415. SetPosition(troop, formations[formationIndex].GetActiveList()[i]);
  416.  
  417. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  418.  
  419. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  420. if (inheritFightingMode) troop.fightingMode = formations[formationIndex].fightingModeTransition;
  421. troop.transform.rotation = transform.rotation;
  422.  
  423. ActivateNextSpawnLocation();
  424.  
  425. if (EventHandler.onTroopSpawn != null) EventHandler.onTroopSpawn(troop);
  426. }
  427.  
  428. if (formations[formationIndex].pathCreator)
  429. {
  430. formations[formationIndex].isFormationMoverActive = true;
  431. }
  432.  
  433. if (EventHandler.onAllTroopsSpawned != null) EventHandler.onAllTroopsSpawned(this);
  434. }
  435.  
  436. private IEnumerator SpawnInBurst()
  437. {
  438. if (formations.Count == 0)
  439. {
  440. DebugManager.NoFormationAtAll(gameObject);
  441. yield break;
  442. }
  443.  
  444. if (formations[formationIndex] == null)
  445. {
  446. DebugManager.MissingFormation(gameObject);
  447. yield break;
  448. }
  449.  
  450. if (troopPrefab == null)
  451. {
  452. DebugManager.NoTroopPrefabSet(gameObject);
  453. yield break;
  454. }
  455.  
  456. if (spawnTroopContainer == null)
  457. {
  458. DebugManager.NoTroopParentSet(gameObject);
  459. yield break;
  460. }
  461.  
  462. List<Vector3> spawnPositions = formations[formationIndex].GetActiveList();
  463. List<Transform> waypoints = CreateWaypoints(spawnPositions);
  464.  
  465. yield return new WaitForSeconds(burstSpawnDelayInitial);
  466.  
  467. int spawnPerBurst = spawnPositions.Count / burstCount;
  468. int spawnIndex = 0;
  469.  
  470. for (int i = 0; i < burstCount; i++)
  471. {
  472. for (int k = 0; k < spawnPerBurst; k++)
  473. {
  474. AIDataHolder troop = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  475.  
  476. SetPosition(troop, spawnPositions[spawnIndex]);
  477.  
  478. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  479.  
  480. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[spawnIndex]);
  481. if (inheritFightingMode) troop.fightingMode = formations[formationIndex].fightingModeTransition;
  482. troop.transform.rotation = transform.rotation;
  483.  
  484. if (EventHandler.onTroopSpawn != null) EventHandler.onTroopSpawn(troop);
  485.  
  486. spawnIndex++;
  487.  
  488. if (i == burstCount - 1 && k == spawnPerBurst - 1)
  489. {
  490. yield return new WaitForSeconds(burstDelay);
  491. ActivateNextSpawnLocation();
  492.  
  493. int remainingTroopCount = spawnPositions.Count - spawnTroopContainer.childCount;
  494.  
  495. for (int l = 0; l < remainingTroopCount; l++)
  496. {
  497. AIDataHolder troopRemainder = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  498.  
  499. SetPosition(troopRemainder, spawnPositions[spawnIndex]);
  500.  
  501. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  502.  
  503. troopRemainder.Reference.LocalBehaviour.SetupAI(this, waypoints[spawnIndex]);
  504. if (inheritFightingMode) troopRemainder.fightingMode = formations[formationIndex].fightingModeTransition;
  505. troopRemainder.transform.rotation = transform.rotation;
  506.  
  507. if (EventHandler.onTroopSpawn != null) EventHandler.onTroopSpawn(troopRemainder);
  508.  
  509. spawnIndex++;
  510. }
  511. }
  512. }
  513.  
  514. yield return new WaitForSeconds(burstDelay);
  515. ActivateNextSpawnLocation();
  516. }
  517.  
  518. if (formations[formationIndex].pathCreator)
  519. {
  520. formations[formationIndex].isFormationMoverActive = true;
  521. }
  522.  
  523. if (EventHandler.onAllTroopsSpawned != null) EventHandler.onAllTroopsSpawned(this);
  524. }
  525.  
  526. private IEnumerator SpawnTroopsWithTimer()
  527. {
  528. if (formations.Count == 0)
  529. {
  530. DebugManager.NoFormationAtAll(gameObject);
  531. yield break;
  532. }
  533.  
  534. if (formations[formationIndex] == null)
  535. {
  536. DebugManager.MissingFormation(gameObject);
  537. yield break;
  538. }
  539.  
  540. if (troopPrefab == null)
  541. {
  542. DebugManager.NoTroopPrefabSet(gameObject);
  543. yield break;
  544. }
  545.  
  546. if (spawnTroopContainer == null)
  547. {
  548. DebugManager.NoTroopParentSet(gameObject);
  549. yield break;
  550. }
  551.  
  552. List<Vector3> spawnPositions = formations[formationIndex].GetActiveList();
  553. List<Transform> waypoints = CreateWaypoints(spawnPositions);
  554.  
  555. yield return new WaitForSeconds(spawnDelayInitial);
  556.  
  557. for (int i = 0; i < spawnPositions.Count; i++)
  558. {
  559. AIDataHolder troop = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  560.  
  561. SetPosition(troop, spawnPositions[i]);
  562.  
  563. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  564.  
  565. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  566. if (inheritFightingMode) troop.fightingMode = formations[formationIndex].fightingModeTransition;
  567. troop.transform.rotation = transform.rotation;
  568.  
  569. ActivateNextSpawnLocation();
  570.  
  571. if (EventHandler.onTroopSpawn != null) EventHandler.onTroopSpawn(troop);
  572.  
  573. yield return new WaitForSeconds(spawnDelayPerTroop);
  574. }
  575.  
  576. if (formations[formationIndex].pathCreator)
  577. {
  578. formations[formationIndex].isFormationMoverActive = true;
  579. }
  580.  
  581. if (EventHandler.onAllTroopsSpawned != null) EventHandler.onAllTroopsSpawned(this);
  582. }
  583.  
  584. private IEnumerator SpawnInBurstEndless()
  585. {
  586. if (troopPrefab == null)
  587. {
  588. DebugManager.NoTroopPrefabSet(gameObject);
  589. yield break;
  590. }
  591.  
  592. if (spawnTroopContainer == null)
  593. {
  594. DebugManager.NoTroopParentSet(gameObject);
  595. yield break;
  596. }
  597.  
  598. yield return new WaitForSeconds(endlessBurstDelayInitial);
  599.  
  600. while (spawnType == SpawnType.SpawnEndless && spawnLocationType == SpawnLocationType.RandomArea)
  601. {
  602. for (int i = 0; i < endlessTroopCountPerBurst; i++)
  603. {
  604. Transform spawnTransform = new GameObject(i.ToString()).transform;
  605. spawnTransform.rotation = transform.rotation;
  606. spawnTransform.SetParent(endlessWaypointContainer);
  607.  
  608. AIDataHolder troop = Instantiate(troopPrefab, spawnTroopContainer).GetComponent<AIDataHolder>();
  609.  
  610. SetPosition(troop, spawnTransform.position);
  611.  
  612. if (OverwriteAIDataHolder) GetComponent<AIDataHolder>().CloneTo(troop);
  613.  
  614. if (endlessTargetAxis == EndlessTargetAxis.X_Axis)
  615. {
  616. spawnTransform.position = GetTargetPositionByPercentage(troop.transform.position.x);
  617. }
  618. else
  619. {
  620. spawnTransform.position = GetTargetPositionByPercentage(troop.transform.position.z);
  621. }
  622.  
  623. troop.Reference.LocalBehaviour.SetupAI(this, spawnTransform, true, endlessDestroyTime);
  624. troop.transform.rotation = transform.rotation;
  625.  
  626. if (EventHandler.onTroopSpawn != null) EventHandler.onTroopSpawn(troop);
  627. }
  628.  
  629. ActivateNextSpawnLocation();
  630. yield return new WaitForSeconds(endlessBurstDelay);
  631. }
  632.  
  633. if (spawnType != SpawnType.SpawnEndless || spawnLocationType != SpawnLocationType.RandomArea)
  634. {
  635. DebugManager.EndlessSpawnError(gameObject);
  636. }
  637.  
  638. if (formations[formationIndex].pathCreator)
  639. {
  640. formations[formationIndex].isFormationMoverActive = true;
  641. }
  642.  
  643. if (EventHandler.onAllTroopsSpawned != null) EventHandler.onAllTroopsSpawned(this);
  644. }
  645. // SPAWN TYPES ==================================================================================================================================================
  646.  
  647. // GUI ==========================================================================================================================================================
  648. [FoldoutGroup("Overwrite"), Button("Transfer Prefab Data"), ShowIf("OverwriteAIDataHolder"), PropertyOrder(1)]
  649. public void OverwritePrefabData()
  650. {
  651. AIDataHolder spawnerAIDataHolder = GetComponent<AIDataHolder>();
  652. troopPrefab.GetComponent<AIDataHolder>().CloneTo(spawnerAIDataHolder);
  653.  
  654. if (prioritizationData.Count > 0)
  655. {
  656. spawnerAIDataHolder.OverwritePrioritizationData = true;
  657. spawnerAIDataHolder.prioritizationData = prioritizationData;
  658. }
  659. else
  660. {
  661. spawnerAIDataHolder.OverwritePrioritizationData = false;
  662. spawnerAIDataHolder.prioritizationData.Clear();
  663. }
  664. }
  665.  
  666. [FoldoutGroup("Overwrite"), Button("Transfer Only Prioritization Data"), ShowIf("OverwriteAIDataHolder"), PropertyOrder(1)]
  667. public void OverwriteOnlyTargetData()
  668. {
  669. AIDataHolder spawnerAIDataHolder = GetComponent<AIDataHolder>();
  670.  
  671. if (prioritizationData.Count > 0)
  672. {
  673. spawnerAIDataHolder.OverwritePrioritizationData = true;
  674. spawnerAIDataHolder.prioritizationData = prioritizationData;
  675. }
  676. else
  677. {
  678. spawnerAIDataHolder.OverwritePrioritizationData = false;
  679. spawnerAIDataHolder.prioritizationData.Clear();
  680. }
  681. }
  682.  
  683. [FoldoutGroup("Overwrite"), Button("Transfer Data At Runtime"), ShowIf("OverwriteAIDataHolder"), PropertyOrder(1)]
  684. public void OverwriteDataAtRuntime()
  685. {
  686. if (!Application.isPlaying) return;
  687.  
  688. AIDataHolder spawnerAIDataHolder = GetComponent<AIDataHolder>();
  689.  
  690. foreach (Transform spawnTroop in spawnTroopContainer)
  691. {
  692. AIDataHolder target = spawnTroop.GetComponent<AIDataHolder>();
  693.  
  694. System.Type type = typeof(AIDataHolder);
  695. foreach (System.Reflection.FieldInfo sourceField in type.GetFields())
  696. {
  697. if (sourceField.Name == "attackerList" || sourceField.Name == "Enemy" || sourceField.Name == "origin"
  698. || sourceField.Name == "currentMoveTo" || sourceField.Name == "Targeted" || sourceField.Name == "CurrentHealth"
  699. || sourceField.Name == "AtOrigin") continue;
  700. System.Reflection.FieldInfo targetField = type.GetField(sourceField.Name);
  701. targetField.SetValue(target, sourceField.GetValue(spawnerAIDataHolder));
  702. }
  703. }
  704. }
  705.  
  706. public void SetFightingMode(AIDataHolder.FightingMode _newFightingMode)
  707. {
  708. if (!Application.isPlaying) return;
  709.  
  710. foreach (Transform spawnTroop in spawnTroopContainer)
  711. {
  712. spawnTroop.GetComponent<AIDataHolder>().fightingMode = _newFightingMode;
  713. }
  714. }
  715.  
  716. [FoldoutGroup("Debug"), Button("Passive"), PropertyOrder(7)]
  717. public void SetFightingModeToPassive()
  718. {
  719. if (!Application.isPlaying) return;
  720.  
  721. foreach (Transform spawnTroop in spawnTroopContainer)
  722. {
  723. spawnTroop.GetComponent<AIDataHolder>().fightingMode = AIDataHolder.FightingMode.Passive;
  724. }
  725. }
  726.  
  727. [FoldoutGroup("Debug"), Button("Aggressive"), PropertyOrder(7)]
  728. public void SetFightingModeToAggressive()
  729. {
  730. if (!Application.isPlaying) return;
  731.  
  732. foreach (Transform spawnTroop in spawnTroopContainer)
  733. {
  734. spawnTroop.GetComponent<AIDataHolder>().fightingMode = AIDataHolder.FightingMode.Aggressive;
  735. }
  736. }
  737.  
  738. [FoldoutGroup("Debug"), Button("Passive-Aggressive"), PropertyOrder(7)]
  739. public void SetFightingModeToPassiveAggressive()
  740. {
  741. if (!Application.isPlaying) return;
  742.  
  743. foreach (Transform spawnTroop in spawnTroopContainer)
  744. {
  745. spawnTroop.GetComponent<AIDataHolder>().fightingMode = AIDataHolder.FightingMode.PassiveAggressive;
  746. }
  747. }
  748.  
  749. [FoldoutGroup("Debug"), Button("Neutral"), PropertyOrder(7)]
  750. public void SetFightingModeToNeutral()
  751. {
  752. if (!Application.isPlaying) return;
  753.  
  754. foreach (Transform spawnTroop in spawnTroopContainer)
  755. {
  756. spawnTroop.GetComponent<AIDataHolder>().fightingMode = AIDataHolder.FightingMode.Neutral;
  757. }
  758. }
  759.  
  760. [FoldoutGroup("Debug"), Button("Spawn Troops"), PropertyOrder(7)]
  761. public void SpawnTroops()
  762. {
  763. if (!Application.isPlaying) return;
  764.  
  765. StopCoroutines();
  766. DestroyAll();
  767. ResetValues();
  768. Spawn();
  769. }
  770.  
  771. [FoldoutGroup("Debug"), Button("Remove Troops"), PropertyOrder(7)]
  772. public void RemoveTroops()
  773. {
  774. if (!Application.isPlaying) return;
  775.  
  776. StopCoroutines();
  777. DestroyAll();
  778. ResetValues();
  779. }
  780.  
  781. [FoldoutGroup("Debug"), Button("Switch To Next Formation"), PropertyOrder(7)]
  782. public void NextFormation()
  783. {
  784. if (!Application.isPlaying) return;
  785.  
  786. if (automateFormationSwitch)
  787. {
  788. Debugger.DebugManager.SwitchFormationError(gameObject);
  789. return;
  790. }
  791.  
  792. SwitchToNextFormation();
  793. }
  794.  
  795. [FoldoutGroup("Debug"), Button("Reset Waypoints"), PropertyOrder(7)]
  796. public void ResetWaypoints()
  797. {
  798. if (!Application.isPlaying) return;
  799.  
  800. ResetWaypointsToCurrentFormation();
  801. }
  802. // GUI ==========================================================================================================================================================
  803.  
  804. // HELPER METHODS ===============================================================================================================================================
  805. public void SetState(AIStateKeeper.States _newState)
  806. {
  807. foreach (Transform spawnTroop in spawnTroopContainer)
  808. {
  809. spawnTroop.GetComponent<AILocalLogic>().SetState(_newState);
  810. }
  811. }
  812.  
  813. private void SetPosition(AIDataHolder _data, Vector3 _position)
  814. {
  815. if (_data.troopType != AIDataHolder.TroopType.Static)
  816. _data.GetComponent<NavMeshAgent>().Warp(GetTroopPosition(_position));
  817. else
  818. _data.transform.position = GetTroopPosition(_position);
  819. }
  820.  
  821. private void UpdateWaypointHeightByRaycast()
  822. {
  823. if (spawnType != SpawnType.SpawnEndless)
  824. {
  825. if (formations.Count > 0)
  826. {
  827. for (int i = 0; i < formations[formationIndex].GetActiveTroopListCount(); i++)
  828. {
  829. RaycastHit hit = new RaycastHit();
  830.  
  831. if (Physics.Raycast(formations[formationIndex].GetActiveList()[i], Vector3.down, out hit, Mathf.Infinity, waypointHeightLayerMask))
  832. {
  833. waypointContainer.GetChild(i).transform.position = hit.point;
  834. }
  835. }
  836. }
  837. else
  838. {
  839. Debug.Log("No formation added to the formations list");
  840. }
  841. }
  842. else
  843. {
  844. for (int i = 0; i < endlessWaypointContainer.childCount; i++)
  845. {
  846. RaycastHit hit = new RaycastHit();
  847. Transform waypoint = endlessWaypointContainer.GetChild(i);
  848.  
  849. if (Physics.Raycast(new Vector3(waypoint.position.x, endlessTargetAreaPosition.y, waypoint.position.z), Vector3.down, out hit, Mathf.Infinity, waypointHeightLayerMask))
  850. {
  851. waypoint.position = hit.point;
  852. }
  853. }
  854. }
  855. }
  856.  
  857. private int GetActiveSpawnLocation()
  858. {
  859. return activeSpawnLocation;
  860. }
  861.  
  862. private void SetActiveSpawnLocation(int _newSpawnLocation)
  863. {
  864. activeSpawnLocation = _newSpawnLocation;
  865. }
  866.  
  867. private void ActivateNextSpawnLocation()
  868. {
  869. if (GetActiveSpawnLocation() + 1 >= spawnLocations.Count)
  870. {
  871. SetActiveSpawnLocation(0);
  872. }
  873. else
  874. {
  875. SetActiveSpawnLocation(GetActiveSpawnLocation() + 1);
  876. }
  877. }
  878.  
  879. private Vector3 GetRandomLocationInArea(Vector3 _areaPosition, Vector3 _areaDimension)
  880. {
  881. return new Vector3(transform.position.x + _areaPosition.x + Random.Range(-_areaDimension.x / 2f, _areaDimension.x / 2f),
  882. transform.position.y + _areaPosition.y,
  883. transform.position.z + _areaPosition.z + Random.Range(-_areaDimension.z / 2f, _areaDimension.z / 2f));
  884. }
  885.  
  886. private Vector3 GetSpawnLocation()
  887. {
  888. if (spawnLocationType == SpawnLocationType.RandomArea)
  889. {
  890. RaycastHit hit = new RaycastHit();
  891.  
  892. if (Physics.Raycast(GetRandomLocationInArea(spawnAreaPosition, spawnAreaDimension), Vector3.down, out hit, Mathf.Infinity))
  893. {
  894. return hit.point;
  895. }
  896. else
  897. {
  898. return GetRandomLocationInArea(spawnAreaPosition, spawnAreaDimension);
  899. }
  900. }
  901. else
  902. {
  903. RaycastHit hit = new RaycastHit();
  904.  
  905. if (Physics.Raycast(spawnLocations[GetActiveSpawnLocation()].transform.position, Vector3.down, out hit, Mathf.Infinity))
  906. {
  907. return hit.point;
  908. }
  909. else
  910. {
  911. return spawnLocations[GetActiveSpawnLocation()].transform.position;
  912. }
  913. }
  914. }
  915.  
  916. private Vector3 GetTargetPositionByPercentage(float _troopPosition)
  917. {
  918. // X = ((Y - Z) / I) * 100f; To get the percentage from location
  919. // (((X / 100) * I) + Z) + targetMinLeft = Y; To get the location from percentage
  920.  
  921. float spawnAreaPosition = 0f;
  922. float spawnAreaDimensionHalf = 0f;
  923. float targetAreaPosition = 0f;
  924. float targetAreaDimensionHalf = 0f;
  925.  
  926. if (endlessTargetAxis == EndlessTargetAxis.X_Axis)
  927. {
  928. spawnAreaPosition = this.spawnAreaPosition.x + transform.position.x;
  929. spawnAreaDimensionHalf = spawnAreaDimension.x / 2f;
  930. targetAreaPosition = endlessTargetAreaPosition.x + transform.position.x;
  931. targetAreaDimensionHalf = endlessTargetAreaDimension.x / 2f;
  932. }
  933. else
  934. {
  935. spawnAreaPosition = this.spawnAreaPosition.z + transform.position.z;
  936. spawnAreaDimensionHalf = spawnAreaDimension.z / 2f;
  937. targetAreaPosition = endlessTargetAreaPosition.z + transform.position.z;
  938. targetAreaDimensionHalf = endlessTargetAreaDimension.z / 2f;
  939. }
  940.  
  941. float minLeft = spawnAreaPosition - spawnAreaDimensionHalf;
  942. float maxRight = spawnAreaPosition + spawnAreaDimensionHalf;
  943. float zeroedRight = maxRight - minLeft;
  944. float zeroedPosition = _troopPosition - minLeft;
  945. float result = (zeroedPosition / zeroedRight) * 100f;
  946.  
  947. float targetMinLeft = targetAreaPosition - targetAreaDimensionHalf;
  948. float targetMaxRight = targetAreaPosition + targetAreaDimensionHalf;
  949. float targetZeroedRight = targetMaxRight - targetMinLeft;
  950. float targetResult = (((result / 100f) * targetZeroedRight) + targetMinLeft);
  951.  
  952. if (endlessTargetAxis == EndlessTargetAxis.X_Axis)
  953. {
  954. return new Vector3(targetResult,
  955. transform.position.y + endlessTargetAreaPosition.y,
  956. transform.position.z + endlessTargetAreaPosition.z + Random.Range(-endlessTargetAreaDimension.z / 2f, endlessTargetAreaDimension.z / 2f));
  957. }
  958. else
  959. {
  960. return new Vector3(transform.position.x + endlessTargetAreaPosition.x + Random.Range(-endlessTargetAreaDimension.x / 2f, endlessTargetAreaDimension.x / 2f),
  961. transform.position.y + endlessTargetAreaPosition.y,
  962. targetResult);
  963. }
  964. }
  965.  
  966. private void DestroyAll()
  967. {
  968. if (spawnType == SpawnManager.SpawnType.SpawnEndless)
  969. {
  970. foreach (Transform waypoint in endlessWaypointContainer)
  971. {
  972. Destroy(waypoint.gameObject);
  973. }
  974. }
  975. else
  976. {
  977. DestroyAllWaypoints();
  978. }
  979.  
  980. foreach (Transform spawnTroop in spawnTroopContainer)
  981. {
  982. Destroy(spawnTroop.gameObject);
  983. }
  984. }
  985.  
  986. private void ResetValues()
  987. {
  988. formationIndex = 0;
  989. activeSpawnLocation = 0;
  990. }
  991.  
  992. private List<Transform> CreateWaypoints(List<Vector3> _spawnPositions)
  993. {
  994. List<Transform> waypoints = new List<Transform>();
  995.  
  996. for (int i = 0; i < _spawnPositions.Count; i++)
  997. {
  998. Transform waypoint = new GameObject(i.ToString()).transform;
  999. waypoint.position = _spawnPositions[i];
  1000.  
  1001. if (formations[formationIndex].formationType == FormationPlanner.FormationType.Image ||
  1002. formations[formationIndex].formationType == FormationPlanner.FormationType.Grid)
  1003. {
  1004. waypoint.rotation = Quaternion.LookRotation(formations[formationIndex].GetActiveDirection()[i], Vector3.up);
  1005. }
  1006. else
  1007. {
  1008. waypoint.rotation = formations[formationIndex].transform.rotation;
  1009. }
  1010.  
  1011. if (formations[formationIndex].pathCreator)
  1012. {
  1013. waypoint.SetParent(formations[formationIndex].pathCreator.transform);
  1014. waypointContainer = formations[formationIndex].pathCreator.transform;
  1015. }
  1016. else if (!formations[formationIndex].pathCreator)
  1017. {
  1018. waypoint.SetParent(formations[formationIndex].transform);
  1019. waypointContainer = formations[formationIndex].transform;
  1020. }
  1021.  
  1022. waypoints.Add(waypoint);
  1023. }
  1024.  
  1025. return waypoints;
  1026. }
  1027.  
  1028. private void DestroyAllWaypoints()
  1029. {
  1030. if (formations[formationIndex].pathCreator)
  1031. {
  1032. foreach (Transform waypoint in formations[formationIndex].pathCreator.transform)
  1033. {
  1034. Destroy(waypoint.gameObject);
  1035. }
  1036. }
  1037. else
  1038. {
  1039. foreach (Transform waypoint in formations[formationIndex].transform)
  1040. {
  1041. Destroy(waypoint.gameObject);
  1042. }
  1043. }
  1044. }
  1045.  
  1046. private Vector3 GetTroopPosition(Vector3 _spawnPosition)
  1047. {
  1048. if (spawnAtTheSpot)
  1049. {
  1050. RaycastHit hit = new RaycastHit();
  1051.  
  1052. if (Physics.Raycast(_spawnPosition, Vector3.down, out hit, Mathf.Infinity, waypointHeightLayerMask))
  1053. {
  1054. return hit.point;
  1055. }
  1056.  
  1057. return _spawnPosition;
  1058. }
  1059. else
  1060. {
  1061. return GetSpawnLocation();
  1062. }
  1063. }
  1064.  
  1065. private void ResetWaypointsToCurrentFormation()
  1066. {
  1067. DestroyAllWaypoints();
  1068.  
  1069. List<Vector3> spawnPositions = formations[formationIndex].GetActiveList();
  1070. List<Transform> waypoints = CreateWaypoints(spawnPositions);
  1071.  
  1072. for (int i = 0; i < spawnPositions.Count; i++)
  1073. {
  1074. if (i < spawnTroopContainer.childCount)
  1075. {
  1076. AIDataHolder troop = spawnTroopContainer.GetChild(i).GetComponent<AIDataHolder>();
  1077. troop.Reference.LocalBehaviour.SetupAI(this, waypoints[i]);
  1078. }
  1079. }
  1080. }
  1081.  
  1082. public void SetReturnToOrigin(bool _returnToOrigin)
  1083. {
  1084. for (int i = 0; i < spawnTroopContainer.childCount; i++)
  1085. {
  1086. AIDataHolder troop = spawnTroopContainer.GetChild(i).GetComponent<AIDataHolder>();
  1087. troop.ReturnToOrigin = _returnToOrigin;
  1088. }
  1089. }
  1090.  
  1091. private void Spawn()
  1092. {
  1093. if (spawnType == SpawnType.SpawnAllAtOnce)
  1094. {
  1095. SpawnAllAtOnce();
  1096. }
  1097. else if (spawnType == SpawnType.SpawnInBurst)
  1098. {
  1099. BurstCoroutine = StartCoroutine(SpawnInBurst());
  1100. }
  1101. else if (spawnType == SpawnType.SpawnWithTimer)
  1102. {
  1103. TimerCoroutine = StartCoroutine(SpawnTroopsWithTimer());
  1104. }
  1105. else if (spawnType == SpawnType.SpawnEndless)
  1106. {
  1107. BurstEndlessCoroutine = StartCoroutine(SpawnInBurstEndless());
  1108. }
  1109. }
  1110.  
  1111. private void StopCoroutines()
  1112. {
  1113. if (BurstCoroutine != null) StopCoroutine(BurstCoroutine);
  1114. if (TimerCoroutine != null) StopCoroutine(TimerCoroutine);
  1115. if (BurstEndlessCoroutine != null) StopCoroutine(BurstEndlessCoroutine);
  1116. if (AutomatedFormationSwitchCoroutine != null) StopCoroutine(AutomatedFormationSwitchCoroutine);
  1117. }
  1118. }
  1119. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement