Merge remote-tracking branch 'upstream/master'

This commit is contained in:
dP
2025-09-28 02:33:49 +05:00
926 changed files with 37901 additions and 27368 deletions
+73 -59
View File
@@ -540,7 +540,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie
static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other)
{
/* Remove already build pieces */
CLRBITS(*pieces, existing);
*pieces &= ~existing;
/* If we can't build anything stop here */
if (*pieces == ROAD_NONE) return CMD_ERROR;
@@ -621,7 +621,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces,
company = OWNER_TOWN;
/* If we are not within a town, we are not owned by the town */
if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
if (town == nullptr || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]) {
company = OWNER_NONE;
}
}
@@ -794,7 +794,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces,
case MP_TUNNELBRIDGE: {
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) goto do_clear;
/* Only allow building the outern roadbit, so building long roads stops at existing bridges */
/* Only allow building the outer roadbit, so building long roads stops at existing bridges */
if (MirrorRoadBits(DiagDirToRoadBits(GetTunnelBridgeDirection(tile))) != pieces) goto do_clear;
if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT);
/* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */
@@ -1356,7 +1356,7 @@ static uint GetRoadSpriteOffset(Slope slope, RoadBits bits)
* @param roadside What sort of road this is
* @return True if snow/desert road sprites should be used.
*/
static bool DrawRoadAsSnowDesert(bool snow_or_desert, Roadside roadside)
static bool DrawRoadAsSnowOrDesert(bool snow_or_desert, Roadside roadside)
{
return (snow_or_desert &&
!(_settings_game.game_creation.landscape == LandscapeType::Tropic && HasGrfMiscBit(GrfMiscBit::DesertPavedRoads) &&
@@ -1417,8 +1417,8 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb)
/* Catenary uses 1st company colour to help identify owner.
* For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GENERAL_SPRITE_COLOUR(COLOUR_GREY) : COMPANY_SPRITE_COLOUR(owner));
int z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(COLOUR_GREY) : GetCompanyPalette(owner));
uint8_t z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
if (back != 0) {
/* The "back" sprite contains the west, north and east pillars.
* We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
@@ -1427,13 +1427,16 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb)
static const SubSprite west = { -INF, -INF, -12, INF };
static const SubSprite north = { -12, -INF, 12, INF };
static const SubSprite east = { 12, -INF, INF, INF };
AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 16, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 15, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_W), &west);
AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_N), &north);
AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 16, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 15, GetSlopePixelZInCorner(ti->tileh, CORNER_E), &east);
int8_t west_z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
int8_t north_z = GetSlopePixelZInCorner(ti->tileh, CORNER_N);
int8_t east_z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
AddSortableSpriteToDraw(back, pal, *ti, {{15, 0, west_z}, {1, 1, z_wires}, {-15, 0, static_cast<int8_t>(-west_z)}}, IsTransparencySet(TO_CATENARY), &west);
AddSortableSpriteToDraw(back, pal, *ti, {{0, 0, north_z}, {1, 1, z_wires}, {0, 0, static_cast<int8_t>(-north_z)}}, IsTransparencySet(TO_CATENARY), &north);
AddSortableSpriteToDraw(back, pal, *ti, {{0, 15, east_z}, {1, 1, z_wires}, {0, -15, static_cast<int8_t>(-east_z)}}, IsTransparencySet(TO_CATENARY), &east);
}
if (front != 0) {
/* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
AddSortableSpriteToDraw(front, pal, ti->x, ti->y, 16, 16, z_wires + 1, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, z_wires);
AddSortableSpriteToDraw(front, pal, *ti, {{0, 0, static_cast<int8_t>(z_wires)}, {TILE_SIZE, TILE_SIZE, 1}, {0, 0, static_cast<int8_t>(-z_wires)}}, IsTransparencySet(TO_CATENARY));
}
}
@@ -1463,7 +1466,7 @@ void DrawRoadCatenary(const TileInfo *ti)
}
}
} else {
// No road here, no catenary to draw
/* No road here, no catenary to draw */
return;
}
@@ -1487,13 +1490,13 @@ void DrawRoadCatenary(const TileInfo *ti)
* @param h the height of the sprite to draw
* @param transparent whether the sprite should be transparent (used for roadside trees)
*/
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int8_t dx, int8_t dy, uint8_t h, bool transparent)
{
int x = ti->x | dx;
int y = ti->y | dy;
int z = ti->z;
if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z, transparent);
AddSortableSpriteToDraw(img, PAL_NONE, ti->x, ti->y, z, {{dx, dy, 0}, {2, 2, h}, {}}, transparent);
}
/**
@@ -1556,7 +1559,7 @@ static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const
{
/* Draw bare ground sprite if no road or road uses overlay system. */
if (rti == nullptr || rti->UsesOverlay()) {
if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
return SPR_FLAT_SNOW_DESERT_TILE + SlopeToSpriteOffset(ti->tileh);
}
@@ -1571,7 +1574,7 @@ static SpriteID GetRoadGroundSprite(const TileInfo *ti, Roadside roadside, const
/* Draw original road base sprite */
SpriteID image = SPR_ROAD_Y + offset;
if (DrawRoadAsSnowDesert(snow_or_desert, roadside)) {
if (DrawRoadAsSnowOrDesert(snow_or_desert, roadside)) {
image += 19;
} else {
switch (roadside) {
@@ -1628,7 +1631,7 @@ static void DrawRoadBits(TileInfo *ti)
/* DrawFoundation() modifies ti. */
}
DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnow(ti->tile));
DrawRoadGroundSprites(ti, road, tram, road_rti, tram_rti, GetRoadside(ti->tile), IsOnSnowOrDesert(ti->tile));
/* Draw one way */
if (road_rti != nullptr) {
@@ -1658,7 +1661,7 @@ static void DrawRoadBits(TileInfo *ti)
DrawRoadCatenary(ti);
/* Return if full detail is disabled, or we are zoomed fully out. */
if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZoomLevel::Detail) return;
/* Do not draw details (street lights, trees) under low bridge */
Roadside roadside = GetRoadside(ti->tile);
@@ -1696,9 +1699,18 @@ static void DrawRoadBits(TileInfo *ti)
/** Tile callback function for rendering a road tile to the screen */
static void DrawTile_Road(TileInfo *ti)
{
BridgePillarFlags blocked_pillars{};
switch (GetRoadTileType(ti->tile)) {
case ROAD_TILE_NORMAL:
DrawRoadBits(ti);
if (IsBridgeAbove(ti->tile)) {
RoadBits bits = GetAllRoadBits(ti->tile);
if ((bits & ROAD_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE);
if ((bits & ROAD_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE);
if ((bits & ROAD_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW);
if ((bits & ROAD_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW);
}
break;
case ROAD_TILE_CROSSING: {
@@ -1720,7 +1732,7 @@ static void DrawTile_Road(TileInfo *ti)
SpriteID image = SPR_ROAD_Y + axis;
Roadside roadside = GetRoadside(ti->tile);
if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
image += 19;
} else {
switch (roadside) {
@@ -1736,7 +1748,7 @@ static void DrawTile_Road(TileInfo *ti)
if (IsCrossingBarred(ti->tile)) image += 2;
Roadside roadside = GetRoadside(ti->tile);
if (DrawRoadAsSnowDesert(IsOnSnow(ti->tile), roadside)) {
if (DrawRoadAsSnowOrDesert(IsOnSnowOrDesert(ti->tile), roadside)) {
image += 8;
} else {
switch (roadside) {
@@ -1761,32 +1773,32 @@ static void DrawTile_Road(TileInfo *ti)
const Axis road_axis = GetCrossingRoadAxis(ti->tile);
const DiagDirection dir1 = AxisToDiagDir(road_axis);
const DiagDirection dir2 = ReverseDiagDir(dir1);
uint adjacent_diagdirs = 0;
DiagDirections adjacent_diagdirs{};
for (DiagDirection dir : { dir1, dir2 }) {
const TileIndex t = TileAddByDiagDir(ti->tile, dir);
if (t < Map::Size() && IsLevelCrossingTile(t) && GetCrossingRoadAxis(t) == road_axis) {
SetBit(adjacent_diagdirs, dir);
adjacent_diagdirs.Set(dir);
}
}
switch (adjacent_diagdirs) {
case 0:
switch (adjacent_diagdirs.base()) {
case DiagDirections{}.base():
DrawRailTileSeq(ti, &_crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
break;
case (1 << DIAGDIR_NE):
case DiagDirections{DIAGDIR_NE}.base():
DrawRailTileSeq(ti, &_crossing_layout_SW, TO_CATENARY, rail, 0, PAL_NONE);
break;
case (1 << DIAGDIR_SE):
case DiagDirections{DIAGDIR_SE}.base():
DrawRailTileSeq(ti, &_crossing_layout_NW, TO_CATENARY, rail, 0, PAL_NONE);
break;
case (1 << DIAGDIR_SW):
case DiagDirections{DIAGDIR_SW}.base():
DrawRailTileSeq(ti, &_crossing_layout_NE, TO_CATENARY, rail, 0, PAL_NONE);
break;
case (1 << DIAGDIR_NW):
case DiagDirections{DIAGDIR_NW}.base():
DrawRailTileSeq(ti, &_crossing_layout_SE, TO_CATENARY, rail, 0, PAL_NONE);
break;
@@ -1806,7 +1818,7 @@ static void DrawTile_Road(TileInfo *ti)
/* Draw rail catenary */
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
blocked_pillars = {BridgePillarFlag::EdgeSW, BridgePillarFlag::EdgeNE, BridgePillarFlag::EdgeNW, BridgePillarFlag::EdgeSE};
break;
}
@@ -1814,7 +1826,7 @@ static void DrawTile_Road(TileInfo *ti)
case ROAD_TILE_DEPOT: {
if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
PaletteID palette = COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile));
PaletteID palette = GetCompanyPalette(GetTileOwner(ti->tile));
RoadType road_rt = GetRoadTypeRoad(ti->tile);
RoadType tram_rt = GetRoadTypeTram(ti->tile);
@@ -1852,10 +1864,11 @@ static void DrawTile_Road(TileInfo *ti)
}
DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, palette);
/* Depots can't have bridges above so no blocked pillars. */
break;
}
}
DrawBridgeMiddle(ti);
DrawBridgeMiddle(ti, blocked_pillars);
}
/**
@@ -1867,7 +1880,7 @@ static void DrawTile_Road(TileInfo *ti)
*/
void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
{
PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
PaletteID palette = GetCompanyPalette(_local_company);
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
int relocation = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_DEPOT);
@@ -1956,7 +1969,7 @@ static const Roadside _town_road_types[][2] = {
{ ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED }
};
static_assert(lengthof(_town_road_types) == HZB_END);
static_assert(lengthof(_town_road_types) == NUM_HOUSE_ZONES);
static const Roadside _town_road_types_2[][2] = {
{ ROADSIDE_GRASS, ROADSIDE_GRASS },
@@ -1966,7 +1979,7 @@ static const Roadside _town_road_types_2[][2] = {
{ ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED }
};
static_assert(lengthof(_town_road_types_2) == HZB_END);
static_assert(lengthof(_town_road_types_2) == NUM_HOUSE_ZONES);
static void TileLoop_Road(TileIndex tile)
@@ -1975,16 +1988,16 @@ static void TileLoop_Road(TileIndex tile)
case LandscapeType::Arctic: {
/* Roads on flat foundations use the snow level of the height they are elevated to. All others use the snow level of their minimum height. */
int tile_z = (std::get<Slope>(GetFoundationSlope(tile)) == SLOPE_FLAT) ? GetTileMaxZ(tile) : GetTileZ(tile);
if (IsOnSnow(tile) != (tile_z > GetSnowLine())) {
ToggleSnow(tile);
if (IsOnSnowOrDesert(tile) != (tile_z > GetSnowLine())) {
ToggleSnowOrDesert(tile);
MarkTileDirtyByTile(tile);
}
break;
}
case LandscapeType::Tropic:
if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
ToggleDesert(tile);
if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnSnowOrDesert(tile)) {
ToggleSnowOrDesert(tile);
MarkTileDirtyByTile(tile);
}
break;
@@ -1997,14 +2010,14 @@ static void TileLoop_Road(TileIndex tile)
const Town *t = ClosestTownFromTile(tile, UINT_MAX);
if (!HasRoadWorks(tile)) {
HouseZonesBits grp = HZB_TOWN_EDGE;
HouseZone grp = HouseZone::TownEdge;
if (t != nullptr) {
grp = GetTownRadiusGroup(t, tile);
/* Show an animation to indicate road work */
if (t->road_build_months != 0 &&
(DistanceManhattan(t->xy, tile) < 8 || grp != HZB_TOWN_EDGE) &&
(DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) &&
IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) {
if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
StartRoadWorks(tile);
@@ -2023,7 +2036,7 @@ static void TileLoop_Road(TileIndex tile)
{
/* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[grp] : _town_road_types[grp];
const Roadside *new_rs = (_settings_game.game_creation.landscape == LandscapeType::Toyland) ? _town_road_types_2[to_underlying(grp)] : _town_road_types[to_underlying(grp)];
Roadside cur_rs = GetRoadside(tile);
/* We have our desired type, do nothing */
@@ -2250,7 +2263,7 @@ static const uint8_t _roadveh_enter_depot_dir[4] = {
TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE
};
static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
static VehicleEnterTileStates VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
{
switch (GetRoadTileType(tile)) {
case ROAD_TILE_DEPOT: {
@@ -2266,14 +2279,14 @@ static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int,
rv->tile = tile;
InvalidateWindowData(WC_VEHICLE_DEPOT, rv->tile);
return VETSB_ENTERED_WORMHOLE;
return VehicleEnterTileState::EnteredWormhole;
}
break;
}
default: break;
}
return VETSB_CONTINUE;
return {};
}
@@ -2370,17 +2383,6 @@ static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
}
/** Update power of road vehicle under which is the roadtype being converted */
static Vehicle *UpdateRoadVehPowerProc(Vehicle *v, void *data)
{
if (v->type != VEH_ROAD) return nullptr;
RoadVehicleList *affected_rvs = static_cast<RoadVehicleList*>(data);
include(*affected_rvs, RoadVehicle::From(v)->First());
return nullptr;
}
/**
* Checks the tile and returns whether the current player is allowed to convert the roadtype to another roadtype without taking ownership
* @param owner the tile owner.
@@ -2402,10 +2404,10 @@ static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt)
*/
static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, RoadType from_type, RoadType to_type)
{
// Scenario editor, maybe? Don't touch the owners when converting roadtypes...
/* Scenario editor, maybe? Don't touch the owners when converting roadtypes... */
if (_current_company >= MAX_COMPANIES) return;
// We can't get a company from invalid owners but we can get ownership of roads without an owner
/* We can't get a company from invalid owners but we can get ownership of roads without an owner */
if (owner >= MAX_COMPANIES && owner != OWNER_NONE) return;
Company *c;
@@ -2538,7 +2540,9 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_
MarkTileDirtyByTile(tile);
/* update power of train on this tile */
FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
for (Vehicle *v : VehiclesOnTile(tile)) {
if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
}
if (IsRoadDepotTile(tile)) {
/* Update build vehicle window related to this depot */
@@ -2595,8 +2599,12 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_
SetRoadType(tile, rtt, to_type);
SetRoadType(endtile, rtt, to_type);
FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
FindVehicleOnPos(endtile, &affected_rvs, &UpdateRoadVehPowerProc);
for (Vehicle *v : VehiclesOnTile(tile)) {
if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
}
for (Vehicle *v : VehiclesOnTile(endtile)) {
if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First());
}
if (IsBridge(tile)) {
MarkBridgeDirty(tile);
@@ -2618,6 +2626,11 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_
return found_convertible_road ? cost : error;
}
static CommandCost CheckBuildAbove_Road(TileIndex tile, DoCommandFlags flags, Axis, int)
{
if (!IsRoadDepot(tile)) return CommandCost();
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
}
/** Tile callback functions for road tiles */
extern const TileTypeProcs _tile_type_road_procs = {
@@ -2635,4 +2648,5 @@ extern const TileTypeProcs _tile_type_road_procs = {
VehicleEnter_Road, // vehicle_enter_tile_proc
GetFoundation_Road, // get_foundation_proc
TerraformTile_Road, // terraform_tile_proc
CheckBuildAbove_Road, // check_build_above_proc
};