public void StartIntegrationFieldCreation(Tile destinationTile, List <List <int> > areasAndSectorsParam, FlowFieldPath flowPathParam, SearchPathJob pathJob, int key, bool pathEdit) { FlowFieldPath flowPath = null; bool aPathIsCreated = false; List <List <int> > areasAndSectors = areasAndSectorsParam; List <int> areas = new List <int>(); List <List <int> > sectors = new List <List <int> >(); Dictionary <IntVector2, List <Tile> > areaConnectionTiles = new Dictionary <IntVector2, List <Tile> >(); bool firstWorldArea = !pathEdit; for (int a = 0; a < areasAndSectors.Count; a++) // each separate search //areasAndSectors.Count { var firstWorldAreaOfNewSearch = true; var index = 0; areas.Clear(); sectors.Clear(); Dictionary <IntVector2, int[]> alreadyFilledInSector = null; IntVector2 areaSectorKey = new IntVector2(0, 0); //area.index, sectorIndex); if (pathEdit && flowPathParam != null) { flowPath = flowPathParam; } //setup/starting point of the sectors- and areas- lists int startIndex; if (a == 0 && !pathEdit) // first search { startIndex = 0; areas.Add(areasAndSectors[a][0]); sectors.Add(new List <int>()); } else // we start with a search that is not the first one. we might be able to skip a lot of already integrated sectors { if (flowPath == null) { flowPath = WorldData.FlowFieldManager.FlowFieldPaths[ WorldData.FlowFieldManager.FlowFieldPaths.Count - 1]; } alreadyFilledInSector = flowPath.IntegrationField.Field; startIndex = -1; for (int i = 0; i < areasAndSectors[a].Count; i += 2) { areaSectorKey.X = areasAndSectors[a][i]; areaSectorKey.Y = areasAndSectors[a][i + 1]; if (!alreadyFilledInSector.ContainsKey(areaSectorKey)) // sector not yet filled in { startIndex = i; areas.Add(areasAndSectors[a][startIndex]); sectors.Add(new List <int>()); break; } } } // if -1 we can skip it all if (startIndex != -1) // else entire path already calculated by a different search { // set what tiles to cross over during a search // separate areas and sectors in arrays for (int i = startIndex; i < areasAndSectors[a].Count; i += 2) { areaSectorKey.X = areasAndSectors[a][i]; areaSectorKey.Y = areasAndSectors[a][i + 1]; if (areasAndSectors[a][i] == areas[index]) { sectors[index].Add(areasAndSectors[a][i + 1]); } else { index++; areas.Add(areasAndSectors[a][i]); sectors.Add(new List <int>()); sectors[index].Add(areasAndSectors[a][i + 1]); } if (alreadyFilledInSector != null && alreadyFilledInSector.ContainsKey(areaSectorKey) ) // added sector already filled in { // a couple of sectors where not already found, then they were, then they aren't again // we split up this search, so that every search in the flowing steps is a list of sectors that all directly connect. // no gaps of already filled in sectors areasAndSectors.Add(new List <int>()); for (int j = i; j < areasAndSectors[a].Count; j++) { areasAndSectors[areasAndSectors.Count - 1].Add(areasAndSectors[a][j]); } break; } } if (!firstWorldArea && areasAndSectors[a][startIndex] != areasAndSectors[a][startIndex - 2]) // different world areas { firstWorldAreaOfNewSearch = false; } // going through our areas- and sectors- lists for (int i = 0; i < areas.Count; i++) { WorldData.MultiLevelSectorManager.SetSearchFields(areas[i], sectors[i], true); WorldArea currentWorldArea = WorldData.WorldAreas[areas[i]]; if (firstWorldAreaOfNewSearch) { _openSet.Clear(); List <Tile> oldSectorTiles = new List <Tile>(); if (firstWorldArea) { _tilesSearchList.Add(destinationTile); _tilesSearchList[0].IntegrationValue = 0; } else { WorldArea area = WorldData.WorldAreas[areasAndSectors[a][startIndex]]; MultiLevelSector start = area.SectorGrid[0][areasAndSectors[a][startIndex - 1]]; MultiLevelSector next = area.SectorGrid[0][areasAndSectors[a][startIndex + 1]]; oldSectorTiles = WorldData.MultiLevelSectorManager.RowBetweenSectorsWithinWorldArea(start, next, area); if (pathEdit) // put old values back in the old tiles { IntVector2 oldTileKey = new IntVector2(); foreach (Tile tile in oldSectorTiles) { oldTileKey.X = tile.WorldAreaIndex; oldTileKey.Y = tile.SectorIndex; tile.IntegrationValue = flowPath.IntegrationField.Field[oldTileKey][tile.IndexWithinSector]; } } _tilesSearchList.AddRange(oldSectorTiles); } foreach (Tile oldTile in oldSectorTiles) { _closedSet.Remove(oldTile); } } else { WorldArea previousWorldArea; int lastSectorOfPreviousWorldArea; if (i == 0) // previous world area is not in array, removed because of already covered { previousWorldArea = WorldData.WorldAreas[areasAndSectors[a][startIndex - 2]]; lastSectorOfPreviousWorldArea = areasAndSectors[a][startIndex - 1]; } else { previousWorldArea = WorldData.WorldAreas[areas[i - 1]]; lastSectorOfPreviousWorldArea = sectors[i - 1][sectors[i - 1].Count - 1]; } int sectorOfCurrentArea = sectors[i][0]; IntVector2 areaConnectionKey = new IntVector2(currentWorldArea.Index, previousWorldArea.Index); if (!areaConnectionTiles.ContainsKey(areaConnectionKey)) { areaConnectionTiles.Add(areaConnectionKey, new List <Tile>()); } List <Tile> tiles = SwitchToNextWorldArea(previousWorldArea, currentWorldArea, lastSectorOfPreviousWorldArea, sectorOfCurrentArea, flowPath); areaConnectionTiles[areaConnectionKey].AddRange(tiles); } WaveExpansionSearchTiles(currentWorldArea); _closedSetFinish.AddRange(_closedSet); // all integration fields generated, create flow field if (firstWorldArea) { aPathIsCreated = true; WorldData.FlowFieldManager.CreateFlowFieldPath(_closedSet, sectors[i], areas, destinationTile, currentWorldArea, key); } else { WorldData.FlowFieldManager.AddToFlowFieldPath(_closedSet, sectors[i], currentWorldArea); if (pathEdit) { aPathIsCreated = true; } } _closedSet.Clear(); firstWorldAreaOfNewSearch = false; firstWorldArea = false; WorldData.MultiLevelSectorManager.SetSearchFields(areas[i], sectors[i], false); } } } if (flowPath == null && WorldData.FlowFieldManager.FlowFieldPaths.Count > 0) { flowPath = WorldData.FlowFieldManager.FlowFieldPaths[ WorldData.FlowFieldManager.FlowFieldPaths.Count - 1]; } if (flowPath != null) { flowPath.FlowField.FillFlowField(_closedSetFinish, WorldData); WorldData.FlowFieldManager.AddAreaTilesToFlowFieldPath(areaConnectionTiles); } if (pathJob != null) { pathJob.PathCreated(aPathIsCreated ? flowPath : null, false); } else { if (aPathIsCreated) { if (flowPath != null) { WorldData.Pathfinder.PathCreated(flowPath, flowPath.Key, pathEdit); } } else { WorldData.Pathfinder.PathCreated(null, 0, pathEdit); } } ResetTilesAfterSearch(); }
public int GetDirBetweenVectors(IntVector2 start, IntVector2 end) { if (start == end) { return(0); } else { if (start.x == end.x) { if (end.y > start.y) { return(2); } else { return(1); } } else { if (end.x > start.x) { if (end.y > start.y) { return(5); } else { if (end.y < start.y) { return(4); } else { return(3); } } } else { if (end.x < start.x) { if (end.y > start.y) { return(8); } else { if (end.y < start.y) { return(7); } else { return(6); } } } else { return(0); } } } } }