00001
00002
00049 #include "stdafx.h"
00050 #include "openttd.h"
00051 #include "station_map.h"
00052 #include "viewport_func.h"
00053 #include "landscape.h"
00054 #include "train.h"
00055 #include "rail_gui.h"
00056 #include "tunnelbridge_map.h"
00057 #include "vehicle_func.h"
00058 #include "tunnelbridge.h"
00059 #include "elrail_func.h"
00060 #include "engine_base.h"
00061
00062 #include "table/sprites.h"
00063 #include "table/elrail_data.h"
00064
00065 static inline TLG GetTLG(TileIndex t)
00066 {
00067 return (TLG)((HasBit(TileX(t), 0) << 1) + HasBit(TileY(t), 0));
00068 }
00069
00076 static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
00077 {
00078 switch (GetTileType(t)) {
00079 case MP_RAILWAY:
00080 if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
00081 switch (GetRailTileType(t)) {
00082 case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
00083 return GetTrackBits(t);
00084 case RAIL_TILE_WAYPOINT:
00085 return GetRailWaypointBits(t);
00086 default:
00087 return TRACK_BIT_NONE;
00088 }
00089 break;
00090
00091 case MP_TUNNELBRIDGE:
00092 if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
00093 if (override != NULL && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
00094 *override = 1 << GetTunnelBridgeDirection(t);
00095 }
00096 return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t));
00097
00098 case MP_ROAD:
00099 if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
00100 if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
00101 return GetCrossingRailBits(t);
00102
00103 case MP_STATION:
00104 if (!IsRailwayStation(t)) return TRACK_BIT_NONE;
00105 if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
00106 if (!IsStationTileElectrifiable(t)) return TRACK_BIT_NONE;
00107 return TrackToTrackBits(GetRailStationTrack(t));
00108
00109 default:
00110 return TRACK_BIT_NONE;
00111 }
00112 }
00113
00117 static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
00118 {
00119 if (!IsTileType(t, MP_RAILWAY) || !IsPlainRailTile(t)) return tracks;
00120
00121 TrackdirBits neighbour_tdb = TRACKDIR_BIT_NONE;
00122 for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
00123
00124
00125
00126 RailType rt = GetTileRailType(TileAddByDiagDir(t, d));
00127 if (rt == INVALID_RAILTYPE || !HasCatenary(rt) || (TrackStatusToTrackBits(GetTileTrackStatus(TileAddByDiagDir(t, d), TRANSPORT_RAIL, 0)) & DiagdirReachesTracks(d)) == TRACK_BIT_NONE) {
00128 neighbour_tdb |= DiagdirReachesTrackdirs(ReverseDiagDir(d));
00129 }
00130 }
00131
00132
00133
00134
00135 TrackBits mask;
00136 if (tracks == TRACK_BIT_CROSS || !TracksOverlap(tracks)) {
00137
00138
00139 mask = ~(TrackBits)((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_MASK);
00140
00141
00142 if (tracks != TRACK_BIT_CROSS && (mask & TRACK_BIT_MASK) == TRACK_BIT_MASK) mask = ~TrackdirBitsToTrackBits(neighbour_tdb);
00143 } else {
00144
00145 mask = ~TrackdirBitsToTrackBits(neighbour_tdb);
00146
00147 if ((tracks & mask) == TRACK_BIT_NONE) {
00148 if ((neighbour_tdb & TRACKDIR_BIT_X_NE) == 0 || (neighbour_tdb & TRACKDIR_BIT_X_SW) == 0) mask |= TRACK_BIT_X;
00149 if ((neighbour_tdb & TRACKDIR_BIT_Y_NW) == 0 || (neighbour_tdb & TRACKDIR_BIT_Y_SE) == 0) mask |= TRACK_BIT_Y;
00150
00151 if ((tracks & mask) == TRACK_BIT_NONE) mask = ~(TrackBits)((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_MASK);
00152 }
00153 }
00154
00155
00156 return (tracks & mask) != TRACK_BIT_NONE ? tracks & mask : tracks;
00157 }
00158
00162 static inline SpriteID GetWireBase(TileIndex tile)
00163 {
00164 return SPR_WIRE_BASE;
00165 }
00166
00170 static inline SpriteID GetPylonBase(TileIndex tile)
00171 {
00172 return SPR_PYLON_BASE;
00173 }
00174
00179 static void AdjustTileh(TileIndex tile, Slope *tileh)
00180 {
00181 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
00182 if (IsTunnel(tile)) {
00183 *tileh = SLOPE_STEEP;
00184 } else if (*tileh != SLOPE_FLAT) {
00185 *tileh = SLOPE_FLAT;
00186 } else {
00187 *tileh = InclinedSlope(GetTunnelBridgeDirection(tile));
00188 }
00189 }
00190 }
00191
00199 static byte GetPCPElevation(TileIndex tile, DiagDirection PCPpos)
00200 {
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 byte z = GetSlopeZ(TileX(tile) * TILE_SIZE + min(x_pcp_offsets[PCPpos], TILE_SIZE - 1), TileY(tile) * TILE_SIZE + min(y_pcp_offsets[PCPpos], TILE_SIZE - 1));
00216 return (z + 2) & ~3;
00217 }
00218
00226 void DrawCatenaryOnTunnel(const TileInfo *ti)
00227 {
00228
00229 static const int _tunnel_wire_BB[4][4] = {
00230 { 0, 1, 16, 15 },
00231 { 1, 0, 15, 16 },
00232 { 0, 1, 16, 15 },
00233 { 1, 0, 15, 16 },
00234 };
00235
00236 DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
00237
00238 SpriteID wire_base = GetWireBase(ti->tile);
00239
00240 const SortableSpriteStruct *sss = &CatenarySpriteData_Tunnel[dir];
00241 const int *BB_data = _tunnel_wire_BB[dir];
00242 AddSortableSpriteToDraw(
00243 wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00244 BB_data[2] - sss->x_offset, BB_data[3] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset + 1,
00245 GetTileZ(ti->tile) + sss->z_offset,
00246 IsTransparencySet(TO_CATENARY),
00247 BB_data[0] - sss->x_offset, BB_data[1] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset
00248 );
00249 }
00250
00254 static void DrawCatenaryRailway(const TileInfo *ti)
00255 {
00256
00257
00258
00259 TrackBits trackconfig[TS_END];
00260 TrackBits wireconfig[TS_END];
00261 bool isflat[TS_END];
00262
00263 Slope tileh[TS_END] = { ti->tileh, SLOPE_FLAT };
00264
00265
00266
00267 if (IsHalftileSlope(tileh[TS_HOME])) tileh[TS_HOME] = SLOPE_FLAT;
00268
00269 TLG tlg = GetTLG(ti->tile);
00270 byte PCPstatus = 0;
00271 byte OverridePCP = 0;
00272 byte PPPpreferred[DIAGDIR_END];
00273 byte PPPallowed[DIAGDIR_END];
00274
00275
00276
00277
00278
00279
00280
00281 trackconfig[TS_HOME] = GetRailTrackBitsUniversal(ti->tile, &OverridePCP);
00282 wireconfig[TS_HOME] = MaskWireBits(ti->tile, trackconfig[TS_HOME]);
00283
00284 isflat[TS_HOME] = ((trackconfig[TS_HOME] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
00285
00286 AdjustTileh(ti->tile, &tileh[TS_HOME]);
00287
00288 SpriteID pylon_base = GetPylonBase(ti->tile);
00289
00290 for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
00291 TileIndex neighbour = ti->tile + TileOffsByDiagDir(i);
00292 Foundation foundation = FOUNDATION_NONE;
00293 byte elevation = GetPCPElevation(ti->tile, i);
00294
00295
00296
00297 tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour, NULL);
00298 trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL);
00299 wireconfig[TS_NEIGHBOUR] = MaskWireBits(neighbour, trackconfig[TS_NEIGHBOUR]);
00300 if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) wireconfig[TS_NEIGHBOUR] = trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
00301
00302
00303
00304 if (elevation != GetPCPElevation(neighbour, ReverseDiagDir(i))) wireconfig[TS_NEIGHBOUR] = trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
00305
00306 isflat[TS_NEIGHBOUR] = ((trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
00307
00308 PPPpreferred[i] = 0xFF;
00309 PPPallowed[i] = AllowedPPPonPCP[i];
00310
00311
00312
00313 for (uint k = 0; k < NUM_TRACKS_AT_PCP; k++) {
00314
00315 if (TrackSourceTile[i][k] == TS_NEIGHBOUR &&
00316 IsBridgeTile(neighbour) &&
00317 GetTunnelBridgeDirection(neighbour) == ReverseDiagDir(i)) {
00318 continue;
00319 }
00320
00321
00322
00323 DiagDirection PCPpos = i;
00324 if (HasBit(wireconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
00325
00326
00327 PCPpos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i);
00328 SetBit(PCPstatus, i);
00329 PPPpreferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
00330 }
00331
00332 if (HasBit(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
00333 PPPallowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
00334 }
00335 }
00336
00337
00338 if (!HasBit(PCPstatus, i)) {
00339 PPPpreferred[i] = 0;
00340 PPPallowed[i] = 0;
00341 }
00342
00343
00344 if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
00345
00346
00347 if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
00348 if (IsBridgeTile(neighbour)) {
00349 foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetTunnelBridgeDirection(neighbour)));
00350 }
00351
00352 ApplyFoundationToSlope(foundation, &tileh[TS_NEIGHBOUR]);
00353
00354
00355
00356 if (IsHalftileSlope(tileh[TS_NEIGHBOUR])) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
00357
00358 AdjustTileh(neighbour, &tileh[TS_NEIGHBOUR]);
00359
00360
00361
00362
00363 if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) {
00364 for (uint k = 0; k < NUM_IGNORE_GROUPS; k++) {
00365 if (PPPpreferred[i] == IgnoredPCP[k][tlg][i]) ClrBit(PCPstatus, i);
00366 }
00367 }
00368
00369
00370
00371
00372
00373 if ((PPPallowed[i] & PPPpreferred[i]) != 0) PPPallowed[i] &= PPPpreferred[i];
00374
00375 if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile)) {
00376 Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y;
00377 uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
00378
00379 if ((height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) &&
00380 (i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) {
00381 SetBit(OverridePCP, i);
00382 }
00383 }
00384
00385 if (PPPallowed[i] != 0 && HasBit(PCPstatus, i) && !HasBit(OverridePCP, i)) {
00386 for (Direction k = DIR_BEGIN; k < DIR_END; k++) {
00387 byte temp = PPPorder[i][GetTLG(ti->tile)][k];
00388
00389 if (HasBit(PPPallowed[i], temp)) {
00390 uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
00391 uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
00392
00393
00394 if (!HasBit(OwnedPPPonPCP[i], temp)) {
00395
00396 if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE) break;
00397 continue;
00398 }
00399
00400 AddSortableSpriteToDraw(pylon_base + pylon_sprites[temp], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE,
00401 elevation, IsTransparencySet(TO_CATENARY), -1, -1);
00402
00403 break;
00404 }
00405 }
00406 }
00407 }
00408
00409
00410 if (IsTunnelTile(ti->tile)) return;
00411
00412
00413 if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !IsTransparencySet(TO_CATENARY)) {
00414 uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
00415
00416 if (height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) return;
00417 }
00418
00419 SpriteID wire_base = GetWireBase(ti->tile);
00420
00421
00422 for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00423 if (HasBit(wireconfig[TS_HOME], t)) {
00424 byte PCPconfig = HasBit(PCPstatus, PCPpositions[t][0]) +
00425 (HasBit(PCPstatus, PCPpositions[t][1]) << 1);
00426
00427 const SortableSpriteStruct *sss;
00428 int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3;
00429
00430 assert(PCPconfig != 0);
00431 assert(!IsSteepSlope(tileh[TS_HOME]));
00432 sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
00433
00434
00435
00436
00437
00438
00439 AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00440 sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + sss->x_offset, ti->y + sss->y_offset) + sss->z_offset,
00441 IsTransparencySet(TO_CATENARY));
00442 }
00443 }
00444 }
00445
00446 void DrawCatenaryOnBridge(const TileInfo *ti)
00447 {
00448 TileIndex end = GetSouthernBridgeEnd(ti->tile);
00449 TileIndex start = GetOtherBridgeEnd(end);
00450
00451 uint length = GetTunnelBridgeLength(start, end);
00452 uint num = GetTunnelBridgeLength(ti->tile, start) + 1;
00453 uint height;
00454
00455 const SortableSpriteStruct *sss;
00456 Axis axis = GetBridgeAxis(ti->tile);
00457 TLG tlg = GetTLG(ti->tile);
00458
00459 CatenarySprite offset = (CatenarySprite)(axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH);
00460
00461 if ((length % 2) && num == length) {
00462
00463
00464 sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
00465 } else {
00466
00467 sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
00468 }
00469
00470 height = GetBridgeHeight(end);
00471
00472 SpriteID wire_base = GetWireBase(start);
00473
00474 AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00475 sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset,
00476 IsTransparencySet(TO_CATENARY)
00477 );
00478
00479 SpriteID pylon_base = GetPylonBase(start);
00480
00481
00482
00483 if (num % 2) {
00484 DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_NE : DIAGDIR_NW);
00485 Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
00486 if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
00487 uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
00488 uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
00489 AddSortableSpriteToDraw(pylon_base + pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_CATENARY), -1, -1);
00490 }
00491
00492
00493 if (GetTunnelBridgeLength(ti->tile, start) + 1 == length) {
00494 DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_SW : DIAGDIR_SE);
00495 Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
00496 if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
00497 uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
00498 uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
00499 AddSortableSpriteToDraw(pylon_base + pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_CATENARY), -1, -1);
00500 }
00501 }
00502
00503 void DrawCatenary(const TileInfo *ti)
00504 {
00505 switch (GetTileType(ti->tile)) {
00506 case MP_RAILWAY:
00507 if (IsRailDepot(ti->tile)) {
00508 const SortableSpriteStruct *sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
00509
00510 SpriteID wire_base = GetWireBase(ti->tile);
00511
00512
00513 AddSortableSpriteToDraw(
00514 wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00515 sss->x_size, sss->y_size, sss->z_size,
00516 GetTileMaxZ(ti->tile) + sss->z_offset,
00517 IsTransparencySet(TO_CATENARY)
00518 );
00519 return;
00520 }
00521 break;
00522
00523 case MP_TUNNELBRIDGE:
00524 case MP_ROAD:
00525 case MP_STATION:
00526 break;
00527
00528 default: return;
00529 }
00530 DrawCatenaryRailway(ti);
00531 }
00532
00533 bool SettingsDisableElrail(int32 p1)
00534 {
00535 Vehicle *v;
00536 Company *c;
00537 bool disable = (p1 != 0);
00538
00539
00540 const RailType old_railtype = disable ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL;
00541 const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC;
00542
00543
00544 Engine *e;
00545 FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
00546 RailVehicleInfo *rv_info = &e->u.rail;
00547
00548 if (rv_info->engclass == 2 && rv_info->railtype == old_railtype) {
00549
00550 rv_info->railtype = new_railtype;
00551 }
00552 }
00553
00554
00555
00556 if (disable) {
00557 FOR_ALL_VEHICLES(v) {
00558 if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
00559
00560
00561 v->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
00562 v->u.rail.railtype = RAILTYPE_RAIL;
00563 SetBit(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
00564 }
00565 }
00566 }
00567
00568
00569 FOR_ALL_VEHICLES(v) {
00570
00571 if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
00572 TrainPowerChanged(v);
00573 UpdateTrainAcceleration(v);
00574 }
00575 }
00576
00577 FOR_ALL_COMPANIES(c) c->avail_railtypes = GetCompanyRailtypes(c->index);
00578
00579
00580
00581
00582 ReinitGuiAfterToggleElrail(disable);
00583 return true;
00584 }