* Draw foundation \a f at tile \a ti. Updates \a ti. * @param ti Tile to draw foundation on * @param f Foundation to draw */
| 427 | * @param f Foundation to draw |
| 428 | */ |
| 429 | void DrawFoundation(TileInfo *ti, Foundation f) |
| 430 | { |
| 431 | if (!IsFoundation(f)) return; |
| 432 | |
| 433 | /* Two part foundations must be drawn separately */ |
| 434 | assert(f != FOUNDATION_STEEP_BOTH); |
| 435 | |
| 436 | uint sprite_block = 0; |
| 437 | auto [slope, z] = GetFoundationPixelSlope(ti->tile); |
| 438 | |
| 439 | /* Select the needed block of foundations sprites |
| 440 | * Block 0: Walls at NW and NE edge |
| 441 | * Block 1: Wall at NE edge |
| 442 | * Block 2: Wall at NW edge |
| 443 | * Block 3: No walls at NW or NE edge |
| 444 | */ |
| 445 | if (!HasFoundationNW(ti->tile, slope, z)) sprite_block += 1; |
| 446 | if (!HasFoundationNE(ti->tile, slope, z)) sprite_block += 2; |
| 447 | |
| 448 | /* Use the original slope sprites if NW and NE borders should be visible */ |
| 449 | SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * TRKFOUND_BLOCK_SIZE)); |
| 450 | SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SLOPES_INCLINED_OFFSET + sprite_block * TRKFOUND_BLOCK_SIZE; |
| 451 | SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * HALFTILE_BLOCK_SIZE; |
| 452 | |
| 453 | if (IsSteepSlope(ti->tileh)) { |
| 454 | if (!IsNonContinuousFoundation(f)) { |
| 455 | /* Lower part of foundation */ |
| 456 | static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}}; |
| 457 | AddSortableSpriteToDraw(leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, *ti, bounds); |
| 458 | } |
| 459 | |
| 460 | Corner highest_corner = GetHighestSlopeCorner(ti->tileh); |
| 461 | ti->z += ApplyPixelFoundationToSlope(f, ti->tileh); |
| 462 | |
| 463 | if (IsInclinedFoundation(f)) { |
| 464 | /* inclined foundation */ |
| 465 | uint8_t inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0); |
| 466 | |
| 467 | SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}}; |
| 468 | if (f == FOUNDATION_INCLINED_X) bounds.extent.x = TILE_SIZE; |
| 469 | if (f == FOUNDATION_INCLINED_Y) bounds.extent.y = TILE_SIZE; |
| 470 | AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds); |
| 471 | OffsetGroundSprite(0, 0); |
| 472 | } else if (IsLeveledFoundation(f)) { |
| 473 | static constexpr SpriteBounds bounds{{0, 0, -(int)TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}}; |
| 474 | AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, *ti, bounds); |
| 475 | OffsetGroundSprite(0, -(int)TILE_HEIGHT); |
| 476 | } else if (f == FOUNDATION_STEEP_LOWER) { |
| 477 | /* one corner raised */ |
| 478 | OffsetGroundSprite(0, -(int)TILE_HEIGHT); |
| 479 | } else { |
| 480 | /* halftile foundation */ |
| 481 | int8_t x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? TILE_SIZE / 2 : 0); |
| 482 | int8_t y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? TILE_SIZE / 2 : 0); |
| 483 | |
| 484 | SpriteBounds bounds{{x_bb, y_bb, TILE_HEIGHT}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}}; |
| 485 | AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, *ti, bounds); |
| 486 | /* Reposition ground sprite back to original position after bounding box change above. This is similar to |
no test coverage detected