00001
00048 #include "stdafx.h"
00049 #include "openttd.h"
00050 #include "station_map.h"
00051 #include "viewport_func.h"
00052 #include "settings_type.h"
00053 #include "landscape.h"
00054 #include "rail_type.h"
00055 #include "debug.h"
00056 #include "tunnel_map.h"
00057 #include "road_map.h"
00058 #include "bridge_map.h"
00059 #include "bridge.h"
00060 #include "rail_map.h"
00061 #include "train.h"
00062 #include "rail_gui.h"
00063 #include "transparency.h"
00064 #include "tunnelbridge_map.h"
00065 #include "vehicle_func.h"
00066 #include "player_base.h"
00067 #include "tunnelbridge.h"
00068
00069 #include "table/sprites.h"
00070 #include "table/elrail_data.h"
00071
00072 static inline TLG GetTLG(TileIndex t)
00073 {
00074 return (TLG)((HasBit(TileX(t), 0) << 1) + HasBit(TileY(t), 0));
00075 }
00076
00083 static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
00084 {
00085 switch (GetTileType(t)) {
00086 case MP_RAILWAY:
00087 if (GetRailType(t) != RAILTYPE_ELECTRIC) return TRACK_BIT_NONE;
00088 switch (GetRailTileType(t)) {
00089 case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
00090 return GetTrackBits(t);
00091 case RAIL_TILE_WAYPOINT:
00092 return GetRailWaypointBits(t);
00093 default:
00094 return TRACK_BIT_NONE;
00095 }
00096 break;
00097
00098 case MP_TUNNELBRIDGE:
00099 if (GetRailType(t) != RAILTYPE_ELECTRIC) return TRACK_BIT_NONE;
00100 if (override != NULL && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
00101 *override = 1 << GetTunnelBridgeDirection(t);
00102 }
00103 return AxisToTrackBits(DiagDirToAxis(GetTunnelBridgeDirection(t)));
00104
00105 case MP_ROAD:
00106 if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
00107 if (GetRailType(t) != RAILTYPE_ELECTRIC) return TRACK_BIT_NONE;
00108 return GetCrossingRailBits(t);
00109
00110 case MP_STATION:
00111 if (!IsRailwayStation(t)) return TRACK_BIT_NONE;
00112 if (GetRailType(t) != RAILTYPE_ELECTRIC) return TRACK_BIT_NONE;
00113 if (!IsStationTileElectrifiable(t)) return TRACK_BIT_NONE;
00114 return TrackToTrackBits(GetRailStationTrack(t));
00115
00116 default:
00117 return TRACK_BIT_NONE;
00118 }
00119 }
00120
00125 static void AdjustTileh(TileIndex tile, Slope *tileh)
00126 {
00127 if (IsTileType(tile, MP_TUNNELBRIDGE)) {
00128 if (IsTunnel(tile)) {
00129 *tileh = SLOPE_STEEP;
00130 } else if (*tileh != SLOPE_FLAT) {
00131 *tileh = SLOPE_FLAT;
00132 } else {
00133 *tileh = InclinedSlope(GetTunnelBridgeDirection(tile));
00134 }
00135 }
00136 }
00137
00145 static byte GetPCPElevation(TileIndex tile, DiagDirection PCPpos)
00146 {
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 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));
00162 return (z + 2) & ~3;
00163 }
00164
00172 void DrawCatenaryOnTunnel(const TileInfo *ti)
00173 {
00174
00175 static const int _tunnel_wire_BB[4][4] = {
00176 { 0, 1, 16, 15 },
00177 { 1, 0, 15, 16 },
00178 { 0, 1, 16, 15 },
00179 { 1, 0, 15, 16 },
00180 };
00181
00182 if ((GetRailType(ti->tile) != RAILTYPE_ELECTRIC) || _patches.disable_elrails) return;
00183
00184 DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
00185
00186 const SortableSpriteStruct *sss = &CatenarySpriteData_Tunnel[dir];
00187 const int *BB_data = _tunnel_wire_BB[dir];
00188 AddSortableSpriteToDraw(
00189 sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00190 BB_data[2] - sss->x_offset, BB_data[3] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset + 1,
00191 GetTileZ(ti->tile) + sss->z_offset,
00192 IsTransparencySet(TO_CATENARY),
00193 BB_data[0] - sss->x_offset, BB_data[1] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset
00194 );
00195 }
00196
00200 static void DrawCatenaryRailway(const TileInfo *ti)
00201 {
00202
00203
00204
00205 TrackBits trackconfig[TS_END];
00206 bool isflat[TS_END];
00207
00208 Slope tileh[TS_END] = { ti->tileh, SLOPE_FLAT };
00209
00210
00211
00212 if (IsHalftileSlope(tileh[TS_HOME])) tileh[TS_HOME] = SLOPE_FLAT;
00213
00214 TLG tlg = GetTLG(ti->tile);
00215 byte PCPstatus = 0;
00216 byte OverridePCP = 0;
00217 byte PPPpreferred[DIAGDIR_END];
00218 byte PPPallowed[DIAGDIR_END];
00219 DiagDirection i;
00220 Track t;
00221
00222
00223
00224
00225
00226
00227
00228 trackconfig[TS_HOME] = GetRailTrackBitsUniversal(ti->tile, &OverridePCP);
00229
00230 isflat[TS_HOME] = ((trackconfig[TS_HOME] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
00231
00232 AdjustTileh(ti->tile, &tileh[TS_HOME]);
00233
00234 for (i = DIAGDIR_NE; i < DIAGDIR_END; i++) {
00235 TileIndex neighbour = ti->tile + TileOffsByDiagDir(i);
00236 Foundation foundation = FOUNDATION_NONE;
00237 int k;
00238
00239
00240
00241 tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour, NULL);
00242 trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL);
00243 if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
00244
00245
00246
00247 if (GetPCPElevation(ti->tile, i) != GetPCPElevation(neighbour, ReverseDiagDir(i))) trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
00248
00249 isflat[TS_NEIGHBOUR] = ((trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
00250
00251 PPPpreferred[i] = 0xFF;
00252 PPPallowed[i] = AllowedPPPonPCP[i];
00253
00254
00255
00256 for (k = 0; k < NUM_TRACKS_AT_PCP; k++) {
00257
00258 if (TrackSourceTile[i][k] == TS_NEIGHBOUR &&
00259 IsBridgeTile(neighbour) &&
00260 GetTunnelBridgeDirection(neighbour) == ReverseDiagDir(i)) {
00261 continue;
00262 }
00263
00264
00265
00266 if (HasBit(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
00267
00268
00269 DiagDirection PCPpos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i);
00270 SetBit(PCPstatus, i);
00271
00272 PPPpreferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
00273 PPPallowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
00274 }
00275 }
00276
00277
00278 PPPpreferred[i] *= HasBit(PCPstatus, i);
00279 PPPallowed[i] *= HasBit(PCPstatus, i);
00280
00281
00282 if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
00283
00284
00285 if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && GetRailType(neighbour) == RAILTYPE_ELECTRIC) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
00286 if (IsBridgeTile(neighbour)) {
00287 foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetTunnelBridgeDirection(neighbour)));
00288 }
00289
00290 ApplyFoundationToSlope(foundation, &tileh[TS_NEIGHBOUR]);
00291
00292
00293
00294 if (IsHalftileSlope(tileh[TS_NEIGHBOUR])) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
00295
00296 AdjustTileh(neighbour, &tileh[TS_NEIGHBOUR]);
00297
00298
00299
00300
00301 if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) {
00302 for (k = 0; k < NUM_IGNORE_GROUPS; k++)
00303 if (PPPpreferred[i] == IgnoredPCP[k][tlg][i]) ClrBit(PCPstatus, i);
00304 }
00305
00306
00307
00308
00309
00310 if ((PPPallowed[i] & PPPpreferred[i]) != 0) PPPallowed[i] &= PPPpreferred[i];
00311
00312 if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile)) {
00313 Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y;
00314 uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
00315
00316 if ((height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) &&
00317 (i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) {
00318 SetBit(OverridePCP, i);
00319 }
00320 }
00321
00322 if (PPPallowed[i] != 0 && HasBit(PCPstatus, i) && !HasBit(OverridePCP, i)) {
00323 for (k = 0; k < DIR_END; k++) {
00324 byte temp = PPPorder[i][GetTLG(ti->tile)][k];
00325
00326 if (HasBit(PPPallowed[i], temp)) {
00327 uint x = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
00328 uint y = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
00329
00330
00331 if (!HasBit(OwnedPPPonPCP[i], temp)) {
00332
00333 if (trackconfig[TS_NEIGHBOUR] != 0) break;
00334 continue;
00335 }
00336
00337 AddSortableSpriteToDraw(pylon_sprites[temp], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE,
00338 GetPCPElevation(ti->tile, i),
00339 IsTransparencySet(TO_CATENARY), -1, -1);
00340 break;
00341 }
00342 }
00343 }
00344 }
00345
00346
00347 if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !IsTransparencySet(TO_CATENARY)) {
00348 uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
00349
00350 if (height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) return;
00351 }
00352
00353
00354 for (t = TRACK_BEGIN; t < TRACK_END; t++) {
00355 if (HasBit(trackconfig[TS_HOME], t)) {
00356 if (IsTunnelTile(ti->tile)) break;
00357 byte PCPconfig = HasBit(PCPstatus, PCPpositions[t][0]) +
00358 (HasBit(PCPstatus, PCPpositions[t][1]) << 1);
00359
00360 const SortableSpriteStruct *sss;
00361 int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3;
00362
00363 assert(PCPconfig != 0);
00364 assert(!IsSteepSlope(tileh[TS_HOME]));
00365 sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
00366
00367
00368
00369
00370
00371
00372 AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00373 sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + sss->x_offset, ti->y + sss->y_offset) + sss->z_offset,
00374 IsTransparencySet(TO_CATENARY));
00375 }
00376 }
00377 }
00378
00379 static void DrawCatenaryOnBridge(const TileInfo *ti)
00380 {
00381 TileIndex end = GetSouthernBridgeEnd(ti->tile);
00382 TileIndex start = GetOtherBridgeEnd(end);
00383
00384 uint length = GetTunnelBridgeLength(start, end);
00385 uint num = GetTunnelBridgeLength(ti->tile, start) + 1;
00386 uint height;
00387
00388 const SortableSpriteStruct *sss;
00389 Axis axis = GetBridgeAxis(ti->tile);
00390 TLG tlg = GetTLG(ti->tile);
00391
00392 CatenarySprite offset = (CatenarySprite)(axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH);
00393
00394 if ((length % 2) && num == length) {
00395
00396
00397 sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
00398 } else {
00399
00400 sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
00401 }
00402
00403 height = GetBridgeHeight(end);
00404
00405 AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00406 sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset,
00407 IsTransparencySet(TO_CATENARY)
00408 );
00409
00410
00411
00412 if (num % 2) {
00413 DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_NE : DIAGDIR_NW);
00414 Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
00415 if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
00416 uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
00417 uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
00418 AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_CATENARY), -1, -1);
00419 }
00420
00421
00422 if (GetTunnelBridgeLength(ti->tile, start) + 1 == length) {
00423 DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_SW : DIAGDIR_SE);
00424 Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
00425 if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
00426 uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
00427 uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
00428 AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_CATENARY), -1, -1);
00429 }
00430 }
00431
00432 void DrawCatenary(const TileInfo *ti)
00433 {
00434 if (_patches.disable_elrails) return;
00435
00436 if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile)) {
00437 TileIndex head = GetNorthernBridgeEnd(ti->tile);
00438
00439 if (GetTunnelBridgeTransportType(head) == TRANSPORT_RAIL && GetRailType(head) == RAILTYPE_ELECTRIC) {
00440 DrawCatenaryOnBridge(ti);
00441 }
00442 }
00443
00444 switch (GetTileType(ti->tile)) {
00445 case MP_RAILWAY:
00446 if (IsRailDepot(ti->tile)) {
00447 const SortableSpriteStruct *sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
00448
00449
00450 AddSortableSpriteToDraw(
00451 sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
00452 sss->x_size, sss->y_size, sss->z_size,
00453 GetTileMaxZ(ti->tile) + sss->z_offset,
00454 IsTransparencySet(TO_CATENARY)
00455 );
00456 return;
00457 }
00458 break;
00459
00460 case MP_TUNNELBRIDGE:
00461 case MP_ROAD:
00462 case MP_STATION:
00463 break;
00464
00465 default: return;
00466 }
00467 DrawCatenaryRailway(ti);
00468 }
00469
00470 int32 SettingsDisableElrail(int32 p1)
00471 {
00472 Vehicle *v;
00473 Player *p;
00474 bool disable = (p1 != 0);
00475
00476
00477 const RailType old_railtype = disable ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL;
00478 const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC;
00479
00480
00481 EngineID eid;
00482 FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_TRAIN) {
00483 RailVehicleInfo *rv_info = &_rail_vehicle_info[eid];
00484
00485 if (rv_info->engclass == 2 && rv_info->railtype == old_railtype) {
00486
00487 rv_info->railtype = new_railtype;
00488 }
00489 }
00490
00491
00492
00493 if (disable) {
00494 FOR_ALL_VEHICLES(v) {
00495 if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
00496
00497
00498 v->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
00499 v->u.rail.railtype = RAILTYPE_RAIL;
00500 SetBit(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
00501 }
00502 }
00503 }
00504
00505
00506 FOR_ALL_VEHICLES(v) {
00507
00508 if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
00509 TrainPowerChanged(v);
00510 UpdateTrainAcceleration(v);
00511 }
00512 }
00513
00514 FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index);
00515
00516
00517
00518
00519 ReinitGuiAfterToggleElrail(disable);
00520 return 0;
00521 }