src/elrail.cpp
branchnoai
changeset 9722 ebf0ece7d8f6
parent 9703 d2a6acdbd665
child 9723 eee46cb39750
equal deleted inserted replaced
9721:9a27928bcd5e 9722:ebf0ece7d8f6
    63 #include "table/sprites.h"
    63 #include "table/sprites.h"
    64 #include "table/elrail_data.h"
    64 #include "table/elrail_data.h"
    65 #include "vehicle.h"
    65 #include "vehicle.h"
    66 #include "train.h"
    66 #include "train.h"
    67 #include "gui.h"
    67 #include "gui.h"
       
    68 #include "transparency.h"
    68 
    69 
    69 static inline TLG GetTLG(TileIndex t)
    70 static inline TLG GetTLG(TileIndex t)
    70 {
    71 {
    71 	return (TLG)((HASBIT(TileX(t), 0) << 1) + HASBIT(TileY(t), 0));
    72 	return (TLG)((HasBit(TileX(t), 0) << 1) + HasBit(TileY(t), 0));
    72 }
    73 }
    73 
    74 
    74 /** Finds which Rail Bits are present on a given tile. For bridge tiles,
    75 /** Finds which Rail Bits are present on a given tile. For bridge tiles,
    75  * returns track bits under the bridge
    76  * returns track bits under the bridge
    76  */
    77  */
   193 	const int *BB_data = _tunnel_wire_BB[dir];
   194 	const int *BB_data = _tunnel_wire_BB[dir];
   194 	AddSortableSpriteToDraw(
   195 	AddSortableSpriteToDraw(
   195 		sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   196 		sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   196 		BB_data[2] - sss->x_offset, BB_data[3] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset + 1,
   197 		BB_data[2] - sss->x_offset, BB_data[3] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset + 1,
   197 		GetTileZ(ti->tile) + sss->z_offset,
   198 		GetTileZ(ti->tile) + sss->z_offset,
   198 		HASBIT(_transparent_opt, TO_BUILDINGS),
   199 		IsTransparencySet(TO_BUILDINGS),
   199 		BB_data[0] - sss->x_offset, BB_data[1] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset
   200 		BB_data[0] - sss->x_offset, BB_data[1] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset
   200 	);
   201 	);
   201 }
   202 }
   202 
   203 
   203 /** Draws wires and, if required, pylons on a given tile
   204 /** Draws wires and, if required, pylons on a given tile
   210 	 * current tile (home tile) while [1] holds the neighbour */
   211 	 * current tile (home tile) while [1] holds the neighbour */
   211 	TrackBits trackconfig[TS_END];
   212 	TrackBits trackconfig[TS_END];
   212 	bool isflat[TS_END];
   213 	bool isflat[TS_END];
   213 	/* Note that ti->tileh has already been adjusted for Foundations */
   214 	/* Note that ti->tileh has already been adjusted for Foundations */
   214 	Slope tileh[TS_END] = { ti->tileh, SLOPE_FLAT };
   215 	Slope tileh[TS_END] = { ti->tileh, SLOPE_FLAT };
       
   216 
       
   217 	/* Half tile slopes coincide only with horizontal/vertical track.
       
   218 	 * Faking a flat slope results in the correct sprites on positions. */
       
   219 	if (IsHalftileSlope(tileh[TS_HOME])) tileh[TS_HOME] = SLOPE_FLAT;
   215 
   220 
   216 	TLG tlg = GetTLG(ti->tile);
   221 	TLG tlg = GetTLG(ti->tile);
   217 	byte PCPstatus = 0;
   222 	byte PCPstatus = 0;
   218 	byte OverridePCP = 0;
   223 	byte OverridePCP = 0;
   219 	byte PPPpreferred[DIAGDIR_END];
   224 	byte PPPpreferred[DIAGDIR_END];
   263 				continue;
   268 				continue;
   264 			}
   269 			}
   265 
   270 
   266 			/* We check whether the track in question (k) is present in the tile
   271 			/* We check whether the track in question (k) is present in the tile
   267 			 * (TrackSourceTile) */
   272 			 * (TrackSourceTile) */
   268 			if (HASBIT(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
   273 			if (HasBit(trackconfig[TrackSourceTile[i][k]], TracksAtPCP[i][k])) {
   269 				/* track found, if track is in the neighbour tile, adjust the number
   274 				/* track found, if track is in the neighbour tile, adjust the number
   270 				 * of the PCP for preferred/allowed determination*/
   275 				 * of the PCP for preferred/allowed determination*/
   271 				DiagDirection PCPpos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i);
   276 				DiagDirection PCPpos = (TrackSourceTile[i][k] == TS_HOME) ? i : ReverseDiagDir(i);
   272 				SETBIT(PCPstatus, i); // This PCP is in use
   277 				SetBit(PCPstatus, i); // This PCP is in use
   273 
   278 
   274 				PPPpreferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
   279 				PPPpreferred[i] &= PreferredPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
   275 				PPPallowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
   280 				PPPallowed[i] &= ~DisallowedPPPofTrackAtPCP[TracksAtPCP[i][k]][PCPpos];
   276 			}
   281 			}
   277 		}
   282 		}
   278 
   283 
   279 		/* Deactivate all PPPs if PCP is not used */
   284 		/* Deactivate all PPPs if PCP is not used */
   280 		PPPpreferred[i] *= HASBIT(PCPstatus, i);
   285 		PPPpreferred[i] *= HasBit(PCPstatus, i);
   281 		PPPallowed[i] *= HASBIT(PCPstatus, i);
   286 		PPPallowed[i] *= HasBit(PCPstatus, i);
   282 
   287 
   283 		/* A station is always "flat", so adjust the tileh accordingly */
   288 		/* A station is always "flat", so adjust the tileh accordingly */
   284 		if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
   289 		if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
   285 
   290 
   286 		/* Read the foundataions if they are present, and adjust the tileh */
   291 		/* Read the foundataions if they are present, and adjust the tileh */
   288 		if (IsBridgeTile(neighbour)) {
   293 		if (IsBridgeTile(neighbour)) {
   289 			foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetBridgeRampDirection(neighbour)));
   294 			foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetBridgeRampDirection(neighbour)));
   290 		}
   295 		}
   291 
   296 
   292 		ApplyFoundationToSlope(foundation, &tileh[TS_NEIGHBOUR]);
   297 		ApplyFoundationToSlope(foundation, &tileh[TS_NEIGHBOUR]);
       
   298 
       
   299 	/* Half tile slopes coincide only with horizontal/vertical track.
       
   300 	 * Faking a flat slope results in the correct sprites on positions. */
       
   301 		if (IsHalftileSlope(tileh[TS_NEIGHBOUR])) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
   293 
   302 
   294 		AdjustTileh(neighbour, &tileh[TS_NEIGHBOUR]);
   303 		AdjustTileh(neighbour, &tileh[TS_NEIGHBOUR]);
   295 
   304 
   296 		/* If we have a straight (and level) track, we want a pylon only every 2 tiles
   305 		/* If we have a straight (and level) track, we want a pylon only every 2 tiles
   297 		 * Delete the PCP if this is the case. */
   306 		 * Delete the PCP if this is the case. */
   298 		/* Level means that the slope is the same, or the track is flat */
   307 		/* Level means that the slope is the same, or the track is flat */
   299 		if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) {
   308 		if (tileh[TS_HOME] == tileh[TS_NEIGHBOUR] || (isflat[TS_HOME] && isflat[TS_NEIGHBOUR])) {
   300 			for (k = 0; k < NUM_IGNORE_GROUPS; k++)
   309 			for (k = 0; k < NUM_IGNORE_GROUPS; k++)
   301 				if (PPPpreferred[i] == IgnoredPCP[k][tlg][i]) CLRBIT(PCPstatus, i);
   310 				if (PPPpreferred[i] == IgnoredPCP[k][tlg][i]) ClrBit(PCPstatus, i);
   302 		}
   311 		}
   303 
   312 
   304 		/* Now decide where we draw our pylons. First try the preferred PPPs, but they may not exist.
   313 		/* Now decide where we draw our pylons. First try the preferred PPPs, but they may not exist.
   305 		 * In that case, we try the any of the allowed ones. if they don't exist either, don't draw
   314 		 * In that case, we try the any of the allowed ones. if they don't exist either, don't draw
   306 		 * anything. Note that the preferred PPPs still contain the end-of-line markers.
   315 		 * anything. Note that the preferred PPPs still contain the end-of-line markers.
   311 			Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y;
   320 			Track bridgetrack = GetBridgeAxis(ti->tile) == AXIS_X ? TRACK_X : TRACK_Y;
   312 			uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
   321 			uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
   313 
   322 
   314 			if ((height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) &&
   323 			if ((height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) &&
   315 					(i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) {
   324 					(i == PCPpositions[bridgetrack][0] || i == PCPpositions[bridgetrack][1])) {
   316 				SETBIT(OverridePCP, i);
   325 				SetBit(OverridePCP, i);
   317 			}
   326 			}
   318 		}
   327 		}
   319 
   328 
   320 		if (PPPallowed[i] != 0 && HASBIT(PCPstatus, i) && !HASBIT(OverridePCP, i)) {
   329 		if (PPPallowed[i] != 0 && HasBit(PCPstatus, i) && !HasBit(OverridePCP, i)) {
   321 			for (k = 0; k < DIR_END; k++) {
   330 			for (k = 0; k < DIR_END; k++) {
   322 				byte temp = PPPorder[i][GetTLG(ti->tile)][k];
   331 				byte temp = PPPorder[i][GetTLG(ti->tile)][k];
   323 
   332 
   324 				if (HASBIT(PPPallowed[i], temp)) {
   333 				if (HasBit(PPPallowed[i], temp)) {
   325 					uint x  = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
   334 					uint x  = ti->x + x_pcp_offsets[i] + x_ppp_offsets[temp];
   326 					uint y  = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
   335 					uint y  = ti->y + y_pcp_offsets[i] + y_ppp_offsets[temp];
   327 
   336 
   328 					/* Don't build the pylon if it would be outside the tile */
   337 					/* Don't build the pylon if it would be outside the tile */
   329 					if (!HASBIT(OwnedPPPonPCP[i], temp)) {
   338 					if (!HasBit(OwnedPPPonPCP[i], temp)) {
   330 						/* We have a neighour that will draw it, bail out */
   339 						/* We have a neighour that will draw it, bail out */
   331 						if (trackconfig[TS_NEIGHBOUR] != 0) break;
   340 						if (trackconfig[TS_NEIGHBOUR] != 0) break;
   332 						continue; /* No neighbour, go looking for a better position */
   341 						continue; /* No neighbour, go looking for a better position */
   333 					}
   342 					}
   334 
   343 
   335 					AddSortableSpriteToDraw(pylon_sprites[temp], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE,
   344 					AddSortableSpriteToDraw(pylon_sprites[temp], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE,
   336 							GetPCPElevation(ti->tile, i),
   345 							GetPCPElevation(ti->tile, i),
   337 							HASBIT(_transparent_opt, TO_BUILDINGS), -1, -1);
   346 							IsTransparencySet(TO_BUILDINGS), -1, -1);
   338 					break; /* We already have drawn a pylon, bail out */
   347 					break; /* We already have drawn a pylon, bail out */
   339 				}
   348 				}
   340 			}
   349 			}
   341 		}
   350 		}
   342 	}
   351 	}
   343 
   352 
   344 	/* Don't draw a wire under a low bridge */
   353 	/* Don't draw a wire under a low bridge */
   345 	if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !HASBIT(_transparent_opt, TO_BUILDINGS)) {
   354 	if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !IsTransparencySet(TO_BUILDINGS)) {
   346 		uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
   355 		uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
   347 
   356 
   348 		if (height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) return;
   357 		if (height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) return;
   349 	}
   358 	}
   350 
   359 
   351 	/* Drawing of pylons is finished, now draw the wires */
   360 	/* Drawing of pylons is finished, now draw the wires */
   352 	for (t = TRACK_BEGIN; t < TRACK_END; t++) {
   361 	for (t = TRACK_BEGIN; t < TRACK_END; t++) {
   353 		if (HASBIT(trackconfig[TS_HOME], t)) {
   362 		if (HasBit(trackconfig[TS_HOME], t)) {
   354 			if (IsTunnelTile(ti->tile)) break; // drawn together with tunnel-roof (see DrawCatenaryOnTunnel())
   363 			if (IsTunnelTile(ti->tile)) break; // drawn together with tunnel-roof (see DrawCatenaryOnTunnel())
   355 			byte PCPconfig = HASBIT(PCPstatus, PCPpositions[t][0]) +
   364 			byte PCPconfig = HasBit(PCPstatus, PCPpositions[t][0]) +
   356 				(HASBIT(PCPstatus, PCPpositions[t][1]) << 1);
   365 				(HasBit(PCPstatus, PCPpositions[t][1]) << 1);
   357 
   366 
   358 			const SortableSpriteStruct *sss;
   367 			const SortableSpriteStruct *sss;
   359 			int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; /* tileh for the slopes, 0 otherwise */
   368 			int tileh_selector = !(tileh[TS_HOME] % 3) * tileh[TS_HOME] / 3; /* tileh for the slopes, 0 otherwise */
   360 
   369 
   361 			assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */
   370 			assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */
   367 			 * Therefore it is save to use GetSlopeZ() for the elevation.
   376 			 * Therefore it is save to use GetSlopeZ() for the elevation.
   368 			 * Also note, that the result of GetSlopeZ() is very special for bridge-ramps.
   377 			 * Also note, that the result of GetSlopeZ() is very special for bridge-ramps.
   369 			 */
   378 			 */
   370 			AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   379 			AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   371 				sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + sss->x_offset, ti->y + sss->y_offset) + sss->z_offset,
   380 				sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + sss->x_offset, ti->y + sss->y_offset) + sss->z_offset,
   372 				HASBIT(_transparent_opt, TO_BUILDINGS));
   381 				IsTransparencySet(TO_BUILDINGS));
   373 		}
   382 		}
   374 	}
   383 	}
   375 }
   384 }
   376 
   385 
   377 static void DrawCatenaryOnBridge(const TileInfo *ti)
   386 static void DrawCatenaryOnBridge(const TileInfo *ti)
   400 
   409 
   401 	height = GetBridgeHeight(end);
   410 	height = GetBridgeHeight(end);
   402 
   411 
   403 	AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   412 	AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   404 		sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset,
   413 		sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset,
   405 		HASBIT(_transparent_opt, TO_BUILDINGS)
   414 		IsTransparencySet(TO_BUILDINGS)
   406 	);
   415 	);
   407 
   416 
   408 	/* Finished with wires, draw pylons */
   417 	/* Finished with wires, draw pylons */
   409 	/* every other tile needs a pylon on the northern end */
   418 	/* every other tile needs a pylon on the northern end */
   410 	if (num % 2) {
   419 	if (num % 2) {
   411 		DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_NE : DIAGDIR_NW);
   420 		DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_NE : DIAGDIR_NW);
   412 		Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
   421 		Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
   413 		if (HASBIT(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
   422 		if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
   414 		uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
   423 		uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
   415 		uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
   424 		uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
   416 		AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, HASBIT(_transparent_opt, TO_BUILDINGS), -1, -1);
   425 		AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_BUILDINGS), -1, -1);
   417 	}
   426 	}
   418 
   427 
   419 	/* need a pylon on the southern end of the bridge */
   428 	/* need a pylon on the southern end of the bridge */
   420 	if (DistanceMax(ti->tile, start) == length) {
   429 	if (DistanceMax(ti->tile, start) == length) {
   421 		DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_SW : DIAGDIR_SE);
   430 		DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_SW : DIAGDIR_SE);
   422 		Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
   431 		Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
   423 		if (HASBIT(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
   432 		if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
   424 		uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
   433 		uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
   425 		uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
   434 		uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
   426 		AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, HASBIT(_transparent_opt, TO_BUILDINGS), -1, -1);
   435 		AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_BUILDINGS), -1, -1);
   427 	}
   436 	}
   428 }
   437 }
   429 
   438 
   430 void DrawCatenary(const TileInfo *ti)
   439 void DrawCatenary(const TileInfo *ti)
   431 {
   440 {
   447 				/* This wire is not visible with the default depot sprites */
   456 				/* This wire is not visible with the default depot sprites */
   448 				AddSortableSpriteToDraw(
   457 				AddSortableSpriteToDraw(
   449 					sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   458 					sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   450 					sss->x_size, sss->y_size, sss->z_size,
   459 					sss->x_size, sss->y_size, sss->z_size,
   451 					GetTileMaxZ(ti->tile) + sss->z_offset,
   460 					GetTileMaxZ(ti->tile) + sss->z_offset,
   452 					HASBIT(_transparent_opt, TO_BUILDINGS)
   461 					IsTransparencySet(TO_BUILDINGS)
   453 				);
   462 				);
   454 				return;
   463 				return;
   455 			}
   464 			}
   456 			break;
   465 			break;
   457 
   466 
   493 			if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
   502 			if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
   494 				/* this railroad vehicle is now compatible only with elrail,
   503 				/* this railroad vehicle is now compatible only with elrail,
   495 				*  so add there also normal rail compatibility */
   504 				*  so add there also normal rail compatibility */
   496 				v->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
   505 				v->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
   497 				v->u.rail.railtype = RAILTYPE_RAIL;
   506 				v->u.rail.railtype = RAILTYPE_RAIL;
   498 				SETBIT(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
   507 				SetBit(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
   499 			}
   508 			}
   500 		}
   509 		}
   501 	}
   510 	}
   502 
   511 
   503 	/* setup total power for trains */
   512 	/* setup total power for trains */