Codechange: pass "ground vehicle" to GetTileSlopeZ since for tunnel/bridges there are two states

Previously it checked the position in non-driving direction to "guess" whether
a ground vehicle was using the function, so on tunnels/bridges it could either
return the Z of the (virtual) ground compared to the Z of the path the vehicle
would take.
This commit is contained in:
Rubidium 2023-03-12 18:14:44 +01:00 committed by rubidium42
parent 1321e48465
commit e8af8daa68
21 changed files with 64 additions and 45 deletions

View File

@ -127,7 +127,7 @@ static void DrawTile_Clear(TileInfo *ti)
DrawBridgeMiddle(ti);
}
static int GetSlopePixelZ_Clear(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Clear(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
int z;
Slope tileh = GetTilePixelSlope(tile, &z);

View File

@ -233,7 +233,7 @@ static int GetPCPElevation(TileIndex tile, DiagDirection PCPpos)
*/
int z = GetSlopePixelZ(TileX(tile) * TILE_SIZE + std::min<int8>(x_pcp_offsets[PCPpos], TILE_SIZE - 1),
TileY(tile) * TILE_SIZE + std::min<int8>(y_pcp_offsets[PCPpos], TILE_SIZE - 1));
TileY(tile) * TILE_SIZE + std::min<int8>(y_pcp_offsets[PCPpos], TILE_SIZE - 1), true);
/* Round the Z to the nearest half tile height. */
static const uint HALF_TILE_HEIGHT = TILE_HEIGHT / 2;
return (z + HALF_TILE_HEIGHT / 2) / HALF_TILE_HEIGHT * HALF_TILE_HEIGHT;
@ -491,7 +491,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
* down to the nearest full height change.
*/
AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
sss->x_size, sss->y_size, sss->z_size, (GetSlopePixelZ(ti->x + sss->x_offset, ti->y + sss->y_offset) + 4) / 8 * 8 + sss->z_offset,
sss->x_size, sss->y_size, sss->z_size, (GetSlopePixelZ(ti->x + sss->x_offset, ti->y + sss->y_offset, true) + 4) / 8 * 8 + sss->z_offset,
IsTransparencySet(TO_CATENARY));
}
}

View File

@ -134,7 +134,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
*/
inline void UpdateZPositionAndInclination()
{
this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos);
this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos, true);
ClrBit(this->gv_flags, GVF_GOINGUP_BIT);
ClrBit(this->gv_flags, GVF_GOINGDOWN_BIT);
@ -143,7 +143,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
* direction it is sloped, we get the 'z' at the center of
* the tile (middle_z) and the edge of the tile (old_z),
* which we then can compare. */
int middle_z = GetSlopePixelZ((this->x_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), (this->y_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2));
int middle_z = GetSlopePixelZ((this->x_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), (this->y_pos & ~TILE_UNIT_MASK) | (TILE_SIZE / 2), true);
if (middle_z != this->z_pos) {
SetBit(this->gv_flags, (middle_z > this->z_pos) ? GVF_GOINGUP_BIT : GVF_GOINGDOWN_BIT);
@ -200,7 +200,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
if (HasBit(this->gv_flags, GVF_GOINGUP_BIT) || HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
if (T::From(this)->HasToUseGetSlopePixelZ()) {
/* In some cases, we have to use GetSlopePixelZ() */
this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos);
this->z_pos = GetSlopePixelZ(this->x_pos, this->y_pos, true);
return;
}
/* DirToDiagDir() is a simple right shift */
@ -220,7 +220,7 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
this->z_pos += HasBit(this->gv_flags, GVF_GOINGUP_BIT) ? d : -d;
}
assert(this->z_pos == GetSlopePixelZ(this->x_pos, this->y_pos));
assert(this->z_pos == GetSlopePixelZ(this->x_pos, this->y_pos, true));
}
/**

View File

@ -385,7 +385,7 @@ static void DrawTile_Industry(TileInfo *ti)
}
}
static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
return GetTileMaxPixelZ(tile);
}

View File

@ -343,11 +343,22 @@ uint GetPartialPixelZ(int x, int y, Slope corners)
return z;
}
int GetSlopePixelZ(int x, int y)
/**
* Return world \c Z coordinate of a given point of a tile. Normally this is the
* Z of the ground/foundation at the given location, but in some cases the
* ground/foundation can differ from the Z coordinate that the (ground) vehicle
* passing over it would take. For example when entering a tunnel or bridge.
*
* @param x World X coordinate in tile "units".
* @param y World Y coordinate in tile "units".
* @param ground_vehicle Whether to get the Z coordinate of the ground vehicle, or the ground.
* @return World Z coordinate at tile ground (vehicle) level, including slopes and foundations.
*/
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
{
TileIndex tile = TileVirtXY(x, y);
return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y);
return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y, ground_vehicle);
}
/**
@ -361,9 +372,9 @@ int GetSlopePixelZ(int x, int y)
int GetSlopePixelZOutsideMap(int x, int y)
{
if (IsInsideBS(x, 0, Map::SizeX() * TILE_SIZE) && IsInsideBS(y, 0, Map::SizeY() * TILE_SIZE)) {
return GetSlopePixelZ(x, y);
return GetSlopePixelZ(x, y, false);
} else {
return _tile_type_procs[MP_VOID]->get_slope_z_proc(INVALID_TILE, x, y);
return _tile_type_procs[MP_VOID]->get_slope_z_proc(INVALID_TILE, x, y, false);
}
}

View File

@ -37,7 +37,7 @@ int GetSlopeZInCorner(Slope tileh, Corner corner);
Slope GetFoundationSlope(TileIndex tile, int *z = nullptr);
uint GetPartialPixelZ(int x, int y, Slope corners);
int GetSlopePixelZ(int x, int y);
int GetSlopePixelZ(int x, int y, bool ground_vehicle = false);
int GetSlopePixelZOutsideMap(int x, int y);
void GetSlopePixelZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2);
@ -97,7 +97,7 @@ static inline Point RemapCoords(int x, int y, int z)
*/
static inline Point RemapCoords2(int x, int y)
{
return RemapCoords(x, y, GetSlopePixelZ(x, y));
return RemapCoords(x, y, GetSlopePixelZ(x, y, false));
}
/**

View File

@ -486,7 +486,7 @@ static void DrawTile_Object(TileInfo *ti)
DrawBridgeMiddle(ti);
}
static int GetSlopePixelZ_Object(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Object(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
if (IsObjectType(tile, OBJECT_OWNED_LAND)) {
int z;

View File

@ -245,8 +245,8 @@ static uint NPFSlopeCost(AyStarNode *current)
/* Get the height on both sides of the tile edge.
* Avoid testing the height on the tile-center. This will fail for halftile-foundations.
*/
int z1 = GetSlopePixelZ(x1 + dx4, y1 + dy4);
int z2 = GetSlopePixelZ(x2 - dx4, y2 - dy4);
int z1 = GetSlopePixelZ(x1 + dx4, y1 + dy4, true);
int z2 = GetSlopePixelZ(x2 - dx4, y2 - dy4, true);
if (z2 - z1 > 1) {
/* Slope up */

View File

@ -40,12 +40,12 @@ protected:
/* height of the center of the current tile */
int x1 = TileX(tile) * TILE_SIZE;
int y1 = TileY(tile) * TILE_SIZE;
int z1 = GetSlopePixelZ(x1 + TILE_SIZE / 2, y1 + TILE_SIZE / 2);
int z1 = GetSlopePixelZ(x1 + TILE_SIZE / 2, y1 + TILE_SIZE / 2, true);
/* height of the center of the next tile */
int x2 = TileX(next_tile) * TILE_SIZE;
int y2 = TileY(next_tile) * TILE_SIZE;
int z2 = GetSlopePixelZ(x2 + TILE_SIZE / 2, y2 + TILE_SIZE / 2);
int z2 = GetSlopePixelZ(x2 + TILE_SIZE / 2, y2 + TILE_SIZE / 2, true);
if (z2 - z1 > 1) {
/* Slope up */

View File

@ -2550,7 +2550,7 @@ void DrawTrainDepotSprite(int x, int y, int dir, RailType railtype)
DrawRailTileSeqInGUI(x, y, dts, offset, 0, palette);
}
static int GetSlopePixelZ_Track(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Track(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
if (IsPlainRail(tile)) {
int z;

View File

@ -1886,7 +1886,7 @@ void UpdateNearestTownForRoadTiles(bool invalidate)
}
}
static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
if (IsNormalRoad(tile)) {

View File

@ -277,7 +277,7 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin
int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
v->x_pos = x;
v->y_pos = y;
v->z_pos = GetSlopePixelZ(x, y);
v->z_pos = GetSlopePixelZ(x, y, true);
v->state = RVSB_IN_DEPOT;
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;

View File

@ -510,12 +510,12 @@ static uint FixVehicleInclination(Vehicle *v, Direction dir)
case INVALID_DIR: break;
default: NOT_REACHED();
}
byte entry_z = GetSlopePixelZ(entry_x, entry_y);
byte entry_z = GetSlopePixelZ(entry_x, entry_y, true);
/* Compute middle of the tile. */
int middle_x = (v->x_pos & ~TILE_UNIT_MASK) + TILE_SIZE / 2;
int middle_y = (v->y_pos & ~TILE_UNIT_MASK) + TILE_SIZE / 2;
byte middle_z = GetSlopePixelZ(middle_x, middle_y);
byte middle_z = GetSlopePixelZ(middle_x, middle_y, true);
/* middle_z == entry_z, no height change. */
if (middle_z == entry_z) return 0;
@ -1249,7 +1249,7 @@ bool AfterLoadGame()
case DIAGDIR_SW: if ((v->x_pos & 0xF) != TILE_SIZE - 1) continue; break;
case DIAGDIR_NW: if ((v->y_pos & 0xF) != 0) continue; break;
}
} else if (v->z_pos > GetSlopePixelZ(v->x_pos, v->y_pos)) {
} else if (v->z_pos > GetSlopePixelZ(v->x_pos, v->y_pos, true)) {
v->tile = GetNorthernBridgeEnd(v->tile);
v->UpdatePosition();
} else {
@ -2515,7 +2515,7 @@ bool AfterLoadGame()
if (!IsTunnelTile(vtile)) continue;
/* Are we actually in this tunnel? Or maybe a lower tunnel? */
if (GetSlopePixelZ(v->x_pos, v->y_pos) != v->z_pos) continue;
if (GetSlopePixelZ(v->x_pos, v->y_pos, true) != v->z_pos) continue;
/* What way are we going? */
const DiagDirection dir = GetTunnelBridgeDirection(vtile);
@ -2661,7 +2661,7 @@ bool AfterLoadGame()
/* 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 = GetSlopePixelZ(v->x_pos, v->y_pos);
v->z_pos = GetSlopePixelZ(v->x_pos, v->y_pos, true);
DiagDirection dir = GetTunnelBridgeDirection(v->tile);
if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) &&
v->direction != DiagDirToDir(dir)) {
@ -2675,7 +2675,7 @@ bool AfterLoadGame()
/* 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 == GetSlopePixelZ(v->x_pos, v->y_pos));
assert(v->tile != TileVirtXY(v->x_pos, v->y_pos) || v->z_pos == GetSlopePixelZ(v->x_pos, v->y_pos, true));
}
/* Fill Vehicle::cur_real_order_index */
@ -3183,7 +3183,7 @@ bool AfterLoadGame()
int y = TileY(closestDepot.location) * TILE_SIZE + TILE_SIZE / 2;
u->x_pos = x;
u->y_pos = y;
u->z_pos = GetSlopePixelZ(x, y);
u->z_pos = GetSlopePixelZ(x, y, true);
u->vehstatus |= VS_HIDDEN;
u->state = RVSB_IN_DEPOT;

View File

@ -3269,7 +3269,7 @@ void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, Ro
DrawRailTileSeqInGUI(x, y, t, st == STATION_WAYPOINT ? 0 : total_offset, 0, pal);
}
static int GetSlopePixelZ_Station(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Station(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
return GetTileMaxPixelZ(tile);
}

View File

@ -73,7 +73,19 @@ struct TileDesc {
* @param ti Information about the tile to draw
*/
typedef void DrawTileProc(TileInfo *ti);
typedef int GetSlopeZProc(TileIndex tile, uint x, uint y);
/**
* Tile callback function signature for obtaining the world \c Z coordinate of a given
* point of a tile.
*
* @param tile The queries tile for the Z coordinate.
* @param x World X coordinate in tile "units".
* @param y World Y coordinate in tile "units".
* @param ground_vehicle Whether to get the Z coordinate of the ground vehicle, or the ground.
* @return World Z coordinate at tile ground (vehicle) level, including slopes and foundations.
* @see GetSlopePixelZ
*/
typedef int GetSlopeZProc(TileIndex tile, uint x, uint y, bool ground_vehicle);
typedef CommandCost ClearTileProc(TileIndex tile, DoCommandFlag flags);
/**

View File

@ -306,7 +306,7 @@ static void DrawTile_Town(TileInfo *ti)
}
}
static int GetSlopePixelZ_Town(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Town(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
return GetTileMaxPixelZ(tile);
}

View File

@ -635,7 +635,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const
v->x_pos = x;
v->y_pos = y;
v->z_pos = GetSlopePixelZ(x, y);
v->z_pos = GetSlopePixelZ(x, y, true);
v->owner = _current_company;
v->track = TRACK_BIT_DEPOT;
v->vehstatus = VS_HIDDEN | VS_DEFPAL;
@ -761,7 +761,7 @@ CommandCost CmdBuildRailVehicle(DoCommandFlag flags, TileIndex tile, const Engin
v->owner = _current_company;
v->x_pos = x;
v->y_pos = y;
v->z_pos = GetSlopePixelZ(x, y);
v->z_pos = GetSlopePixelZ(x, y, true);
v->track = TRACK_BIT_DEPOT;
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
v->spritenum = rvi->image_index;

View File

@ -586,7 +586,7 @@ static void DrawTile_Trees(TileInfo *ti)
}
static int GetSlopePixelZ_Trees(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Trees(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
int z;
Slope tileh = GetTilePixelSlope(tile, &z);

View File

@ -1663,7 +1663,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
}
static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
int z;
Slope tileh = GetTilePixelSlope(tile, &z);
@ -1672,18 +1672,14 @@ static int GetSlopePixelZ_TunnelBridge(TileIndex tile, uint x, uint y)
y &= 0xF;
if (IsTunnel(tile)) {
uint pos = (DiagDirToAxis(GetTunnelBridgeDirection(tile)) == AXIS_X ? y : x);
/* In the tunnel entrance? */
if (5 <= pos && pos <= 10) return z;
if (ground_vehicle) return z;
} else { // IsBridge(tile)
DiagDirection dir = GetTunnelBridgeDirection(tile);
uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
z += ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
/* On the bridge ramp? */
if (5 <= pos && pos <= 10) {
if (ground_vehicle) {
int delta;
if (tileh != SLOPE_FLAT) return z + TILE_HEIGHT;
@ -1881,7 +1877,7 @@ extern const byte _tunnel_visibility_frame[DIAGDIR_END] = {12, 8, 8, 12};
static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y)
{
int z = GetSlopePixelZ(x, y) - v->z_pos;
int z = GetSlopePixelZ(x, y, true) - v->z_pos;
if (abs(z) > 2) return VETSB_CANNOT_ENTER;
/* Direction into the wormhole */

View File

@ -25,7 +25,7 @@ static void DrawTile_Void(TileInfo *ti)
}
static int GetSlopePixelZ_Void(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Void(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
/* This function may be called on tiles outside the map, don't assume
* that 'tile' is a valid tile index. See GetSlopePixelZOutsideMap. */

View File

@ -936,7 +936,7 @@ void DrawShipDepotSprite(int x, int y, Axis axis, DepotPart part)
}
static int GetSlopePixelZ_Water(TileIndex tile, uint x, uint y)
static int GetSlopePixelZ_Water(TileIndex tile, uint x, uint y, bool ground_vehicle)
{
int z;
Slope tileh = GetTilePixelSlope(tile, &z);