Beispiel #1
0
        public bool IsObjectSpawnValid(GameObject spawnPoint, Vector3 checkTarget)
        {
            CombatGameState    combatState         = UnityGameInstance.BattleTechGame.Combat;
            EncounterLayerData encounterLayerData  = MissionControl.Instance.EncounterLayerData;
            Vector3            checkTargetPosition = checkTarget.GetClosestHexLerpedPointOnGrid();

            Vector3 spawnPointPosition = GetClosestValidPathFindingHex(spawnPoint, spawnPoint.transform.position, $"IsObjectSpawnInvalid.{spawnPoint.name}", Vector3.zero, 2);

            Main.LogDebug($"[SpawnLanceLogic.IsObjectSpawnInvalid] Object spawn point's closest hex lerped point on grid for '{spawnPoint.name}' is '{spawnPointPosition}'");

            if (!encounterLayerData.IsInEncounterBounds(spawnPointPosition))
            {
                Main.LogDebugWarning("[SpawnLanceLogic.IsObjectSpawnInvalid] Object spawn is outside of the boundary. Select a new object spawn point.");
                return(false);
            }

            if (!PathFinderManager.Instance.IsSpawnValid(spawnPoint, spawnPointPosition, checkTargetPosition, UnitType.Mech, spawnPoint.name))
            {
                Main.LogDebugWarning($"[SpawnLanceLogic.IsObjectSpawnInvalid] Object spawn '{spawnPoint.name}' path to check target '{checkTarget}' is blocked. Select a new object spawn point");
                return(false);
            }

            spawnPoint.transform.position = spawnPointPosition;
            return(true);
        }
Beispiel #2
0
        protected GameObject GetClosestPlot(Vector3 origin)
        {
            GameObject plotsParentGo   = GameObject.Find("PlotParent");
            GameObject closestPlot     = null;
            float      closestDistance = -1;

            foreach (Transform t in plotsParentGo.transform)
            {
                Vector3 plotPosition = t.position;
                if (EncounterLayerData.IsInEncounterBounds(plotPosition))
                {
                    if (IsPlotValidForEncounter(t))
                    {
                        float distance = Vector3.Distance(t.position, origin);
                        if (closestDistance == -1 || closestDistance < distance)
                        {
                            closestDistance = distance;
                            closestPlot     = t.gameObject;
                        }
                    }
                }
            }

            return(closestPlot);
        }
Beispiel #3
0
        protected List <GameObject> GetInvalidLanceMemberSpawns(GameObject lance, Vector3 checkTarget)
        {
            CombatGameState    combatState        = UnityGameInstance.BattleTechGame.Combat;
            EncounterLayerData encounterLayerData = MissionControl.Instance.EncounterLayerData;

            List <GameObject> invalidLanceSpawns  = new List <GameObject>();
            List <GameObject> spawnPoints         = lance.FindAllContains("SpawnPoint");
            Vector3           checkTargetPosition = checkTarget.GetClosestHexLerpedPointOnGrid();

            foreach (GameObject spawnPoint in spawnPoints)
            {
                // Vector3 spawnPointPosition = spawnPoint.transform.position.GetClosestHexLerpedPointOnGrid();
                Vector3 spawnPointPosition = GetClosestValidPathFindingHex(spawnPoint, spawnPoint.transform.position, $"GetInvalidLanceMemberSpawns.{spawnPoint.name}", IsLancePlayerLance(lance.name) ? checkTargetPosition : Vector3.zero, 2);
                Main.LogDebug($"[SpawnLanceLogic.GetInvalidLanceMemberSpawns] Spawn point's closest hex lerped point on grid for '{spawnPoint.name}' is '{spawnPointPosition}'");

                if (!encounterLayerData.IsInEncounterBounds(spawnPointPosition))
                {
                    Main.LogDebugWarning("[SpawnLanceLogic.GetInvalidLanceMemberSpawns] Lance member spawn is outside of the boundary. Select a new lance spawn point.");
                    invalidLanceSpawns.Add(spawnPoint);
                    continue;
                }

                // Ensure the lance member's spawn's closest valid point isn't on another spawn point's closest valid point
                if (IsPointTooCloseToOtherPointsClosestPointOnGrid(spawnPointPosition, spawnPoints.Where(sp => spawnPoint.name != sp.name).ToList()))
                {
                    Main.LogDebugWarning("[SpawnLanceLogic.GetInvalidLanceMemberSpawns] Lance member spawn is too close to the other spawns when snapped to the grid");
                    invalidLanceSpawns.Add(spawnPoint);
                    continue;
                }

                if (!PathFinderManager.Instance.IsSpawnValid(spawnPoint, spawnPointPosition, checkTargetPosition, UnitType.Mech, spawnPoint.name))
                {
                    Main.LogDebugWarning($"[SpawnLanceLogic.GetInvalidLanceMemberSpawns] Lance member spawn '{spawnPoint.name}' path to check target '{checkTarget}' is blocked. Select a new lance spawn point");
                    invalidLanceSpawns.Add(spawnPoint);
                    continue;
                }

                spawnPoint.transform.position = spawnPointPosition;
            }

            return(invalidLanceSpawns);
        }
Beispiel #4
0
        private GameObject CheckAllPlotsForValidPlot(GameObject plotsParent, Vector3 origin, string name)
        {
            GameObject closestPlot     = null;
            float      closestDistance = -1;

            foreach (Transform t in plotsParent.transform)
            {
                Vector3 plotPosition = t.position;
                if (EncounterLayerData.IsInEncounterBounds(plotPosition))
                {
                    if (IsPlotValidForEncounter(t, name))
                    {
                        float distance = Vector3.Distance(t.position, origin);
                        if (closestDistance == -1 || closestDistance < distance)
                        {
                            closestDistance = distance;
                            closestPlot     = t.gameObject;
                        }
                    }
                }
            }

            return(closestPlot);
        }
        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);
        }
Beispiel #6
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);
        }
Beispiel #7
0
        private Vector3 PathfindFromPointToSpawn(GameObject originGo, Vector3 origin, int radius, string identifier, Vector3 pathfindingTarget)
        {
            EncounterLayerData encounterLayerData = MissionControl.Instance.EncounterLayerData;
            CombatGameState    combatState        = UnityGameInstance.BattleTechGame.Combat;
            Vector3            originOnGrid       = origin.GetClosestHexLerpedPointOnGrid();

            // TODO: If the SpawnerPlayerLanceGo's closest hex point is in an inaccessible location - this will cause infinite loading issues
            // TODO: Need to find a reliably accessible location (hard to do in a proc-genned setup)
            Vector3 pathfindingPoint = (pathfindingTarget == Vector3.zero) ?
                                       EncounterRules.SpawnerPlayerLanceGo.transform.position.GetClosestHexLerpedPointOnGrid()
      : pathfindingTarget.GetClosestHexLerpedPointOnGrid();

            Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Using pathfinding point '{pathfindingPoint}'");

            if (!PathFinderManager.Instance.IsSpawnValid(originGo, originOnGrid, pathfindingPoint, UnitType.Mech, identifier))
            {
                List <Vector3> adjacentPointsOnGrid = combatState.HexGrid.GetGridPointsAroundPointWithinRadius(originOnGrid, radius);
                Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Adjacent point count is '{adjacentPointsOnGrid.Count}'");

                adjacentPointsOnGrid = adjacentPointsOnGrid.Where(point => {
                    return(!checkedAdjacentPoints.Contains(point) && encounterLayerData.IsInEncounterBounds(point));
                }).ToList();

                Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Removed already checked points & out of bounds points. Adjacent point count is now '{adjacentPointsOnGrid.Count}'");

                adjacentPointsOnGrid.Shuffle();

                int count = 0;
                foreach (Vector3 point in adjacentPointsOnGrid)
                {
                    if (count > ADJACENT_NODE_LIMITED)
                    {
                        Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Adjacent point count limited exceeded (random selection of {ADJACENT_NODE_LIMITED} / {adjacentPointsOnGrid.Count}). Bailing.");
                        break;
                    }

                    Vector3 validPoint = point.GetClosestHexLerpedPointOnGrid();

                    Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Testing an adjacent point of '{validPoint}'");
                    if (PathFinderManager.Instance.IsSpawnValid(originGo, validPoint, pathfindingPoint, UnitType.Mech, identifier))
                    {
                        return(validPoint);
                    }

                    bool isBadPathfindTest = PathFinderManager.Instance.IsProbablyABadPathfindTest(pathfindingPoint);
                    if (isBadPathfindTest)
                    {
                        Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Estimated this is a bad pathfind setup so trying something new.");
                        radius = 100;
                        count  = ADJACENT_NODE_LIMITED;
                    }

                    checkedAdjacentPoints.Add(point);
                    count++;
                }

                return(Vector3.zero);
            }
            else
            {
                Main.LogDebug($"[PathfindFromPointToPlayerSpawn] Spawn has been found valid by pathfinding '{originOnGrid}'");
            }

            return(originOnGrid);
        }