--- a/src/rail_cmd.cpp Fri Nov 23 16:59:30 2007 +0000
+++ b/src/rail_cmd.cpp Wed Jan 09 18:11:12 2008 +0000
@@ -8,30 +8,25 @@
#include "bridge.h"
#include "cmd_helper.h"
#include "debug.h"
-#include "functions.h"
+#include "tile_cmd.h"
#include "rail_map.h"
#include "road_map.h"
#include "table/sprites.h"
#include "table/strings.h"
-#include "map.h"
#include "landscape.h"
-#include "tile.h"
#include "town_map.h"
#include "tunnel_map.h"
-#include "vehicle.h"
-#include "viewport.h"
-#include "command.h"
+#include "viewport_func.h"
+#include "command_func.h"
#include "pathfind.h"
#include "engine.h"
#include "town.h"
-#include "sound.h"
#include "station.h"
#include "sprite.h"
#include "depot.h"
#include "waypoint.h"
-#include "window.h"
#include "rail.h"
-#include "railtypes.h" // include table for railtypes
+#include "table/railtypes.h" // include table for railtypes
#include "newgrf.h"
#include "yapf/yapf.h"
#include "newgrf_engine.h"
@@ -39,8 +34,15 @@
#include "newgrf_station.h"
#include "train.h"
#include "misc/autoptr.hpp"
+#include "variables.h"
#include "autoslope.h"
#include "transparency.h"
+#include "water.h"
+#include "tunnelbridge_map.h"
+#include "window_func.h"
+#include "vehicle_func.h"
+#include "sound_func.h"
+
const byte _track_sloped_sprites[14] = {
14, 15, 22, 13,
@@ -81,21 +83,14 @@
* 11uuuudd => rail depot
*/
-/** Struct used in EnsureNoTrainOnTrack() */
-struct TrainOnTrackData {
- TileIndex tile; ///< tile to check
- uint z; ///< tile max Z
- TrackBits rail_bits; ///< trackbits of interest
-};
static void *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
{
- const TrainOnTrackData *info = (const TrainOnTrackData *)data;
-
- if (v->tile != info->tile || v->type != VEH_TRAIN) return NULL;
- if (v->z_pos > info->z) return NULL;
-
- if ((v->u.rail.track != info->rail_bits) && !TracksOverlap(v->u.rail.track | info->rail_bits)) return NULL;
+ TrackBits rail_bits = *(TrackBits *)data;
+
+ if (v->type != VEH_TRAIN) return NULL;
+
+ if ((v->u.rail.track != rail_bits) && !TracksOverlap(v->u.rail.track | rail_bits)) return NULL;
_error_message = VehicleInTheWayErrMsg(v);
return v;
@@ -110,13 +105,9 @@
*/
static bool EnsureNoTrainOnTrack(TileIndex tile, Track track)
{
- TrainOnTrackData info;
-
- info.tile = tile;
- info.z = GetTileMaxZ(tile);
- info.rail_bits = TrackToTrackBits(track);
-
- return VehicleFromPos(tile, &info, EnsureNoTrainOnTrackProc) == NULL;
+ TrackBits rail_bits = TrackToTrackBits(track);
+
+ return VehicleFromPos(tile, &rail_bits, &EnsureNoTrainOnTrackProc) == NULL;
}
static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
@@ -297,7 +288,7 @@
) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
Foundation f_old = GetRailFoundation(tileh, existing);
- return CommandCost(f_new != f_old ? _price.terraform : (Money)0);
+ return CommandCost(EXPENSES_CONSTRUCTION, f_new != f_old ? _price.terraform : (Money)0);
}
/* Validate functions for rail building */
@@ -315,7 +306,7 @@
RailType railtype;
Track track;
TrackBits trackbit;
- CommandCost cost;
+ CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost ret;
if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
@@ -325,8 +316,6 @@
tileh = GetTileSlope(tile, NULL);
trackbit = TrackToTrackBits(track);
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
switch (GetTileType(tile)) {
case MP_RAILWAY:
if (!CheckTrackCombination(tile, trackbit, flags) ||
@@ -418,7 +407,7 @@
if (water_ground) {
cost.AddCost(-_price.clear_water);
- cost.AddCost(_price.purchase_land);
+ cost.AddCost(_price.clear_roughland);
}
if (flags & DC_EXEC) {
@@ -447,14 +436,12 @@
{
Track track = (Track)p2;
TrackBits trackbit;
- CommandCost cost(_price.remove_rail);
+ CommandCost cost(EXPENSES_CONSTRUCTION, _price.remove_rail );
bool crossing = false;
if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
trackbit = TrackToTrackBits(track);
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
switch (GetTileType(tile)) {
case MP_ROAD: {
if (!IsLevelCrossing(tile) ||
@@ -633,7 +620,7 @@
*/
static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- CommandCost ret, total_cost;
+ CommandCost ret, total_cost(EXPENSES_CONSTRUCTION);
Track track = (Track)GB(p2, 4, 3);
Trackdir trackdir;
byte mode = HasBit(p2, 7);
@@ -645,8 +632,6 @@
end_tile = p1;
trackdir = TrackToTrackdir(track);
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile);
@@ -715,11 +700,8 @@
*/
CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- CommandCost cost;
Slope tileh;
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
/* check railtype and valid direction for depot (0 through 3), 4 in total */
if (!ValParamRailtype(p1)) return CMD_ERROR;
@@ -743,7 +725,7 @@
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
}
- cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+ CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(cost)) return CMD_ERROR;
if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
@@ -774,16 +756,20 @@
* @param flags operation to perform
* @param p1 various bitstuffed elements
* - p1 = (bit 0-2) - track-orientation, valid values: 0-5 (Track enum)
- * - p1 = (bit 3) - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
+ * - p1 = (bit 3) - 1 = override signal/semaphore, or pre/exit/combo signal or (for bit 7) toggle variant (CTRL-toggle)
* - p1 = (bit 4) - 0 = signals, 1 = semaphores
+ * - p1 = (bit 5-6) - type of the signal, for valid values see enum SignalType in rail_map.h
+ * - p1 = (bit 7) - convert the present signal type and variant
* @param p2 used for CmdBuildManySignals() to copy direction of first signal
* TODO: p2 should be replaced by two bits for "along" and "against" the track.
*/
CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
Track track = (Track)GB(p1, 0, 3);
- bool pre_signal = HasBit(p1, 3);
- SignalVariant sigvar = (pre_signal ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC;
+ bool ctrl_pressed = HasBit(p1, 3); // was the CTRL button pressed
+ SignalVariant sigvar = (ctrl_pressed ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; // the signal variant of the new signal
+ SignalType sigtype = (SignalType)GB(p1, 5, 2); // the signal type of the new signal
+ bool convert_signal = HasBit(p1, 7); // convert button pressed
CommandCost cost;
if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track))
@@ -797,27 +783,37 @@
if (!CheckTileOwnership(tile)) return CMD_ERROR;
- _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
-
{
/* See if this is a valid track combination for signals, (ie, no overlap) */
TrackBits trackbits = GetTrackBits(tile);
if (KillFirstBit(trackbits) != TRACK_BIT_NONE && /* More than one track present */
trackbits != TRACK_BIT_HORZ &&
trackbits != TRACK_BIT_VERT) {
- return CMD_ERROR;
+ return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
}
}
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
+ /* you can not convert a signal if no signal is on track */
+ if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR;
if (!HasSignalOnTrack(tile, track)) {
/* build new signals */
- cost = CommandCost(_price.build_signals);
+ cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals);
} else {
if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) {
/* convert signals <-> semaphores */
- cost = CommandCost(_price.build_signals + _price.remove_signals);
+ cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals);
+
+ } else if (convert_signal) {
+ /* convert button pressed */
+ if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) {
+ /* convert electric <-> semaphore */
+ cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals);
+ } else {
+ /* it is free to change signal type: normal-pre-exit-combo */
+ cost = CommandCost();
+ }
+
} else {
/* it is free to change orientation/pre-exit-combo signals */
cost = CommandCost();
@@ -830,7 +826,7 @@
SetHasSignals(tile, true);
SetSignalStates(tile, 0xF); // all signals are on
SetPresentSignals(tile, 0); // no signals built by default
- SetSignalType(tile, track, SIGTYPE_NORMAL);
+ SetSignalType(tile, track, sigtype);
SetSignalVariant(tile, track, sigvar);
}
@@ -838,15 +834,28 @@
if (!HasSignalOnTrack(tile, track)) {
/* build new signals */
SetPresentSignals(tile, GetPresentSignals(tile) | SignalOnTrack(track));
- SetSignalType(tile, track, SIGTYPE_NORMAL);
+ SetSignalType(tile, track, sigtype);
SetSignalVariant(tile, track, sigvar);
} else {
- if (pre_signal) {
+ if (convert_signal) {
+ /* convert signal button pressed */
+ if (ctrl_pressed) {
+ /* toggle the pressent signal variant: SIG_ELECTRIC <-> SIG_SEMAPHORE */
+ SetSignalVariant(tile, track, (GetSignalVariant(tile, track) == SIG_ELECTRIC) ? SIG_SEMAPHORE : SIG_ELECTRIC);
+
+ } else {
+ /* convert the present signal to the chosen type and variant */
+ SetSignalType(tile, track, sigtype);
+ SetSignalVariant(tile, track, sigvar);
+ }
+
+ } else if (ctrl_pressed) {
/* cycle between normal -> pre -> exit -> combo -> ... */
- SignalType type = GetSignalType(tile, track);
-
- SetSignalType(tile, track, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
+ sigtype = GetSignalType(tile, track);
+
+ SetSignalType(tile, track, sigtype == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(sigtype + 1));
} else {
+ /* cycle the signal side: both -> left -> right -> both -> ... */
CycleSignalSide(tile, track);
}
}
@@ -904,17 +913,15 @@
return true;
case MP_TUNNELBRIDGE: {
- TileIndex orig_tile = tile;
- /* Skip to end of tunnel or bridge */
- if (IsBridge(tile)) {
- if (GetBridgeTransportType(tile) != TRANSPORT_RAIL) return false;
- if (GetBridgeRampDirection(tile) != TrackdirToExitdir(trackdir)) return false;
- tile = GetOtherBridgeEnd(tile);
- } else {
- if (GetTunnelTransportType(tile) != TRANSPORT_RAIL) return false;
- if (GetTunnelDirection(tile) != TrackdirToExitdir(trackdir)) return false;
- tile = GetOtherTunnelEnd(tile);
- }
+ TileIndex orig_tile = tile; // backup old value
+
+ if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return false;
+ if (GetTunnelBridgeDirection(tile) != TrackdirToExitdir(trackdir)) return false;
+
+ /* Skip to end of tunnel or bridge
+ * note that tile is a parameter by reference, so it must be updated */
+ tile = GetOtherTunnelBridgeEnd(tile);
+
signal_ctr += 2 + DistanceMax(orig_tile, tile) * 2;
return true;
}
@@ -937,7 +944,7 @@
*/
static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- CommandCost ret, total_cost;
+ CommandCost ret, total_cost(EXPENSES_CONSTRUCTION);
int signal_ctr;
byte signals;
bool error = true;
@@ -958,8 +965,6 @@
if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR;
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
/* for vertical/horizontal tracks, double the given signals density
* since the original amount will be too dense (shorter tracks) */
signal_density *= 2;
@@ -1082,8 +1087,6 @@
/* Only water can remove signals from anyone */
if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR;
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
/* Do it? */
if (flags & DC_EXEC) {
SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
@@ -1101,7 +1104,7 @@
MarkTileDirtyByTile(tile);
}
- return CommandCost(_price.remove_signals);
+ return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_signals);
}
/** Remove signals on a stretch of track.
@@ -1123,13 +1126,12 @@
return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5)); // bit 5 is remove bit
}
-typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
-
+/** Update power of train under which is the railtype being converted */
void *UpdateTrainPowerProc(Vehicle *v, void *data)
{
/* Similiar checks as in TrainPowerChanged() */
- if (v->type == VEH_TRAIN && v->tile == *(TileIndex*)data && !IsArticulatedPart(v)) {
+ if (v->type == VEH_TRAIN && !IsArticulatedPart(v)) {
const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First());
}
@@ -1137,46 +1139,6 @@
return NULL;
}
-/**
- * Switches the rail type.
- * Railtypes are stored on a per-tile basis, not on a per-track basis, so
- * all the tracks in the given tile will be converted.
- * @param tile The tile on which the railtype is to be convert.
- * @param totype The railtype we want to convert to
- * @param exec Switches between test and execute mode
- * @return The cost and state of the operation
- * @retval CMD_ERROR An error occured during the operation.
- */
-static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec)
-{
- /* change type. */
- if (exec) {
- SetRailType(tile, totype);
- MarkTileDirtyByTile(tile);
-
- /* notify YAPF about the track layout change */
- TrackBits tracks = GetTrackBits(tile);
- while (tracks != TRACK_BIT_NONE) {
- YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
- }
-
- if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
- /* Update build vehicle window related to this depot */
- InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
- InvalidateWindowData(WC_BUILD_VEHICLE, tile);
- }
-
- /* update power of train engines on this tile */
- VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
- }
-
- return CommandCost(RailBuildCost(totype) / 2);
-}
-
-extern CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec);
-extern CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec);
-extern CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec);
-
/** Convert one rail type to the other. You can convert normal rail to
* monorail/maglev easily or vice-versa.
* @param tile end tile of rail conversion drag
@@ -1186,72 +1148,152 @@
*/
CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- CommandCost ret, cost;
- Money money;
- int ex;
- int ey;
- int sx, sy, x, y;
-
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
+ CommandCost cost(EXPENSES_CONSTRUCTION);
if (!ValParamRailtype(p2)) return CMD_ERROR;
if (p1 >= MapSize()) return CMD_ERROR;
+ RailType totype = (RailType)p2;
+
+ uint ex = TileX(tile);
+ uint ey = TileY(tile);
+ uint sx = TileX(p1);
+ uint sy = TileY(p1);
+
/* make sure sx,sy are smaller than ex,ey */
- ex = TileX(tile);
- ey = TileY(tile);
- sx = TileX(p1);
- sy = TileY(p1);
if (ex < sx) Swap(ex, sx);
if (ey < sy) Swap(ey, sy);
- money = GetAvailableMoneyForCommand();
-
- for (x = sx; x <= ex; ++x) {
- for (y = sy; y <= ey; ++y) {
+ _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert
+
+ for (uint x = sx; x <= ex; ++x) {
+ for (uint y = sy; y <= ey; ++y) {
TileIndex tile = TileXY(x, y);
- DoConvertRailProc *proc;
- RailType totype = (RailType)p2;
-
- switch (GetTileType(tile)) {
- case MP_RAILWAY: proc = DoConvertRail; break;
- case MP_STATION: proc = DoConvertStationRail; break;
- case MP_ROAD: proc = DoConvertStreetRail; break;
- case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break;
+ TileType tt = GetTileType(tile);
+
+ /* Check if there is any track on tile */
+ switch (tt) {
+ case MP_RAILWAY:
+ break;
+ case MP_STATION:
+ if (!IsRailwayStation(tile)) continue;
+ break;
+ case MP_ROAD:
+ if (!IsLevelCrossing(tile)) continue;
+ break;
+ case MP_TUNNELBRIDGE:
+ if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
+ break;
default: continue;
}
- /* It is possible that 'type' is invalid when there is no rail on the tile,
- * but this situation will be detected in proc()
- */
+ /* Original railtype we are converting from */
RailType type = GetRailType(tile);
- /* Not own tile or track is already converted */
- if ((!CheckTileOwnership(tile) || type == totype) ||
- /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */
- (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC) ||
- /* Vehicle on a tile while not converting Rail <-> ElRail */
- (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile))) {
- ret = CMD_ERROR;
- continue;
+ /* Converting to the same type or converting 'hidden' elrail -> rail */
+ if (type == totype || (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
+
+ /* Trying to convert other's rail */
+ if (!CheckTileOwnership(tile)) continue;
+
+ /* Vehicle on the tile when not converting Rail <-> ElRail
+ * Tunnels and bridges have special check later */
+ if (tt != MP_TUNNELBRIDGE) {
+ if (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile)) continue;
+ if (flags & DC_EXEC) { // we can safely convert, too
+ SetRailType(tile, totype);
+ MarkTileDirtyByTile(tile);
+ /* update power of train engines on this tile */
+ VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
+ }
}
- ret = proc(tile, totype, false);
- if (CmdFailed(ret)) continue;
-
- if (flags & DC_EXEC) {
- money -= ret.GetCost();
- if (money < 0) {
- _additional_cash_required = ret.GetCost();
- return cost;
- }
- proc(tile, totype, true);
+ switch (tt) {
+ case MP_RAILWAY:
+ switch (GetRailTileType(tile)) {
+ case RAIL_TILE_WAYPOINT:
+ if (flags & DC_EXEC) {
+ /* notify YAPF about the track layout change */
+ YapfNotifyTrackLayoutChange(tile, AxisToTrack(GetWaypointAxis(tile)));
+ }
+ cost.AddCost(RailConvertCost(type, totype));
+ break;
+
+ case RAIL_TILE_DEPOT:
+ if (flags & DC_EXEC) {
+ /* notify YAPF about the track layout change */
+ YapfNotifyTrackLayoutChange(tile, AxisToTrack(DiagDirToAxis(GetRailDepotDirection(tile))));
+
+ /* Update build vehicle window related to this depot */
+ InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
+ InvalidateWindowData(WC_BUILD_VEHICLE, tile);
+ }
+ cost.AddCost(RailConvertCost(type, totype));
+ break;
+
+ default: // RAIL_TILE_NORMAL, RAIL_TILE_SIGNALS
+ if (flags & DC_EXEC) {
+ /* notify YAPF about the track layout change */
+ TrackBits tracks = GetTrackBits(tile);
+ while (tracks != TRACK_BIT_NONE) {
+ YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
+ }
+ }
+ cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
+ break;
+ }
+ break;
+
+ case MP_TUNNELBRIDGE: {
+ TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
+
+ /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
+ * it would cause assert because of different test and exec runs */
+ if (endtile < tile && TileX(endtile) >= sx && TileX(endtile) <= ex &&
+ TileY(endtile) >= sy && TileY(endtile) <= ey) continue;
+
+ /* When not coverting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
+ if (!IsCompatibleRail(GetRailType(tile), totype) &&
+ GetVehicleTunnelBridge(tile, endtile) != NULL) continue;
+
+ if (flags & DC_EXEC) {
+ SetRailType(tile, totype);
+ SetRailType(endtile, totype);
+
+ VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
+ VehicleFromPos(endtile, NULL, &UpdateTrainPowerProc);
+
+ Track track = AxisToTrack(DiagDirToAxis(GetTunnelBridgeDirection(tile)));
+
+ YapfNotifyTrackLayoutChange(tile, track);
+ YapfNotifyTrackLayoutChange(endtile, track);
+
+ MarkTileDirtyByTile(tile);
+ MarkTileDirtyByTile(endtile);
+
+ if (IsBridge(tile)) {
+ TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
+ TileIndex t = tile + delta;
+ for (; t != endtile; t += delta) MarkTileDirtyByTile(t); // TODO encapsulate this into a function
+ }
+ }
+
+ cost.AddCost((DistanceManhattan(tile, endtile) + 1) * RailConvertCost(type, totype));
+ } break;
+
+ default: // MP_STATION, MP_ROAD
+ if (flags & DC_EXEC) {
+ Track track = (tt == MP_STATION) ? GetRailStationTrack(tile) : AxisToTrack(OtherAxis(GetCrossingRoadAxis(tile)));
+ YapfNotifyTrackLayoutChange(tile, track);
+ }
+
+ cost.AddCost(RailConvertCost(type, totype));
+ break;
}
- cost.AddCost(ret);
}
}
- return (cost.GetCost() == 0) ? ret : cost;
+ return (cost.GetCost() == 0) ? CMD_ERROR : cost;
}
static CommandCost RemoveTrainDepot(TileIndex tile, uint32 flags)
@@ -1271,12 +1313,12 @@
YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
}
- return CommandCost(_price.remove_train_depot);
+ return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot);
}
static CommandCost ClearTile_Track(TileIndex tile, byte flags)
{
- CommandCost cost;
+ CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost ret;
if (flags & DC_AUTO) {
@@ -1752,7 +1794,7 @@
image += relocation;
}
- if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
+ if (!(!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
pal = _drawtile_track_palette;
} else {
pal = dtss->pal;
@@ -1764,7 +1806,7 @@
ti->x + dtss->delta_x, ti->y + dtss->delta_y,
dtss->size_x, dtss->size_y,
dtss->size_z, ti->z + dtss->delta_z,
- IsTransparencySet(TO_BUILDINGS)
+ !HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)
);
} else {
AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
@@ -1862,23 +1904,14 @@
return false;
}
-/* Struct to parse data from VehicleFromPos to SignalVehicleCheckProc */
-struct SignalVehicleCheckStruct {
- TileIndex tile;
- uint track;
-};
-
static void *SignalVehicleCheckProc(Vehicle *v, void *data)
{
- const SignalVehicleCheckStruct* dest = (SignalVehicleCheckStruct*)data;
+ uint track = *(uint*)data;
if (v->type != VEH_TRAIN) return NULL;
- /* Wrong tile, or no train? Not a match */
- if (v->tile != dest->tile) return NULL;
-
/* Are we on the same piece of track? */
- if (dest->track & v->u.rail.track * 0x101) return v;
+ if (track & v->u.rail.track * 0x101) return v;
return NULL;
}
@@ -1886,42 +1919,12 @@
/* Special check for SetSignalsAfterProc, to see if there is a vehicle on this tile */
static bool SignalVehicleCheck(TileIndex tile, uint track)
{
- SignalVehicleCheckStruct dest;
-
- dest.tile = tile;
- dest.track = track;
-
- /* Locate vehicles in tunnels or on bridges */
- if (IsTunnelTile(tile) || IsBridgeTile(tile)) {
- TileIndex end;
- DiagDirection direction;
-
- if (IsTunnelTile(tile)) {
- end = GetOtherTunnelEnd(tile);
- direction = GetTunnelDirection(tile);
- } else {
- end = GetOtherBridgeEnd(tile);
- direction = GetBridgeRampDirection(tile);
- }
-
- dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible)
-
- /* check for a vehicle with that trackdir on the start tile of the tunnel */
- if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true;
-
- /* check for a vehicle with that trackdir on the end tile of the tunnel */
- if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true;
-
- /* now check all tiles from start to end for a warping vehicle */
- dest.track = 0x40; //Vehicle inside a tunnel or on a bridge
- if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true;
- if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true;
-
- /* no vehicle found */
- return false;
+ if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+ /* Locate vehicles in tunnels or on bridges */
+ return GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL;
+ } else {
+ return VehicleFromPos(tile, &track, &SignalVehicleCheckProc) != NULL;
}
-
- return VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL;
}
static void SetSignalsAfterProc(TrackPathFinder *tpf)
@@ -2329,7 +2332,7 @@
0, 1, 0, -1 /* y */
};
-static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
+static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
{
byte fract_coord;
byte fract_coord_leave;
@@ -2412,7 +2415,7 @@
case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
/* Surface slope must not be changed */
- default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform);
+ default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : CommandCost(EXPENSES_CONSTRUCTION, _price.terraform));
}
/* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */
@@ -2420,7 +2423,7 @@
z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner);
if (z_old != z_new) return CMD_ERROR;
- CommandCost cost = CommandCost(_price.terraform);
+ CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
/* Make the ground dirty, if surface slope has changed */
if (tileh_old != tileh_new) {
if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water);
@@ -2467,7 +2470,7 @@
if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
/* allow terraforming */
- return (was_water ? CommandCost(_price.clear_water) : CommandCost());
+ return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0);
} else {
if (_patches.build_on_slopes && AutoslopeEnabled()) {
switch (GetRailTileType(tile)) {
@@ -2478,7 +2481,7 @@
}
case RAIL_TILE_DEPOT:
- if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return _price.terraform;
+ if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
break;
default: NOT_REACHED();