1
0
Fork 0

Compare commits

...

5 Commits

Author SHA1 Message Date
Tyler Trahan 6664921c67
Merge 1e1b2c8037 into 10eeba86a6 2025-07-23 19:33:27 +00:00
Peter Nelson 10eeba86a6 Codechange: Simplify/breakout logic for selecting bridge table sprites.
Move various base offsets to separate functions where they can be reused and documented.

No longer rely on coincidences to select the correct data between bridges and aqueducts.
2025-07-23 20:31:15 +01:00
Peter Nelson d99dad9e9e Codechange: Pass bridge pillar palette/sprite by reference. 2025-07-23 20:31:15 +01:00
Tyler Trahan 1e1b2c8037 Change: Convert house placer protection buttons to a single toggle 2025-07-21 14:18:29 -04:00
Tyler Trahan 632029e277 Feature: House placer mode to overbuild existing houses 2025-07-21 14:18:29 -04:00
7 changed files with 139 additions and 110 deletions

View File

@ -2859,10 +2859,11 @@ STR_HOUSE_PICKER_CLASS_ZONE3 :Outer Suburbs
STR_HOUSE_PICKER_CLASS_ZONE4 :Inner Suburbs
STR_HOUSE_PICKER_CLASS_ZONE5 :Town centre
STR_HOUSE_PICKER_PROTECT_TITLE :Prevent upgrades
STR_HOUSE_PICKER_PROTECT :Prevent upgrades
STR_HOUSE_PICKER_PROTECT_TOOLTIP :Choose whether this house will be protected from replacement as the town grows
STR_HOUSE_PICKER_PROTECT_OFF :Off
STR_HOUSE_PICKER_PROTECT_ON :On
STR_HOUSE_PICKER_OVERBUILD :Overbuild existing
STR_HOUSE_PICKER_OVERBUILD_TOOLTIP :Choose whether to automatically remove an existing house on the tile where this house is placed
STR_STATION_CLASS_DFLT :Default
STR_STATION_CLASS_DFLT_STATION :Default station

View File

@ -36,9 +36,14 @@
# define MW(a) {a, PALETTE_TO_STRUCT_WHITE}
# define MC(a) {a, PALETTE_TO_STRUCT_CONCRETE}
static const PalSpriteID _aqueduct_sprites[] = {
{ SPR_AQUEDUCT_MIDDLE_X, PAL_NONE }, { 0x0, PAL_NONE }, { SPR_AQUEDUCT_PILLAR_X, PAL_NONE }, { 0x0, PAL_NONE },
{ SPR_AQUEDUCT_MIDDLE_Y, PAL_NONE }, { 0x0, PAL_NONE }, { SPR_AQUEDUCT_PILLAR_Y, PAL_NONE }, { 0x0, PAL_NONE },
/* Sprite table for middle part of aqueduct. */
static const PalSpriteID _aqueduct_sprite_table_middle[] = {
{SPR_AQUEDUCT_MIDDLE_X, PAL_NONE}, {0x0, PAL_NONE}, {SPR_AQUEDUCT_PILLAR_X, PAL_NONE}, {0x0, PAL_NONE}, // AXIS_X
{SPR_AQUEDUCT_MIDDLE_Y, PAL_NONE}, {0x0, PAL_NONE}, {SPR_AQUEDUCT_PILLAR_Y, PAL_NONE}, {0x0, PAL_NONE}, // AIXS_Y
};
/* Sprite table for head part of aqueduct. */
static const PalSpriteID _aqueduct_sprite_table_heads[] = {
{SPR_AQUEDUCT_RAMP_SW, PAL_NONE}, {SPR_AQUEDUCT_RAMP_SE, PAL_NONE}, {SPR_AQUEDUCT_RAMP_NE, PAL_NONE}, {SPR_AQUEDUCT_RAMP_NW, PAL_NONE},
};

View File

@ -2894,9 +2894,10 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile, TownExpandModes modes)
* @param tile Tile on which to place the house.
* @param HouseID The HouseID of the house spec.
* @param is_protected Whether the house is protected from the town upgrading it.
* @param overbuild Whether to automatically demolish an existing house on this tile, if present.
* @return Empty cost or an error.
*/
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool is_protected)
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool is_protected, bool overbuild)
{
if (_game_mode != GM_EDITOR && _settings_game.economy.place_houses == PH_FORBIDDEN) return CMD_ERROR;
@ -2906,39 +2907,45 @@ CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, b
const HouseSpec *hs = HouseSpec::Get(house);
if (!hs->enabled) return CMD_ERROR;
Town *t = ClosestTownFromTile(tile, UINT_MAX);
int maxz = GetTileMaxZ(tile);
/* cannot build on these slopes... */
Slope slope = GetTileSlope(tile);
/* Check each tile of a multi-tile house. */
TileArea ta(tile, 1, 1);
if (hs->building_flags.Test(BuildingFlag::Size2x2)) ta.Add(TileAddXY(tile, 1, 1));
if (hs->building_flags.Test(BuildingFlag::Size2x1)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SW));
if (hs->building_flags.Test(BuildingFlag::Size1x2)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SE));
for (const TileIndex subtile : ta) {
/* Houses cannot be built on steep slopes. */
Slope slope = GetTileSlope(subtile);
if (IsSteepSlope(slope)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
/* building under a bridge? */
if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
/* can we clear the land? */
CommandCost cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, tile);
if (!cost.Succeeded()) return cost;
int maxz = GetTileMaxZ(tile);
/* Houses cannot be built under bridges. */
if (IsBridgeAbove(subtile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
/* Make sure there is no slope? */
bool noslope = hs->building_flags.Test(BuildingFlag::NotSloped);
if (noslope && slope != SLOPE_FLAT) return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
TileArea ta = tile;
if (hs->building_flags.Test(BuildingFlag::Size2x2)) ta.Add(TileAddXY(tile, 1, 1));
if (hs->building_flags.Test(BuildingFlag::Size2x1)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SW));
if (hs->building_flags.Test(BuildingFlag::Size1x2)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SE));
/* All tiles of a multi-tile house must have the same z-level. */
if (GetTileMaxZ(subtile) != maxz) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
/* Check additional tiles covered by this house. */
for (const TileIndex &subtile : ta) {
cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, subtile);
/* We might be overbuilding an existing house, otherwise check if we can clear land. */
if (!(overbuild && GetTileType(subtile) == MP_HOUSE)) {
CommandCost cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, subtile);
if (!cost.Succeeded()) return cost;
if (!CheckBuildHouseSameZ(subtile, maxz, noslope)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
}
}
if (flags.Test(DoCommandFlag::Execute)) {
/* If overbuilding, clear any existing houses first. */
if (overbuild) {
for (const TileIndex &subtile : ta) {
if (GetTileType(subtile) == MP_HOUSE) ClearTownHouse(Town::GetByTile(subtile), subtile);
}
}
Town *t = ClosestTownFromTile(tile, UINT_MAX);
bool house_completed = _settings_game.economy.place_houses == PH_ALLOWED_CONSTRUCTED;
BuildTownHouse(t, tile, hs, house, Random(), house_completed, is_protected);
}

View File

@ -27,7 +27,7 @@ CommandCost CmdTownCargoGoal(DoCommandFlags flags, TownID town_id, TownAcceptanc
CommandCost CmdTownSetText(DoCommandFlags flags, TownID town_id, const EncodedString &text);
CommandCost CmdExpandTown(DoCommandFlags flags, TownID town_id, uint32_t grow_amount, TownExpandModes modes);
CommandCost CmdDeleteTown(DoCommandFlags flags, TownID town_id);
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool house_protected);
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool house_protected, bool overbuild);
DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CommandFlags({CommandFlag::Deity, CommandFlag::NoTest}), CMDT_LANDSCAPE_CONSTRUCTION) // founding random town can fail only in exec run
DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CommandFlags({CommandFlag::Deity, CommandFlag::Server}), CMDT_OTHER_MANAGEMENT)

View File

@ -1629,6 +1629,7 @@ static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
struct BuildHouseWindow : public PickerWindow {
std::string house_info{};
static inline bool house_protected;
static inline bool overbuild;
BuildHouseWindow(WindowDesc &desc, Window *parent) : PickerWindow(desc, parent, 0, HousePickerCallbacks::instance)
{
@ -1733,11 +1734,17 @@ struct BuildHouseWindow : public PickerWindow {
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
case WID_BH_PROTECT_OFF:
case WID_BH_PROTECT_ON:
BuildHouseWindow::house_protected = (widget == WID_BH_PROTECT_ON);
this->SetWidgetLoweredState(WID_BH_PROTECT_OFF, !BuildHouseWindow::house_protected);
this->SetWidgetLoweredState(WID_BH_PROTECT_ON, BuildHouseWindow::house_protected);
case WID_BH_PROTECT_TOGGLE:
BuildHouseWindow::house_protected = !BuildHouseWindow::house_protected;
this->SetWidgetLoweredState(WID_BH_PROTECT_TOGGLE, BuildHouseWindow::house_protected);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
this->SetDirty();
break;
case WID_BH_OVERBUILD_TOGGLE:
BuildHouseWindow::overbuild = !BuildHouseWindow::overbuild;
this->SetWidgetLoweredState(WID_BH_OVERBUILD_TOGGLE, BuildHouseWindow::overbuild);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
this->SetDirty();
@ -1766,17 +1773,16 @@ struct BuildHouseWindow : public PickerWindow {
bool hasflag = spec->extra_flags.Test(HouseExtraFlag::BuildingIsProtected);
if (hasflag) BuildHouseWindow::house_protected = true;
this->SetWidgetLoweredState(WID_BH_PROTECT_OFF, !BuildHouseWindow::house_protected);
this->SetWidgetLoweredState(WID_BH_PROTECT_ON, BuildHouseWindow::house_protected);
this->SetWidgetLoweredState(WID_BH_PROTECT_TOGGLE, BuildHouseWindow::house_protected);
this->SetWidgetLoweredState(WID_BH_OVERBUILD_TOGGLE, BuildHouseWindow::overbuild);
this->SetWidgetDisabledState(WID_BH_PROTECT_OFF, hasflag);
this->SetWidgetDisabledState(WID_BH_PROTECT_ON, hasflag);
this->SetWidgetDisabledState(WID_BH_PROTECT_TOGGLE, hasflag);
}
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
{
const HouseSpec *spec = HouseSpec::Get(HousePickerCallbacks::sel_type);
Command<CMD_PLACE_HOUSE>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER, tile, spec->Index(), BuildHouseWindow::house_protected);
Command<CMD_PLACE_HOUSE>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER, tile, spec->Index(), BuildHouseWindow::house_protected, BuildHouseWindow::overbuild);
}
const IntervalTimer<TimerWindow> view_refresh_interval = {std::chrono::milliseconds(2500), [this](auto) {
@ -1806,15 +1812,11 @@ static constexpr NWidgetPart _nested_build_house_widgets[] = {
NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_picker, 0), SetPadding(WidgetDimensions::unscaled.picker),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BH_INFO), SetFill(1, 1), SetMinimalTextLines(10, 0),
NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_HOUSE_PICKER_PROTECT_TITLE, STR_NULL), SetFill(1, 0),
NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_OFF), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT_OFF, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_ON), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT_ON, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_TOGGLE), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_OVERBUILD_TOGGLE), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_OVERBUILD, STR_HOUSE_PICKER_OVERBUILD_TOOLTIP),
EndContainer(),
EndContainer(),
EndContainer(),
EndContainer(),
NWidgetFunction(MakePickerTypeWidgets),
EndContainer(),
};

View File

@ -138,15 +138,58 @@ bool HasBridgeFlatRamp(Slope tileh, Axis axis)
return (tileh != SLOPE_FLAT);
}
static inline std::span<const PalSpriteID> GetBridgeSpriteTable(int index, BridgePieces table)
/**
* Get the sprite table for a rail/road bridge piece.
* @param bridge_type Bridge type.
* @param piece Bridge piece.
* @return Sprite table for the bridge piece.
*/
static std::span<const PalSpriteID> GetBridgeSpriteTable(BridgeType bridge_type, BridgePieces piece)
{
const BridgeSpec *bridge = GetBridgeSpec(index);
assert(table < NUM_BRIDGE_PIECES);
if (table < bridge->sprite_table.size() && !bridge->sprite_table[table].empty()) return bridge->sprite_table[table];
assert(piece < NUM_BRIDGE_PIECES);
return _bridge_sprite_table[index][table];
const BridgeSpec *bridge = GetBridgeSpec(bridge_type);
if (piece < bridge->sprite_table.size() && !bridge->sprite_table[piece].empty()) return bridge->sprite_table[piece];
return _bridge_sprite_table[bridge_type][piece];
}
/**
* Get the sprite table transport type base offset for a rail/road bridge.
* @param transport_type Transport type of bridge.
* @param ramp Tile of bridge ramp.
* @return Offset for transport type.
*/
static uint8_t GetBridgeSpriteTableBaseOffset(TransportType transport_type, TileIndex ramp)
{
switch (transport_type) {
case TRANSPORT_RAIL: return GetRailTypeInfo(GetRailType(ramp))->bridge_offset;
case TRANSPORT_ROAD: return 8;
default: NOT_REACHED();
}
}
/**
* Get bridge sprite table base offset for the ramp part of bridge.
* @param diagdir Direction of ramp.
* @return Offset for direction.
*/
static uint8_t GetBridgeRampDirectionBaseOffset(DiagDirection diagdir)
{
/* Bridge ramps are ordered SW, SE, NE, NW instead of NE, SE, SW, NW. */
static constexpr uint8_t ramp_offsets[DIAGDIR_END] = {2, 1, 0, 3};
return ramp_offsets[diagdir];
}
/**
* Get bridge sprite table base offset for the middle part of bridge.
* @param axis Axis of bridge.
* @return Offset for axis.
*/
static uint8_t GetBridgeMiddleAxisBaseOffset(Axis axis)
{
return axis == AXIS_X ? 0 : 4;
}
/**
* Determines the foundation for the bridge head, and tests if the resulting slope is valid.
@ -1017,10 +1060,10 @@ static CommandCost ClearTile_TunnelBridge(TileIndex tile, DoCommandFlags flags)
* @param h Bounding box size in Y direction
* @param subsprite Optional subsprite for drawing halfpillars
*/
static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, uint8_t w, uint8_t h, const SubSprite *subsprite)
static inline void DrawPillar(const PalSpriteID &psid, int x, int y, int z, uint8_t w, uint8_t h, const SubSprite *subsprite)
{
static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START; ///< Start offset of pillar wrt. bridge (downwards)
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 0, -PILLAR_Z_OFFSET}, {w, h, BB_HEIGHT_UNDER_BRIDGE}, {0, 0, PILLAR_Z_OFFSET}}, IsTransparencySet(TO_BRIDGES), subsprite);
AddSortableSpriteToDraw(psid.sprite, psid.pal, x, y, z, {{0, 0, -PILLAR_Z_OFFSET}, {w, h, BB_HEIGHT_UNDER_BRIDGE}, {0, 0, PILLAR_Z_OFFSET}}, IsTransparencySet(TO_BRIDGES), subsprite);
}
/**
@ -1034,7 +1077,7 @@ static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, uint
* @param h Bounding box size in Y direction
* @return Reached Z at the bottom
*/
static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, int x, int y, int w, int h)
static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID &psid, int x, int y, int w, int h)
{
int cur_z;
for (cur_z = z_top; cur_z >= z_bottom; cur_z -= TILE_HEIGHT) {
@ -1054,7 +1097,7 @@ static int DrawPillarColumn(int z_bottom, int z_top, const PalSpriteID *psid, in
* @param y Sprite Y position of front pillar.
* @param z_bridge Absolute height of bridge bottom.
*/
static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
static void DrawBridgePillars(const PalSpriteID &psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
{
static const int bounding_box_size[2] = {16, 2}; ///< bounding box size of pillars along bridge direction
static const int back_pillar_offset[2] = { 0, 9}; ///< sprite position offset of back facing pillar
@ -1065,7 +1108,7 @@ static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis
{ { -INF, -INF, 15, INF }, { 16, -INF, INF, INF } }, // Y axis, north and south
};
if (psid->sprite == 0) return;
if (psid.sprite == 0) return;
/* Determine ground height under pillars */
DiagDirection south_dir = AxisToDiagDir(axis);
@ -1404,34 +1447,20 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
DrawBridgeMiddle(ti);
} else { // IsBridge(ti->tile)
const PalSpriteID *psid;
int base_offset;
bool ice = HasTunnelBridgeSnowOrDesert(ti->tile);
if (transport_type == TRANSPORT_RAIL) {
base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset;
assert(base_offset != 8); // This one is used for roads
} else {
base_offset = 8;
}
/* as the lower 3 bits are used for other stuff, make sure they are clear */
assert( (base_offset & 0x07) == 0x00);
DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction)));
/* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
base_offset += (6 - tunnelbridge_direction) % 4;
/* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
uint base_offset = GetBridgeRampDirectionBaseOffset(tunnelbridge_direction);
std::span<const PalSpriteID> psid;
if (transport_type != TRANSPORT_WATER) {
if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
base_offset += GetBridgeSpriteTableBaseOffset(transport_type, ti->tile);
psid = GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD);
} else {
psid = _aqueduct_sprites + base_offset;
psid = _aqueduct_sprite_table_heads;
}
psid = psid.subspan(base_offset, 1);
if (!ice) {
if (!HasTunnelBridgeSnowOrDesert(ti->tile)) {
TileIndex next = ti->tile + TileOffsByDiagDir(tunnelbridge_direction);
if (ti->tileh != SLOPE_FLAT && ti->z == 0 && HasTileWaterClass(next) && GetWaterClass(next) == WATER_CLASS_SEA) {
DrawShoreTile(ti->tileh);
@ -1451,7 +1480,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
* it doesn't disappear behind it
*/
/* Bridge heads are drawn solid no matter how invisibility/transparency is set */
AddSortableSpriteToDraw(psid->sprite, psid->pal, *ti, {{}, {TILE_SIZE, TILE_SIZE, static_cast<uint8_t>(ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT)}, {}});
AddSortableSpriteToDraw(psid[0].sprite, psid[0].pal, *ti, {{}, {TILE_SIZE, TILE_SIZE, static_cast<uint8_t>(ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT)}, {}});
if (transport_type == TRANSPORT_ROAD) {
uint offset = tunnelbridge_direction;
@ -1572,33 +1601,21 @@ void DrawBridgeMiddle(const TileInfo *ti)
TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
Axis axis = GetBridgeAxis(ti->tile);
BridgePieces piece = CalcBridgePiece(
GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
GetTunnelBridgeLength(ti->tile, rampsouth) + 1
);
const PalSpriteID *psid;
uint base_offset = GetBridgeMiddleAxisBaseOffset(axis);
std::span<const PalSpriteID> psid;
bool drawfarpillar;
if (transport_type != TRANSPORT_WATER) {
BridgeType type = GetBridgeType(rampsouth);
drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
uint base_offset;
if (transport_type == TRANSPORT_RAIL) {
base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
} else {
base_offset = 8;
}
psid = &GetBridgeSpriteTable(type, piece)[base_offset];
BridgeType bridge_type = GetBridgeType(rampsouth);
drawfarpillar = !HasBit(GetBridgeSpec(bridge_type)->flags, 0);
base_offset += GetBridgeSpriteTableBaseOffset(transport_type, rampsouth);
psid = GetBridgeSpriteTable(bridge_type, CalcBridgePiece(GetTunnelBridgeLength(ti->tile, rampnorth) + 1, GetTunnelBridgeLength(ti->tile, rampsouth) + 1));
} else {
drawfarpillar = true;
psid = _aqueduct_sprites;
psid = _aqueduct_sprite_table_middle;
}
if (axis != AXIS_X) psid += 4;
psid = psid.subspan(base_offset, 3);
int x = ti->x;
int y = ti->y;
@ -1614,14 +1631,12 @@ void DrawBridgeMiddle(const TileInfo *ti)
/* Draw floor and far part of bridge*/
if (!IsInvisibilitySet(TO_BRIDGES)) {
if (axis == AXIS_X) {
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 0, BRIDGE_Z_START}, {TILE_SIZE, 1, 40}, {0, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
AddSortableSpriteToDraw(psid[0].sprite, psid[0].pal, x, y, z, {{0, 0, BRIDGE_Z_START}, {TILE_SIZE, 1, 40}, {0, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
} else {
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 0, BRIDGE_Z_START}, {1, TILE_SIZE, 40}, {0, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
AddSortableSpriteToDraw(psid[0].sprite, psid[0].pal, x, y, z, {{0, 0, BRIDGE_Z_START}, {1, TILE_SIZE, 40}, {0, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
}
}
psid++;
if (transport_type == TRANSPORT_ROAD) {
/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false);
@ -1654,10 +1669,10 @@ void DrawBridgeMiddle(const TileInfo *ti)
if (!IsInvisibilitySet(TO_BRIDGES)) {
if (axis == AXIS_X) {
y += 12;
if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 3, BRIDGE_Z_START}, {TILE_SIZE, 1, 40}, {0, -3, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
if (psid[1].sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid[1].sprite, psid[1].pal, x, y, z, {{0, 3, BRIDGE_Z_START}, {TILE_SIZE, 1, 40}, {0, -3, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
} else {
x += 12;
if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{3, 0, BRIDGE_Z_START}, {1, TILE_SIZE, 40}, {-3, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
if (psid[1].sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid[1].sprite, psid[1].pal, x, y, z, {{3, 0, BRIDGE_Z_START}, {1, TILE_SIZE, 40}, {-3, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
}
}
@ -1667,8 +1682,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
/* Do not draw anything more if bridges are invisible */
if (IsInvisibilitySet(TO_BRIDGES)) return;
psid++;
DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
DrawBridgePillars(psid[2], ti, axis, drawfarpillar, x, y, z);
}

View File

@ -77,8 +77,8 @@ enum TownFoundingWidgets : WidgetID {
/** Widgets of the #BuildHouseWindow class. */
enum BuildHouseWidgets : WidgetID {
WID_BH_INFO, ///< Information panel of selected house.
WID_BH_PROTECT_OFF, ///< Button to protect the next house built.
WID_BH_PROTECT_ON, ///< Button to not protect the next house built.
WID_BH_PROTECT_TOGGLE, ///< Button to toggle protecting the next house built.
WID_BH_OVERBUILD_TOGGLE, ///< Button to toggle overbuilding existing houses.
};
#endif /* WIDGETS_TOWN_WIDGET_H */