Merge branch 'master' into jgrpp-nrt

Merge NRT feature

# Conflicts:
#	docs/landscape.html
#	docs/landscape_grid.html
#	src/bridge_map.h
#	src/build_vehicle_gui.cpp
#	src/company_base.h
#	src/company_cmd.cpp
#	src/misc_gui.cpp
#	src/newgrf.cpp
#	src/newgrf_engine.cpp
#	src/pathfinder/follow_track.hpp
#	src/pathfinder/npf/npf.cpp
#	src/road_cmd.cpp
#	src/road_func.h
#	src/road_gui.cpp
#	src/road_map.h
#	src/road_type.h
#	src/roadveh_cmd.cpp
#	src/saveload/afterload.cpp
#	src/saveload/company_sl.cpp
#	src/script/api/script_bridge.cpp
#	src/table/newgrf_debug_data.h
#	src/tile_cmd.h
#	src/town_cmd.cpp
#	src/tunnel_map.h
#	src/tunnelbridge_cmd.cpp
This commit is contained in:
Jonathan G Rennison
2019-07-11 19:45:56 +01:00
177 changed files with 4839 additions and 1461 deletions

View File

@@ -40,6 +40,7 @@
#include "pbs.h"
#include "company_base.h"
#include "newgrf_railtype.h"
#include "newgrf_roadtype.h"
#include "object_base.h"
#include "water.h"
#include "company_gui.h"
@@ -287,7 +288,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
CompanyID company = _current_company;
RailType railtype = INVALID_RAILTYPE;
RoadTypes roadtypes = ROADTYPES_NONE;
RoadType roadtype = INVALID_ROADTYPE;
/* unpack parameters */
BridgeType bridge_type = GB(p2, 0, 8);
@@ -299,8 +300,8 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
/* type of bridge */
switch (transport_type) {
case TRANSPORT_ROAD:
roadtypes = Extract<RoadTypes, 8, 2>(p2);
if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(company, roadtypes)) return CMD_ERROR;
roadtype = Extract<RoadType, 8, 6>(p2);
if (!ValParamRoadType(roadtype)) return CMD_ERROR;
break;
case TRANSPORT_RAIL:
@@ -380,6 +381,15 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
}
/* If this is a road bridge, make sure the roadtype matches. */
if (transport_type == TRANSPORT_ROAD) {
RoadType start_existing_rt = GetRoadType(tile_start, GetRoadTramType(roadtype));
RoadType end_existing_rt = GetRoadType(tile_end, GetRoadTramType(roadtype));
if ((start_existing_rt != roadtype && start_existing_rt != INVALID_ROADTYPE) || (end_existing_rt != roadtype && end_existing_rt != INVALID_ROADTYPE)) {
return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
}
}
/* Do not replace town bridges with lower speed bridges, unless in scenario editor. */
if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed &&
@@ -395,7 +405,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
}
/* Do not replace the bridge with the same bridge type. */
if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || (roadtypes & ~GetRoadTypes(tile_start)) == 0)) {
if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || (GetRoadType(tile_start, GetRoadTramType(roadtype)) == roadtype && GetRoadType(tile_end, GetRoadTramType(roadtype)) == roadtype))) {
return_cmd_error(STR_ERROR_ALREADY_BUILT);
}
@@ -580,21 +590,25 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
case TRANSPORT_ROAD: {
if (is_upgrade) SubtractRoadTunnelBridgeInfrastructure(tile_start, tile_end);
auto make_bridge_ramp = [company, owner, is_upgrade, is_new_owner, bridge_type, roadtypes](TileIndex t, DiagDirection d) {
RoadTypes new_roadtypes = roadtypes | GetRoadTypes(t);
RoadTypes prev_roadtypes = IsBridgeTile(t) ? GetRoadTypes(t) : ROADTYPES_NONE;
auto make_bridge_ramp = [company, owner, is_upgrade, is_new_owner, bridge_type, roadtype](TileIndex t, DiagDirection d) {
RoadType road_rt = is_upgrade ? GetRoadTypeRoad(t) : INVALID_ROADTYPE;
RoadType tram_rt = is_upgrade ? GetRoadTypeTram(t) : INVALID_ROADTYPE;
bool hasroad = road_rt != INVALID_ROADTYPE;
bool hastram = tram_rt != INVALID_ROADTYPE;
if (RoadTypeIsRoad(roadtype)) road_rt = roadtype;
if (RoadTypeIsTram(roadtype)) tram_rt = roadtype;
if (is_new_owner) {
/* Also give unowned present roadtypes to new owner */
if (HasBit(prev_roadtypes, ROADTYPE_ROAD) && GetRoadOwner(t, ROADTYPE_ROAD) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_ROAD);
if (HasBit(prev_roadtypes, ROADTYPE_TRAM) && GetRoadOwner(t, ROADTYPE_TRAM) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_TRAM);
if (hasroad && GetRoadOwner(t, RTT_ROAD) == OWNER_NONE) hasroad = false;
if (hastram && GetRoadOwner(t, RTT_TRAM) == OWNER_NONE) hastram = false;
}
Owner owner_road = HasBit(prev_roadtypes, ROADTYPE_ROAD) ? GetRoadOwner(t, ROADTYPE_ROAD) : company;
Owner owner_tram = HasBit(prev_roadtypes, ROADTYPE_TRAM) ? GetRoadOwner(t, ROADTYPE_TRAM) : company;
MakeRoadBridgeRamp(t, owner, owner_road, owner_tram, bridge_type, d, new_roadtypes, is_upgrade);
Owner owner_road = hasroad ? GetRoadOwner(t, RTT_ROAD) : company;
Owner owner_tram = hastram ? GetRoadOwner(t, RTT_TRAM) : company;
MakeRoadBridgeRamp(t, owner, owner_road, owner_tram, bridge_type, d, road_rt, tram_rt, is_upgrade);
if (is_upgrade) {
if (HasBit(roadtypes, ROADTYPE_ROAD)) SetCustomBridgeHeadRoadBits(t, ROADTYPE_ROAD, GetCustomBridgeHeadRoadBits(t, ROADTYPE_ROAD) | DiagDirToRoadBits(d));
if (HasBit(roadtypes, ROADTYPE_TRAM)) SetCustomBridgeHeadRoadBits(t, ROADTYPE_TRAM, GetCustomBridgeHeadRoadBits(t, ROADTYPE_TRAM) | DiagDirToRoadBits(d));
if (road_rt != INVALID_ROADTYPE) SetCustomBridgeHeadRoadBits(t, RTT_ROAD, GetCustomBridgeHeadRoadBits(t, RTT_ROAD) | DiagDirToRoadBits(d));
if (tram_rt != INVALID_ROADTYPE) SetCustomBridgeHeadRoadBits(t, RTT_TRAM, GetCustomBridgeHeadRoadBits(t, RTT_TRAM) | DiagDirToRoadBits(d));
}
};
make_bridge_ramp(tile_start, dir);
@@ -603,8 +617,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
if (IsRoadCustomBridgeHead(tile_start) || IsRoadCustomBridgeHead(tile_end)) {
NotifyRoadLayoutChanged();
} else {
if (HasBit(roadtypes, ROADTYPE_ROAD)) NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile_start, tile_end, dir, ROADTYPE_ROAD);
if (HasBit(roadtypes, ROADTYPE_TRAM)) NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile_start, tile_end, dir, ROADTYPE_TRAM);
NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile_start, tile_end, dir, GetRoadTramType(roadtype));
}
break;
}
@@ -639,7 +652,14 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
bridge_len += 2; // begin and end tiles/ramps
switch (transport_type) {
case TRANSPORT_ROAD: cost.AddCost(bridge_len * _price[PR_BUILD_ROAD] * 2 * CountBits(roadtypes)); break;
case TRANSPORT_ROAD: {
cost.AddCost(bridge_len * 2 * RoadBuildCost(roadtype));
if (is_upgrade && DiagDirToRoadBits(GetTunnelBridgeDirection(tile_start)) & GetCustomBridgeHeadRoadBits(tile_start, OtherRoadTramType(GetRoadTramType(roadtype)))) {
cost.AddCost(bridge_len * 2 * RoadBuildCost(GetRoadType(tile_start, OtherRoadTramType(GetRoadTramType(roadtype)))));
}
break;
}
case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
default: break;
}
@@ -762,7 +782,7 @@ static inline CommandCost CanBuildChunnel(TileIndex tile, DiagDirection directio
* Build Tunnel.
* @param start_tile start tile of tunnel
* @param flags type of operation
* @param p1 bit 0-5 railtype or roadtypes
* @param p1 bit 0-5 railtype or roadtype
* bit 8-9 transport type
* @param p2 unused
* @param text unused
@@ -773,9 +793,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
CompanyID company = _current_company;
TransportType transport_type = Extract<TransportType, 8, 2>(p1);
RailType railtype = INVALID_RAILTYPE;
RoadTypes rts = ROADTYPES_NONE;
RoadType roadtype = INVALID_ROADTYPE;
_build_tunnel_endtile = 0;
switch (transport_type) {
case TRANSPORT_RAIL:
@@ -784,8 +803,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
break;
case TRANSPORT_ROAD:
rts = Extract<RoadTypes, 0, 2>(p1);
if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(company, rts)) return CMD_ERROR;
roadtype = Extract<RoadType, 0, 6>(p1);
if (!ValParamRoadType(roadtype)) return CMD_ERROR;
break;
default: return CMD_ERROR;
@@ -927,7 +946,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
/* Pay for the rail/road in the tunnel including entrances */
switch (transport_type) {
case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * _price[PR_BUILD_ROAD] * 2); break;
case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * RoadBuildCost(roadtype) * 2); break;
case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
default: NOT_REACHED();
}
@@ -953,15 +972,12 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company);
YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
} else {
if (c != nullptr) {
RoadType rt;
FOR_EACH_SET_ROADTYPE(rt, rts ^ (IsTunnelTile(start_tile) ? GetRoadTypes(start_tile) : ROADTYPES_NONE)) {
c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits.
NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(start_tile, end_tile, direction, rt);
}
}
MakeRoadTunnel(start_tile, company, t->index, direction, rts);
MakeRoadTunnel(end_tile, company, t->index, ReverseDiagDir(direction), rts);
if (c != nullptr) c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits.
NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(start_tile, end_tile, direction, GetRoadTramType(roadtype));
RoadType road_rt = RoadTypeIsRoad(roadtype) ? roadtype : INVALID_ROADTYPE;
RoadType tram_rt = RoadTypeIsTram(roadtype) ? roadtype : INVALID_ROADTYPE;
MakeRoadTunnel(start_tile, company, t->index, direction, road_rt, tram_rt);
MakeRoadTunnel(end_tile, company, t->index, ReverseDiagDir(direction), road_rt, tram_rt);
}
DirtyCompanyInfrastructureWindows(company);
}
@@ -982,12 +998,13 @@ static inline CommandCost CheckAllowRemoveTunnelBridge(TileIndex tile)
switch (GetTunnelBridgeTransportType(tile)) {
case TRANSPORT_ROAD: {
RoadTypes rts = GetRoadTypes(tile);
RoadType road_rt = GetRoadTypeRoad(tile);
RoadType tram_rt = GetRoadTypeTram(tile);
Owner road_owner = _current_company;
Owner tram_owner = _current_company;
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
if (road_rt != INVALID_ROADTYPE) road_owner = GetRoadOwner(tile, RTT_ROAD);
if (tram_rt != INVALID_ROADTYPE) tram_owner = GetRoadOwner(tile, RTT_TRAM);
/* We can remove unowned road and if the town allows it */
if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) {
@@ -1089,16 +1106,11 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
if (v != nullptr) TryPathReserve(v);
} else {
RoadType rt;
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
/* A full diagonal road tile has two road bits. */
Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
if (c != nullptr) {
c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
DirtyCompanyInfrastructureWindows(c->index);
}
NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, GetTunnelBridgeDirection(tile), rt);
}
/* A full diagonal road tile has two road bits. */
UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, GetTunnelBridgeDirection(tile), RTT_ROAD);
NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, GetTunnelBridgeDirection(tile), RTT_TRAM);
delete Tunnel::GetByTile(tile);
@@ -1196,9 +1208,8 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
if (IsRoadCustomBridgeHead(tile) || IsRoadCustomBridgeHead(endtile)) {
NotifyRoadLayoutChanged();
} else {
RoadTypes roadtypes = GetRoadTypes(tile);
if (HasBit(roadtypes, ROADTYPE_ROAD)) NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, direction, ROADTYPE_ROAD);
if (HasBit(roadtypes, ROADTYPE_TRAM)) NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, direction, ROADTYPE_TRAM);
if (HasRoadTypeRoad(tile)) NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, direction, RTT_ROAD);
if (HasRoadTypeTram(tile)) NotifyRoadLayoutChangedIfSimpleTunnelBridgeNonLeaf(tile, endtile, direction, RTT_TRAM);
}
} else { // Aqueduct
if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
@@ -1358,19 +1369,95 @@ static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis
}
/**
* Draws the trambits over an already drawn (lower end) of a bridge.
* @param x the x of the bridge
* @param y the y of the bridge
* @param z the z of the bridge
* @param offset number representing whether to level or sloped and the direction
* @param overlay do we want to still see the road?
* @param head are we drawing bridge head?
* Draws the road and trambits over an already drawn (lower end) of a bridge.
* @param head_tile bridge head tile with roadtype information
* @param x the x of the bridge
* @param y the y of the bridge
* @param z the z of the bridge
* @param offset sprite offset identifying flat to sloped bridge tiles
* @param head are we drawing bridge head?
*/
static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head)
static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head)
{
static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
RoadType road_rt = GetRoadTypeRoad(head_tile);
RoadType tram_rt = GetRoadTypeTram(head_tile);
if (IsRoadCustomBridgeHeadTile(head_tile)) {
RoadBits entrance_bit = DiagDirToRoadBits(GetTunnelBridgeDirection(head_tile));
if (road_rt != INVALID_ROADTYPE && !(GetCustomBridgeHeadRoadBits(head_tile, RTT_ROAD) & entrance_bit)) road_rt = INVALID_ROADTYPE;
if (tram_rt != INVALID_ROADTYPE && !(GetCustomBridgeHeadRoadBits(head_tile, RTT_TRAM) & entrance_bit)) tram_rt = INVALID_ROADTYPE;
}
const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
SpriteID seq_back[4] = { 0 };
bool trans_back[4] = { false };
SpriteID seq_front[4] = { 0 };
bool trans_front[4] = { false };
static const SpriteID overlay_offsets[6] = { 0, 1, 11, 12, 13, 14 };
static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
if (head || !IsInvisibilitySet(TO_BRIDGES)) {
/* Road underlay takes precendence over tram */
trans_back[0] = !head && IsTransparencySet(TO_BRIDGES);
if (road_rti != nullptr) {
if (road_rti->UsesOverlay()) {
seq_back[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
}
} else if (tram_rti != nullptr) {
if (tram_rti->UsesOverlay()) {
seq_back[0] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
} else {
seq_back[0] = SPR_TRAMWAY_BRIDGE + offset;
}
}
/* Draw road overlay */
trans_back[1] = !head && IsTransparencySet(TO_BRIDGES);
if (road_rti != nullptr) {
if (road_rti->UsesOverlay()) {
seq_back[1] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
if (seq_back[1] != 0) seq_back[1] += overlay_offsets[offset];
}
}
/* Draw tram overlay */
trans_back[2] = !head && IsTransparencySet(TO_BRIDGES);
if (tram_rti != nullptr) {
if (tram_rti->UsesOverlay()) {
seq_back[2] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
if (seq_back[2] != 0) seq_back[2] += overlay_offsets[offset];
} else if (road_rti != nullptr) {
seq_back[2] = SPR_TRAMWAY_OVERLAY + overlay_offsets[offset];
}
}
/* Road catenary takes precendence over tram */
trans_back[3] = IsTransparencySet(TO_CATENARY);
trans_front[0] = IsTransparencySet(TO_CATENARY);
if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
seq_back[3] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_CATENARY_BACK, head ? TCX_NORMAL : TCX_ON_BRIDGE);
seq_front[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_CATENARY_FRONT, head ? TCX_NORMAL : TCX_ON_BRIDGE);
if (seq_back[3] == 0 || seq_front[0] == 0) {
seq_back[3] = SPR_TRAMWAY_BASE + back_offsets[offset];
seq_front[0] = SPR_TRAMWAY_BASE + front_offsets[offset];
} else {
seq_back[3] += 23 + offset;
seq_front[0] += 23 + offset;
}
} else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
seq_back[3] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_CATENARY_BACK, head ? TCX_NORMAL : TCX_ON_BRIDGE);
seq_front[0] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_CATENARY_FRONT, head ? TCX_NORMAL : TCX_ON_BRIDGE);
if (seq_back[3] == 0 || seq_front[0] == 0) {
seq_back[3] = SPR_TRAMWAY_BASE + back_offsets[offset];
seq_front[0] = SPR_TRAMWAY_BASE + front_offsets[offset];
} else {
seq_back[3] += 23 + offset;
seq_front[0] += 23 + offset;
}
}
}
static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
@@ -1379,28 +1466,25 @@ static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bo
/* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
* The bounding boxes here are the same as for bridge front/roof */
if (head || !IsInvisibilitySet(TO_BRIDGES)) {
AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
x, y, size_x[offset], size_y[offset], 0x28, z,
!head && IsTransparencySet(TO_BRIDGES));
}
/* Do not draw catenary if it is set invisible */
if (!IsInvisibilitySet(TO_CATENARY)) {
AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE,
x, y, size_x[offset], size_y[offset], 0x28, z,
IsTransparencySet(TO_CATENARY));
for (uint i = 0; i < lengthof(seq_back); ++i) {
if (seq_back[i] != 0) {
AddSortableSpriteToDraw(seq_back[i], PAL_NONE,
x, y, size_x[offset], size_y[offset], 0x28, z,
trans_back[i]);
}
}
/* Start a new SpriteCombine for the front part */
EndSpriteCombine();
StartSpriteCombine();
/* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
if (!IsInvisibilitySet(TO_CATENARY)) {
AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE,
x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
for (uint i = 0; i < lengthof(seq_front); ++i) {
if (seq_front[i] != 0) {
AddSortableSpriteToDraw(seq_front[i], PAL_NONE,
x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
trans_front[i],
front_bb_offset_x[offset], front_bb_offset_y[offset]);
}
}
}
@@ -1586,19 +1670,36 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
DrawGroundSprite(image, PAL_NONE);
if (transport_type == TRANSPORT_ROAD) {
RoadTypes rts = GetRoadTypes(ti->tile);
RoadType road_rt = GetRoadTypeRoad(ti->tile);
RoadType tram_rt = GetRoadTypeTram(ti->tile);
const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
uint sprite_offset = DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? 1 : 0;
if (HasBit(rts, ROADTYPE_TRAM)) {
static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } };
DrawRoadOverlays(ti, PAL_NONE, road_rti, tram_rti, sprite_offset, sprite_offset);
DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE);
/* Do not draw wires if they are invisible */
if (!IsInvisibilitySet(TO_CATENARY)) {
catenary = true;
StartSpriteCombine();
AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
/* Road catenary takes precendence over tram */
SpriteID catenary_sprite_base = 0;
if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
catenary_sprite_base = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_CATENARY_FRONT);
if (catenary_sprite_base == 0) {
catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
} else {
catenary_sprite_base += 19;
}
} else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
catenary_sprite_base = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_CATENARY_FRONT);
if (catenary_sprite_base == 0) {
catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
} else {
catenary_sprite_base += 19;
}
}
if (catenary_sprite_base != 0) {
catenary = true;
StartSpriteCombine();
AddSortableSpriteToDraw(catenary_sprite_base + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
}
} else {
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
@@ -1747,20 +1848,18 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
if (transport_type == TRANSPORT_ROAD) {
RoadTypes rts = GetRoadTypes(ti->tile);
if (HasBit(rts, ROADTYPE_TRAM)) {
uint offset = tunnelbridge_direction;
int z = ti->z;
if (ti->tileh != SLOPE_FLAT) {
offset = (offset + 1) & 1;
z += TILE_HEIGHT;
} else {
offset += 2;
}
/* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
uint offset = tunnelbridge_direction;
int z = ti->z;
if (ti->tileh != SLOPE_FLAT) {
offset = (offset + 1) & 1;
z += TILE_HEIGHT;
} else {
offset += 2;
}
/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
DrawBridgeRoadBits(ti->tile, ti->x, ti->y, z, offset, true);
EndSpriteCombine();
} else if (transport_type == TRANSPORT_RAIL) {
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
@@ -1949,23 +2048,8 @@ void DrawBridgeMiddle(const TileInfo *ti)
psid++;
if (transport_type == TRANSPORT_ROAD) {
const RoadTypes rts = GetRoadTypes(rampsouth);
bool has_tram = HasBit(rts, ROADTYPE_TRAM);
bool has_road = HasBit(rts, ROADTYPE_ROAD);
if (IsRoadCustomBridgeHeadTile(rampsouth)) {
RoadBits entrance_bit = DiagDirToRoadBits(GetTunnelBridgeDirection(rampsouth));
has_tram = has_tram && (GetCustomBridgeHeadRoadBits(rampsouth, ROADTYPE_TRAM) & entrance_bit);
has_road = has_road && (GetCustomBridgeHeadRoadBits(rampsouth, ROADTYPE_ROAD) & entrance_bit);
}
if (has_tram) {
/* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, has_road, false);
} else {
EndSpriteCombine();
StartSpriteCombine();
}
/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false);
} else if (transport_type == TRANSPORT_RAIL) {
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
@@ -2097,9 +2181,20 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
Owner road_owner = INVALID_OWNER;
Owner tram_owner = INVALID_OWNER;
RoadTypes rts = GetRoadTypes(tile);
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
RoadType road_rt = GetRoadTypeRoad(tile);
RoadType tram_rt = GetRoadTypeTram(tile);
if (road_rt != INVALID_ROADTYPE) {
const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
td->roadtype = rti->strings.name;
td->road_speed = rti->max_speed / 2;
road_owner = GetRoadOwner(tile, RTT_ROAD);
}
if (tram_rt != INVALID_ROADTYPE) {
const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
td->tramtype = rti->strings.name;
td->tram_speed = rti->max_speed / 2;
tram_owner = GetRoadOwner(tile, RTT_TRAM);
}
/* Is there a mix of owners? */
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
@@ -2135,7 +2230,9 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
}
}
} else if (tt == TRANSPORT_ROAD && !IsTunnel(tile)) {
td->road_speed = GetBridgeSpec(GetBridgeType(tile))->speed;
uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
if (road_rt != INVALID_ROADTYPE && (td->road_speed == 0 || spd < td->road_speed)) td->road_speed = spd;
if (tram_rt != INVALID_ROADTYPE && (td->tram_speed == 0 || spd < td->tram_speed)) td->tram_speed = spd;
}
}
@@ -2193,15 +2290,13 @@ extern const TrackBits _road_trackbits[16];
static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
{
TransportType transport_type = GetTunnelBridgeTransportType(tile);
if (transport_type != mode || (transport_type == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0)) return 0;
if (transport_type != mode || (transport_type == TRANSPORT_ROAD && !HasTileRoadType(tile, (RoadTramType)sub_mode))) return 0;
DiagDirection dir = GetTunnelBridgeDirection(tile);
if (side != INVALID_DIAGDIR && side == dir) return 0;
if (mode == TRANSPORT_ROAD && IsRoadCustomBridgeHeadTile(tile)) {
TrackBits bits = TRACK_BIT_NONE;
if (sub_mode & ROADTYPES_TRAM) bits |= _road_trackbits[GetCustomBridgeHeadRoadBits(tile, ROADTYPE_TRAM)];
if (sub_mode & ROADTYPES_ROAD) bits |= _road_trackbits[GetCustomBridgeHeadRoadBits(tile, ROADTYPE_ROAD)];
TrackBits bits = _road_trackbits[GetCustomBridgeHeadRoadBits(tile, (RoadTramType)sub_mode)];
return CombineTrackStatus(TrackBitsToTrackdirBits(bits), TRACKDIR_BIT_NONE);
}
return CombineTrackStatus(TrackBitsToTrackdirBits(mode == TRANSPORT_RAIL ? GetTunnelBridgeTrackBits(tile) : DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
@@ -2212,14 +2307,14 @@ static void UpdateRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end,
const uint middle_len = 2 * GetTunnelBridgeLength(begin, end) * TUNNELBRIDGE_TRACKBIT_FACTOR;
const uint len = middle_len + (4 * TUNNELBRIDGE_TRACKBIT_FACTOR);
/* Iterate all present road types as each can have a different owner. */
RoadType rt;
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(begin)) {
Company * const c = Company::GetIfValid(GetRoadOwner(begin, rt));
FOR_ALL_ROADTRAMTYPES(rtt) {
RoadType rt = GetRoadType(begin, rtt);
if (rt == INVALID_ROADTYPE) continue;
Company * const c = Company::GetIfValid(GetRoadOwner(begin, rtt));
if (c != nullptr) {
uint infra = 0;
if (IsBridge(begin)) {
const RoadBits bits = GetCustomBridgeHeadRoadBits(begin, rt);
const RoadBits bits = GetCustomBridgeHeadRoadBits(begin, rtt);
infra += CountBits(bits) * TUNNELBRIDGE_TRACKBIT_FACTOR;
if (bits & DiagDirToRoadBits(GetTunnelBridgeDirection(begin))) {
infra += middle_len;
@@ -2234,12 +2329,14 @@ static void UpdateRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end,
}
}
}
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(end)) {
Company * const c = Company::GetIfValid(GetRoadOwner(end, rt));
FOR_ALL_ROADTRAMTYPES(rtt) {
RoadType rt = GetRoadType(end, rtt);
if (rt == INVALID_ROADTYPE) continue;
Company * const c = Company::GetIfValid(GetRoadOwner(end, rtt));
if (c != nullptr) {
uint infra = 0;
if (IsBridge(end)) {
const RoadBits bits = GetCustomBridgeHeadRoadBits(end, rt);
const RoadBits bits = GetCustomBridgeHeadRoadBits(end, rtt);
infra += CountBits(bits) * TUNNELBRIDGE_TRACKBIT_FACTOR;
}
if (add) {
@@ -2318,13 +2415,13 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner
/* Only execute this for one of the two ends */
SubtractRoadTunnelBridgeInfrastructure(tile, other_end);
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
FOR_ALL_ROADTRAMTYPES(rtt) {
/* Update all roadtypes, no matter if they are present */
if (GetRoadOwner(tile, rt) == old_owner) {
SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
if (GetRoadOwner(tile, rtt) == old_owner) {
SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
}
if (GetRoadOwner(other_end, rt) == old_owner) {
SetRoadOwner(other_end, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
if (GetRoadOwner(other_end, rtt) == old_owner) {
SetRoadOwner(other_end, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
}
}
@@ -2497,8 +2594,8 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
RoadVehicle *rv = RoadVehicle::From(v);
if (IsRoadCustomBridgeHeadTile(tile)) {
RoadBits bits = ROAD_NONE;
if (rv->compatible_roadtypes & ROADTYPES_TRAM) bits |= GetCustomBridgeHeadRoadBits(tile, ROADTYPE_TRAM);
if (rv->compatible_roadtypes & ROADTYPES_ROAD) bits |= GetCustomBridgeHeadRoadBits(tile, ROADTYPE_ROAD);
if (HasRoadTypeRoad(tile) && rv->compatible_roadtypes & GetRoadTypeRoad(tile)) bits |= GetCustomBridgeHeadRoadBits(tile, RTT_ROAD);
if (HasRoadTypeTram(tile) && rv->compatible_roadtypes & GetRoadTypeTram(tile)) bits |= GetCustomBridgeHeadRoadBits(tile, RTT_TRAM);
if (!(bits & DiagDirToRoadBits(GetTunnelBridgeDirection(tile)))) return VETSB_CONTINUE;
}
rv->cur_image_valid_dir = INVALID_DIR;