public bool IsSpawnValid(GameObject spawnGo, Vector3 position, Vector3 validityPosition, UnitType type, string identifier)
        {
            CombatGameState    combatState        = UnityGameInstance.BattleTechGame.Combat;
            EncounterLayerData encounterLayerData = MissionControl.Instance.EncounterLayerData;
            MapTerrainDataCell cellData           = combatState.MapMetaData.GetCellAt(position);

            Main.LogDebug($"");
            Main.LogDebug($"-------- [PFM.IsSpawnValid] [{identifier}] --------");

            if (position.IsTooCloseToAnotherSpawn(spawnGo))
            {
                Main.LogDebug($"[PFM] Position '{position}' is too close to another spawn point. Not a valid location.");
                return(false);
            }

            if (cellData.cachedSteepness > MAX_SLOPE_FOR_PATHFINDING)
            {
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Spawn point of '{cellData.cachedSteepness}' is too steep (> {MAX_SLOPE_FOR_PATHFINDING}). Not a valid spawn");
                return(false);
            }

            if (IsCellImpassableOrDeepWater(cellData))
            {
                return(false);
            }
            if (!encounterLayerData.IsInEncounterBounds(position))
            {
                return(false);
            }
            if (cellData.cachedHeight > (cellData.terrainHeight + 50f))
            {
                return(false);
            }

            float         pathFindingZoneRadius = 25f;
            AbstractActor pathfindingActor      = GetPathFindingActor(type);

            SetupPathfindingActor(position, pathfindingActor);

            PathNode positionPathNode = null;

            try {
                PathNodeGrid pathfinderPathGrid = pathfindingActor.Pathing.CurrentGrid;
                positionPathNode = pathfinderPathGrid.GetValidPathNodeAt(position, pathfindingActor.Pathing.MaxCost);
                if (positionPathNode == null)
                {
                    Reset();
                    return(false);
                }
            } catch (Exception e) {
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Caught error in 'pathfinderPathGrid.GetValidPathNodeAt' chunk. Flagging as invalid spawn. Select a new spawn point. {e.Message}, {e.StackTrace}");
                WasABadPathfindTest(validityPosition);
                return(false);
            }

            if (positionPathNode == null)
            {
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] PositionPathNode not set from 'pathfinderPathGrid.GetValidPathNodeAt'. No valid path found so not a valid spawn.");
                WasABadPathfindTest(validityPosition);
                return(false);
            }

            List <Vector3> path = null;

            try {
                DynamicLongRangePathfinder.PointWithCost pointWithCost = new DynamicLongRangePathfinder.PointWithCost(combatState.HexGrid.GetClosestHexPoint3OnGrid(positionPathNode.Position), 0, (validityPosition - positionPathNode.Position).magnitude);
                path = DynamicLongRangePathfinder.GetDynamicPathToDestination(new List <DynamicLongRangePathfinder.PointWithCost>()
                {
                    pointWithCost
                }, validityPosition, float.MaxValue, pathfindingActor, false, new List <AbstractActor>(), pathfindingActor.Pathing.CurrentGrid, pathFindingZoneRadius);
            } catch (Exception e) {
                // TODO: Sometimes this gets triggered in very large amounts. It's usually because the SpawnLogic.GetClosestValidPathFindingHex is increasing
                // the radius larger and larger and the checks keep going off the map
                // I need a way to hard abort out of this and either use the original origin of the focus or trigger the rule logic again (random, around a position etc)
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Caught error in 'DynamicLongRangePathfinder' chunk. Flagging as invalid spawn. Select a new spawn point. {e.Message}, {e.StackTrace}");
                WasABadPathfindTest(validityPosition);
                return(false);
            }

            if (path == null)
            {
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Path not set from DynamicLongRangePathfinder so not a valid spawn.");
                WasABadPathfindTest(validityPosition);
                return(false);
            }

            Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Path count is: '{path.Count}', Current position is: '{position}'");

            // GUARD: Against deep water and other impassables that have slipped through
            if (HasPathImpassableOrDeepWaterTiles(combatState, path))
            {
                return(false);
            }

            if (path != null && path.Count > 1 && (path[path.Count - 1].DistanceFlat(validityPosition) <= pathFindingZoneRadius))
            {
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Path count is: '{path.Count}', Current position is: '{position}'");
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Last point is '{path[path.Count - 1]}', Validity position is '{validityPosition}'");
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Distance from last path to valdity position is: '{(path[path.Count - 1].DistanceFlat(validityPosition))}' and is it within zone radius? '{(path[path.Count - 1].DistanceFlat(validityPosition) <= pathFindingZoneRadius)}'");
                Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Has valid long range path finding");
                if (HasValidNeighbours(positionPathNode, validityPosition, type))
                {
                    Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Has at least two valid neighbours");

                    if (HasValidLocalPathfinding(positionPathNode, validityPosition, type))
                    {
                        Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Has a valid path");
                        Reset();
                        Main.LogDebug($"-------- END [PFM.IsSpawnValid] [{identifier}] END --------");
                        Main.LogDebug($"");
                        return(true);
                    }
                    else
                    {
                        Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Does NOT have a valid path");
                    }
                }
                else
                {
                    Main.LogDebug($"[PFM.IsSpawnValid] [{identifier}] Does not have two valid neighbours");
                }
            }

            Main.LogDebug($"-------- END [PFM.IsSpawnValid] [{identifier}] END --------");
            Main.LogDebug($"");
            Reset();
            return(false);
        }
Exemple #2
0
        public bool IsSpawnValid(Vector3 position, Vector3 validityPosition, UnitType type, string identifier)
        {
            CombatGameState    combatState        = UnityGameInstance.BattleTechGame.Combat;
            EncounterLayerData encounterLayerData = MissionControl.Instance.EncounterLayerData;
            MapTerrainDataCell cellData           = combatState.MapMetaData.GetCellAt(position);

            Main.LogDebug($"");
            Main.LogDebug($"-------- [PathFinderManager.IsSpawnValid] [{identifier}] --------");

            if (cellData.cachedSteepness > MAX_SLOPE_FOR_PATHFINDING)
            {
                Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Spawn point of '{cellData.cachedSteepness}' is too steep (> {MAX_SLOPE_FOR_PATHFINDING}). Not a valid spawn");
                return(false);
            }

            if (IsCellImpassableOrDeepWater(cellData))
            {
                return(false);
            }
            if (!encounterLayerData.IsInEncounterBounds(position))
            {
                return(false);
            }
            if (cellData.cachedHeight > (cellData.terrainHeight + 50f))
            {
                return(false);
            }

            float         pathFindingZoneRadius = 25f;
            AbstractActor pathfindingActor      = GetPathFindingActor(type);

            SetupPathfindingActor(position, pathfindingActor);

            try {
                PathNodeGrid pathfinderPathGrid = pathfindingActor.Pathing.CurrentGrid;
                PathNode     positionPathNode   = pathfinderPathGrid.GetValidPathNodeAt(position, pathfindingActor.Pathing.MaxCost);
                if (positionPathNode == null)
                {
                    Reset();
                    return(false);
                }

                DynamicLongRangePathfinder.PointWithCost pointWithCost = new DynamicLongRangePathfinder.PointWithCost(combatState.HexGrid.GetClosestHexPoint3OnGrid(positionPathNode.Position), 0, (validityPosition - positionPathNode.Position).magnitude)
                {
                    pathNode = positionPathNode
                };
                List <Vector3> path = DynamicLongRangePathfinder.GetDynamicPathToDestination(new List <DynamicLongRangePathfinder.PointWithCost>()
                {
                    pointWithCost
                }, validityPosition, float.MaxValue, pathfindingActor, false, new List <AbstractActor>(), pathfindingActor.Pathing.CurrentGrid, pathFindingZoneRadius);

                // List<Vector3> path = DynamicLongRangePathfinder.GetPathToDestination(position, float.MaxValue, pathfindingActor, true, pathFindingZoneRadius);
                // List<Vector3> path = DynamicLongRangePathfinder.GetDynamicPathToDestination(position, float.MaxValue, pathfindingActor, true, new List<AbstractActor>(), pathfindingActor.Pathing.CurrentGrid, pathFindingZoneRadius);

                Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Path count is: '{path.Count}', Current position is: '{position}'");

                // GUARD: Against deep water and other impassables that have slipped through
                if (HasPathImpassableOrDeepWaterTiles(combatState, path))
                {
                    return(false);
                }

                if (path != null && path.Count > 1 && (path[path.Count - 1].DistanceFlat(validityPosition) <= pathFindingZoneRadius))
                {
                    Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Path count is: '{path.Count}', Current position is: '{position}'");
                    Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Last point is '{path[path.Count - 1]}', Validity position is '{validityPosition}'");
                    Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Distance from last path to valdity position is: '{(path[path.Count - 1].DistanceFlat(validityPosition))}' and is it within zone radius? '{(path[path.Count - 1].DistanceFlat(validityPosition) <= pathFindingZoneRadius)}'");
                    Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Has valid long range path finding");
                    if (HasValidNeighbours(positionPathNode, validityPosition, type))
                    {
                        Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Has at least two valid neighbours");

                        if (HasValidLocalPathfinding(positionPathNode, validityPosition, type))
                        {
                            Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Has a valid path");
                            Reset();
                            Main.LogDebug($"-------- END [PathFinderManager.IsSpawnValid] [{identifier}] END --------");
                            Main.LogDebug($"");
                            return(true);
                        }
                        else
                        {
                            Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Does NOT have a valid path");
                        }
                    }
                    else
                    {
                        Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Does not have two valid neighbours");
                    }
                }

                /* // Failed attempt to improve spawn checks
                 * List<Vector3> path = DynamicLongRangePathfinder.GetDynamicPathToDestination(validityPosition, float.MaxValue, pathfindingActor, true, new List<AbstractActor>(), pathfindingActor.Pathing.CurrentGrid, pathFindingZoneRadius);
                 * if (path != null && (path[path.Count - 1].DistanceFlat(validityPosition) <= pathFindingZoneRadius)) {
                 * if (path.Count > 4) { // very strong pathfinding location
                 *  return true;
                 * } else {
                 *  Main.Logger.Log($"[PathFinderManager] Spawn point is valid due to proximity but is not strong enough success for pathing. Attempting to confirm.");
                 *  CombatGameState combatState = UnityGameInstance.BattleTechGame.Combat;
                 *  List<Vector3> pointsAroundPosition = combatState.HexGrid.GetGridPointsAroundPointWithinRadius(position, 3, 5);
                 *
                 *  foreach (Vector3 point in pointsAroundPosition) {
                 *    List<Vector3> secondaryPath = DynamicLongRangePathfinder.GetDynamicPathToDestination(point, float.MaxValue, pathfindingActor, true, new List<AbstractActor>(), pathfindingActor.Pathing.CurrentGrid, 2);
                 *    if (path != null && path.Count > 2) {
                 *      Main.Logger.Log($"[PathFinderManager] Spawn point is valid. It is close to the validation point but can be moved away from. Success.");
                 *      return true;
                 *    }
                 *  }
                 * }
                 * }
                 */
            } catch (Exception e) {
                // TODO: Sometimes this gets triggered in very large amounts. It's usually because the SpawnLogic.GetClosestValidPathFindingHex is increasing
                // the radius larger and larger and the checks keep going off the map
                // I need a way to hard abort out of this and either use the original origin of the focus or trigger the rule logic again (random, around a position etc)
                Main.LogDebug($"[PathFinderManager.IsSpawnValid] [{identifier}] Array out of bounds detected in the path finding code. Flagging as invalid spawn. Select a new spawn point. {e.Message}, {e.StackTrace}");
            }

            Main.LogDebug($"-------- END [PathFinderManager.IsSpawnValid] [{identifier}] END --------");
            Main.LogDebug($"");
            Reset();
            return(false);
        }