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); } /**