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)
@@ -430,7 +430,7 @@
*/
static void FixOwnerOfRailTrack(TileIndex t)
{
- assert(!Company::IsValidID(GetTileOwner(t)) && (IsLevelCrossingTile(t) || IsPlainRailTile(t)));
+ assert(!Company::IsValidID(GetTileOwnerOld(t)) && (IsLevelCrossingTile(t) || IsPlainRailTile(t)));
/* remove leftover rail piece from crossing (from very old savegames) */
Train *v = NULL, *w;
@@ -452,8 +452,8 @@
TileIndex tt = t + TileOffsByDiagDir(dd);
if (GetTileTrackStatus(t, TRANSPORT_RAIL, 0, dd) != 0 &&
GetTileTrackStatus(tt, TRANSPORT_RAIL, 0, ReverseDiagDir(dd)) != 0 &&
- Company::IsValidID(GetTileOwner(tt))) {
- SetTileOwner(t, GetTileOwner(tt));
+ Company::IsValidID(GetTileOwnerOld(tt))) {
+ SetTileOwner(t, GetTileOwnerOld(tt));
return;
}
}
@@ -614,7 +614,7 @@
* walk through the whole map.. */
if (IsSavegameVersionBefore(4, 3)) {
for (TileIndex t = 0; t < map_size; t++) {
- if (IsTileType(t, MP_WATER) && GetTileOwner(t) >= MAX_COMPANIES) {
+ if (IsTileType(t, MP_WATER) && GetTileOwnerOld(t) >= MAX_COMPANIES) {
SetTileOwner(t, OWNER_WATER);
}
}
@@ -820,7 +820,7 @@
default: break;
case MP_WATER:
- if (GetWaterTileType(t) == WATER_TILE_LOCK && GetTileOwner(t) == OWNER_WATER) SetTileOwner(t, OWNER_NONE);
+ if (GetWaterTileType(t) == WATER_TILE_LOCK && GetTileOwnerOld(t) == OWNER_WATER) SetTileOwner(t, OWNER_NONE);
break;
case MP_STATION: {
@@ -949,7 +949,7 @@
case MP_ROAD:
_m[t].m4 |= (_m[t].m2 << 4);
- if ((GB(_m[t].m5, 4, 2) == ROAD_TILE_CROSSING ? (Owner)_m[t].m3 : GetTileOwner(t)) == OWNER_TOWN) {
+ if ((GB(_m[t].m5, 4, 2) == ROAD_TILE_CROSSING ? (Owner)_m[t].m3 : GetTileOwnerOld(t)) == OWNER_TOWN) {
SetTownIndex(t, CalcClosestTownFromTile(t)->index);
} else {
SetTownIndex(t, 0);
@@ -1104,7 +1104,7 @@
if (!IsRoadStop(t)) break;
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
- SB(_me[t].m7, 0, 5, HasBit(_me[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
+ SB(_me[t].m7, 0, 5, HasBit(_me[t].m6, 2) ? OWNER_TOWN : GetTileOwnerOld(t));
SB(_m[t].m3, 4, 4, _m[t].m1);
_m[t].m4 = 0;
break;
@@ -1114,7 +1114,7 @@
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(_m[t].m5, 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
- Owner o = GetTileOwner(t);
+ Owner o = GetTileOwnerOld(t);
SB(_me[t].m7, 0, 5, o); // road owner
SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner
}
@@ -1143,7 +1143,7 @@
if (GB(_m[t].m5, 3, 2) == TRANSPORT_RAIL) {
MakeRailNormal(
t,
- GetTileOwner(t),
+ GetTileOwnerOld(t),
axis == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X,
GetRailType(t)
);
@@ -1155,7 +1155,7 @@
axis == AXIS_X ? ROAD_Y : ROAD_X,
ROADTYPES_ROAD,
town,
- GetTileOwner(t), OWNER_NONE
+ GetTileOwnerOld(t), OWNER_NONE
);
}
} else {
@@ -1165,10 +1165,10 @@
if (!IsTileFlat(t)) {
MakeShore(t);
} else {
- if (GetTileOwner(t) == OWNER_WATER) {
+ if (GetTileOwnerOld(t) == OWNER_WATER) {
MakeSea(t);
} else {
- MakeCanal(t, GetTileOwner(t), Random());
+ MakeCanal(t, GetTileOwnerOld(t), Random());
}
}
}
@@ -1604,7 +1604,7 @@
for (TileIndex t = 0; t < map_size; t++) {
if (IsTileType(t, MP_WATER) &&
GetWaterTileType(t) == WATER_TILE_CLEAR &&
- GetTileOwner(t) == OWNER_WATER &&
+ GetTileOwnerOld(t) == OWNER_WATER &&
TileHeight(t) != 0) {
SetTileOwner(t, OWNER_NONE);
}
@@ -1756,7 +1756,7 @@
if (IsTileType(t, MP_WATER)) {
if (GetWaterClass(t) != WATER_CLASS_RIVER) {
if (IsWater(t)) {
- Owner o = GetTileOwner(t);
+ Owner o = GetTileOwnerOld(t);
if (o == OWNER_WATER) {
MakeSea(t);
} else {
@@ -1792,7 +1792,7 @@
}
if (IsBuoyTile(t) || IsDriveThroughStopTile(t) || IsTileType(t, MP_WATER)) {
- Owner o = GetTileOwner(t);
+ Owner o = GetTileOwnerOld(t);
if (o < MAX_COMPANIES && !Company::IsValidID(o)) {
Backup<CompanyByte> cur_company(_current_company, o, FILE_LINE);
ChangeTileOwner(t, o, INVALID_OWNER);
@@ -1811,10 +1811,10 @@
if (o < MAX_COMPANIES && !Company::IsValidID(o)) SetRoadOwner(t, rt, OWNER_NONE);
}
if (IsLevelCrossing(t)) {
- if (!Company::IsValidID(GetTileOwner(t))) FixOwnerOfRailTrack(t);
+ if (!Company::IsValidID(GetTileOwnerOld(t))) FixOwnerOfRailTrack(t);
}
} else if (IsPlainRailTile(t)) {
- if (!Company::IsValidID(GetTileOwner(t))) FixOwnerOfRailTrack(t);
+ if (!Company::IsValidID(GetTileOwnerOld(t))) FixOwnerOfRailTrack(t);
}
}
@@ -2447,7 +2447,7 @@
if (IsSavegameVersionBefore(148)) {
Object *o;
FOR_ALL_OBJECTS(o) {
- Owner owner = GetTileOwner(o->location.tile);
+ Owner owner = GetTileOwnerOld(o->location.tile);
o->colour = (owner == OWNER_NONE) ? Random() & 0xF : Company::Get(owner)->livery->colour1;
}
}
@@ -2821,7 +2821,7 @@
if (IsSavegameVersionBefore(172)) {
for (TileIndex t = 0; t < map_size; t++) {
if (!IsStandardRoadStopTile(t)) continue;
- Owner o = GetTileOwner(t);
+ Owner o = GetTileOwnerOld(t);
SetRoadOwner(t, ROADTYPE_ROAD, o);
SetRoadOwner(t, ROADTYPE_TRAM, o);
}
@@ -2985,6 +2985,18 @@
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);
+ }
+ }
+ }
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);
}
/**