using HPJ.Simulation; using HPJ.Simulation.Enums; using HPJ.Simulation.Map; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace HPJ.Presentation.Obstacle { // A Simple Obstacle based on a sphere or circle public class NavigationObstacleSphere : NavigationObstacle { #region Unity // Start is called before the first frame update public override void Start() { if (!NavigationManager.Instance.Initialized) { Invoke(nameof(Start), 01f); return; } MapTileRelationships = new Dictionary(); _previousPosition = new Vector3(-1111111, -112321321321312, 233414212); base.Start(); } public virtual void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, _radius); Gizmos.color = Color.blue; Gizmos.DrawLine(transform.position, transform.position - Vector3.up * _checkMapHeight); } #endregion #region Obstacle [SerializeField] protected float _radius = 1f; public float Radius { get { return _radius; } set { _radius = value; } } private Vector3 _previousPosition; public override void UpdatePosition(Vector3 NewPosition, bool ForceCheck = false) { if (!NavigationManager.Instance.Initialized) { return; } // No need to update if no tiles need updating if (PositionChanged(NewPosition)) { _previousPosition = NewPosition; foreach (MapObstacleRelationshipData Data in MapTileRelationships.Values) { Data.UnvalidateTiles(); } foreach (MapSet Set in NavigationManager.Instance.MapSets) { if (transform.position.y - Set.SetSettings.MapSettings.Offset.y / 100f > _checkMapHeight) { //Debug.Log("Too high or Too low"); continue; } if (!NavigationManager.Instance.CircleOnMap(Set, NewPosition, Radius)) { //Debug.Log("Not on Map"); continue; } MapObstacleRelationshipData RelationshipData; if (MapTileRelationships.ContainsKey(Set)) { RelationshipData = MapTileRelationships[Set]; } else { RelationshipData = new MapObstacleRelationshipData(Set, this, _obstacleTileType); MapTileRelationships.Add(Set, RelationshipData); } Vector3 RadiusVector = new Vector3(Radius, 0, Radius); IntVector2 Center = Set.GetMapTileIndex(NavigationManager.Instance.GetTileWorldPosition(NewPosition)); IntVector2 HigherBound = Set.GetMapTileIndex(NavigationManager.Instance.GetTileWorldPosition(NewPosition + RadiusVector)); IntVector2 LowerBound = Set.GetMapTileIndex(NavigationManager.Instance.GetTileWorldPosition(NewPosition - RadiusVector)); float TileRadiusSqr = (HigherBound.y - LowerBound.y) / 2f; TileRadiusSqr *= TileRadiusSqr; for (int x = LowerBound.x; x <= HigherBound.x; x++) { for (int y = LowerBound.y; y <= HigherBound.y; y++) { int X_Distance = Center.x - x; int Y_Distance = Center.y - y; if (X_Distance * X_Distance + Y_Distance * Y_Distance > TileRadiusSqr) { //Debug.Log($"({X_Distance}, {Y_Distance}) Not In Bounds"); continue; } // Make sure its close enough to the ground to count as an obstacle if (Set.GetTileType(x, y) != TileTypes.OutOfBounds) { //Debug.Log("Change Tile"); IntVector3 TileKey = new IntVector3(x, y, Set.InstanceID); RelationshipData.AddOrValidateTile(TileKey); } } } } foreach (MapObstacleRelationshipData Data in MapTileRelationships.Values) { ChangeMapJob GeneratedMapChangeJob = Data.GenerateMapChangeJob(); if (GeneratedMapChangeJob != null) { //Debug.Log("Change Map From Job"); Data.Map.ChangeMap(GeneratedMapChangeJob); } Data.SortRelatedTileData(); } } else { RevalidateTiles(); } } public override void RevalidateTiles() { foreach (MapObstacleRelationshipData Data in MapTileRelationships.Values) { Data.Revalidate(); } } protected override bool PositionChanged(Vector3 NewPosition) { return _previousPosition != NewPosition; } /// /// Rotates the obstacle based on the desired Rotation. Basic NavigationObstacle will only swap the object size x and y values. Inherit to ovverride this behaviour /// /// public override void Rotate(Quaternion Rotation) { } #endregion } }