|
|
|
@ -77,7 +77,7 @@ extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMP
|
|
|
|
|
* @param t the tile to change.
|
|
|
|
|
* @param include_invalid_water_class Also consider WATER_CLASS_INVALID, i.e. industry tiles on land
|
|
|
|
|
*/
|
|
|
|
|
void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_water_class)
|
|
|
|
|
void SetWaterClassDependingOnSurroundings(Tile t, bool include_invalid_water_class)
|
|
|
|
|
{
|
|
|
|
|
/* If the slope is not flat, we always assume 'land' (if allowed). Also for one-corner-raised-shores.
|
|
|
|
|
* Note: Wrt. autosloping under industry tiles this is the most fool-proof behaviour. */
|
|
|
|
@ -104,7 +104,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate
|
|
|
|
|
bool has_river = false;
|
|
|
|
|
|
|
|
|
|
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
|
|
|
|
|
TileIndex neighbour = TileAddByDiagDir(t, dir);
|
|
|
|
|
Tile neighbour = TileAddByDiagDir(t, dir);
|
|
|
|
|
switch (GetTileType(neighbour)) {
|
|
|
|
|
case MP_WATER:
|
|
|
|
|
/* clear water and shipdepots have already a WaterClass associated */
|
|
|
|
@ -127,7 +127,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate
|
|
|
|
|
|
|
|
|
|
case MP_TREES:
|
|
|
|
|
/* trees on shore */
|
|
|
|
|
has_water |= (GB(_m[neighbour].m2, 4, 2) == TREE_GROUND_SHORE);
|
|
|
|
|
has_water |= (GB(neighbour.m2(), 4, 2) == TREE_GROUND_SHORE);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
@ -153,13 +153,13 @@ static void ConvertTownOwner()
|
|
|
|
|
for (auto tile : Map::Iterate()) {
|
|
|
|
|
switch (GetTileType(tile)) {
|
|
|
|
|
case MP_ROAD:
|
|
|
|
|
if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HasBit(_m[tile].m3, 7)) {
|
|
|
|
|
_m[tile].m3 = OWNER_TOWN;
|
|
|
|
|
if (GB(tile.m5(), 4, 2) == ROAD_TILE_CROSSING && HasBit(tile.m3(), 7)) {
|
|
|
|
|
tile.m3() = OWNER_TOWN;
|
|
|
|
|
}
|
|
|
|
|
FALLTHROUGH;
|
|
|
|
|
|
|
|
|
|
case MP_TUNNELBRIDGE:
|
|
|
|
|
if (_m[tile].m1 & 0x80) SetTileOwner(tile, OWNER_TOWN);
|
|
|
|
|
if (tile.m1() & 0x80) SetTileOwner(tile, OWNER_TOWN);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
@ -439,14 +439,14 @@ static void CDECL HandleSavegameLoadCrash(int signum)
|
|
|
|
|
* a rail track had an invalid owner. When conversion isn't possible, track is removed.
|
|
|
|
|
* @param t tile to update
|
|
|
|
|
*/
|
|
|
|
|
static void FixOwnerOfRailTrack(TileIndex t)
|
|
|
|
|
static void FixOwnerOfRailTrack(Tile t)
|
|
|
|
|
{
|
|
|
|
|
assert(!Company::IsValidID(GetTileOwner(t)) && (IsLevelCrossingTile(t) || IsPlainRailTile(t)));
|
|
|
|
|
|
|
|
|
|
/* remove leftover rail piece from crossing (from very old savegames) */
|
|
|
|
|
Train *v = nullptr;
|
|
|
|
|
for (Train *w : Train::Iterate()) {
|
|
|
|
|
if (w->tile == t) {
|
|
|
|
|
if (w->tile == TileIndex(t)) {
|
|
|
|
|
v = w;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -474,15 +474,15 @@ static void FixOwnerOfRailTrack(TileIndex t)
|
|
|
|
|
Owner road = GetRoadOwner(t, RTT_ROAD);
|
|
|
|
|
Owner tram = GetRoadOwner(t, RTT_TRAM);
|
|
|
|
|
RoadBits bits = GetCrossingRoadBits(t);
|
|
|
|
|
bool hasroad = HasBit(_me[t].m7, 6);
|
|
|
|
|
bool hastram = HasBit(_me[t].m7, 7);
|
|
|
|
|
bool hasroad = HasBit(t.m7(), 6);
|
|
|
|
|
bool hastram = HasBit(t.m7(), 7);
|
|
|
|
|
|
|
|
|
|
/* MakeRoadNormal */
|
|
|
|
|
SetTileType(t, MP_ROAD);
|
|
|
|
|
SetTileOwner(t, road);
|
|
|
|
|
_m[t].m3 = (hasroad ? bits : 0);
|
|
|
|
|
_m[t].m5 = (hastram ? bits : 0) | ROAD_TILE_NORMAL << 6;
|
|
|
|
|
SB(_me[t].m6, 2, 4, 0);
|
|
|
|
|
t.m3() = (hasroad ? bits : 0);
|
|
|
|
|
t.m5() = (hastram ? bits : 0) | ROAD_TILE_NORMAL << 6;
|
|
|
|
|
SB(t.m6(), 2, 4, 0);
|
|
|
|
|
SetRoadOwner(t, RTT_TRAM, tram);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -533,7 +533,7 @@ static uint FixVehicleInclination(Vehicle *v, Direction dir)
|
|
|
|
|
* @param t The tile to analyze
|
|
|
|
|
* @return True if a bridge might have been present prior to savegame 194.
|
|
|
|
|
*/
|
|
|
|
|
static inline bool MayHaveBridgeAbove(TileIndex t)
|
|
|
|
|
static inline bool MayHaveBridgeAbove(Tile t)
|
|
|
|
|
{
|
|
|
|
|
return IsTileType(t, MP_CLEAR) || IsTileType(t, MP_RAILWAY) || IsTileType(t, MP_ROAD) ||
|
|
|
|
|
IsTileType(t, MP_WATER) || IsTileType(t, MP_TUNNELBRIDGE) || IsTileType(t, MP_OBJECT);
|
|
|
|
@ -614,8 +614,8 @@ bool AfterLoadGame()
|
|
|
|
|
}
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (!IsTileType(t, MP_STATION)) continue;
|
|
|
|
|
if (_m[t].m5 > 7) continue; // is it a rail station tile?
|
|
|
|
|
Station *st = Station::Get(_m[t].m2);
|
|
|
|
|
if (t.m5() > 7) continue; // is it a rail station tile?
|
|
|
|
|
Station *st = Station::Get(t.m2());
|
|
|
|
|
assert(st->train_station.tile != 0);
|
|
|
|
|
int dx = TileX(t) - TileX(st->train_station.tile);
|
|
|
|
|
int dy = TileY(t) - TileY(st->train_station.tile);
|
|
|
|
@ -630,14 +630,14 @@ bool AfterLoadGame()
|
|
|
|
|
|
|
|
|
|
/* In old savegame versions, the heightlevel was coded in bits 0..3 of the type field */
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
_m[t].height = GB(_m[t].type, 0, 4);
|
|
|
|
|
SB(_m[t].type, 0, 2, GB(_me[t].m6, 0, 2));
|
|
|
|
|
SB(_me[t].m6, 0, 2, 0);
|
|
|
|
|
t.height() = GB(t.type(), 0, 4);
|
|
|
|
|
SB(t.type(), 0, 2, GB(t.m6(), 0, 2));
|
|
|
|
|
SB(t.m6(), 0, 2, 0);
|
|
|
|
|
if (MayHaveBridgeAbove(t)) {
|
|
|
|
|
SB(_m[t].type, 2, 2, GB(_me[t].m6, 6, 2));
|
|
|
|
|
SB(_me[t].m6, 6, 2, 0);
|
|
|
|
|
SB(t.type(), 2, 2, GB(t.m6(), 6, 2));
|
|
|
|
|
SB(t.m6(), 6, 2, 0);
|
|
|
|
|
} else {
|
|
|
|
|
SB(_m[t].type, 2, 2, 0);
|
|
|
|
|
SB(t.type(), 2, 2, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -847,7 +847,7 @@ bool AfterLoadGame()
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_STATION: {
|
|
|
|
|
if (HasBit(_me[t].m6, 3)) SetBit(_me[t].m6, 2);
|
|
|
|
|
if (HasBit(t.m6(), 3)) SetBit(t.m6(), 2);
|
|
|
|
|
StationGfx gfx = GetStationGfx(t);
|
|
|
|
|
StationType st;
|
|
|
|
|
if ( IsInsideMM(gfx, 0, 8)) { // Rail station
|
|
|
|
@ -885,7 +885,7 @@ bool AfterLoadGame()
|
|
|
|
|
ResetSignalHandlers();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
SB(_me[t].m6, 3, 3, st);
|
|
|
|
|
SB(t.m6(), 3, 3, st);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -965,13 +965,13 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
switch (GetTileType(t)) {
|
|
|
|
|
case MP_HOUSE:
|
|
|
|
|
_m[t].m4 = _m[t].m2;
|
|
|
|
|
t.m4() = t.m2();
|
|
|
|
|
SetTownIndex(t, CalcClosestTownFromTile(t)->index);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
t.m4() |= (t.m2() << 4);
|
|
|
|
|
if ((GB(t.m5(), 4, 2) == ROAD_TILE_CROSSING ? (Owner)t.m3() : GetTileOwner(t)) == OWNER_TOWN) {
|
|
|
|
|
SetTownIndex(t, CalcClosestTownFromTile(t)->index);
|
|
|
|
|
} else {
|
|
|
|
|
SetTownIndex(t, 0);
|
|
|
|
@ -1023,20 +1023,20 @@ bool AfterLoadGame()
|
|
|
|
|
if (IsPlainRail(t)) {
|
|
|
|
|
/* Swap ground type and signal type for plain rail tiles, so the
|
|
|
|
|
* ground type uses the same bits as for depots and waypoints. */
|
|
|
|
|
uint tmp = GB(_m[t].m4, 0, 4);
|
|
|
|
|
SB(_m[t].m4, 0, 4, GB(_m[t].m2, 0, 4));
|
|
|
|
|
SB(_m[t].m2, 0, 4, tmp);
|
|
|
|
|
} else if (HasBit(_m[t].m5, 2)) {
|
|
|
|
|
uint tmp = GB(t.m4(), 0, 4);
|
|
|
|
|
SB(t.m4(), 0, 4, GB(t.m2(), 0, 4));
|
|
|
|
|
SB(t.m2(), 0, 4, tmp);
|
|
|
|
|
} else if (HasBit(t.m5(), 2)) {
|
|
|
|
|
/* Split waypoint and depot rail type and remove the subtype. */
|
|
|
|
|
ClrBit(_m[t].m5, 2);
|
|
|
|
|
ClrBit(_m[t].m5, 6);
|
|
|
|
|
ClrBit(t.m5(), 2);
|
|
|
|
|
ClrBit(t.m5(), 6);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_ROAD:
|
|
|
|
|
/* Swap m3 and m4, so the track type for rail crossings is the
|
|
|
|
|
* same as for normal rail. */
|
|
|
|
|
Swap(_m[t].m3, _m[t].m4);
|
|
|
|
|
Swap(t.m3(), t.m4());
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
@ -1050,31 +1050,31 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
switch (GetTileType(t)) {
|
|
|
|
|
case MP_ROAD:
|
|
|
|
|
SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2));
|
|
|
|
|
SB(t.m5(), 6, 2, GB(t.m5(), 4, 2));
|
|
|
|
|
switch (GetRoadTileType(t)) {
|
|
|
|
|
default: SlErrorCorrupt("Invalid road tile type");
|
|
|
|
|
case ROAD_TILE_NORMAL:
|
|
|
|
|
SB(_m[t].m4, 0, 4, GB(_m[t].m5, 0, 4));
|
|
|
|
|
SB(_m[t].m4, 4, 4, 0);
|
|
|
|
|
SB(_me[t].m6, 2, 4, 0);
|
|
|
|
|
SB(t.m4(), 0, 4, GB(t.m5(), 0, 4));
|
|
|
|
|
SB(t.m4(), 4, 4, 0);
|
|
|
|
|
SB(t.m6(), 2, 4, 0);
|
|
|
|
|
break;
|
|
|
|
|
case ROAD_TILE_CROSSING:
|
|
|
|
|
SB(_m[t].m4, 5, 2, GB(_m[t].m5, 2, 2));
|
|
|
|
|
SB(t.m4(), 5, 2, GB(t.m5(), 2, 2));
|
|
|
|
|
break;
|
|
|
|
|
case ROAD_TILE_DEPOT: break;
|
|
|
|
|
}
|
|
|
|
|
SB(_me[t].m7, 6, 2, 1); // Set pre-NRT road type bits for conversion later.
|
|
|
|
|
SB(t.m7(), 6, 2, 1); // Set pre-NRT road type bits for conversion later.
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_STATION:
|
|
|
|
|
if (IsRoadStop(t)) SB(_me[t].m7, 6, 2, 1);
|
|
|
|
|
if (IsRoadStop(t)) SB(t.m7(), 6, 2, 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_TUNNELBRIDGE:
|
|
|
|
|
/* Middle part of "old" bridges */
|
|
|
|
|
if (old_bridge && IsBridge(t) && HasBit(_m[t].m5, 6)) break;
|
|
|
|
|
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(_m[t].m5, 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
|
|
|
|
|
SB(_me[t].m7, 6, 2, 1); // Set pre-NRT road type bits for conversion later.
|
|
|
|
|
if (old_bridge && IsBridge(t) && HasBit(t.m5(), 6)) break;
|
|
|
|
|
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(t.m5(), 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
|
|
|
|
|
SB(t.m7(), 6, 2, 1); // Set pre-NRT road type bits for conversion later.
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -1090,24 +1090,24 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
switch (GetTileType(t)) {
|
|
|
|
|
case MP_ROAD:
|
|
|
|
|
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_me[t].m7, 5, 3));
|
|
|
|
|
SB(_me[t].m7, 5, 1, GB(_m[t].m3, 7, 1)); // snow/desert
|
|
|
|
|
if (fix_roadtypes) SB(t.m7(), 6, 2, (RoadTypes)GB(t.m7(), 5, 3));
|
|
|
|
|
SB(t.m7(), 5, 1, GB(t.m3(), 7, 1)); // snow/desert
|
|
|
|
|
switch (GetRoadTileType(t)) {
|
|
|
|
|
default: SlErrorCorrupt("Invalid road tile type");
|
|
|
|
|
case ROAD_TILE_NORMAL:
|
|
|
|
|
SB(_me[t].m7, 0, 4, GB(_m[t].m3, 0, 4)); // road works
|
|
|
|
|
SB(_me[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
|
|
|
|
SB(_m[t].m3, 0, 4, GB(_m[t].m4, 4, 4)); // tram bits
|
|
|
|
|
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
|
|
|
|
|
SB(_m[t].m5, 0, 4, GB(_m[t].m4, 0, 4)); // road bits
|
|
|
|
|
SB(t.m7(), 0, 4, GB(t.m3(), 0, 4)); // road works
|
|
|
|
|
SB(t.m6(), 3, 3, GB(t.m3(), 4, 3)); // ground
|
|
|
|
|
SB(t.m3(), 0, 4, GB(t.m4(), 4, 4)); // tram bits
|
|
|
|
|
SB(t.m3(), 4, 4, GB(t.m5(), 0, 4)); // tram owner
|
|
|
|
|
SB(t.m5(), 0, 4, GB(t.m4(), 0, 4)); // road bits
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ROAD_TILE_CROSSING:
|
|
|
|
|
SB(_me[t].m7, 0, 5, GB(_m[t].m4, 0, 5)); // road owner
|
|
|
|
|
SB(_me[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
|
|
|
|
|
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
|
|
|
|
|
SB(_m[t].m5, 0, 1, GB(_m[t].m4, 6, 1)); // road axis
|
|
|
|
|
SB(_m[t].m5, 5, 1, GB(_m[t].m4, 5, 1)); // crossing state
|
|
|
|
|
SB(t.m7(), 0, 5, GB(t.m4(), 0, 5)); // road owner
|
|
|
|
|
SB(t.m6(), 3, 3, GB(t.m3(), 4, 3)); // ground
|
|
|
|
|
SB(t.m3(), 4, 4, GB(t.m5(), 0, 4)); // tram owner
|
|
|
|
|
SB(t.m5(), 0, 1, GB(t.m4(), 6, 1)); // road axis
|
|
|
|
|
SB(t.m5(), 5, 1, GB(t.m4(), 5, 1)); // crossing state
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ROAD_TILE_DEPOT:
|
|
|
|
@ -1117,32 +1117,32 @@ bool AfterLoadGame()
|
|
|
|
|
const Town *town = CalcClosestTownFromTile(t);
|
|
|
|
|
if (town != nullptr) SetTownIndex(t, town->index);
|
|
|
|
|
}
|
|
|
|
|
_m[t].m4 = 0;
|
|
|
|
|
t.m4() = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_STATION:
|
|
|
|
|
if (!IsRoadStop(t)) break;
|
|
|
|
|
|
|
|
|
|
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_m[t].m3, 0, 3));
|
|
|
|
|
SB(_me[t].m7, 0, 5, HasBit(_me[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
|
|
|
|
|
SB(_m[t].m3, 4, 4, _m[t].m1);
|
|
|
|
|
_m[t].m4 = 0;
|
|
|
|
|
if (fix_roadtypes) SB(t.m7(), 6, 2, (RoadTypes)GB(t.m3(), 0, 3));
|
|
|
|
|
SB(t.m7(), 0, 5, HasBit(t.m6(), 2) ? OWNER_TOWN : GetTileOwner(t));
|
|
|
|
|
SB(t.m3(), 4, 4, t.m1());
|
|
|
|
|
t.m4() = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_TUNNELBRIDGE:
|
|
|
|
|
if (old_bridge && IsBridge(t) && HasBit(_m[t].m5, 6)) break;
|
|
|
|
|
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(_m[t].m5, 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
|
|
|
|
|
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_m[t].m3, 0, 3));
|
|
|
|
|
if (old_bridge && IsBridge(t) && HasBit(t.m5(), 6)) break;
|
|
|
|
|
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(t.m5(), 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
|
|
|
|
|
if (fix_roadtypes) SB(t.m7(), 6, 2, (RoadTypes)GB(t.m3(), 0, 3));
|
|
|
|
|
|
|
|
|
|
Owner o = GetTileOwner(t);
|
|
|
|
|
SB(_me[t].m7, 0, 5, o); // road owner
|
|
|
|
|
SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner
|
|
|
|
|
SB(t.m7(), 0, 5, o); // road owner
|
|
|
|
|
SB(t.m3(), 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner
|
|
|
|
|
}
|
|
|
|
|
SB(_me[t].m6, 2, 4, GB(_m[t].m2, 4, 4)); // bridge type
|
|
|
|
|
SB(_me[t].m7, 5, 1, GB(_m[t].m4, 7, 1)); // snow/desert
|
|
|
|
|
SB(t.m6(), 2, 4, GB(t.m2(), 4, 4)); // bridge type
|
|
|
|
|
SB(t.m7(), 5, 1, GB(t.m4(), 7, 1)); // snow/desert
|
|
|
|
|
|
|
|
|
|
_m[t].m2 = 0;
|
|
|
|
|
_m[t].m4 = 0;
|
|
|
|
|
t.m2() = 0;
|
|
|
|
|
t.m4() = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
@ -1155,24 +1155,24 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
switch (GetTileType(t)) {
|
|
|
|
|
case MP_RAILWAY:
|
|
|
|
|
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
|
|
|
|
|
SetRailType(t, (RailType)GB(t.m3(), 0, 4));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_ROAD:
|
|
|
|
|
if (IsLevelCrossing(t)) {
|
|
|
|
|
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
|
|
|
|
|
SetRailType(t, (RailType)GB(t.m3(), 0, 4));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_STATION:
|
|
|
|
|
if (HasStationRail(t)) {
|
|
|
|
|
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
|
|
|
|
|
SetRailType(t, (RailType)GB(t.m3(), 0, 4));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_TUNNELBRIDGE:
|
|
|
|
|
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
|
|
|
|
|
SetRailType(t, (RailType)GB(_m[t].m3, 0, 4));
|
|
|
|
|
SetRailType(t, (RailType)GB(t.m3(), 0, 4));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -1186,11 +1186,11 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (MayHaveBridgeAbove(t)) ClearBridgeMiddle(t);
|
|
|
|
|
if (IsBridgeTile(t)) {
|
|
|
|
|
if (HasBit(_m[t].m5, 6)) { // middle part
|
|
|
|
|
Axis axis = (Axis)GB(_m[t].m5, 0, 1);
|
|
|
|
|
if (HasBit(t.m5(), 6)) { // middle part
|
|
|
|
|
Axis axis = (Axis)GB(t.m5(), 0, 1);
|
|
|
|
|
|
|
|
|
|
if (HasBit(_m[t].m5, 5)) { // transport route under bridge?
|
|
|
|
|
if (GB(_m[t].m5, 3, 2) == TRANSPORT_RAIL) {
|
|
|
|
|
if (HasBit(t.m5(), 5)) { // transport route under bridge?
|
|
|
|
|
if (GB(t.m5(), 3, 2) == TRANSPORT_RAIL) {
|
|
|
|
|
MakeRailNormal(
|
|
|
|
|
t,
|
|
|
|
|
GetTileOwner(t),
|
|
|
|
@ -1202,15 +1202,15 @@ bool AfterLoadGame()
|
|
|
|
|
|
|
|
|
|
/* MakeRoadNormal */
|
|
|
|
|
SetTileType(t, MP_ROAD);
|
|
|
|
|
_m[t].m2 = town;
|
|
|
|
|
_m[t].m3 = 0;
|
|
|
|
|
_m[t].m5 = (axis == AXIS_X ? ROAD_Y : ROAD_X) | ROAD_TILE_NORMAL << 6;
|
|
|
|
|
SB(_me[t].m6, 2, 4, 0);
|
|
|
|
|
_me[t].m7 = 1 << 6;
|
|
|
|
|
t.m2() = town;
|
|
|
|
|
t.m3() = 0;
|
|
|
|
|
t.m5() = (axis == AXIS_X ? ROAD_Y : ROAD_X) | ROAD_TILE_NORMAL << 6;
|
|
|
|
|
SB(t.m6(), 2, 4, 0);
|
|
|
|
|
t.m7() = 1 << 6;
|
|
|
|
|
SetRoadOwner(t, RTT_TRAM, OWNER_NONE);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (GB(_m[t].m5, 3, 2) == 0) {
|
|
|
|
|
if (GB(t.m5(), 3, 2) == 0) {
|
|
|
|
|
MakeClear(t, CLEAR_GRASS, 3);
|
|
|
|
|
} else {
|
|
|
|
|
if (!IsTileFlat(t)) {
|
|
|
|
@ -1226,12 +1226,12 @@ bool AfterLoadGame()
|
|
|
|
|
}
|
|
|
|
|
SetBridgeMiddle(t, axis);
|
|
|
|
|
} else { // ramp
|
|
|
|
|
Axis axis = (Axis)GB(_m[t].m5, 0, 1);
|
|
|
|
|
uint north_south = GB(_m[t].m5, 5, 1);
|
|
|
|
|
Axis axis = (Axis)GB(t.m5(), 0, 1);
|
|
|
|
|
uint north_south = GB(t.m5(), 5, 1);
|
|
|
|
|
DiagDirection dir = ReverseDiagDir(XYNSToDiagDir(axis, north_south));
|
|
|
|
|
TransportType type = (TransportType)GB(_m[t].m5, 1, 2);
|
|
|
|
|
TransportType type = (TransportType)GB(t.m5(), 1, 2);
|
|
|
|
|
|
|
|
|
|
_m[t].m5 = 1 << 7 | type << 2 | dir;
|
|
|
|
|
t.m5() = 1 << 7 | type << 2 | dir;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1282,12 +1282,12 @@ bool AfterLoadGame()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (has_road) {
|
|
|
|
|
RoadType road_rt = HasBit(_me[t].m7, 6) ? ROADTYPE_ROAD : INVALID_ROADTYPE;
|
|
|
|
|
RoadType tram_rt = HasBit(_me[t].m7, 7) ? ROADTYPE_TRAM : INVALID_ROADTYPE;
|
|
|
|
|
RoadType road_rt = HasBit(t.m7(), 6) ? ROADTYPE_ROAD : INVALID_ROADTYPE;
|
|
|
|
|
RoadType tram_rt = HasBit(t.m7(), 7) ? ROADTYPE_TRAM : INVALID_ROADTYPE;
|
|
|
|
|
|
|
|
|
|
assert(road_rt != INVALID_ROADTYPE || tram_rt != INVALID_ROADTYPE);
|
|
|
|
|
SetRoadTypes(t, road_rt, tram_rt);
|
|
|
|
|
SB(_me[t].m7, 6, 2, 0); // Clear pre-NRT road type bits.
|
|
|
|
|
SB(t.m7(), 6, 2, 0); // Clear pre-NRT road type bits.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1365,23 +1365,23 @@ bool AfterLoadGame()
|
|
|
|
|
* (see the code somewhere above) so don't use m4, use m2 instead. */
|
|
|
|
|
|
|
|
|
|
/* convert PBS signals to combo-signals */
|
|
|
|
|
if (HasBit(_m[t].m2, 2)) SB(_m[t].m2, 0, 2, SIGTYPE_COMBO);
|
|
|
|
|
if (HasBit(t.m2(), 2)) SB(t.m2(), 0, 2, SIGTYPE_COMBO);
|
|
|
|
|
|
|
|
|
|
/* move the signal variant back */
|
|
|
|
|
SB(_m[t].m2, 2, 1, HasBit(_m[t].m2, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
|
|
|
|
ClrBit(_m[t].m2, 3);
|
|
|
|
|
SB(t.m2(), 2, 1, HasBit(t.m2(), 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
|
|
|
|
ClrBit(t.m2(), 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clear PBS reservation on track */
|
|
|
|
|
if (!IsRailDepotTile(t)) {
|
|
|
|
|
SB(_m[t].m4, 4, 4, 0);
|
|
|
|
|
SB(t.m4(), 4, 4, 0);
|
|
|
|
|
} else {
|
|
|
|
|
ClrBit(_m[t].m3, 6);
|
|
|
|
|
ClrBit(t.m3(), 6);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_STATION: // Clear PBS reservation on station
|
|
|
|
|
ClrBit(_m[t].m3, 6);
|
|
|
|
|
ClrBit(t.m3(), 6);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
@ -1475,31 +1475,31 @@ bool AfterLoadGame()
|
|
|
|
|
if (IsSavegameVersionBefore(SLV_53)) {
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsTileType(t, MP_HOUSE)) {
|
|
|
|
|
if (GB(_m[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) {
|
|
|
|
|
if (GB(t.m3(), 6, 2) != TOWN_HOUSE_COMPLETED) {
|
|
|
|
|
/* Move the construction stage from m3[7..6] to m5[5..4].
|
|
|
|
|
* The construction counter does not have to move. */
|
|
|
|
|
SB(_m[t].m5, 3, 2, GB(_m[t].m3, 6, 2));
|
|
|
|
|
SB(_m[t].m3, 6, 2, 0);
|
|
|
|
|
SB(t.m5(), 3, 2, GB(t.m3(), 6, 2));
|
|
|
|
|
SB(t.m3(), 6, 2, 0);
|
|
|
|
|
|
|
|
|
|
/* The "house is completed" bit is now in m6[2]. */
|
|
|
|
|
SetHouseCompleted(t, false);
|
|
|
|
|
} else {
|
|
|
|
|
/* The "lift has destination" bit has been moved from
|
|
|
|
|
* m5[7] to m7[0]. */
|
|
|
|
|
SB(_me[t].m7, 0, 1, HasBit(_m[t].m5, 7));
|
|
|
|
|
ClrBit(_m[t].m5, 7);
|
|
|
|
|
SB(t.m7(), 0, 1, HasBit(t.m5(), 7));
|
|
|
|
|
ClrBit(t.m5(), 7);
|
|
|
|
|
|
|
|
|
|
/* The "lift is moving" bit has been removed, as it does
|
|
|
|
|
* the same job as the "lift has destination" bit. */
|
|
|
|
|
ClrBit(_m[t].m1, 7);
|
|
|
|
|
ClrBit(t.m1(), 7);
|
|
|
|
|
|
|
|
|
|
/* The position of the lift goes from m1[7..0] to m6[7..2],
|
|
|
|
|
* making m1 totally free, now. The lift position does not
|
|
|
|
|
* have to be a full byte since the maximum value is 36. */
|
|
|
|
|
SetLiftPosition(t, GB(_m[t].m1, 0, 6 ));
|
|
|
|
|
SetLiftPosition(t, GB(t.m1(), 0, 6 ));
|
|
|
|
|
|
|
|
|
|
_m[t].m1 = 0;
|
|
|
|
|
_m[t].m3 = 0;
|
|
|
|
|
t.m1() = 0;
|
|
|
|
|
t.m3() = 0;
|
|
|
|
|
SetHouseCompleted(t, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1514,19 +1514,19 @@ bool AfterLoadGame()
|
|
|
|
|
if (IsTileType(t, MP_INDUSTRY)) {
|
|
|
|
|
switch (GetIndustryGfx(t)) {
|
|
|
|
|
case GFX_POWERPLANT_SPARKS:
|
|
|
|
|
_m[t].m3 = GB(_m[t].m1, 2, 5);
|
|
|
|
|
t.m3() = GB(t.m1(), 2, 5);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GFX_OILWELL_ANIMATED_1:
|
|
|
|
|
case GFX_OILWELL_ANIMATED_2:
|
|
|
|
|
case GFX_OILWELL_ANIMATED_3:
|
|
|
|
|
_m[t].m3 = GB(_m[t].m1, 0, 2);
|
|
|
|
|
t.m3() = GB(t.m1(), 0, 2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GFX_COAL_MINE_TOWER_ANIMATED:
|
|
|
|
|
case GFX_COPPER_MINE_TOWER_ANIMATED:
|
|
|
|
|
case GFX_GOLD_MINE_TOWER_ANIMATED:
|
|
|
|
|
_m[t].m3 = _m[t].m1;
|
|
|
|
|
t.m3() = t.m1();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: // No animation states to change
|
|
|
|
@ -1571,8 +1571,8 @@ bool AfterLoadGame()
|
|
|
|
|
|
|
|
|
|
if (IsSavegameVersionBefore(SLV_52)) {
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsTileType(t, MP_OBJECT) && _m[t].m5 == OBJECT_STATUE) {
|
|
|
|
|
_m[t].m2 = CalcClosestTownFromTile(t)->index;
|
|
|
|
|
if (IsTileType(t, MP_OBJECT) && t.m5() == OBJECT_STATUE) {
|
|
|
|
|
t.m2() = CalcClosestTownFromTile(t)->index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1631,10 +1631,10 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsTileType(t, MP_RAILWAY) && HasSignals(t)) {
|
|
|
|
|
/* move signal states */
|
|
|
|
|
SetSignalStates(t, GB(_m[t].m2, 4, 4));
|
|
|
|
|
SB(_m[t].m2, 4, 4, 0);
|
|
|
|
|
SetSignalStates(t, GB(t.m2(), 4, 4));
|
|
|
|
|
SB(t.m2(), 4, 4, 0);
|
|
|
|
|
/* clone signal type and variant */
|
|
|
|
|
SB(_m[t].m2, 4, 3, GB(_m[t].m2, 0, 3));
|
|
|
|
|
SB(t.m2(), 4, 3, GB(t.m2(), 0, 3));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1675,7 +1675,7 @@ bool AfterLoadGame()
|
|
|
|
|
if (IsSavegameVersionBefore(SLV_83)) {
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsShipDepotTile(t)) {
|
|
|
|
|
_m[t].m4 = (TileHeight(t) == 0) ? OWNER_WATER : OWNER_NONE;
|
|
|
|
|
t.m4() = (TileHeight(t) == 0) ? OWNER_WATER : OWNER_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1709,8 +1709,8 @@ bool AfterLoadGame()
|
|
|
|
|
if (IsSavegameVersionBefore(SLV_81)) {
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (GetTileType(t) == MP_TREES) {
|
|
|
|
|
TreeGround groundType = (TreeGround)GB(_m[t].m2, 4, 2);
|
|
|
|
|
if (groundType != TREE_GROUND_SNOW_DESERT) SB(_m[t].m2, 6, 2, 3);
|
|
|
|
|
TreeGround groundType = (TreeGround)GB(t.m2(), 4, 2);
|
|
|
|
|
if (groundType != TREE_GROUND_SNOW_DESERT) SB(t.m2(), 6, 2, 3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1772,8 +1772,8 @@ bool AfterLoadGame()
|
|
|
|
|
case STATION_OILRIG:
|
|
|
|
|
case STATION_DOCK:
|
|
|
|
|
case STATION_BUOY:
|
|
|
|
|
SetWaterClass(t, (WaterClass)GB(_m[t].m3, 0, 2));
|
|
|
|
|
SB(_m[t].m3, 0, 2, 0);
|
|
|
|
|
SetWaterClass(t, (WaterClass)GB(t.m3(), 0, 2));
|
|
|
|
|
SB(t.m3(), 0, 2, 0);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
@ -1783,8 +1783,8 @@ bool AfterLoadGame()
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_WATER:
|
|
|
|
|
SetWaterClass(t, (WaterClass)GB(_m[t].m3, 0, 2));
|
|
|
|
|
SB(_m[t].m3, 0, 2, 0);
|
|
|
|
|
SetWaterClass(t, (WaterClass)GB(t.m3(), 0, 2));
|
|
|
|
|
SB(t.m3(), 0, 2, 0);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_OBJECT:
|
|
|
|
@ -1811,7 +1811,7 @@ bool AfterLoadGame()
|
|
|
|
|
MakeCanal(t, o, Random());
|
|
|
|
|
}
|
|
|
|
|
} else if (IsShipDepot(t)) {
|
|
|
|
|
Owner o = (Owner)_m[t].m4; // Original water owner
|
|
|
|
|
Owner o = (Owner)t.m4(); // Original water owner
|
|
|
|
|
SetWaterClass(t, o == OWNER_WATER ? WATER_CLASS_SEA : WATER_CLASS_CANAL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1899,8 +1899,8 @@ bool AfterLoadGame()
|
|
|
|
|
/* Increase HouseAnimationFrame from 5 to 7 bits */
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsTileType(t, MP_HOUSE) && GetHouseType(t) >= NEW_HOUSE_OFFSET) {
|
|
|
|
|
SB(_me[t].m6, 2, 6, GB(_me[t].m6, 3, 5));
|
|
|
|
|
SB(_m[t].m3, 5, 1, 0);
|
|
|
|
|
SB(t.m6(), 2, 6, GB(t.m6(), 3, 5));
|
|
|
|
|
SB(t.m3(), 5, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1933,7 +1933,7 @@ bool AfterLoadGame()
|
|
|
|
|
|
|
|
|
|
/* Replace "house construction year" with "house age" */
|
|
|
|
|
if (IsTileType(t, MP_HOUSE) && IsHouseCompleted(t)) {
|
|
|
|
|
_m[t].m5 = Clamp(_cur_year - (_m[t].m5 + ORIGINAL_BASE_YEAR), 0, 0xFF);
|
|
|
|
|
t.m5() = Clamp(_cur_year - (t.m5() + ORIGINAL_BASE_YEAR), 0, 0xFF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1947,10 +1947,10 @@ bool AfterLoadGame()
|
|
|
|
|
case MP_RAILWAY:
|
|
|
|
|
if (HasSignals(t)) {
|
|
|
|
|
/* move the signal variant */
|
|
|
|
|
SetSignalVariant(t, TRACK_UPPER, HasBit(_m[t].m2, 2) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
|
|
|
|
SetSignalVariant(t, TRACK_LOWER, HasBit(_m[t].m2, 6) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
|
|
|
|
ClrBit(_m[t].m2, 2);
|
|
|
|
|
ClrBit(_m[t].m2, 6);
|
|
|
|
|
SetSignalVariant(t, TRACK_UPPER, HasBit(t.m2(), 2) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
|
|
|
|
SetSignalVariant(t, TRACK_LOWER, HasBit(t.m2(), 6) ? SIG_SEMAPHORE : SIG_ELECTRIC);
|
|
|
|
|
ClrBit(t.m2(), 2);
|
|
|
|
|
ClrBit(t.m2(), 6);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clear PBS reservation on track */
|
|
|
|
@ -2028,11 +2028,11 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
/* Check for HQ bit being set, instead of using map accessor,
|
|
|
|
|
* since we've already changed it code-wise */
|
|
|
|
|
if (IsTileType(t, MP_OBJECT) && HasBit(_m[t].m5, 7)) {
|
|
|
|
|
if (IsTileType(t, MP_OBJECT) && HasBit(t.m5(), 7)) {
|
|
|
|
|
/* Move size and part identification of HQ out of the m5 attribute,
|
|
|
|
|
* on new locations */
|
|
|
|
|
_m[t].m3 = GB(_m[t].m5, 0, 5);
|
|
|
|
|
_m[t].m5 = OBJECT_HQ;
|
|
|
|
|
t.m3() = GB(t.m5(), 0, 5);
|
|
|
|
|
t.m5() = OBJECT_HQ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2041,13 +2041,13 @@ bool AfterLoadGame()
|
|
|
|
|
if (!IsTileType(t, MP_OBJECT)) continue;
|
|
|
|
|
|
|
|
|
|
/* Reordering/generalisation of the object bits. */
|
|
|
|
|
ObjectType type = _m[t].m5;
|
|
|
|
|
SB(_me[t].m6, 2, 4, type == OBJECT_HQ ? GB(_m[t].m3, 2, 3) : 0);
|
|
|
|
|
_m[t].m3 = type == OBJECT_HQ ? GB(_m[t].m3, 1, 1) | GB(_m[t].m3, 0, 1) << 4 : 0;
|
|
|
|
|
ObjectType type = t.m5();
|
|
|
|
|
SB(t.m6(), 2, 4, type == OBJECT_HQ ? GB(t.m3(), 2, 3) : 0);
|
|
|
|
|
t.m3() = type == OBJECT_HQ ? GB(t.m3(), 1, 1) | GB(t.m3(), 0, 1) << 4 : 0;
|
|
|
|
|
|
|
|
|
|
/* Make sure those bits are clear as well! */
|
|
|
|
|
_m[t].m4 = 0;
|
|
|
|
|
_me[t].m7 = 0;
|
|
|
|
|
t.m4() = 0;
|
|
|
|
|
t.m7() = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2060,15 +2060,15 @@ bool AfterLoadGame()
|
|
|
|
|
/* No towns, so remove all objects! */
|
|
|
|
|
DoClearSquare(t);
|
|
|
|
|
} else {
|
|
|
|
|
uint offset = _m[t].m3;
|
|
|
|
|
uint offset = t.m3();
|
|
|
|
|
|
|
|
|
|
/* Also move the animation state. */
|
|
|
|
|
_m[t].m3 = GB(_me[t].m6, 2, 4);
|
|
|
|
|
SB(_me[t].m6, 2, 4, 0);
|
|
|
|
|
t.m3() = GB(t.m6(), 2, 4);
|
|
|
|
|
SB(t.m6(), 2, 4, 0);
|
|
|
|
|
|
|
|
|
|
if (offset == 0) {
|
|
|
|
|
/* No offset, so make the object. */
|
|
|
|
|
ObjectType type = _m[t].m5;
|
|
|
|
|
ObjectType type = t.m5();
|
|
|
|
|
int size = type == OBJECT_HQ ? 2 : 1;
|
|
|
|
|
|
|
|
|
|
if (!Object::CanAllocateItem()) {
|
|
|
|
@ -2078,18 +2078,18 @@ bool AfterLoadGame()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Object *o = new Object();
|
|
|
|
|
o->location.tile = t;
|
|
|
|
|
o->location.tile = (TileIndex)t;
|
|
|
|
|
o->location.w = size;
|
|
|
|
|
o->location.h = size;
|
|
|
|
|
o->build_date = _date;
|
|
|
|
|
o->town = type == OBJECT_STATUE ? Town::Get(_m[t].m2) : CalcClosestTownFromTile(t, UINT_MAX);
|
|
|
|
|
_m[t].m2 = o->index;
|
|
|
|
|
o->town = type == OBJECT_STATUE ? Town::Get(t.m2()) : CalcClosestTownFromTile(t, UINT_MAX);
|
|
|
|
|
t.m2() = o->index;
|
|
|
|
|
Object::IncTypeCount(type);
|
|
|
|
|
} else {
|
|
|
|
|
/* We're at an offset, so get the ID from our "root". */
|
|
|
|
|
TileIndex northern_tile = t - TileXY(GB(offset, 0, 4), GB(offset, 4, 4));
|
|
|
|
|
Tile northern_tile = t - TileXY(GB(offset, 0, 4), GB(offset, 4, 4));
|
|
|
|
|
assert(IsTileType(northern_tile, MP_OBJECT));
|
|
|
|
|
_m[t].m2 = _m[northern_tile].m2;
|
|
|
|
|
t.m2() = northern_tile.m2();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2294,16 +2294,17 @@ bool AfterLoadGame()
|
|
|
|
|
|
|
|
|
|
if (IsSavegameVersionBefore(SLV_128)) {
|
|
|
|
|
for (const Depot *d : Depot::Iterate()) {
|
|
|
|
|
Tile tile = d->xy;
|
|
|
|
|
/* At some point, invalid depots were saved into the game (possibly those removed in the past?)
|
|
|
|
|
* Remove them here, so they don't cause issues further down the line */
|
|
|
|
|
if (!IsDepotTile(d->xy)) {
|
|
|
|
|
if (!IsDepotTile(tile)) {
|
|
|
|
|
Debug(sl, 0, "Removing invalid depot {} at {}, {}", d->index, TileX(d->xy), TileY(d->xy));
|
|
|
|
|
delete d;
|
|
|
|
|
d = nullptr;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
_m[d->xy].m2 = d->index;
|
|
|
|
|
if (IsTileType(d->xy, MP_WATER)) _m[GetOtherShipDepotTile(d->xy)].m2 = d->index;
|
|
|
|
|
tile.m2() = d->index;
|
|
|
|
|
if (IsTileType(tile, MP_WATER)) Tile(GetOtherShipDepotTile(tile)).m2() = d->index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2324,15 +2325,15 @@ bool AfterLoadGame()
|
|
|
|
|
if (IsTileType(t, MP_CLEAR)) {
|
|
|
|
|
if (GetRawClearGround(t) == CLEAR_SNOW) {
|
|
|
|
|
SetClearGroundDensity(t, CLEAR_GRASS, GetClearDensity(t));
|
|
|
|
|
SetBit(_m[t].m3, 4);
|
|
|
|
|
SetBit(t.m3(), 4);
|
|
|
|
|
} else {
|
|
|
|
|
ClrBit(_m[t].m3, 4);
|
|
|
|
|
ClrBit(t.m3(), 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (IsTileType(t, MP_TREES)) {
|
|
|
|
|
uint density = GB(_m[t].m2, 6, 2);
|
|
|
|
|
uint ground = GB(_m[t].m2, 4, 2);
|
|
|
|
|
_m[t].m2 = ground << 6 | density << 4;
|
|
|
|
|
uint density = GB(t.m2(), 6, 2);
|
|
|
|
|
uint ground = GB(t.m2(), 4, 2);
|
|
|
|
|
t.m2() = ground << 6 | density << 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2440,23 +2441,23 @@ bool AfterLoadGame()
|
|
|
|
|
switch (GetTileType(t)) {
|
|
|
|
|
case MP_HOUSE:
|
|
|
|
|
if (GetHouseType(t) >= NEW_HOUSE_OFFSET) {
|
|
|
|
|
uint per_proc = _me[t].m7;
|
|
|
|
|
_me[t].m7 = GB(_me[t].m6, 2, 6) | (GB(_m[t].m3, 5, 1) << 6);
|
|
|
|
|
SB(_m[t].m3, 5, 1, 0);
|
|
|
|
|
SB(_me[t].m6, 2, 6, std::min(per_proc, 63U));
|
|
|
|
|
uint per_proc = t.m7();
|
|
|
|
|
t.m7() = GB(t.m6(), 2, 6) | (GB(t.m3(), 5, 1) << 6);
|
|
|
|
|
SB(t.m3(), 5, 1, 0);
|
|
|
|
|
SB(t.m6(), 2, 6, std::min(per_proc, 63U));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MP_INDUSTRY: {
|
|
|
|
|
uint rand = _me[t].m7;
|
|
|
|
|
_me[t].m7 = _m[t].m3;
|
|
|
|
|
_m[t].m3 = rand;
|
|
|
|
|
uint rand = t.m7();
|
|
|
|
|
t.m7() = t.m3();
|
|
|
|
|
t.m3() = rand;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case MP_OBJECT:
|
|
|
|
|
_me[t].m7 = _m[t].m3;
|
|
|
|
|
_m[t].m3 = 0;
|
|
|
|
|
t.m7() = t.m3();
|
|
|
|
|
t.m3() = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
@ -2771,16 +2772,16 @@ bool AfterLoadGame()
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (!IsTileType(t, MP_CLEAR) && !IsTileType(t, MP_TREES)) continue;
|
|
|
|
|
if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) continue;
|
|
|
|
|
uint fence = GB(_m[t].m4, 5, 3);
|
|
|
|
|
uint fence = GB(t.m4(), 5, 3);
|
|
|
|
|
if (fence != 0 && IsTileType(TILE_ADDXY(t, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 1, 0), CLEAR_FIELDS)) {
|
|
|
|
|
SetFence(TILE_ADDXY(t, 1, 0), DIAGDIR_NE, fence);
|
|
|
|
|
}
|
|
|
|
|
fence = GB(_m[t].m4, 2, 3);
|
|
|
|
|
fence = GB(t.m4(), 2, 3);
|
|
|
|
|
if (fence != 0 && IsTileType(TILE_ADDXY(t, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 0, 1), CLEAR_FIELDS)) {
|
|
|
|
|
SetFence(TILE_ADDXY(t, 0, 1), DIAGDIR_NW, fence);
|
|
|
|
|
}
|
|
|
|
|
SB(_m[t].m4, 2, 3, 0);
|
|
|
|
|
SB(_m[t].m4, 5, 3, 0);
|
|
|
|
|
SB(t.m4(), 2, 3, 0);
|
|
|
|
|
SB(t.m4(), 5, 3, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2880,9 +2881,9 @@ bool AfterLoadGame()
|
|
|
|
|
/* Move ObjectType from map to pool */
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsTileType(t, MP_OBJECT)) {
|
|
|
|
|
Object *o = Object::Get(_m[t].m2);
|
|
|
|
|
o->type = _m[t].m5;
|
|
|
|
|
_m[t].m5 = 0; // zero upper bits of (now bigger) ObjectID
|
|
|
|
|
Object *o = Object::Get(t.m2());
|
|
|
|
|
o->type = t.m5();
|
|
|
|
|
t.m5() = 0; // zero upper bits of (now bigger) ObjectID
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3191,7 +3192,7 @@ bool AfterLoadGame()
|
|
|
|
|
/* Reset unused tree counters to reduce the savegame size. */
|
|
|
|
|
for (auto t : Map::Iterate()) {
|
|
|
|
|
if (IsTileType(t, MP_TREES)) {
|
|
|
|
|
SB(_m[t].m2, 0, 4, 0);
|
|
|
|
|
SB(t.m2(), 0, 4, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|