Index: src/industry_cmd.cpp
===================================================================
--- src/industry_cmd.cpp (revision 27177)
+++ src/industry_cmd.cpp (working copy)
@@ -1756,8 +1756,13 @@
WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
+ /* While it's true Industry Tiles don't have any owner, the following
+ DoCommand below is inadvertently setting bit 4 of m1 to 1. To preserve its
+ original value, store it first before executing DoCommand, then restore it
+ before MakeIndustry takes action. */
+ Owner old_owner = GetTileOwner(cur_tile);
DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
-
+ SetTileOwner(cur_tile, old_owner);
MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
if (_generating_world) {
Index: src/industry_map.h
===================================================================
--- src/industry_map.h (revision 27177)
+++ src/industry_map.h (working copy)
@@ -280,7 +280,7 @@
static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx, uint8 random, WaterClass wc)
{
SetTileType(t, MP_INDUSTRY);
- _m[t].m1 = 0;
+ _m[t].m1 &= 1<<4; // Make sure bit 4 is unaffected.
_m[t].m2 = index;
SetIndustryRandomBits(t, random); // m3
_m[t].m4 = 0;
Index: src/saveload/afterload.cpp
===================================================================
--- src/saveload/afterload.cpp (revision 27177)
+++ src/saveload/afterload.cpp (working copy)
@@ -2985,6 +2985,30 @@
ResetSignalHandlers();
AfterLoadLinkGraphs();
+
+ /* Convert m1 bit 4 value for all industry tiles */
+ if (IsSavegameVersionBefore(195)) {
+ for (TileIndex t = 0; t < map_size; t++) {
+ /* It's not possible to know who was the original owner of a canal tile built under
+ an Oil Rig tile from an old save game. To preserve savegame backward compatibility,
+ don't do anything about them. Old and new values for a given industry tile can co-exist. */
+ if (IsTileType(t, MP_INDUSTRY) && (GetWaterClass(t) != WATER_CLASS_CANAL)) {
+ SB(_m[t].m1, 4, 1, 1);
+ }
+ }
+ }
+ if (IsSavegameVersionBefore(195)) {
+ for (TileIndex t = 0; t < map_size; t++) {
+ if ((IsTileType(t, MP_STATION) || IsTileType(t, MP_WATER) || IsTileType(t, MP_OBJECT)) && GetWaterClass(t) == WATER_CLASS_CANAL) {
+ assert(IsValidTile(t));
+ assert(!IsTileType(t, MP_HOUSE));
+ assert(!IsTileType(t, MP_INDUSTRY));
+ Owner old = (Owner)GB(_m[t].m1, 0, 5);
+ if (old == OWNER_NONE) SB(_m[t].m1, 0, 4, OWNER_TOWN);
+ if (old == OWNER_WATER) SB(_m[t].m1, 0, 4, OWNER_TOWN);
+ }
+ }
+ }
return true;
}
Index: src/saveload/saveload.cpp
===================================================================
--- src/saveload/saveload.cpp (revision 27177)
+++ src/saveload/saveload.cpp (working copy)
@@ -262,8 +262,9 @@
* 192 26700
* 193 26802
* 194 26881
+ * 195 CanalOwner testings
*/
-extern const uint16 SAVEGAME_VERSION = 194; ///< Current savegame version of OpenTTD.
+extern const uint16 SAVEGAME_VERSION = 195; ///< Current savegame version of OpenTTD.
SavegameType _savegame_type; ///< type of savegame we are loading
Index: src/tile_map.h
===================================================================
--- src/tile_map.h (revision 27177)
+++ src/tile_map.h (working copy)
@@ -168,14 +168,27 @@
* @pre IsValidTile(tile)
* @pre The type of the tile must not be MP_HOUSE and MP_INDUSTRY
*/
-static inline Owner GetTileOwner(TileIndex tile)
+
+static inline Owner GetTileOwnerOld(TileIndex tile)
{
assert(IsValidTile(tile));
assert(!IsTileType(tile, MP_HOUSE));
assert(!IsTileType(tile, MP_INDUSTRY));
-
return (Owner)GB(_m[tile].m1, 0, 5);
}
+static inline Owner GetTileOwner(TileIndex tile)
+{
+ assert(IsValidTile(tile));
+ assert(!IsTileType(tile, MP_HOUSE));
+ assert(!IsTileType(tile, MP_INDUSTRY));
+ if ((IsTileType(tile, MP_STATION) || IsTileType(tile, MP_WATER) || IsTileType(tile, MP_OBJECT))) {
+ Owner co = (Owner)GB(_m[tile].m1, 0, 4);
+ return co == OWNER_TOWN ? OWNER_NONE : co;
+
+ } else {
+ return (Owner)GB(_m[tile].m1, 0, 5);
+ }
+}
/**
* Sets the owner of a tile
@@ -193,8 +206,11 @@
assert(IsValidTile(tile));
assert(!IsTileType(tile, MP_HOUSE));
assert(!IsTileType(tile, MP_INDUSTRY));
-
- SB(_m[tile].m1, 0, 5, owner);
+ if ((IsTileType(tile, MP_STATION) || IsTileType(tile, MP_WATER) || IsTileType(tile, MP_OBJECT)) && owner == OWNER_NONE) {
+ SB(_m[tile].m1, 0, 4, OWNER_TOWN);
+ } else {
+ SB(_m[tile].m1, 0, 5, owner);
+ }
}
/**
Index: src/water_cmd.cpp
===================================================================
--- src/water_cmd.cpp (revision 27177)
+++ src/water_cmd.cpp (working copy)
@@ -419,7 +419,9 @@
if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
bool water = IsWaterTile(tile);
+
ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
+
if (ret.Failed()) return ret;
if (!water) cost.AddCost(ret);
Index: src/water_map.h
===================================================================
--- src/water_map.h (revision 27177)
+++ src/water_map.h (working copy)
@@ -176,6 +176,12 @@
return IsWater(t) && GetWaterClass(t) == WATER_CLASS_RIVER;
}
+static inline bool IsCanalOnRiver(TileIndex t)
+{
+ assert(HasTileWaterClass(t));
+ return HasBit(_m[t].m1, 4);
+}
+
/**
* Is it a water tile with plain water?
* @param t Tile to query.
@@ -346,8 +352,33 @@
return HasTileWaterClass(t) && IsTileOnWater(t) && !IsCoastTile(t);
}
+/**
+ * Comment about getting owner of canal
+ */
+static inline Owner GetCanalOwner(TileIndex t)
+{
+ assert(HasTileWaterGround(t));
+ if (GetWaterClass(t) != WATER_CLASS_CANAL) {
+ return GetTileOwner(t);
+ } else {
+ Owner co = (Owner)(GB(_me[t].m6, 0, 2) && GB(_me[t].m6, 6, 2));
+ /* Canals don't have OWNER_TOWN, and remapping OWNER_NONE
+ * to OWNER_TOWN makes it use one bit less */
+ return co == OWNER_TOWN ? OWNER_NONE : co;
+ }
+}
/**
+ * Comment about setting owner of canal
+ */
+static inline void SetCanalOwner(TileIndex t, Owner co)
+{
+ if (co == OWNER_NONE) co = OWNER_TOWN;
+ SB(_me[t].m6, 0, 2, GB(co, 0, 2));
+ SB(_me[t].m6, 6, 2, GB(co, 2, 2));
+}
+
+/**
* Helper function to make a coast tile.
* @param t The tile to change into water
*/
@@ -413,6 +444,7 @@
{
assert(o != OWNER_WATER);
MakeWater(t, o, WATER_CLASS_CANAL, random_bits);
+ SetCanalOwner(t, o);
}
/**