Changeset - r17133:115dde67e317
[Not reviewed]
master
0 1 0
smatz - 14 years ago 2011-01-21 16:48:41
smatz@openttd.org
(svn r21881) -Codechange: ensure that vehicle's GOINGUP/DOWN bits are set correctly and that it has correct z_pos when converting from older savegames
1 file changed with 114 insertions and 0 deletions:
0 comments (0 inline, 0 general)
src/saveload/afterload.cpp
Show inline comments
 
@@ -437,6 +437,42 @@ static void FixOwnerOfRailTrack(TileInde
 
	MakeClear(t, CLEAR_GRASS, 0);
 
}
 

	
 
/**
 
 * Fixes inclination of a vehicle. Older OpenTTD versions didn't update the bits correctly.
 
 * @param v vehicle
 
 * @param dir vehicle's direction, or # INVALID_DIR if it can be ignored
 
 * @return inclination bits to set
 
 */
 
static uint FixVehicleInclination(Vehicle *v, Direction dir)
 
{
 
	/* Compute place where this vehicle entered the tile */
 
	int entry_x = v->x_pos;
 
	int entry_y = v->y_pos;
 
	switch (dir) {
 
		case DIR_NE: entry_x |= TILE_UNIT_MASK; break;
 
		case DIR_NW: entry_y |= TILE_UNIT_MASK; break;
 
		case DIR_SW: entry_x &= ~TILE_UNIT_MASK; break;
 
		case DIR_SE: entry_y &= ~TILE_UNIT_MASK; break;
 
		case INVALID_DIR: break;
 
		default: NOT_REACHED();
 
	}
 
	byte entry_z = GetSlopeZ(entry_x, entry_y);
 

	
 
	/* Compute middle of the tile. */
 
	int middle_x = (v->x_pos & ~TILE_UNIT_MASK) + HALF_TILE_SIZE;
 
	int middle_y = (v->y_pos & ~TILE_UNIT_MASK) + HALF_TILE_SIZE;
 
	byte middle_z = GetSlopeZ(middle_x, middle_y);
 

	
 
	/* middle_z == entry_z, no height change. */
 
	if (middle_z == entry_z) return 0;
 

	
 
	/* middle_z < entry_z, we are going downwards. */
 
	if (middle_z < entry_z) return 1U << GVF_GOINGDOWN_BIT;
 

	
 
	/* middle_z > entry_z, we are going upwards. */
 
	return 1U << GVF_GOINGUP_BIT;
 
}
 

	
 
bool AfterLoadGame()
 
{
 
	SetSignalHandlers();
 
@@ -2419,6 +2455,84 @@ bool AfterLoadGame()
 
		}
 
	}
 

	
 
	if (IsSavegameVersionBefore(158)) {
 
		Vehicle *v;
 
		FOR_ALL_VEHICLES(v) {
 
			switch (v->type) {
 
				case VEH_TRAIN: {
 
					Train *t = Train::From(v);
 
					/* Clear both bits first. */
 
					ClrBit(t->gv_flags, GVF_GOINGUP_BIT);
 
					ClrBit(t->gv_flags, GVF_GOINGDOWN_BIT);
 

	
 
					/* Crashed vehicles can't be going up/down. */
 
					if (t->vehstatus & VS_CRASHED) break;
 

	
 
					/* Only X/Y tracks can be sloped. */
 
					if (t->track != TRACK_BIT_X && t->track != TRACK_BIT_Y) break;
 

	
 
					t->gv_flags |= FixVehicleInclination(t, t->direction);
 
					break;
 
				}
 
				case VEH_ROAD: {
 
					RoadVehicle *rv = RoadVehicle::From(v);
 
					ClrBit(rv->gv_flags, GVF_GOINGUP_BIT);
 
					ClrBit(rv->gv_flags, GVF_GOINGDOWN_BIT);
 

	
 
					/* Crashed vehicles can't be going up/down. */
 
					if (rv->vehstatus & VS_CRASHED) break;
 

	
 
					if (rv->state == RVSB_IN_DEPOT || rv->state == RVSB_WORMHOLE) break;
 

	
 
					TrackStatus ts = GetTileTrackStatus(rv->tile, TRANSPORT_ROAD, rv->compatible_roadtypes);
 
					TrackBits trackbits = TrackStatusToTrackBits(ts);
 

	
 
					/* Only X/Y tracks can be sloped. */
 
					if (trackbits != TRACK_BIT_X && trackbits != TRACK_BIT_Y) break;
 

	
 
					Direction dir = rv->direction;
 

	
 
					/* Test if we are reversing. */
 
					Axis a = trackbits == TRACK_BIT_X ? AXIS_X : AXIS_Y;
 
					if (AxisToDirection(a) != dir &&
 
							AxisToDirection(a) != ReverseDir(dir)) {
 
						/* When reversing, the road vehicle is on the edge of the tile,
 
						 * so it can be safely compared to the middle of the tile. */
 
						dir = INVALID_DIR;
 
					}
 

	
 
					rv->gv_flags |= FixVehicleInclination(rv, dir);
 
					break;
 
				}
 
				case VEH_SHIP:
 
					break;
 

	
 
				default:
 
					continue;
 
			}
 

	
 
			if (IsBridgeTile(v->tile) && TileVirtXY(v->x_pos, v->y_pos) == v->tile) {
 
				/* In old versions, z_pos was 1 unit lower on bridge heads.
 
				 * However, this invalid state could be converted to new savegames
 
				 * by loading and saving the game in a new version. */
 
				v->z_pos = GetSlopeZ(v->x_pos, v->y_pos);
 
				DiagDirection dir = GetTunnelBridgeDirection(v->tile);
 
				if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) &&
 
						v->direction != DiagDirToDir(dir)) {
 
					/* If the train has left the bridge, it shouldn't have
 
					 * track == TRACK_BIT_WORMHOLE - this could happen
 
					 * when the train was reversed while on the last "tick"
 
					 * on the ramp before leaving the ramp to the bridge. */
 
					Train::From(v)->track = DiagDirToDiagTrackBits(dir);
 
				}
 
			}
 

	
 
			/* If the vehicle is really above v->tile (not in a wormhole),
 
			 * it should have set v->z_pos correctly. */
 
			assert(v->tile != TileVirtXY(v->x_pos, v->y_pos) || v->z_pos == GetSlopeZ(v->x_pos, v->y_pos));
 
		}
 
	}
 

	
 
	/* Road stops is 'only' updating some caches */
 
	AfterLoadRoadStops();
 
	AfterLoadLabelMaps();
0 comments (0 inline, 0 general)