src/rail_cmd.cpp
changeset 8266 48fa6a084b98
parent 8260 c7d75cebe3f6
child 8267 c600379bd333
equal deleted inserted replaced
8265:9d7c69a31cdc 8266:48fa6a084b98
   213 		/* Get higher track */
   213 		/* Get higher track */
   214 		Corner highest_corner = GetHighestSlopeCorner(tileh);
   214 		Corner highest_corner = GetHighestSlopeCorner(tileh);
   215 		TrackBits higher_track = CornerToTrackBits(highest_corner);
   215 		TrackBits higher_track = CornerToTrackBits(highest_corner);
   216 
   216 
   217 		/* Only higher track? */
   217 		/* Only higher track? */
   218 		if (bits == higher_track) return FOUNDATION_STEEP_HIGHER;
   218 		if (bits == higher_track) return HalftileFoundation(highest_corner);
   219 
   219 
   220 		/* Overlap with higher track? */
   220 		/* Overlap with higher track? */
   221 		if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
   221 		if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID;
   222 
   222 
   223 		/* either lower track or both higher and lower track */
   223 		/* either lower track or both higher and lower track */
   224 		return ((bits & higher_track) != 0 ? FOUNDATION_INVALID : FOUNDATION_STEEP_LOWER);
   224 		return ((bits & higher_track) != 0 ? FOUNDATION_STEEP_BOTH : FOUNDATION_STEEP_LOWER);
   225 	} else {
   225 	} else {
   226 		if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
   226 		if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE;
   227 
   227 
   228 		bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
   228 		bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0);
   229 
   229 
       
   230 		Corner track_corner;
   230 		switch (bits) {
   231 		switch (bits) {
       
   232 			case TRACK_BIT_LEFT:  track_corner = CORNER_W; break;
       
   233 			case TRACK_BIT_LOWER: track_corner = CORNER_S; break;
       
   234 			case TRACK_BIT_RIGHT: track_corner = CORNER_E; break;
       
   235 			case TRACK_BIT_UPPER: track_corner = CORNER_N; break;
       
   236 
       
   237 			case TRACK_BIT_HORZ:
       
   238 				if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N);
       
   239 				if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S);
       
   240 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
       
   241 
       
   242 			case TRACK_BIT_VERT:
       
   243 				if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W);
       
   244 				if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E);
       
   245 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
       
   246 
   231 			case TRACK_BIT_X:
   247 			case TRACK_BIT_X:
   232 				if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
   248 				if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X;
   233 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   249 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   234 
   250 
   235 			case TRACK_BIT_Y:
   251 			case TRACK_BIT_Y:
   237 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   253 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   238 
   254 
   239 			default:
   255 			default:
   240 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   256 				return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID);
   241 		}
   257 		}
       
   258 		/* Single diagonal track */
       
   259 
       
   260 		/* Track must be at least valid on leveled foundation */
       
   261 		if (!valid_on_leveled) return FOUNDATION_INVALID;
       
   262 
       
   263 		/* If slope has three raised corners, build leveled foundation */
       
   264 		if (HasSlopeHighestCorner(ComplementSlope(tileh))) return FOUNDATION_LEVELED;
       
   265 
       
   266 		/* If neighboured corners of track_corner are lowered, build halftile foundation */
       
   267 		if ((tileh & SlopeWithThreeCornersRaised(OppositeCorner(track_corner))) == SlopeWithOneCornerRaised(track_corner)) return HalftileFoundation(track_corner);
       
   268 
       
   269 		/* else special anti-zig-zag foundation */
       
   270 		return SpecialRailFoundation(track_corner);
   242 	}
   271 	}
   243 }
   272 }
   244 
   273 
   245 
   274 
   246 /**
   275 /**
  1420  * @param track TrackBits to draw
  1449  * @param track TrackBits to draw
  1421  */
  1450  */
  1422 static void DrawTrackBits(TileInfo* ti, TrackBits track)
  1451 static void DrawTrackBits(TileInfo* ti, TrackBits track)
  1423 {
  1452 {
  1424 	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
  1453 	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
       
  1454 	RailGroundType rgt = GetRailGroundType(ti->tile);
       
  1455 	Foundation f = GetRailFoundation(ti->tileh, track);
       
  1456 	Corner halftile_corner = CORNER_INVALID;
       
  1457 
       
  1458 	if (IsNonContinuousFoundation(f)) {
       
  1459 		/* Save halftile corner */
       
  1460 		halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f));
       
  1461 		/* Draw lower part first */
       
  1462 		track &= ~CornerToTrackBits(halftile_corner);
       
  1463 		f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE);
       
  1464 	}
       
  1465 
       
  1466 	DrawFoundation(ti, f);
       
  1467 	/* DrawFoundation modifies ti */
       
  1468 
  1425 	SpriteID image;
  1469 	SpriteID image;
  1426 	SpriteID pal = PAL_NONE;
  1470 	SpriteID pal = PAL_NONE;
  1427 	bool junction = false;
  1471 	bool junction = false;
  1428 
  1472 
  1429 	/* Select the sprite to use. */
  1473 	/* Select the sprite to use. */
  1430 	(image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
  1474 	if (track == 0) {
  1431 	(image++,                           track == TRACK_BIT_X) ||
  1475 		/* Clear ground (only track on halftile foundation) */
  1432 	(image++,                           track == TRACK_BIT_UPPER) ||
  1476 		switch (rgt) {
  1433 	(image++,                           track == TRACK_BIT_LOWER) ||
  1477 			case RAIL_GROUND_BARREN:     image = SPR_FLAT_BARE_LAND;  break;
  1434 	(image++,                           track == TRACK_BIT_RIGHT) ||
  1478 			case RAIL_GROUND_ICE_DESERT: image = SPR_FLAT_SNOWY_TILE; break;
  1435 	(image++,                           track == TRACK_BIT_LEFT) ||
  1479 			default:                     image = SPR_FLAT_GRASS_TILE; break;
  1436 	(image++,                           track == TRACK_BIT_CROSS) ||
  1480 		}
  1437 
  1481 		image += _tileh_to_sprite[ti->tileh];
  1438 	(image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) ||
  1482 	} else {
  1439 	(image++,                            track == TRACK_BIT_VERT) ||
  1483 		if (ti->tileh != SLOPE_FLAT) {
  1440 
  1484 			/* track on non-flat ground */
  1441 	(junction = true, false) ||
  1485 			image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
  1442 	(image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) ||
  1486 		} else {
  1443 	(image++,                          (track & TRACK_BIT_3WAY_SW) == 0) ||
  1487 			/* track on flat ground */
  1444 	(image++,                          (track & TRACK_BIT_3WAY_NW) == 0) ||
  1488 			(image = rti->base_sprites.track_y, track == TRACK_BIT_Y) ||
  1445 	(image++,                          (track & TRACK_BIT_3WAY_SE) == 0) ||
  1489 			(image++,                           track == TRACK_BIT_X) ||
  1446 	(image++, true);
  1490 			(image++,                           track == TRACK_BIT_UPPER) ||
  1447 
  1491 			(image++,                           track == TRACK_BIT_LOWER) ||
  1448 	if (ti->tileh != SLOPE_FLAT) {
  1492 			(image++,                           track == TRACK_BIT_RIGHT) ||
  1449 		DrawFoundation(ti, GetRailFoundation(ti->tileh, track));
  1493 			(image++,                           track == TRACK_BIT_LEFT) ||
  1450 
  1494 			(image++,                           track == TRACK_BIT_CROSS) ||
  1451 		/* DrawFoundation() modifies it.
  1495 
  1452 		 * Default sloped sprites.. */
  1496 			(image = rti->base_sprites.track_ns, track == TRACK_BIT_HORZ) ||
  1453 		if (ti->tileh != SLOPE_FLAT) image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y;
  1497 			(image++,                            track == TRACK_BIT_VERT) ||
  1454 	}
  1498 
  1455 
  1499 			(junction = true, false) ||
  1456 	switch (GetRailGroundType(ti->tile)) {
  1500 			(image = rti->base_sprites.ground, (track & TRACK_BIT_3WAY_NE) == 0) ||
  1457 		case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
  1501 			(image++,                          (track & TRACK_BIT_3WAY_SW) == 0) ||
  1458 		case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset; break;
  1502 			(image++,                          (track & TRACK_BIT_3WAY_NW) == 0) ||
  1459 		default: break;
  1503 			(image++,                          (track & TRACK_BIT_3WAY_SE) == 0) ||
       
  1504 			(image++, true);
       
  1505 		}
       
  1506 
       
  1507 		switch (rgt) {
       
  1508 			case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
       
  1509 			case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset;  break;
       
  1510 			default: break;
       
  1511 		}
  1460 	}
  1512 	}
  1461 
  1513 
  1462 	DrawGroundSprite(image, pal);
  1514 	DrawGroundSprite(image, pal);
  1463 
  1515 
  1464 	/* Draw track pieces individually for junction tiles */
  1516 	/* Draw track pieces individually for junction tiles */
  1467 		if (track & TRACK_BIT_Y)     DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
  1519 		if (track & TRACK_BIT_Y)     DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE);
  1468 		if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
  1520 		if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE);
  1469 		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
  1521 		if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE);
  1470 		if (track & TRACK_BIT_LEFT)  DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
  1522 		if (track & TRACK_BIT_LEFT)  DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE);
  1471 		if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
  1523 		if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE);
       
  1524 	}
       
  1525 
       
  1526 	if (IsValidCorner(halftile_corner)) {
       
  1527 		DrawFoundation(ti, HalftileFoundation(halftile_corner));
       
  1528 
       
  1529 		/* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */
       
  1530 		Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner));
       
  1531 		image = _track_sloped_sprites[fake_slope - 1] + rti->base_sprites.track_y;
       
  1532 		pal = PAL_NONE;
       
  1533 		switch (rgt) {
       
  1534 			case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
       
  1535 			case RAIL_GROUND_ICE_DESERT: image += rti->snow_offset;  break;
       
  1536 			default: break;
       
  1537 		}
       
  1538 
       
  1539 		static const int INF = 1000; // big number compared to tilesprite size
       
  1540 		static const SubSprite _halftile_sub_sprite[4] = {
       
  1541 			{ -INF    , -INF  , 32 - 33, INF     }, // CORNER_W, clip 33 pixels from right
       
  1542 			{ -INF    ,  0 + 7, INF    , INF     }, // CORNER_S, clip 7 pixels from top
       
  1543 			{ -31 + 33, -INF  , INF    , INF     }, // CORNER_E, clip 33 pixels from left
       
  1544 			{ -INF    , -INF  , INF    , 30 - 23 }  // CORNER_N, clip 23 pixels from bottom
       
  1545 		};
       
  1546 
       
  1547 		DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner]));
  1472 	}
  1548 	}
  1473 }
  1549 }
  1474 
  1550 
  1475 static void DrawSignals(TileIndex tile, TrackBits rails)
  1551 static void DrawSignals(TileIndex tile, TrackBits rails)
  1476 {
  1552 {
  2287 
  2363 
  2288 		/* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
  2364 		/* First test autoslope. However if it succeeds we still have to test the rest, because non-autoslope terraforming is cheaper. */
  2289 		CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
  2365 		CommandCost autoslope_result = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, rail_bits);
  2290 
  2366 
  2291 		/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
  2367 		/* When there is only a single horizontal/vertical track, one corner can be terraformed. */
  2292 		Slope allowed_corner;
  2368 		Corner allowed_corner;
  2293 		switch (rail_bits) {
  2369 		switch (rail_bits) {
  2294 			case TRACK_BIT_RIGHT: allowed_corner = SLOPE_W; break;
  2370 			case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break;
  2295 			case TRACK_BIT_UPPER: allowed_corner = SLOPE_S; break;
  2371 			case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break;
  2296 			case TRACK_BIT_LEFT:  allowed_corner = SLOPE_E; break;
  2372 			case TRACK_BIT_LEFT:  allowed_corner = CORNER_E; break;
  2297 			case TRACK_BIT_LOWER: allowed_corner = SLOPE_N; break;
  2373 			case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break;
  2298 			default: return autoslope_result;
  2374 			default: return autoslope_result;
  2299 		}
  2375 		}
  2300 
  2376 
  2301 		Slope track_corners = ComplementSlope(allowed_corner);
       
  2302 
       
  2303 		Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
  2377 		Foundation f_old = GetRailFoundation(tileh_old, rail_bits);
  2304 		switch (f_old) {
  2378 
  2305 			case FOUNDATION_NONE:
  2379 		/* Do not allow terraforming if allowed_corner is part of anti-zig-zag foundations */
  2306 				/* Everything is valid, which only changes allowed_corner */
  2380 		if (tileh_old != SLOPE_NS && tileh_old != SLOPE_EW && IsSpecialRailFoundation(f_old)) return autoslope_result;
  2307 
  2381 
  2308 				/* Compute height of track */
  2382 		/* Everything is valid, which only changes allowed_corner */
  2309 				if (tileh_old == track_corners) z_old += TILE_HEIGHT;
  2383 		for (Corner corner = (Corner)0; corner < CORNER_END; corner = (Corner)(corner + 1)) {
  2310 				if (tileh_new == track_corners) {
  2384 			if (allowed_corner == corner) continue;
  2311 					z_new += TILE_HEIGHT;
  2385 			if (z_old + GetSlopeZInCorner(tileh_old, corner) != z_new + GetSlopeZInCorner(tileh_new, corner)) return autoslope_result;
  2312 				} else {
       
  2313 					/* do not build a foundation */
       
  2314 					if ((tileh_new != SLOPE_FLAT) && (tileh_new != allowed_corner)) return autoslope_result;
       
  2315 				}
       
  2316 
       
  2317 				/* Track height must remain unchanged */
       
  2318 				if (z_old != z_new) return autoslope_result;
       
  2319 				break;
       
  2320 
       
  2321 			case FOUNDATION_LEVELED:
       
  2322 				/* Is allowed_corner covered by the foundation? */
       
  2323 				if ((tileh_old & allowed_corner) == 0) return autoslope_result;
       
  2324 
       
  2325 				/* allowed_corner may only be raised -> steep slope */
       
  2326 				if ((z_old != z_new) || (tileh_new != (tileh_old | SLOPE_STEEP))) return autoslope_result;
       
  2327 				break;
       
  2328 
       
  2329 			case FOUNDATION_STEEP_LOWER:
       
  2330 				/* Only allow to lower highest corner */
       
  2331 				if ((z_old != z_new) || (tileh_new != (tileh_old & ~SLOPE_STEEP))) return autoslope_result;
       
  2332 				break;
       
  2333 
       
  2334 			case FOUNDATION_STEEP_HIGHER:
       
  2335 				return autoslope_result;
       
  2336 
       
  2337 			default: NOT_REACHED();
       
  2338 		}
  2386 		}
  2339 
  2387 
  2340 		/* Make the ground dirty */
  2388 		/* Make the ground dirty */
  2341 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2389 		if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN);
  2342 
  2390