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); }
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); }
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); }
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); }
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); }
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); }