src/elrail.cpp
changeset 7534 2e4dcc2c3bc9
parent 7472 f6ec016b00f4
child 7601 988040ee27f4
equal deleted inserted replaced
7533:787277cc0908 7534:2e4dcc2c3bc9
   139 			}
   139 			}
   140 		}
   140 		}
   141 	}
   141 	}
   142 }
   142 }
   143 
   143 
       
   144 /**
       
   145  * Returns the Z position of a Pylon Control Point.
       
   146  *
       
   147  * @param tile The tile the pylon should stand on.
       
   148  * @param PCPpos The PCP of the tile.
       
   149  * @return The Z position of the PCP.
       
   150  */
       
   151 static byte GetPCPElevation(TileIndex tile, DiagDirection PCPpos)
       
   152 {
       
   153 	/* The elevation of the "pylon"-sprite should be the elevation at the PCP.
       
   154 	 * PCPs are always on a tile edge.
       
   155 	 *
       
   156 	 * This position can be outside of the tile, i.e. ?_pcp_offset == TILE_SIZE > TILE_SIZE - 1.
       
   157 	 * So we have to move it inside the tile, because if the neighboured tile has a foundation,
       
   158 	 * that does not smoothly connect to the current tile, we will get a wrong elevation from GetSlopeZ().
       
   159 	 *
       
   160 	 * When we move the position inside the tile, we will get a wrong elevation if we have a slope.
       
   161 	 * To catch all cases we round the Z position to the next (TILE_HEIGHT / 2).
       
   162 	 * This will return the correct elevation for slopes and will also detect non-continuous elevation on edges.
       
   163 	 *
       
   164 	 * Also note that the result of GetSlopeZ() is very special on bridge-ramps.
       
   165 	 */
       
   166 
       
   167 	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));
       
   168 	return (z + 2) & ~3; // this means z = (z + TILE_HEIGHT / 4) / (TILE_HEIGHT / 2) * (TILE_HEIGHT / 2);
       
   169 }
       
   170 
   144 /** Draws wires and, if required, pylons on a given tile
   171 /** Draws wires and, if required, pylons on a given tile
   145  * @param ti The Tileinfo to draw the tile for
   172  * @param ti The Tileinfo to draw the tile for
   146  */
   173  */
   147 static void DrawCatenaryRailway(const TileInfo *ti)
   174 static void DrawCatenaryRailway(const TileInfo *ti)
   148 {
   175 {
   182 		/* Here's one of the main headaches. GetTileSlope does not correct for possibly
   209 		/* Here's one of the main headaches. GetTileSlope does not correct for possibly
   183 		 * existing foundataions, so we do have to do that manually later on.*/
   210 		 * existing foundataions, so we do have to do that manually later on.*/
   184 		tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour, NULL);
   211 		tileh[TS_NEIGHBOUR] = GetTileSlope(neighbour, NULL);
   185 		trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL);
   212 		trackconfig[TS_NEIGHBOUR] = GetRailTrackBitsUniversal(neighbour, NULL);
   186 		if (IsTunnelTile(neighbour) && i != GetTunnelDirection(neighbour)) trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
   213 		if (IsTunnelTile(neighbour) && i != GetTunnelDirection(neighbour)) trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
       
   214 
       
   215 		/* If the neighboured tile does not smoothly connect to the current tile (because of a foundation),
       
   216 		 * we have to draw all pillars on the current tile. */
       
   217 		if (GetPCPElevation(ti->tile, i) != GetPCPElevation(neighbour, ReverseDiagDir(i))) trackconfig[TS_NEIGHBOUR] = TRACK_BIT_NONE;
       
   218 
   187 		isflat[TS_NEIGHBOUR] = ((trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
   219 		isflat[TS_NEIGHBOUR] = ((trackconfig[TS_NEIGHBOUR] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0);
   188 
   220 
   189 		PPPpreferred[i] = 0xFF; // We start with preferring everything (end-of-line in any direction)
   221 		PPPpreferred[i] = 0xFF; // We start with preferring everything (end-of-line in any direction)
   190 		PPPallowed[i] = AllowedPPPonPCP[i];
   222 		PPPallowed[i] = AllowedPPPonPCP[i];
   191 
   223 
   218 
   250 
   219 		/* A station is always "flat", so adjust the tileh accordingly */
   251 		/* A station is always "flat", so adjust the tileh accordingly */
   220 		if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
   252 		if (IsTileType(neighbour, MP_STATION)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
   221 
   253 
   222 		/* Read the foundataions if they are present, and adjust the tileh */
   254 		/* Read the foundataions if they are present, and adjust the tileh */
   223 		if (IsTileType(neighbour, MP_RAILWAY) && GetRailType(neighbour) == RAILTYPE_ELECTRIC) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
   255 		if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && GetRailType(neighbour) == RAILTYPE_ELECTRIC) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
   224 		if (IsBridgeTile(neighbour)) {
   256 		if (IsBridgeTile(neighbour)) {
   225 			foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetBridgeRampDirection(neighbour)));
   257 			foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetBridgeRampDirection(neighbour)));
   226 		}
   258 		}
   227 
   259 
   228 		ApplyFoundationToSlope(foundation, &tileh[TS_NEIGHBOUR]);
   260 		ApplyFoundationToSlope(foundation, &tileh[TS_NEIGHBOUR]);
   266 						/* We have a neighour that will draw it, bail out */
   298 						/* We have a neighour that will draw it, bail out */
   267 						if (trackconfig[TS_NEIGHBOUR] != 0) break;
   299 						if (trackconfig[TS_NEIGHBOUR] != 0) break;
   268 						continue; /* No neighbour, go looking for a better position */
   300 						continue; /* No neighbour, go looking for a better position */
   269 					}
   301 					}
   270 
   302 
   271 					AddSortableSpriteToDraw(pylons_normal[temp], PAL_NONE, x, y, 1, 1, 10,
   303 					AddSortableSpriteToDraw(pylon_sprites[temp], PAL_NONE, x, y, 1, 1, 10,
   272 							GetSlopeZ(ti->x + x_pcp_offsets[i], ti->y + y_pcp_offsets[i]),
   304 							GetPCPElevation(ti->tile, i),
   273 							HASBIT(_transparent_opt, TO_BUILDINGS));
   305 							HASBIT(_transparent_opt, TO_BUILDINGS));
   274 					break; /* We already have drawn a pylon, bail out */
   306 					break; /* We already have drawn a pylon, bail out */
   275 				}
   307 				}
   276 			}
   308 			}
   277 		}
   309 		}
   306 
   338 
   307 			assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */
   339 			assert(PCPconfig != 0); /* We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) */
   308 			assert(!IsSteepSlope(tileh[TS_HOME]));
   340 			assert(!IsSteepSlope(tileh[TS_HOME]));
   309 			sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
   341 			sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
   310 
   342 
       
   343 			/*
       
   344 			 * The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE.
       
   345 			 * Therefore it is save to use GetSlopeZ() for the elevation.
       
   346 			 * Also note, that the result of GetSlopeZ() is very special for bridge-ramps.
       
   347 			 */
   311 			AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   348 			AddSortableSpriteToDraw(sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   312 				sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + min(sss->x_offset, TILE_SIZE - 1), ti->y + min(sss->y_offset, TILE_SIZE - 1)) + sss->z_offset,
   349 				sss->x_size, sss->y_size, sss->z_size, GetSlopeZ(ti->x + sss->x_offset, ti->y + sss->y_offset) + sss->z_offset,
   313 				HASBIT(_transparent_opt, TO_BUILDINGS));
   350 				HASBIT(_transparent_opt, TO_BUILDINGS));
   314 		}
   351 		}
   315 	}
   352 	}
   316 }
   353 }
   317 
   354 
   347 	);
   384 	);
   348 
   385 
   349 	/* Finished with wires, draw pylons */
   386 	/* Finished with wires, draw pylons */
   350 	/* every other tile needs a pylon on the northern end */
   387 	/* every other tile needs a pylon on the northern end */
   351 	if (num % 2) {
   388 	if (num % 2) {
   352 		if (axis == AXIS_X) {
   389 		DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_NE : DIAGDIR_NW);
   353 			AddSortableSpriteToDraw(pylons_bridge[0 + HASBIT(tlg, 0)], PAL_NONE, ti->x, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, height, HASBIT(_transparent_opt, TO_BUILDINGS));
   390 		Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
   354 		} else {
   391 		if (HASBIT(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
   355 			AddSortableSpriteToDraw(pylons_bridge[2 + HASBIT(tlg, 1)], PAL_NONE, ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y, 1, 1, 10, height, HASBIT(_transparent_opt, TO_BUILDINGS));
   392 		uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
   356 		}
   393 		uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
       
   394 		AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, 10, height, HASBIT(_transparent_opt, TO_BUILDINGS));
   357 	}
   395 	}
   358 
   396 
   359 	/* need a pylon on the southern end of the bridge */
   397 	/* need a pylon on the southern end of the bridge */
   360 	if (DistanceMax(ti->tile, start) == length) {
   398 	if (DistanceMax(ti->tile, start) == length) {
   361 		if (axis == AXIS_X) {
   399 		DiagDirection PCPpos = (axis == AXIS_X ? DIAGDIR_SW : DIAGDIR_SE);
   362 			AddSortableSpriteToDraw(pylons_bridge[0 + HASBIT(tlg, 0)], PAL_NONE, ti->x + 16, ti->y + 4 + 8 * HASBIT(tlg, 0), 1, 1, 10, height, HASBIT(_transparent_opt, TO_BUILDINGS));
   400 		Direction PPPpos = (axis == AXIS_X ? DIR_NW : DIR_NE);
   363 		} else {
   401 		if (HASBIT(tlg, (axis == AXIS_X ? 0 : 1))) PPPpos = ReverseDir(PPPpos);
   364 			AddSortableSpriteToDraw(pylons_bridge[2 + HASBIT(tlg, 1)], PAL_NONE, ti->x + 4 + 8 * HASBIT(tlg, 1), ti->y + 16, 1, 1, 10, height, HASBIT(_transparent_opt, TO_BUILDINGS));
   402 		uint x = ti->x + x_pcp_offsets[PCPpos] + x_ppp_offsets[PPPpos];
   365 		}
   403 		uint y = ti->y + y_pcp_offsets[PCPpos] + y_ppp_offsets[PPPpos];
       
   404 		AddSortableSpriteToDraw(pylon_sprites[PPPpos], PAL_NONE, x, y, 1, 1, 10, height, HASBIT(_transparent_opt, TO_BUILDINGS));
   366 	}
   405 	}
   367 }
   406 }
   368 
   407 
   369 void DrawCatenary(const TileInfo *ti)
   408 void DrawCatenary(const TileInfo *ti)
   370 {
   409 {
   381 	switch (GetTileType(ti->tile)) {
   420 	switch (GetTileType(ti->tile)) {
   382 		case MP_RAILWAY:
   421 		case MP_RAILWAY:
   383 			if (IsRailDepot(ti->tile)) {
   422 			if (IsRailDepot(ti->tile)) {
   384 				const SortableSpriteStruct *sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
   423 				const SortableSpriteStruct *sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
   385 
   424 
       
   425 				/* This wire is not visible with the default depot sprites */
   386 				AddSortableSpriteToDraw(
   426 				AddSortableSpriteToDraw(
   387 					sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   427 					sss->image, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
   388 					sss->x_size, sss->y_size, sss->z_size,
   428 					sss->x_size, sss->y_size, sss->z_size,
   389 					GetTileMaxZ(ti->tile) + sss->z_offset,
   429 					GetTileMaxZ(ti->tile) + sss->z_offset,
   390 					HASBIT(_transparent_opt, TO_BUILDINGS)
   430 					HASBIT(_transparent_opt, TO_BUILDINGS)