(svn r9371) -Feature: Add support for variable snow lines in the arctic climate, supplied
authormaedhros
Tue, 20 Mar 2007 13:47:00 +0000
changeset 6343 76d17f784c13
parent 6342 a44ad9acf82a
child 6344 e5edb531b27e
(svn r9371) -Feature: Add support for variable snow lines in the arctic climate, supplied
by newgrf files. When this is enabled forests cannot be built below the highest
snow line, and farms can't be built above it. Houses still use the
_opt.snow_line so they are all consistent, so to make them respect the snowline
you may want to use some newhouses features as well.
src/clear_cmd.cpp
src/industry_cmd.cpp
src/landscape.cpp
src/landscape.h
src/newgrf.cpp
src/newgrf_house.cpp
src/newgrf_spritegroup.cpp
src/newgrf_station.cpp
src/rail_cmd.cpp
src/road_cmd.cpp
src/town_cmd.cpp
src/tree_cmd.cpp
src/tunnelbridge_cmd.cpp
--- a/src/clear_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/clear_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -16,6 +16,7 @@
 #include "tunnel_map.h"
 #include "bridge_map.h"
 #include "bridge.h"
+#include "landscape.h"
 #include "variables.h"
 #include "table/sprites.h"
 #include "unmovable_map.h"
@@ -620,7 +621,7 @@
 /* convert into snowy tiles */
 static void TileLoopClearAlps(TileIndex tile)
 {
-	int k = GetTileZ(tile) - _opt.snow_line + TILE_HEIGHT;
+	int k = GetTileZ(tile) - GetSnowLine() + TILE_HEIGHT;
 
 	if (k < 0) { // well below the snow line
 		if (!IsClearGround(tile, CLEAR_SNOW)) return;
--- a/src/industry_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/industry_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -12,6 +12,7 @@
 #include "table/sprites.h"
 #include "map.h"
 #include "tile.h"
+#include "landscape.h"
 #include "viewport.h"
 #include "command.h"
 #include "industry.h"
@@ -814,7 +815,7 @@
 	int type;
 
 	if (_opt.landscape == LT_HILLY) {
-		if (GetTileZ(tile) + TILE_HEIGHT * 2 >= _opt.snow_line)
+		if (GetTileZ(tile) + TILE_HEIGHT * 2 >= GetSnowLine())
 			return;
 	}
 
@@ -1016,7 +1017,7 @@
 static bool CheckNewIndustry_Forest(TileIndex tile)
 {
 	if (_opt.landscape == LT_HILLY) {
-		if (GetTileZ(tile) < _opt.snow_line + TILE_HEIGHT * 2U) {
+		if (GetTileZ(tile) < HighestSnowLine() + TILE_HEIGHT * 2U) {
 			_error_message = STR_4831_FOREST_CAN_ONLY_BE_PLANTED;
 			return false;
 		}
@@ -1048,7 +1049,7 @@
 static bool CheckNewIndustry_Farm(TileIndex tile)
 {
 	if (_opt.landscape == LT_HILLY) {
-		if (GetTileZ(tile) + TILE_HEIGHT * 2 >= _opt.snow_line) {
+		if (GetTileZ(tile) + TILE_HEIGHT * 2 >= HighestSnowLine()) {
 			_error_message = STR_0239_SITE_UNSUITABLE;
 			return false;
 		}
--- a/src/landscape.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/landscape.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -5,6 +5,7 @@
 #include "bridge_map.h"
 #include "heightmap.h"
 #include "clear_map.h"
+#include "date.h"
 #include "functions.h"
 #include "map.h"
 #include "player.h"
@@ -14,6 +15,7 @@
 #include <stdarg.h>
 #include "viewport.h"
 #include "command.h"
+#include "landscape.h"
 #include "vehicle.h"
 #include "variables.h"
 #include "void_map.h"
@@ -61,6 +63,7 @@
 	SLOPE_NWS, SLOPE_WSE, SLOPE_SEN, SLOPE_ENW
 };
 
+SnowLine *_snow_line = NULL;
 
 uint GetPartialZ(int x, int y, Slope corners)
 {
@@ -302,6 +305,62 @@
 	_tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
 }
 
+/**
+ * Has a snow line table already been loaded.
+ * @return true if the table has been loaded already.
+ */
+bool IsSnowLineSet(void)
+{
+	return _snow_line != NULL;
+}
+
+/**
+ * Set a variable snow line, as loaded from a newgrf file.
+ * @param table the 12 * 32 byte table containing the snowline for each day
+ */
+void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
+{
+	_snow_line = CallocT<SnowLine>(1);
+	memcpy(_snow_line->table, table, sizeof(_snow_line->table));
+
+	for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
+		for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
+			_snow_line->highest_value = max(_snow_line->highest_value, table[i][j]);
+		}
+	}
+}
+
+/**
+ * Get the current snow line, either variable or static.
+ * @return the snow line height.
+ */
+byte GetSnowLine(void)
+{
+	if (_snow_line == NULL) return _opt.snow_line;
+
+	YearMonthDay ymd;
+	ConvertDateToYMD(_date, &ymd);
+	return _snow_line->table[ymd.month][ymd.day];
+}
+
+/**
+ * Get the highest possible snow line height, either variable or static.
+ * @return the highest snow line height.
+ */
+byte HighestSnowLine(void)
+{
+	return _snow_line == NULL ? _opt.snow_line : _snow_line->highest_value;
+}
+
+/**
+ * Clear the variable snow line table and free the memory.
+ */
+void ClearSnowLine(void)
+{
+	free(_snow_line);
+	_snow_line = NULL;
+}
+
 /** Clear a piece of landscape
  * @param tile tile to clear
  * @param flags of operation to conduct
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/landscape.h	Tue Mar 20 13:47:00 2007 +0000
@@ -0,0 +1,19 @@
+/* $Id$ */
+
+/** @file landscape.h */
+
+enum {
+	SNOW_LINE_MONTHS = 12,
+	SNOW_LINE_DAYS   = 32,
+};
+
+struct SnowLine {
+	byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
+	byte highest_value;
+};
+
+bool IsSnowLineSet(void);
+void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS]);
+byte GetSnowLine(void);
+byte HighestSnowLine(void);
+void ClearSnowLine(void);
--- a/src/newgrf.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/newgrf.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -27,6 +27,7 @@
 #include "fontcache.h"
 #include "date.h"
 #include "currency.h"
+#include "landscape.h"
 #include "sound.h"
 #include "newgrf_config.h"
 #include "newgrf_house.h"
@@ -1510,6 +1511,22 @@
 			break;
 
 		case 0x10: // 12 * 32 * B Snow line height table
+			if (numinfo > 1 || IsSnowLineSet()) {
+				grfmsg(1, "GlobalVarChangeInfo: The snowline can only be set once (%d)", numinfo);
+			} else if (len < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
+				grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (%d)", len);
+			} else {
+				byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
+
+				for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
+					for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
+						table[i][j] = grf_load_byte(&buf);
+					}
+				}
+				SetSnowLine(table);
+			}
+			break;
+
 		default:
 			ret = true;
 	}
@@ -3973,6 +3990,9 @@
 	ResetStationClasses();
 	ResetCustomStations();
 
+	/* Reset the snowline table. */
+	ClearSnowLine();
+
 	/* Reset NewGRF files */
 	ResetNewGRF();
 
--- a/src/newgrf_house.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/newgrf_house.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -8,6 +8,7 @@
 #include "variables.h"
 #include "debug.h"
 #include "viewport.h"
+#include "landscape.h"
 #include "date.h"
 #include "town.h"
 #include "town_map.h"
@@ -252,7 +253,7 @@
 {
 	switch (_opt.landscape) {
 		case LT_DESERT: return GetTropicZone(tile) == TROPICZONE_DESERT ? 1 : 2;
-		case LT_HILLY:  return GetTileZ(tile) >= _opt.snow_line ? 4 : 0;
+		case LT_HILLY:  return GetTileZ(tile) >= GetSnowLine() ? 4 : 0;
 		default:        return 0;
 	}
 }
--- a/src/newgrf_spritegroup.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/newgrf_spritegroup.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -4,6 +4,7 @@
 #include "openttd.h"
 #include "variables.h"
 #include "macros.h"
+#include "landscape.h"
 #include "oldpool.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_spritegroup.h"
@@ -91,7 +92,7 @@
 		case 0x1A: return UINT_MAX;
 		case 0x1B: return GB(_display_opt, 0, 6);
 		case 0x1C: return object->last_value;
-		case 0x20: return _opt.landscape == LT_HILLY ? _opt.snow_line : 0xFF;
+		case 0x20: return _opt.landscape == LT_HILLY ? GetSnowLine() : 0xFF;
 
 		/* Not a common variable, so evalute the feature specific variables */
 		default: return object->GetVariable(object, variable, parameter, available);
--- a/src/newgrf_station.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/newgrf_station.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -6,6 +6,7 @@
 #include "openttd.h"
 #include "variables.h"
 #include "functions.h"
+#include "landscape.h"
 #include "debug.h"
 #include "sprite.h"
 #include "table/sprites.h"
@@ -370,7 +371,7 @@
 		case 0x40: return GetPlatformInfoHelper(tile, false, false, false);
 		case 0x41: return GetPlatformInfoHelper(tile, true,  false, false);
 		case 0x42: /* Terrain and rail type */
-			return ((_opt.landscape == LT_HILLY && GetTileZ(tile) > _opt.snow_line) ? 4 : 0) |
+			return ((_opt.landscape == LT_HILLY && GetTileZ(tile) > GetSnowLine()) ? 4 : 0) |
 			       (_opt.landscape == LT_DESERT ? GetTropicZone(tile) : 0) |
 			       (GetRailType(tile) << 8);
 		case 0x43: return st->owner; /* Station owner */
--- a/src/rail_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/rail_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -12,6 +12,7 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 #include "map.h"
+#include "landscape.h"
 #include "tile.h"
 #include "town_map.h"
 #include "tunnel_map.h"
@@ -1738,7 +1739,7 @@
 
 	switch (_opt.landscape) {
 		case LT_HILLY:
-			if (GetTileZ(tile) > _opt.snow_line) {
+			if (GetTileZ(tile) > GetSnowLine()) {
 				new_ground = RAIL_GROUND_ICE_DESERT;
 				goto set_ground;
 			}
--- a/src/road_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/road_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -12,6 +12,7 @@
 #include "table/strings.h"
 #include "functions.h"
 #include "map.h"
+#include "landscape.h"
 #include "tile.h"
 #include "town_map.h"
 #include "vehicle.h"
@@ -864,7 +865,7 @@
 {
 	switch (_opt.landscape) {
 		case LT_HILLY:
-			if (IsOnSnow(tile) != (GetTileZ(tile) > _opt.snow_line)) {
+			if (IsOnSnow(tile) != (GetTileZ(tile) > GetSnowLine())) {
 				ToggleSnow(tile);
 				MarkTileDirtyByTile(tile);
 			}
--- a/src/town_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/town_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -11,6 +11,7 @@
 #include "table/strings.h"
 #include "table/sprites.h"
 #include "map.h"
+#include "landscape.h"
 #include "tile.h"
 #include "town_map.h"
 #include "tunnel_map.h"
@@ -1700,7 +1701,7 @@
 	}
 
 	if (_opt.landscape == LT_HILLY) {
-		if (TilePixelHeight(t->xy) >= _opt.snow_line && t->act_food == 0 && t->population > 90)
+		if (TilePixelHeight(t->xy) >= GetSnowLine() && t->act_food == 0 && t->population > 90)
 			return;
 	} else if (_opt.landscape == LT_DESERT) {
 		if (GetTropicZone(t->xy) == TROPICZONE_DESERT && (t->act_food==0 || t->act_water==0) && t->population > 60)
--- a/src/tree_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/tree_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -9,6 +9,7 @@
 #include "table/tree_land.h"
 #include "functions.h"
 #include "map.h"
+#include "landscape.h"
 #include "tile.h"
 #include "tree_map.h"
 #include "viewport.h"
@@ -53,7 +54,7 @@
 		MakeTree(tile, tree, GB(r, 22, 2), min(GB(r, 16, 3), 6), TREE_GROUND_GRASS, 0);
 
 		// above snowline?
-		if (_opt.landscape == LT_HILLY && GetTileZ(tile) > _opt.snow_line) {
+		if (_opt.landscape == LT_HILLY && GetTileZ(tile) > GetSnowLine()) {
 			SetTreeGroundDensity(tile, TREE_GROUND_SNOW_DESERT, 3);
 			SetTreeCounter(tile, (TreeGround)GB(r, 24, 3));
 		} else {
@@ -150,7 +151,7 @@
 			j = GetTileZ(tile) / TILE_HEIGHT * 2;
 			while (j--) {
 				/* Above snowline more trees! */
-				if (_opt.landscape == LT_HILLY && ht > _opt.snow_line) {
+				if (_opt.landscape == LT_HILLY && ht > GetSnowLine()) {
 					PlaceTreeAtSameHeight(tile, ht);
 					PlaceTreeAtSameHeight(tile, ht);
 				};
@@ -496,7 +497,7 @@
 
 static void TileLoopTreesAlps(TileIndex tile)
 {
-	int k = GetTileZ(tile) - _opt.snow_line + TILE_HEIGHT;
+	int k = GetTileZ(tile) - GetSnowLine() + TILE_HEIGHT;
 
 	if (k < 0) {
 		if (GetTreeGround(tile) != TREE_GROUND_SNOW_DESERT) return;
--- a/src/tunnelbridge_cmd.cpp	Tue Mar 20 10:06:39 2007 +0000
+++ b/src/tunnelbridge_cmd.cpp	Tue Mar 20 13:47:00 2007 +0000
@@ -14,6 +14,7 @@
 #include "table/strings.h"
 #include "functions.h"
 #include "map.h"
+#include "landscape.h"
 #include "tile.h"
 #include "tunnel_map.h"
 #include "unmovable_map.h"
@@ -1178,7 +1179,7 @@
 	bool snow_or_desert = IsTunnelTile(tile) ? HasTunnelSnowOrDesert(tile) : HasBridgeSnowOrDesert(tile);
 	switch (_opt.landscape) {
 		case LT_HILLY:
-			if (snow_or_desert != (GetTileZ(tile) > _opt.snow_line)) {
+			if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) {
 				if (IsTunnelTile(tile)) {
 					SetTunnelSnowOrDesert(tile, !snow_or_desert);
 				} else {