1
0
Fork 0

Compare commits

...

4 Commits

Author SHA1 Message Date
Norbert c583505f81
Merge f02b13d52b into 10eeba86a6 2025-07-23 19:31:25 +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
npabisz f02b13d52b Add: [Script] Text effect 2025-04-27 13:30:23 -04:00
13 changed files with 331 additions and 64 deletions

View File

@ -501,6 +501,8 @@ add_files(
textbuf_type.h
texteff.cpp
texteff.hpp
texteff_cmd.cpp
texteff_cmd.h
textfile_gui.cpp
textfile_gui.h
textfile_type.h

View File

@ -46,6 +46,7 @@
#include "station_cmd.h"
#include "story_cmd.h"
#include "subsidy_cmd.h"
#include "texteff_cmd.h"
#include "terraform_cmd.h"
#include "timetable_cmd.h"
#include "town_cmd.h"

View File

@ -372,6 +372,10 @@ enum Commands : uint8_t {
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, ///< update the score of a league table element
CMD_REMOVE_LEAGUE_TABLE_ELEMENT, ///< remove a league table element
CMD_CREATE_TEXT_EFFECT, ///< create a new text effect
CMD_UPDATE_TEXT_EFFECT, ///< update text effect
CMD_REMOVE_TEXT_EFFECT, ///< remove text effect
CMD_END, ///< Must ALWAYS be on the end of this list!! (period)
};

View File

@ -40,6 +40,7 @@
#include "../station_cmd.h"
#include "../story_cmd.h"
#include "../subsidy_cmd.h"
#include "../texteff_cmd.h"
#include "../terraform_cmd.h"
#include "../timetable_cmd.h"
#include "../town_cmd.h"

View File

@ -206,6 +206,7 @@ add_files(
script_subsidylist.hpp
script_testmode.hpp
script_text.hpp
script_text_effect.hpp
script_tile.hpp
script_tilelist.hpp
script_town.hpp
@ -278,6 +279,7 @@ add_files(
script_subsidylist.cpp
script_testmode.cpp
script_text.cpp
script_text_effect.cpp
script_tile.cpp
script_tilelist.cpp
script_town.cpp

View File

@ -0,0 +1,63 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file script_text_effect.cpp Implementation of ScriptTextEffect with multiplayer support. */
#include "../../stdafx.h"
#include "script_text_effect.hpp"
#include "script_error.hpp"
#include "script_map.hpp"
#include "../script_instance.hpp"
#include "../../texteff.hpp"
#include "../../strings_func.h"
#include "../../tile_map.h"
#include "../../command_func.h"
#include "../../texteff_cmd.h"
#include "../../safeguards.h"
/* static */ TextEffectID ScriptTextEffect::CreateAtPosition(SQInteger x, SQInteger y, Text *text, ScriptTextEffectMode mode)
{
ScriptObjectRef counter(text);
EnforceDeityMode(false);
EnforcePrecondition(false, text != nullptr);
EnforcePrecondition(false, !text->GetEncodedText().empty());
EnforcePrecondition(false, mode == TE_RISING || mode == TE_STATIC);
return ScriptObject::Command<CMD_CREATE_TEXT_EFFECT>::Do(&ScriptInstance::DoCommandReturnTextEffectID, x, y, (TextEffectMode)mode, text->GetEncodedText());
}
/* static */ TextEffectID ScriptTextEffect::Create(TileIndex tile, Text *text, ScriptTextEffectMode mode)
{
EnforcePrecondition(false, ScriptMap::IsValidTile(tile));
int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
return CreateAtPosition(x, y, text, mode);
}
/* static */ bool ScriptTextEffect::Update(TextEffectID te_id, Text *text)
{
ScriptObjectRef counter(text);
EnforceDeityMode(false);
EnforcePrecondition(false, te_id != INVALID_TE_ID);
EnforcePrecondition(false, text != nullptr);
EnforcePrecondition(false, !text->GetEncodedText().empty());
return ScriptObject::Command<CMD_UPDATE_TEXT_EFFECT>::Do(te_id, text->GetEncodedText());
}
/* static */ bool ScriptTextEffect::Remove(TextEffectID te_id)
{
EnforceDeityMode(false);
EnforcePrecondition(false, te_id != INVALID_TE_ID);
return ScriptObject::Command<CMD_REMOVE_TEXT_EFFECT>::Do(te_id);
}

View File

@ -0,0 +1,66 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file script_text_effect.hpp Everything to display animated text in the game world. */
#ifndef SCRIPT_TEXT_EFFECT_HPP
#define SCRIPT_TEXT_EFFECT_HPP
#include "script_object.hpp"
#include "script_text.hpp"
#include "../../texteff.hpp"
/**
* Class that handles text effect display in the game world.
* @api game
*/
class ScriptTextEffect : public ScriptObject {
public:
/**
* Text effect animation modes.
*/
enum ScriptTextEffectMode {
TE_RISING = ::TE_RISING, ///< Text slowly rises upwards
TE_STATIC = ::TE_STATIC, ///< Text stays in place
};
/**
* Create animated text at a tile location.
* @param tile The tile where to show the text.
* @param text The text to display.
* @param mode The animation mode to use.
* @return True if the text effect was created successfully.
*/
static TextEffectID Create(TileIndex tile, Text *text, ScriptTextEffectMode mode);
/**
* Create animated text at the specified location.
* @param x X coordinate in the game world.
* @param y Y coordinate in the game world.
* @param text The text to display.
* @param mode The animation mode to use.
* @return True if the text effect was created successfully.
*/
static TextEffectID CreateAtPosition(SQInteger x, SQInteger y, Text *text, ScriptTextEffectMode mode);
/**
* Update animated text
* @param te_id Text effect ID.
* @param text The text to update
* @return True if the text effect was updated successfully
*/
static bool Update(TextEffectID te_id, Text *text);
/**
* Update animated text
* @param te_id Text effect ID.
* @return True if the text effect was removed successfully
*/
static bool Remove(TextEffectID te_id);
};
#endif /* SCRIPT_TEXT_EFFECT_HPP */

View File

@ -31,6 +31,7 @@
#include "../signs_type.h"
#include "../story_type.h"
#include "../misc/endian_buffer.hpp"
#include "../texteff.hpp"
#include "../safeguards.h"
@ -325,6 +326,10 @@ void ScriptInstance::CollectGarbage()
instance.engine->InsertResult(EndianBufferReader::ToValue<LeagueTableID>(ScriptObject::GetLastCommandResData()));
}
/* static */ void ScriptInstance::DoCommandReturnTextEffectID(ScriptInstance *instance)
{
instance->engine->InsertResult(EndianBufferReader::ToValue<TextEffectID>(ScriptObject::GetLastCommandResData()));
}
ScriptStorage &ScriptInstance::GetStorage()
{

View File

@ -143,6 +143,11 @@ public:
*/
static void DoCommandReturnLeagueTableElementID(ScriptInstance &instance);
/**
* Return a TextEffectID reply for a DoCommand.
*/
static void DoCommandReturnTextEffectID(ScriptInstance *instance);
/**
* Get the controller attached to the instance.
*/

View File

@ -36,10 +36,15 @@
# 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 },
{ SPR_AQUEDUCT_RAMP_SW, PAL_NONE }, { SPR_AQUEDUCT_RAMP_SE, PAL_NONE }, { SPR_AQUEDUCT_RAMP_NE, PAL_NONE }, { SPR_AQUEDUCT_RAMP_NW, 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},
};
static const PalSpriteID _bridge_sprite_table_4_0[] = {

View File

@ -0,0 +1,75 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file texteff_cmd.cpp Command handling for text effects */
#include "stdafx.h"
#include "command_func.h"
#include "texteff.hpp"
#include "strings_func.h"
#include "tile_map.h"
#include "texteff_cmd.h"
#include "table/strings.h"
#include "safeguards.h"
#include "landscape.h"
/**
* Show a text effect at the specified location.
* @param flags operation to perform
* @param x X coordinate in the game
* @param y Y coordinate in the game
* @param mode The animation mode to use
* @param text The text to display
* @return the cost of this operation or an error
*/
std::tuple<CommandCost, TextEffectID> CmdCreateTextEffect(DoCommandFlags flags, int32_t x, int32_t y, TextEffectMode mode, const EncodedString &text)
{
if (text.empty()) return { CMD_ERROR, INVALID_TE_ID };
if (mode != TE_RISING && mode != TE_STATIC) return { CMD_ERROR, INVALID_TE_ID };
if (flags.Test(DoCommandFlag::Execute)) {
Point pt = RemapCoords2(x, y);
EncodedString encoded_text = text;
TextEffectID te_id;
if (mode == TE_RISING) {
te_id = AddTextEffect(std::move(encoded_text), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
} else {
te_id = AddTextEffect(std::move(encoded_text), pt.x, pt.y, 0, TE_STATIC);
}
return { CommandCost(), te_id };
}
return { CommandCost(), INVALID_TE_ID };
}
CommandCost CmdUpdateTextEffect(DoCommandFlags flags, TextEffectID te_id, const EncodedString &text)
{
if (te_id == INVALID_TE_ID) return CMD_ERROR;
if (text.empty()) return CMD_ERROR;
if (flags.Test(DoCommandFlag::Execute)) {
EncodedString encoded_text = text;
UpdateTextEffect(te_id, std::move(encoded_text));
}
return CommandCost();
}
CommandCost CmdRemoveTextEffect(DoCommandFlags flags, TextEffectID te_id)
{
if (te_id == INVALID_TE_ID) return CMD_ERROR;
if (flags.Test(DoCommandFlag::Execute)) {
RemoveTextEffect(te_id);
}
return CommandCost();
}

24
src/texteff_cmd.h 100644
View File

@ -0,0 +1,24 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file texteff_cmd.h Command declarations for text effects */
#ifndef TEXTEFF_CMD_H
#define TEXTEFF_CMD_H
#include "command_type.h"
#include "texteff.hpp"
std::tuple<CommandCost, TextEffectID> CmdCreateTextEffect(DoCommandFlags flags, int32_t x, int32_t y, TextEffectMode mode, const EncodedString &text);
CommandCost CmdUpdateTextEffect(DoCommandFlags flags, TextEffectID te_id, const EncodedString &text);
CommandCost CmdRemoveTextEffect(DoCommandFlags flags, TextEffectID te_id);
DEF_CMD_TRAIT(CMD_CREATE_TEXT_EFFECT, CmdCreateTextEffect, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_UPDATE_TEXT_EFFECT, CmdUpdateTextEffect, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT)
DEF_CMD_TRAIT(CMD_REMOVE_TEXT_EFFECT, CmdRemoveTextEffect, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT)
#endif /* TEXTEFF_CMD_H */

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);
}