3 #include "../../services/Randomizer.hxx"
38 std::vector<Point> nodesToUpdate{isoCoordinates};
48 for (
const Point &neighborCoord : neighorCoordinates)
66 int initialHeight = startCoordinate.
height;
76 char directNeighbors =
77 NeighborNodesPosition::LEFT | NeighborNodesPosition::TOP | NeighborNodesPosition::RIGHT | NeighborNodesPosition::BOTTOM;
80 int nonSelectedNeighborsCount = 0;
81 int elevatedNonSelectedNeighborsCount = 0;
89 if (!isSloped && (neighborPosToOrigin & directNeighbors) > 0 &&
90 std::find(levelArea.begin(), levelArea.end(), neighbor) == levelArea.end())
92 nonSelectedNeighborsCount++;
94 if ((neighborPosToOrigin & elBitmask) > 0)
95 elevatedNonSelectedNeighborsCount++;
99 if (elevatedNonSelectedNeighborsCount * 2 > nonSelectedNeighborsCount)
104 std::vector<Point> neighborsToLower;
106 for (
const Point &levelPoint : levelArea)
110 if (
getMapNode(levelPoint).getCoordinates().height > initialHeight)
115 neighborsToLower.insert(neighborsToLower.end(), neighbors.begin(), neighbors.end());
118 Point newCoordinates =
Point(levelPoint.x, levelPoint.y, levelPoint.z, initialHeight);
123 for (
const Point &levelPoint : neighborsToLower)
125 Point newCoordinates =
Point(levelPoint.x, levelPoint.y, levelPoint.z, initialHeight);
137 constexpr
unsigned char elevateTileComb[] = {
138 NeighborNodesPosition::TOP | NeighborNodesPosition::BOTTOM,
139 NeighborNodesPosition::LEFT | NeighborNodesPosition::RIGHT,
140 NeighborNodesPosition::TOP_LEFT | NeighborNodesPosition::RIGHT | NeighborNodesPosition::BOTTOM,
141 NeighborNodesPosition::TOP_RIGHT | NeighborNodesPosition::LEFT | NeighborNodesPosition::BOTTOM,
142 NeighborNodesPosition::BOTTOM_LEFT | NeighborNodesPosition::RIGHT | NeighborNodesPosition::TOP,
143 NeighborNodesPosition::BOTTOM_RIGHT | NeighborNodesPosition::LEFT | NeighborNodesPosition::TOP};
145 std::vector<Point> nodesToBeUpdated;
146 std::map<int, std::vector<Point>> nodeCache;
147 std::queue<Point> updatedNodes;
148 std::vector<Point> nodesToElevate;
149 std::vector<Point> nodesToDemolish;
151 for (
auto currentNode : nodes)
153 updatedNodes.push(currentNode);
155 while (!updatedNodes.empty() || !nodesToElevate.empty())
157 while (!updatedNodes.empty())
161 const int tileHeight = pHeighChangedNode.
height;
163 if (nodeCache.count(pHeighChangedNode.
toIndex()) == 0)
168 if (std::find(nodesToElevate.begin(), nodesToElevate.end(), pHeighChangedNode) == nodesToElevate.end())
170 nodesToElevate.push_back(pHeighChangedNode);
173 for (
auto neighbor : nodeCache[pHeighChangedNode.
toIndex()])
177 const int heightDiff = tileHeight - neighborCoords.
height;
179 if (nodeCache.count(neighborCoords.
toIndex()) == 0)
184 if (std::find(nodesToElevate.begin(), nodesToElevate.end(), neighborCoords) == nodesToElevate.end())
186 nodesToElevate.push_back(neighborCoords);
189 if (std::abs(heightDiff) > 1)
191 updatedNodes.push(
getMapNode(neighborCoords).getCoordinates());
192 updateHeight(neighborCoords, (heightDiff > 1) ?
true :
false);
197 while (updatedNodes.empty() && !nodesToElevate.empty())
199 Point nodeToElevate = nodesToElevate.back();
200 nodesToBeUpdated.push_back(nodeToElevate);
201 nodesToElevate.pop_back();
203 if (nodeCache.count(nodeToElevate.
toIndex()) == 0)
209 if (elevationBitmask !=
getMapNode(nodeToElevate).getElevationBitmask())
211 nodesToDemolish.push_back(nodeToElevate);
215 for (
const auto &elBitMask : elevateTileComb)
217 if ((elevationBitmask & elBitMask) == elBitMask)
220 updatedNodes.push(
getMapNode(nodeToElevate).getCoordinates());
228 if (!nodesToDemolish.empty())
233 for (
Point node : nodesToBeUpdated)
238 for (
Point node : nodesToBeUpdated)
248 [](
MapNode &mn) { return mn.getCoordinates(); });
255 std::vector<NeighborNode> neighbors;
274 bool shouldAllNodesPlaced =
true;
275 bool areaPlacementAllowed =
true;
276 bool tilePlacementAllowed =
true;
283 shouldAllNodesPlaced =
true;
287 shouldAllNodesPlaced =
false;
289 areaPlacementAllowed = shouldAllNodesPlaced;
291 for (
auto coord : targetCoordinates)
295 if (tilePlacementAllowed && !shouldAllNodesPlaced)
297 areaPlacementAllowed =
true;
300 if (!tilePlacementAllowed && shouldAllNodesPlaced)
302 areaPlacementAllowed =
false;
307 return areaPlacementAllowed;
312 unsigned char bitmask = 0;
317 if (
getMapNode(neighborCoordinates).getCoordinates().height > centralNodeHeight)
338 std::vector<uint8_t> tileOrientationBitmask(
LAYERS_COUNT, 0);
344 if (pCurrentTileData)
350 const auto pTileData = neighbor.pNode->getMapNodeDataForLayer(
Layer::WATER).tileData;
354 tileOrientationBitmask[currentLayer] |= neighbor.position;
365 const MapNodeData &nodeData = neighbor.pNode->getMapNodeDataForLayer(currentLayer);
369 tileOrientationBitmask[currentLayer] |= neighbor.position;
375 return tileOrientationBitmask;
383 if (!tileData || targetCoordinates.empty())
393 std::vector<Point> nodesToBeUpdated;
398 randomGroundDecorationTileID =
409 for (
auto coord : targetCoordinates)
414 if (coord != coordinate && targetCoordinates.size() > 1)
423 if ((!targetCoordinates.size()) == 1)
429 currentMapNode.
setTileID(tileID, coordinate);
433 if (!randomGroundDecorationTileID.empty())
435 currentMapNode.
setTileID(randomGroundDecorationTileID, coord);
448 if (!nodesToBeUpdated.empty())
457 bool setTileResult =
false;
458 for (
auto coord : coordinates)
460 setTileResult |=
setTileID(tileID, coord);
462 return setTileResult;
467 std::vector<Point> nodesToDemolish;
469 for (
Point currentCoordinate : isoCoordinates)
471 if (currentCoordinate.isWithinMapBoundaries())
480 if (pNodeTileData && ((pNodeTileData->RequiredTiles.height > 1) || (pNodeTileData->RequiredTiles.width > 1)))
491 nodesToDemolish.push_back(buildingCoords);
496 nodesToDemolish.push_back(currentCoordinate);
500 std::vector<Point> updateNodes;
501 for (
auto nodeCoordinate : nodesToDemolish)
506 if (updateNeighboringTiles)
508 updateNodes.push_back(nodeCoordinate);
512 if (!updateNodes.empty())
541 pSprite->highlightSprite =
true;
562 int isoX = calculatedIsoCoords.
x;
563 int isoY = calculatedIsoCoords.
y;
579 const int neighborReach = 2;
583 const int xMax = std::min(isoX + neighborReach + isoY, mapSize - 1);
585 const int xMin = std::max(isoX - neighborReach, 0);
587 for (
int x = xMax; x >= xMin; --x)
589 const int diff = x - isoX;
590 const int yMiddlePoint = isoY - diff;
593 for (
int y = std::max(yMiddlePoint - neighborReach, 0); (y <= yMiddlePoint + neighborReach) && (y < mapSize); ++y)
605 return Point{-1, -1, 0, 0};
617 auto pSprite = node.getSprite();
618 std::vector<Layer> layersToGoOver;
624 layersToGoOver.insert(layersToGoOver.begin(), layersOrdered.begin(), layersOrdered.end());
628 layersToGoOver.push_back(layer);
631 for (
const auto &curLayer : layersToGoOver)
638 SDL_Rect spriteRect = pSprite->getDestRect(curLayer);
639 SDL_Rect clipRect = pSprite->getClipRect(curLayer);
646 if (SDL_PointInRect(&screenCoordinates, &spriteRect))
648 std::string tileID = node.getMapNodeDataForLayer(curLayer).tileID;
649 assert(!tileID.empty());
657 tileID.append(
"_shore");
674 Map *
newMap =
new Map(mapSize, mapSize, generateTerrain);
688 if (jsonAsString.empty())
693 json saveGameJSON = json::parse(jsonAsString,
nullptr,
false);
695 if (saveGameJSON.is_discarded())
698 size_t saveGameVersion = saveGameJSON.value(
"Savegame version", 0);
703 throw CytopiaError(
TRACE_INFO "Trying to load a Savegame with version " + std::to_string(saveGameVersion) +
704 " but only save-games with version " + std::to_string(
SAVEGAME_VERSION) +
" are supported");
707 int columns = saveGameJSON.value(
"columns", -1);
708 int rows = saveGameJSON.value(
"rows", -1);
710 if (columns == -1 || rows == -1)
715 Map *map =
new Map(columns, rows);
716 map->
mapNodes.reserve(columns * rows);
718 for (
const auto &it : saveGameJSON[
"mapNode"].items())
724 map->
mapNodes.back().setMapNodeData(
json(it.value())[
"mapNodeData"]);
728 for (
int x = 0; x < columns; x++)
730 for (
int y = columns - 1; y >= 0; y--)