| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  | using System; | 
					
						
							|  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  | using NUnit.Framework.Constraints; | 
					
						
							|  |  |  | using UnityEditor.UIElements; | 
					
						
							|  |  |  | using UnityEngine; | 
					
						
							|  |  |  | using UnityEngine.Assertions; | 
					
						
							|  |  |  | using Random = UnityEngine.Random; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Weapons.Spawning | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     public enum SpawnType { Circle, Square, Polygon, Composite } | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |     public enum SpawnPlane { XY, XZ } | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |     public enum SpawnDir { None, Randomised, Spherised, Directional} | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |     [Serializable] | 
					
						
							|  |  |  |     public struct SpawnZone | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         [SerializeField] private int numToSpawn; | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         [SerializeField] private Vector3 offset; | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |          | 
					
						
							|  |  |  |         [SerializeField] private SpawnType spawnType; | 
					
						
							|  |  |  |         [SerializeField] private SpawnDir spawnDir; | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         [SerializeField] private SpawnPlane spawnPlane; | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |          | 
					
						
							|  |  |  |         [SerializeField] private float width; | 
					
						
							|  |  |  |         [SerializeField] private float height; | 
					
						
							|  |  |  |         [SerializeField] private bool surfaceOnly; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         [SerializeField] private bool evenDistribution; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [SerializeField] private int numSides; | 
					
						
							|  |  |  |         [SerializeField] private int numPerSide; | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         [SerializeField] private bool flipVertical; | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |          | 
					
						
							|  |  |  |         [SerializeField] private float radius; | 
					
						
							|  |  |  |         [SerializeField, Range(0, 360)] private float arc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [SerializeField] private SpawnZone[] composite; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         public SpawnDir SpawnDir => spawnDir; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         public int NumToSpawn => numToSpawn; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         public void GetPoint(Transform transform, Action<Vector3, Vector3> onGetPoint) | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             switch (spawnType) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 case SpawnType.Circle: | 
					
						
							|  |  |  |                     SpawnCircle(transform, onGetPoint); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case SpawnType.Square: | 
					
						
							|  |  |  |                     SpawnSquare(transform, onGetPoint); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case SpawnType.Composite: | 
					
						
							|  |  |  |                     SpawnComposite(transform, onGetPoint); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case SpawnType.Polygon: | 
					
						
							|  |  |  |                     SpawnPoly(transform, onGetPoint); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     throw new ArgumentOutOfRangeException(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         private void SpawnPoly(Transform transform, Action<Vector3, Vector3> onGetPoint) | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             var points = new Vector2[numSides]; | 
					
						
							|  |  |  |             for (int i = 0; i < numSides; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var angle = (i * (arc * Mathf.Deg2Rad) / numSides) + | 
					
						
							|  |  |  |                             (90 - transform.eulerAngles.y - arc/2) * Mathf.Deg2Rad; | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                 points[i] = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (int i = 0; i < numSides; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var next = i + 1; | 
					
						
							|  |  |  |                 if (next == numSides) | 
					
						
							|  |  |  |                     next = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 var direction = Vector2.Lerp(points[i], points[next], 0.5f).normalized; | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 for (int j = 0; j < numPerSide; j++) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     var t = j / (float) numPerSide; | 
					
						
							|  |  |  |                     t += (1f / numPerSide)/2f; | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                     var point = Vector3.Lerp(points[i], points[next], t); | 
					
						
							|  |  |  |                     if (flipVertical) | 
					
						
							|  |  |  |                         point.y = 1 - point.y; | 
					
						
							|  |  |  |                      | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                     point *= radius; | 
					
						
							|  |  |  |                      | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                     if (spawnPlane == SpawnPlane.XZ) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         point.z = point.y; | 
					
						
							|  |  |  |                         point.y = 0; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                     var dir = Vector3.up; | 
					
						
							|  |  |  |                      | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                     if (spawnDir == SpawnDir.Directional) | 
					
						
							|  |  |  |                         dir = direction; | 
					
						
							|  |  |  |                     else if (spawnDir == SpawnDir.Spherised) | 
					
						
							|  |  |  |                         dir = point.normalized; | 
					
						
							|  |  |  |                     else if (spawnDir == SpawnDir.Randomised) | 
					
						
							|  |  |  |                         dir = Random.insideUnitCircle.normalized; | 
					
						
							|  |  |  |                      | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                     if (!surfaceOnly) | 
					
						
							|  |  |  |                         point = Vector2.Lerp(point, Vector3.zero, Random.Range(0, 1f)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                     onGetPoint?.Invoke(point, dir); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         private void SpawnComposite(Transform transform, Action<Vector3, Vector3> onGetPoint) | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             for (int i = 0; i < numToSpawn; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 composite[Random.Range(0, composite.Length)].GetPoint(transform, onGetPoint); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         private void SpawnCircle(Transform transform, Action<Vector3, Vector3> onGetPoint) | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             Assert.IsNotNull(onGetPoint); | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             for (int i = 0; i < numToSpawn; i++) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 var point = Vector3.zero; | 
					
						
							|  |  |  |                  | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 if (!evenDistribution) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     var angle = (Random.Range(-arc / 2f, arc / 2f) + 90 - transform.eulerAngles.y) * Mathf.Deg2Rad; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     point.x = Mathf.Cos(angle); | 
					
						
							|  |  |  |                     point.y = Mathf.Sin(angle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (!surfaceOnly) | 
					
						
							|  |  |  |                         point *= Random.Range(0, 1f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     var angle = (i * (arc * Mathf.Deg2Rad) / numToSpawn) + | 
					
						
							|  |  |  |                                 (90 - transform.eulerAngles.y - arc/2) * Mathf.Deg2Rad; | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                     point = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                     if (!surfaceOnly) | 
					
						
							|  |  |  |                         point *= Random.Range(0, 1f); | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                  | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 if (spawnPlane == SpawnPlane.XZ) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     point.z = point.y; | 
					
						
							|  |  |  |                     point.y = 0; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                  | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 var dir = Vector3.up; | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 if (spawnDir == SpawnDir.Spherised || spawnDir == SpawnDir.Directional) | 
					
						
							|  |  |  |                     dir = point.normalized; | 
					
						
							|  |  |  |                 else if (spawnDir == SpawnDir.Randomised) | 
					
						
							|  |  |  |                     dir = Random.insideUnitCircle.normalized; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 onGetPoint((point * radius) + offset, dir); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |         private void SpawnSquare(Transform transform, Action<Vector3, Vector3> onGetPoint) | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             Assert.IsNotNull(onGetPoint); | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             for (int i = 0; i < numToSpawn; i++) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 var point = new Vector3 | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 { | 
					
						
							|  |  |  |                     x = Random.Range(-.5f, .5f), | 
					
						
							|  |  |  |                     y = Random.Range(-.5f, .5f) | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (surfaceOnly) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     int axis = Random.Range(0, 2); | 
					
						
							|  |  |  |                     point[axis] = point[axis] < 0f ? -0.5f : 0.5f; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 point.x *= width; | 
					
						
							|  |  |  |                 point.y *= height; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 if (spawnPlane == SpawnPlane.XZ) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     point.z = point.y; | 
					
						
							|  |  |  |                     point.y = 0; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                  | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 var dir = Vector3.up; | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 if (spawnDir == SpawnDir.Spherised || spawnDir == SpawnDir.Directional) | 
					
						
							|  |  |  |                     dir = point.normalized; | 
					
						
							|  |  |  |                 else if (spawnDir == SpawnDir.Randomised) | 
					
						
							|  |  |  |                     dir = Random.insideUnitCircle.normalized; | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 onGetPoint(point + offset, dir); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public void DrawGizmos(Color color, Transform transform) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             switch (spawnType) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 case SpawnType.Circle: | 
					
						
							|  |  |  |                     DrawGizmosCircle(color, transform); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case SpawnType.Square: | 
					
						
							|  |  |  |                     DrawGizmosSquare(color, transform); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case SpawnType.Composite: | 
					
						
							|  |  |  |                     DrawComposite(color, transform); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case SpawnType.Polygon: | 
					
						
							|  |  |  |                     DrawGizmosPoly(color,transform); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     throw new ArgumentOutOfRangeException(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private void DrawComposite(Color color, Transform transform) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             foreach (var zone in composite) | 
					
						
							|  |  |  |                 zone.DrawGizmos(color, transform); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         private void DrawGizmosCircle(Color color, Transform transform) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Gizmos.color = color; | 
					
						
							|  |  |  |             SpawnCircle(transform, (point, dir) => | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 Gizmos.DrawSphere( transform.position + point, 0.25f); | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 if (color.a > 0.5f) | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                     Gizmos.DrawRay( transform.position + point, new Vector3(dir.x, 0, dir.y)); | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private void DrawGizmosPoly(Color color, Transform transform) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Gizmos.color = color; | 
					
						
							|  |  |  |             SpawnPoly(transform, (point, dir) => | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 Gizmos.DrawSphere(transform.position + point, 0.25f); | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 if (color.a > 0.5f) | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                     Gizmos.DrawRay(transform.position + point, new Vector3(dir.x, 0, dir.y)); | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         private void DrawGizmosSquare(Color color, Transform transform) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Gizmos.color = color; | 
					
						
							|  |  |  |             SpawnSquare(transform, (point, dir) => | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                 Gizmos.DrawSphere(transform.position + point, 0.25f); | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |                 if (color.a > 0.5f) | 
					
						
							| 
									
										
										
										
											2021-01-09 16:18:29 +00:00
										 |  |  |                     Gizmos.DrawRay(transform.position + point, new Vector3(dir.x, 0, dir.y)); | 
					
						
							| 
									
										
										
										
											2021-01-05 12:10:20 +00:00
										 |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |