-
-
Save michicc/91ac9d01052605150e6d31ba781ff01d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/landscape.cpp b/src/landscape.cpp | |
index 442bb61cda..c10c2191a6 100644 | |
--- a/src/landscape.cpp | |
+++ b/src/landscape.cpp | |
@@ -89,11 +89,6 @@ extern const byte _slope_to_sprite_offset[32] = { | |
*/ | |
static SnowLine *_snow_line = nullptr; | |
-/** The current spring during river generation */ | |
-static TileIndex _current_spring = INVALID_TILE; | |
- | |
-/** Whether the current river is a big river that others flow into */ | |
-static bool _is_main_river = false; | |
/** | |
* Map 2D viewport or smallmap coordinate to 3D world or tile coordinate. | |
@@ -1115,6 +1110,12 @@ static bool FlowsDown(TileIndex begin, TileIndex end) | |
((slopeEnd == slopeBegin && heightEnd < heightBegin) || slopeEnd == SLOPE_FLAT || slopeBegin == SLOPE_FLAT); | |
} | |
+/** Parameters for river generation to pass as AyStar user data. */ | |
+struct River_UserData { | |
+ TileIndex spring; ///< The current spring during river generation. | |
+ bool main_river; ///< Whether the current river is a big river that others flow into. | |
+}; | |
+ | |
/* AyStar callback for checking whether we reached our destination. */ | |
static int32 River_EndNodeCheck(const AyStar *aystar, const OpenListNode *current) | |
{ | |
@@ -1152,6 +1153,8 @@ static void River_GetNeighbours(AyStar *aystar, OpenListNode *current) | |
/* AyStar callback when an route has been found. */ | |
static void River_FoundEndNode(AyStar *aystar, OpenListNode *current) | |
{ | |
+ River_UserData *data = (River_UserData *)aystar->user_data; | |
+ | |
/* Count river length. */ | |
uint length = 0; | |
for (PathNode *path = ¤t->path; path != nullptr; path = path->parent) { | |
@@ -1165,14 +1168,14 @@ static void River_FoundEndNode(AyStar *aystar, OpenListNode *current) | |
MakeRiver(tile, Random()); | |
/* Check if we should widen river depending on how far we are away from the source. */ | |
- const uint current_river_length = DistanceManhattan(_current_spring, path->node.tile); | |
+ const uint current_river_length = DistanceManhattan(data->spring, path->node.tile); | |
const uint long_river_length = _settings_game.game_creation.min_river_length * 4; | |
const uint radius = std::min(3u, (current_river_length / (long_river_length / 3u)) + 1u); | |
MarkTileDirtyByTile(tile); | |
/* If building a main river, try to widen it. */ | |
- if (_is_main_river && (radius > 1)) { | |
+ if (data->main_river && (radius > 1)) { | |
CircularTileSearch(&tile, radius + RandomRange(1), RiverMakeWider, (void*)&path->node.tile); | |
} | |
else { | |
@@ -1200,9 +1203,13 @@ static uint River_Hash(uint tile, uint dir) | |
* Actually build the river between the begin and end tiles using AyStar. | |
* @param begin The begin of the river. | |
* @param end The end of the river. | |
+ * @param spring The springing point of the river. | |
+ * @param main_river Whether the current river is a big river that others flow into. | |
*/ | |
-static void BuildRiver(TileIndex begin, TileIndex end) | |
+static void BuildRiver(TileIndex begin, TileIndex end, TileIndex spring, bool main_river) | |
{ | |
+ River_UserData user_data = { spring, main_river }; | |
+ | |
AyStar finder = {}; | |
finder.CalculateG = River_CalculateG; | |
finder.CalculateH = River_CalculateH; | |
@@ -1210,6 +1217,7 @@ static void BuildRiver(TileIndex begin, TileIndex end) | |
finder.EndNodeCheck = River_EndNodeCheck; | |
finder.FoundEndNode = River_FoundEndNode; | |
finder.user_target = &end; | |
+ finder.user_data = &user_data; | |
finder.Init(River_Hash, 1 << RIVER_HASH_SIZE); | |
@@ -1226,20 +1234,16 @@ static void BuildRiver(TileIndex begin, TileIndex end) | |
* @param spring The springing point of the river. | |
* @param begin The begin point we are looking from; somewhere down hill from the spring. | |
* @param min_river_length The minimum length for the river. | |
- * @return True iff a river could/has been built, otherwise false. | |
+ * @return First element: True iff a river could/has been built, otherwise false; second element: River ends at sea. | |
*/ | |
-static bool FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) | |
+static std::tuple<bool, bool> FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) | |
{ | |
# define SET_MARK(x) marks.insert(x) | |
# define IS_MARKED(x) (marks.find(x) != marks.end()) | |
uint height = TileHeight(begin); | |
- if (IsWaterTile(begin)) | |
- { | |
- if (GetTileZ(begin) == 0) { | |
- _is_main_river = true; | |
- } | |
- return DistanceManhattan(spring, begin) > min_river_length; | |
+ if (IsWaterTile(begin)) { | |
+ return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 }; | |
} | |
std::set<TileIndex> marks; | |
@@ -1272,9 +1276,10 @@ static bool FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) | |
} | |
} while (!queue.empty()); | |
+ bool main_river = false; | |
if (found) { | |
/* Flow further down hill. */ | |
- found = FlowRiver(spring, end, min_river_length); | |
+ std::tie(found, main_river) = FlowRiver(spring, end, min_river_length); | |
} else if (count > 32) { | |
/* Maybe we can make a lake. Find the Nth of the considered tiles. */ | |
TileIndex lakeCenter = 0; | |
@@ -1310,8 +1315,8 @@ static bool FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) | |
} | |
marks.clear(); | |
- if (found) BuildRiver(begin, end); | |
- return found; | |
+ if (found) BuildRiver(begin, end, spring, main_river); | |
+ return { found, main_river }; | |
} | |
/** | |
@@ -1332,9 +1337,7 @@ static void CreateRivers() | |
for (int tries = 0; tries < 512; tries++) { | |
TileIndex t = RandomTile(); | |
if (!CircularTileSearch(&t, 8, FindSpring, nullptr)) continue; | |
- _current_spring = t; | |
- _is_main_river = false; | |
- if (FlowRiver(t, t, _settings_game.game_creation.min_river_length * 4)) break; | |
+ if (std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length * 4))) break; | |
} | |
} | |
@@ -1344,9 +1347,7 @@ static void CreateRivers() | |
for (int tries = 0; tries < 128; tries++) { | |
TileIndex t = RandomTile(); | |
if (!CircularTileSearch(&t, 8, FindSpring, nullptr)) continue; | |
- _current_spring = t; | |
- _is_main_river = false; | |
- if (FlowRiver(t, t, _settings_game.game_creation.min_river_length)) break; | |
+ if (std::get<0>(FlowRiver(t, t, _settings_game.game_creation.min_river_length))) break; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment