OpenRCT2/src/openrct2/paint/tile_element/Paint.Path.cpp

1283 lines
46 KiB
C++
Raw Normal View History

/*****************************************************************************
* Copyright (c) 2014-2019 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
2017-11-30 18:17:06 +01:00
#include "../../Game.h"
2018-06-22 23:03:53 +02:00
#include "../../config/Config.h"
#include "../../drawing/LightFX.h"
2018-01-06 00:45:53 +01:00
#include "../../interface/Viewport.h"
2018-01-06 18:32:25 +01:00
#include "../../localisation/Localisation.h"
2018-01-02 20:36:42 +01:00
#include "../../object/ObjectList.h"
2017-10-13 10:06:36 +02:00
#include "../../peep/Staff.h"
2017-10-17 13:51:47 +02:00
#include "../../ride/Track.h"
2018-03-19 23:28:40 +01:00
#include "../../ride/TrackDesign.h"
2018-01-10 00:00:09 +01:00
#include "../../ride/TrackPaint.h"
2018-01-11 10:59:26 +01:00
#include "../../world/Footpath.h"
2018-06-22 23:03:53 +02:00
#include "../../world/Map.h"
2018-01-11 10:59:26 +01:00
#include "../../world/Scenery.h"
2018-03-19 23:28:40 +01:00
#include "../../world/Sprite.h"
2018-05-01 16:33:16 +02:00
#include "../../world/Surface.h"
2017-12-14 10:34:12 +01:00
#include "../Paint.h"
#include "../Supports.h"
#include "Paint.Surface.h"
2018-06-22 23:03:53 +02:00
#include "Paint.TileElement.h"
bool gPaintWidePathsAsGhost = false;
// clang-format off
2019-01-18 20:35:43 +01:00
const uint8_t PathSlopeToLandSlope[] =
{
TILE_ELEMENT_SLOPE_SW_SIDE_UP,
TILE_ELEMENT_SLOPE_NW_SIDE_UP,
TILE_ELEMENT_SLOPE_NE_SIDE_UP,
TILE_ELEMENT_SLOPE_SE_SIDE_UP
2016-04-30 22:09:53 +02:00
};
static constexpr const uint8_t byte_98D6E0[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 20, 4, 5, 6, 22, 8, 9, 10, 26, 12, 13, 14, 36,
0, 1, 2, 3, 4, 5, 21, 23, 8, 9, 10, 11, 12, 13, 33, 37,
0, 1, 2, 3, 4, 5, 6, 24, 8, 9, 10, 11, 12, 13, 14, 38,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 29, 30, 34, 39,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 40,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 35, 41,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 42,
0, 1, 2, 3, 4, 5, 6, 7, 8, 25, 10, 27, 12, 31, 14, 43,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 28, 12, 13, 14, 44,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 45,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 46,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 32, 14, 47,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 49,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 50
2016-04-30 22:09:53 +02:00
};
static constexpr const int16_t stru_98D804[][4] = {
{3, 3, 26, 26},
{0, 3, 29, 26},
{3, 3, 26, 29},
{0, 3, 29, 29},
{3, 3, 29, 26},
{0, 3, 32, 26},
{3, 3, 29, 29},
{0, 3, 32, 29},
{3, 0, 26, 29},
{0, 0, 29, 29},
{3, 0, 26, 32},
{0, 0, 29, 32},
{3, 0, 29, 29},
{0, 0, 32, 29},
{3, 0, 29, 32},
{0, 0, 32, 32},
2016-04-30 22:09:53 +02:00
};
static constexpr const uint8_t byte_98D8A4[] = {
0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0
2016-04-30 22:09:53 +02:00
};
// clang-format on
2016-04-30 22:09:53 +02:00
void path_paint_box_support(
paint_session* session, const TileElement* tileElement, int32_t height, PathSurfaceEntry* footpathEntry,
PathRailingsEntry* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags);
void path_paint_pole_support(
paint_session* session, const TileElement* tileElement, int16_t height, PathSurfaceEntry* footpathEntry,
PathRailingsEntry* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags);
2017-12-08 16:47:54 +01:00
2016-06-08 20:53:55 +02:00
/* rct2: 0x006A5AE5 */
static void path_bit_lights_paint(
2018-11-01 13:53:50 +01:00
paint_session* session, rct_scenery_entry* pathBitEntry, const TileElement* tileElement, int32_t height, uint8_t edges,
2018-06-22 23:03:53 +02:00
uint32_t pathBitImageFlags)
{
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
height += 8;
2016-06-08 20:53:55 +02:00
uint32_t imageId;
2016-06-08 20:53:55 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_NE))
{
imageId = pathBitEntry->image + 1;
2016-06-08 20:53:55 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
sub_98197C(session, imageId, 2, 16, 1, 1, 23, height, 3, 16, height + 2);
}
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_SE))
{
imageId = pathBitEntry->image + 2;
2016-06-08 20:53:55 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
sub_98197C(session, imageId, 16, 30, 1, 0, 23, height, 16, 29, height + 2);
}
2016-06-08 20:53:55 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_SW))
{
imageId = pathBitEntry->image + 3;
2016-06-08 20:53:55 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
sub_98197C(session, imageId, 30, 16, 0, 1, 23, height, 29, 16, height + 2);
}
2016-06-08 20:53:55 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_NW))
{
imageId = pathBitEntry->image + 4;
2016-06-08 20:53:55 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
sub_98197C(session, imageId, 16, 2, 1, 1, 23, height, 16, 3, height + 2);
}
2016-06-08 20:53:55 +02:00
}
/* rct2: 0x006A5C94 */
static void path_bit_bins_paint(
2018-11-01 13:53:50 +01:00
paint_session* session, rct_scenery_entry* pathBitEntry, const TileElement* tileElement, int32_t height, uint8_t edges,
2018-06-22 23:03:53 +02:00
uint32_t pathBitImageFlags)
{
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
height += 8;
2016-06-08 20:53:55 +02:00
uint32_t imageId;
2019-02-26 10:29:25 +01:00
bool binsAreVandalised = tileElement->AsPath()->IsBroken();
2016-06-08 20:53:55 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_NE))
{
imageId = pathBitEntry->image + 5;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
2018-02-03 01:07:28 +01:00
bool binIsFull = false;
2018-06-22 23:03:53 +02:00
if (!binsAreVandalised)
{
imageId -= 4;
2016-11-13 20:17:49 +01:00
// Edges have been rotated around the rotation to check addition status
// this will also need to be rotated.
binIsFull = !(tileElement->AsPath()->GetAdditionStatus() & ror8(0x3, (2 * session->CurrentRotation)));
2018-02-03 01:07:28 +01:00
if (binIsFull)
imageId += 8;
}
2016-11-13 20:17:49 +01:00
2018-12-05 19:29:51 +01:00
if (!(session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) || binIsFull || binsAreVandalised)
sub_98197C(session, imageId, 7, 16, 1, 1, 7, height, 7, 16, height + 2);
}
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_SE))
{
imageId = pathBitEntry->image + 6;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
2018-02-03 01:07:28 +01:00
bool binIsFull = false;
2018-06-22 23:03:53 +02:00
if (!binsAreVandalised)
{
imageId -= 4;
2016-06-08 20:53:55 +02:00
// Edges have been rotated around the rotation to check addition status
// this will also need to be rotated.
binIsFull = !(tileElement->AsPath()->GetAdditionStatus() & ror8(0xC, (2 * session->CurrentRotation)));
2018-02-03 01:07:28 +01:00
if (binIsFull)
imageId += 8;
}
2016-11-13 20:17:49 +01:00
2018-12-05 19:29:51 +01:00
if (!(session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) || binIsFull || binsAreVandalised)
sub_98197C(session, imageId, 16, 25, 1, 1, 7, height, 16, 25, height + 2);
}
2016-06-08 20:53:55 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_SW))
{
imageId = pathBitEntry->image + 7;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
2018-02-03 01:07:28 +01:00
bool binIsFull = false;
2018-06-22 23:03:53 +02:00
if (!binsAreVandalised)
{
imageId -= 4;
2016-11-13 20:17:49 +01:00
// Edges have been rotated around the rotation to check addition status
// this will also need to be rotated.
binIsFull = !(tileElement->AsPath()->GetAdditionStatus() & ror8(0x30, (2 * session->CurrentRotation)));
2018-02-03 01:07:28 +01:00
if (binIsFull)
imageId += 8;
}
2016-11-13 20:17:49 +01:00
2018-12-05 19:29:51 +01:00
if (!(session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) || binIsFull || binsAreVandalised)
sub_98197C(session, imageId, 25, 16, 1, 1, 7, height, 25, 16, height + 2);
}
2016-06-08 20:53:55 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_NW))
{
imageId = pathBitEntry->image + 8;
2016-06-08 20:53:55 +02:00
imageId |= pathBitImageFlags;
2016-06-08 20:53:55 +02:00
2018-02-03 01:07:28 +01:00
bool binIsFull = false;
2018-06-22 23:03:53 +02:00
if (!binsAreVandalised)
{
imageId -= 4;
2016-06-08 20:53:55 +02:00
// Edges have been rotated around the rotation to check addition status
// this will also need to be rotated.
binIsFull = !(tileElement->AsPath()->GetAdditionStatus() & ror8(0xC0, (2 * session->CurrentRotation)));
2018-02-03 01:07:28 +01:00
if (binIsFull)
imageId += 8;
}
2016-11-13 20:17:49 +01:00
2018-12-05 19:29:51 +01:00
if (!(session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) || binIsFull || binsAreVandalised)
sub_98197C(session, imageId, 16, 7, 1, 1, 7, height, 16, 7, height + 2);
}
2016-06-08 20:53:55 +02:00
}
/* rct2: 0x006A5E81 */
static void path_bit_benches_paint(
2018-11-01 13:53:50 +01:00
paint_session* session, rct_scenery_entry* pathBitEntry, const TileElement* tileElement, int32_t height, uint8_t edges,
2018-06-22 23:03:53 +02:00
uint32_t pathBitImageFlags)
{
uint32_t imageId;
2016-06-09 20:47:36 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_NE))
{
imageId = pathBitEntry->image + 1;
2016-06-09 20:47:36 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-09 20:47:36 +02:00
imageId |= pathBitImageFlags;
2016-06-09 20:47:36 +02:00
sub_98197C(session, imageId, 7, 16, 0, 16, 7, height, 6, 8, height + 2);
}
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_SE))
{
imageId = pathBitEntry->image + 2;
2016-06-09 20:47:36 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-09 20:47:36 +02:00
imageId |= pathBitImageFlags;
2016-06-09 20:47:36 +02:00
sub_98197C(session, imageId, 16, 25, 16, 0, 7, height, 8, 23, height + 2);
}
2016-06-09 20:47:36 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_SW))
{
imageId = pathBitEntry->image + 3;
2016-06-09 20:47:36 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-09 20:47:36 +02:00
imageId |= pathBitImageFlags;
2016-06-09 20:47:36 +02:00
sub_98197C(session, imageId, 25, 16, 0, 16, 7, height, 23, 8, height + 2);
}
2016-06-09 20:47:36 +02:00
2018-06-22 23:03:53 +02:00
if (!(edges & EDGE_NW))
{
imageId = pathBitEntry->image + 4;
2016-06-09 20:47:36 +02:00
2019-02-26 10:29:25 +01:00
if (tileElement->AsPath()->IsBroken())
imageId += 4;
2016-06-09 20:47:36 +02:00
imageId |= pathBitImageFlags;
2016-06-09 20:47:36 +02:00
sub_98197C(session, imageId, 16, 7, 16, 0, 7, height, 8, 6, height + 2);
}
2016-06-08 20:53:55 +02:00
}
/* rct2: 0x006A6008 */
static void path_bit_jumping_fountains_paint(
2018-06-22 23:03:53 +02:00
paint_session* session, rct_scenery_entry* pathBitEntry, int32_t height, uint32_t pathBitImageFlags, rct_drawpixelinfo* dpi)
{
if (dpi->zoom_level != 0)
return;
2016-06-09 20:47:36 +02:00
uint32_t imageId = pathBitEntry->image;
imageId |= pathBitImageFlags;
2016-06-09 20:47:36 +02:00
sub_98197C(session, imageId + 1, 0, 0, 1, 1, 2, height, 3, 3, height + 2);
sub_98197C(session, imageId + 2, 0, 0, 1, 1, 2, height, 3, 29, height + 2);
sub_98197C(session, imageId + 3, 0, 0, 1, 1, 2, height, 29, 29, height + 2);
sub_98197C(session, imageId + 4, 0, 0, 1, 1, 2, height, 29, 3, height + 2);
2016-06-08 20:53:55 +02:00
}
2016-04-30 22:09:53 +02:00
/**
* rct2: 0x006A4101
2017-10-31 12:57:40 +01:00
* @param tile_element (esi)
2016-04-30 22:09:53 +02:00
*/
static void sub_6A4101(
2019-01-20 12:20:41 +01:00
paint_session* session, const TileElement* tile_element, uint16_t height, uint32_t connectedEdges, bool word_F3F038,
PathRailingsEntry* railingEntry, uint32_t imageFlags)
2016-04-30 22:09:53 +02:00
{
uint32_t base_image_id = railingEntry->railings_image | imageFlags;
2018-10-03 10:57:29 +02:00
if (tile_element->AsPath()->IsQueue())
2018-06-22 23:03:53 +02:00
{
2019-01-20 12:20:41 +01:00
uint8_t local_ebp = connectedEdges & 0x0F;
2018-09-16 16:17:35 +02:00
if (tile_element->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
switch ((tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation)
2018-06-22 23:03:53 +02:00
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
{
case 0:
sub_98197C(session, 22 + base_image_id, 0, 4, 32, 1, 23, height, 0, 4, height + 2);
sub_98197C(session, 22 + base_image_id, 0, 28, 32, 1, 23, height, 0, 28, height + 2);
break;
case 1:
sub_98197C(session, 21 + base_image_id, 4, 0, 1, 32, 23, height, 4, 0, height + 2);
sub_98197C(session, 21 + base_image_id, 28, 0, 1, 32, 23, height, 28, 0, height + 2);
break;
case 2:
sub_98197C(session, 23 + base_image_id, 0, 4, 32, 1, 23, height, 0, 4, height + 2);
sub_98197C(session, 23 + base_image_id, 0, 28, 32, 1, 23, height, 0, 28, height + 2);
break;
case 3:
sub_98197C(session, 20 + base_image_id, 4, 0, 1, 32, 23, height, 4, 0, height + 2);
sub_98197C(session, 20 + base_image_id, 28, 0, 1, 32, 23, height, 28, 0, height + 2);
break;
}
2018-06-22 23:03:53 +02:00
}
else
{
switch (local_ebp)
{
case 1:
sub_98197C(session, 17 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 17 + base_image_id, 0, 28, 28, 1, 7, height, 0, 28, height + 2);
break;
case 2:
sub_98197C(session, 18 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(session, 18 + base_image_id, 28, 0, 1, 28, 7, height, 28, 0, height + 2);
break;
case 3:
sub_98197C(session, 17 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(
session, 18 + base_image_id, 28, 0, 1, 28, 7, height, 28, 4,
height + 2); // bound_box_offset_y seems to be a bug
sub_98197C(session, 25 + base_image_id, 0, 0, 4, 4, 7, height, 0, 28, height + 2);
break;
case 4:
sub_98197C(session, 19 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 19 + base_image_id, 0, 28, 28, 1, 7, height, 0, 28, height + 2);
break;
case 5:
sub_98197C(session, 15 + base_image_id, 0, 4, 32, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 15 + base_image_id, 0, 28, 32, 1, 7, height, 0, 28, height + 2);
break;
case 6:
sub_98197C(session, 18 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(session, 19 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 26 + base_image_id, 0, 0, 4, 4, 7, height, 28, 28, height + 2);
break;
case 8:
sub_98197C(session, 16 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(session, 16 + base_image_id, 28, 0, 1, 28, 7, height, 28, 0, height + 2);
break;
case 9:
sub_98197C(session, 16 + base_image_id, 28, 0, 1, 28, 7, height, 28, 0, height + 2);
sub_98197C(session, 17 + base_image_id, 0, 28, 28, 1, 7, height, 0, 28, height + 2);
sub_98197C(session, 24 + base_image_id, 0, 0, 4, 4, 7, height, 0, 0, height + 2);
break;
case 10:
sub_98197C(session, 14 + base_image_id, 4, 0, 1, 32, 7, height, 4, 0, height + 2);
sub_98197C(session, 14 + base_image_id, 28, 0, 1, 32, 7, height, 28, 0, height + 2);
break;
case 12:
sub_98197C(session, 16 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(
session, 19 + base_image_id, 0, 28, 28, 1, 7, height, 4, 28,
height + 2); // bound_box_offset_x seems to be a bug
sub_98197C(session, 27 + base_image_id, 0, 0, 4, 4, 7, height, 28, 0, height + 2);
break;
default:
// purposely left empty
break;
}
}
if (!tile_element->AsPath()->HasQueueBanner())
2018-06-22 23:03:53 +02:00
{
return;
}
uint8_t direction = tile_element->AsPath()->GetQueueBannerDirection();
// Draw ride sign
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_RIDE;
2018-09-16 16:17:35 +02:00
if (tile_element->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
if (tile_element->AsPath()->GetSlopeDirection() == direction)
height += 16;
}
direction += session->CurrentRotation;
direction &= 3;
LocationXYZ16 boundBoxOffsets = { BannerBoundBoxes[direction][0].x, BannerBoundBoxes[direction][0].y,
static_cast<int16_t>(height + 2) };
uint32_t imageId = (direction << 1) + base_image_id + 28;
// Draw pole in the back
sub_98197C(session, imageId, 0, 0, 1, 1, 21, height, boundBoxOffsets.x, boundBoxOffsets.y, boundBoxOffsets.z);
// Draw pole in the front and banner
boundBoxOffsets.x = BannerBoundBoxes[direction][1].x;
boundBoxOffsets.y = BannerBoundBoxes[direction][1].y;
imageId++;
sub_98197C(session, imageId, 0, 0, 1, 1, 21, height, boundBoxOffsets.x, boundBoxOffsets.y, boundBoxOffsets.z);
direction--;
// If text shown
if (direction < 2 && tile_element->AsPath()->GetRideIndex() != RIDE_ID_NULL && imageFlags == 0)
2018-06-22 23:03:53 +02:00
{
uint16_t scrollingMode = railingEntry->scrolling_mode;
scrollingMode += direction;
set_format_arg(0, uint32_t, 0);
set_format_arg(4, uint32_t, 0);
Ride* ride = get_ride(tile_element->AsPath()->GetRideIndex());
rct_string_id string_id = STR_RIDE_ENTRANCE_CLOSED;
2018-06-22 23:03:53 +02:00
if (ride->status == RIDE_STATUS_OPEN && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
{
set_format_arg(0, rct_string_id, ride->name);
set_format_arg(2, uint32_t, ride->name_arguments);
string_id = STR_RIDE_ENTRANCE_NAME;
}
2018-06-22 23:03:53 +02:00
if (gConfigGeneral.upper_case_banners)
{
format_string_to_upper(
gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), string_id, gCommonFormatArgs);
2018-06-22 23:03:53 +02:00
}
else
{
format_string(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), string_id, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;
uint16_t string_width = gfx_get_string_width(gCommonStringFormatBuffer);
uint16_t scroll = (gCurrentTicks / 2) % string_width;
sub_98199C(
session, scrolling_text_setup(session, string_id, scroll, scrollingMode), 0, 0, 1, 1, 21, height + 7,
boundBoxOffsets.x, boundBoxOffsets.y, boundBoxOffsets.z);
}
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_FOOTPATH;
2018-06-22 23:03:53 +02:00
if (imageFlags != 0)
{
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_NONE;
}
return;
}
uint32_t drawnCorners = 0;
2019-01-20 12:20:41 +01:00
// If the path is not drawn over the supports, then no corner sprites will be drawn (making double-width paths
// look like connected series of intersections).
if (tile_element->AsPath()->ShouldDrawPathOverSupports())
2018-06-22 23:03:53 +02:00
{
drawnCorners = (connectedEdges & FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK) >> 4;
}
2018-09-16 16:17:35 +02:00
if (tile_element->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
switch ((tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation)
2018-06-22 23:03:53 +02:00
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
{
case 0:
sub_98197C(session, 8 + base_image_id, 0, 4, 32, 1, 23, height, 0, 4, height + 2);
sub_98197C(session, 8 + base_image_id, 0, 28, 32, 1, 23, height, 0, 28, height + 2);
break;
case 1:
sub_98197C(session, 7 + base_image_id, 4, 0, 1, 32, 23, height, 4, 0, height + 2);
sub_98197C(session, 7 + base_image_id, 28, 0, 1, 32, 23, height, 28, 0, height + 2);
break;
case 2:
sub_98197C(session, 9 + base_image_id, 0, 4, 32, 1, 23, height, 0, 4, height + 2);
sub_98197C(session, 9 + base_image_id, 0, 28, 32, 1, 23, height, 0, 28, height + 2);
break;
case 3:
sub_98197C(session, 6 + base_image_id, 4, 0, 1, 32, 23, height, 4, 0, height + 2);
sub_98197C(session, 6 + base_image_id, 28, 0, 1, 32, 23, height, 28, 0, height + 2);
break;
}
2018-06-22 23:03:53 +02:00
}
else
{
if (!word_F3F038)
{
return;
}
2019-01-20 12:20:41 +01:00
switch (connectedEdges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK)
2018-06-22 23:03:53 +02:00
{
case 0:
// purposely left empty
break;
case 1:
sub_98197C(session, 3 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 3 + base_image_id, 0, 28, 28, 1, 7, height, 0, 28, height + 2);
break;
case 2:
sub_98197C(session, 4 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(session, 4 + base_image_id, 28, 0, 1, 28, 7, height, 28, 0, height + 2);
break;
case 4:
sub_98197C(session, 5 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 5 + base_image_id, 0, 28, 28, 1, 7, height, 0, 28, height + 2);
break;
case 5:
sub_98197C(session, 1 + base_image_id, 0, 4, 32, 1, 7, height, 0, 4, height + 2);
sub_98197C(session, 1 + base_image_id, 0, 28, 32, 1, 7, height, 0, 28, height + 2);
break;
case 8:
sub_98197C(session, 2 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(session, 2 + base_image_id, 28, 0, 1, 28, 7, height, 28, 0, height + 2);
break;
case 10:
sub_98197C(session, 0 + base_image_id, 4, 0, 1, 32, 7, height, 4, 0, height + 2);
sub_98197C(session, 0 + base_image_id, 28, 0, 1, 32, 7, height, 28, 0, height + 2);
break;
case 3:
sub_98197C(session, 3 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
sub_98197C(
session, 4 + base_image_id, 28, 0, 1, 28, 7, height, 28, 4,
height + 2); // bound_box_offset_y seems to be a bug
if (!(drawnCorners & FOOTPATH_CORNER_0))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 11 + base_image_id, 0, 0, 4, 4, 7, height, 0, 28, height + 2);
}
break;
case 6:
sub_98197C(session, 4 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(session, 5 + base_image_id, 0, 4, 28, 1, 7, height, 0, 4, height + 2);
if (!(drawnCorners & FOOTPATH_CORNER_1))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 12 + base_image_id, 0, 0, 4, 4, 7, height, 28, 28, height + 2);
}
break;
case 9:
sub_98197C(session, 2 + base_image_id, 28, 0, 1, 28, 7, height, 28, 0, height + 2);
sub_98197C(session, 3 + base_image_id, 0, 28, 28, 1, 7, height, 0, 28, height + 2);
if (!(drawnCorners & FOOTPATH_CORNER_3))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 10 + base_image_id, 0, 0, 4, 4, 7, height, 0, 0, height + 2);
}
break;
case 12:
sub_98197C(session, 2 + base_image_id, 4, 0, 1, 28, 7, height, 4, 0, height + 2);
sub_98197C(
session, 5 + base_image_id, 0, 28, 28, 1, 7, height, 4, 28,
height + 2); // bound_box_offset_x seems to be a bug
if (!(drawnCorners & FOOTPATH_CORNER_2))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 13 + base_image_id, 0, 0, 4, 4, 7, height, 28, 0, height + 2);
}
break;
case 7:
sub_98197C(session, 1 + base_image_id, 0, 4, 32, 1, 7, height, 0, 4, height + 2);
if (!(drawnCorners & FOOTPATH_CORNER_0))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 11 + base_image_id, 0, 0, 4, 4, 7, height, 0, 28, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_1))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 12 + base_image_id, 0, 0, 4, 4, 7, height, 28, 28, height + 2);
}
break;
case 13:
sub_98197C(session, 1 + base_image_id, 0, 28, 32, 1, 7, height, 0, 28, height + 2);
if (!(drawnCorners & FOOTPATH_CORNER_2))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 13 + base_image_id, 0, 0, 4, 4, 7, height, 28, 0, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_3))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 10 + base_image_id, 0, 0, 4, 4, 7, height, 0, 0, height + 2);
}
break;
case 14:
sub_98197C(session, 0 + base_image_id, 4, 0, 1, 32, 7, height, 4, 0, height + 2);
if (!(drawnCorners & FOOTPATH_CORNER_1))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 12 + base_image_id, 0, 0, 4, 4, 7, height, 28, 28, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_2))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 13 + base_image_id, 0, 0, 4, 4, 7, height, 28, 0, height + 2);
}
break;
case 11:
sub_98197C(session, 0 + base_image_id, 28, 0, 1, 32, 7, height, 28, 0, height + 2);
if (!(drawnCorners & FOOTPATH_CORNER_0))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 11 + base_image_id, 0, 0, 4, 4, 7, height, 0, 28, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_3))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 10 + base_image_id, 0, 0, 4, 4, 7, height, 0, 0, height + 2);
}
break;
case 15:
if (!(drawnCorners & FOOTPATH_CORNER_0))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 11 + base_image_id, 0, 0, 4, 4, 7, height, 0, 28, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_1))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 12 + base_image_id, 0, 0, 4, 4, 7, height, 28, 28, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_2))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 13 + base_image_id, 0, 0, 4, 4, 7, height, 28, 0, height + 2);
}
if (!(drawnCorners & FOOTPATH_CORNER_3))
2018-06-22 23:03:53 +02:00
{
sub_98197C(session, 10 + base_image_id, 0, 0, 4, 4, 7, height, 0, 0, height + 2);
}
break;
}
}
2016-04-30 22:09:53 +02:00
}
/**
* rct2: 0x006A3F61
2017-10-31 12:57:40 +01:00
* @param tile_element (esp[0])
* @param connectedEdges (bp) (relative to the camera's rotation)
2016-04-30 22:09:53 +02:00
* @param height (dx)
* @param railingEntry (0x00F3EF6C)
2016-06-14 21:33:56 +02:00
* @param imageFlags (0x00F3EF70)
* @param sceneryImageFlags (0x00F3EF74)
2016-04-30 22:09:53 +02:00
*/
static void sub_6A3F61(
2018-11-01 13:53:50 +01:00
paint_session* session, const TileElement* tile_element, uint16_t connectedEdges, uint16_t height,
PathRailingsEntry* railingEntry, uint32_t imageFlags, uint32_t sceneryImageFlags, bool word_F3F038)
2016-04-30 22:09:53 +02:00
{
// eax --
// ebx --
// ecx
// edx
// esi --
// edi --
// ebp
// esp: [ esi, ???, 000]
// Probably drawing benches etc.
2018-12-18 16:40:28 +01:00
rct_drawpixelinfo* dpi = &session->DPI;
2018-06-22 23:03:53 +02:00
if (dpi->zoom_level <= 1)
{
if (!gTrackDesignSaveMode)
{
if (tile_element->AsPath()->HasAddition())
2018-06-22 23:03:53 +02:00
{
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM;
2018-06-22 23:03:53 +02:00
if (sceneryImageFlags != 0)
{
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_NONE;
}
// Draw additional path bits (bins, benches, lamps, queue screens)
rct_scenery_entry* sceneryEntry = tile_element->AsPath()->GetAdditionEntry();
2018-02-03 01:07:28 +01:00
// Can be null if the object is not loaded.
if (sceneryEntry == nullptr)
return;
2019-02-27 11:54:08 +01:00
if ((session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES) && !(tile_element->AsPath()->IsBroken())
2018-06-22 23:03:53 +02:00
&& !(sceneryEntry->path_bit.draw_type == PATH_BIT_DRAW_TYPE_BINS))
2018-02-03 01:07:28 +01:00
{
return;
}
2018-06-22 23:03:53 +02:00
switch (sceneryEntry->path_bit.draw_type)
{
case PATH_BIT_DRAW_TYPE_LIGHTS:
path_bit_lights_paint(
session, sceneryEntry, tile_element, height, (uint8_t)connectedEdges, sceneryImageFlags);
break;
case PATH_BIT_DRAW_TYPE_BINS:
path_bit_bins_paint(
session, sceneryEntry, tile_element, height, (uint8_t)connectedEdges, sceneryImageFlags);
break;
case PATH_BIT_DRAW_TYPE_BENCHES:
path_bit_benches_paint(
session, sceneryEntry, tile_element, height, (uint8_t)connectedEdges, sceneryImageFlags);
break;
case PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS:
path_bit_jumping_fountains_paint(session, sceneryEntry, height, sceneryImageFlags, dpi);
break;
}
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_FOOTPATH;
2018-06-22 23:03:53 +02:00
if (sceneryImageFlags != 0)
{
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_NONE;
}
}
}
// Redundant zoom-level check removed
sub_6A4101(session, tile_element, height, connectedEdges, word_F3F038, railingEntry, imageFlags);
}
// This is about tunnel drawing
uint8_t direction = (tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation)
2018-06-22 23:03:53 +02:00
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
2018-09-16 16:17:35 +02:00
bool sloped = tile_element->AsPath()->IsSloped();
2018-06-22 23:03:53 +02:00
if (connectedEdges & EDGE_SE)
{
// Bottom right of tile is a tunnel
2018-06-22 23:03:53 +02:00
if (sloped && direction == EDGE_NE)
{
// Path going down into the tunnel
2017-09-03 02:51:59 +02:00
paint_util_push_tunnel_right(session, height + 16, TUNNEL_10);
2018-06-22 23:03:53 +02:00
}
else if (connectedEdges & EDGE_NE)
{
// Flat path with edge to the right (north-east)
2017-09-03 02:51:59 +02:00
paint_util_push_tunnel_right(session, height, TUNNEL_11);
2018-06-22 23:03:53 +02:00
}
else
{
// Path going up, or flat and not connected to the right
2017-09-03 02:51:59 +02:00
paint_util_push_tunnel_right(session, height, TUNNEL_10);
}
}
2018-06-22 23:03:53 +02:00
if (!(connectedEdges & EDGE_SW))
{
return;
}
// Bottom left of the tile is a tunnel
2018-06-22 23:03:53 +02:00
if (sloped && direction == EDGE_SE)
{
// Path going down into the tunnel
2017-09-03 02:51:59 +02:00
paint_util_push_tunnel_left(session, height + 16, TUNNEL_10);
2018-06-22 23:03:53 +02:00
}
else if (connectedEdges & EDGE_NW)
{
// Flat path with edge to the left (north-west)
2018-06-22 23:03:53 +02:00
paint_util_push_tunnel_left(session, height, TUNNEL_11);
}
else
{
// Path going up, or flat and not connected to the left
2018-06-22 23:03:53 +02:00
paint_util_push_tunnel_left(session, height, TUNNEL_10);
}
2016-04-30 22:09:53 +02:00
}
/**
* rct2: 0x0006A3590
*/
2018-11-01 13:53:50 +01:00
void path_paint(paint_session* session, uint16_t height, const TileElement* tile_element)
2016-04-30 22:09:53 +02:00
{
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_FOOTPATH;
2019-01-18 20:35:43 +01:00
bool hasSupports = false;
uint32_t sceneryImageFlags = 0;
uint32_t imageFlags = 0;
2018-06-22 23:03:53 +02:00
if (gTrackDesignSaveMode)
{
2018-10-03 10:57:29 +02:00
if (tile_element->AsPath()->IsQueue())
2018-06-22 23:03:53 +02:00
{
if (tile_element->AsPath()->GetRideIndex() != gTrackDesignSaveRideIndex)
2018-06-22 23:03:53 +02:00
{
return;
}
}
2018-06-22 23:03:53 +02:00
if (!track_design_save_contains_tile_element(tile_element))
{
2018-01-29 20:54:49 +01:00
imageFlags = SPRITE_ID_PALETTE_COLOUR_1(PALETTE_46);
}
}
2018-12-05 19:29:51 +01:00
if (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES)
{
2018-01-29 20:54:49 +01:00
imageFlags = SPRITE_ID_PALETTE_COLOUR_1(PALETTE_46);
}
if (tile_element->AsPath()->AdditionIsGhost())
2018-06-22 23:03:53 +02:00
{
2017-12-04 10:12:42 +01:00
sceneryImageFlags = CONSTRUCTION_MARKER;
}
if (tile_element->IsGhost())
2018-06-22 23:03:53 +02:00
{
2017-09-02 23:31:39 +02:00
session->InteractionType = VIEWPORT_INTERACTION_ITEM_NONE;
2017-12-04 10:12:42 +01:00
imageFlags = CONSTRUCTION_MARKER;
}
// For debugging purpose, show blocked tiles with a colour
2019-02-26 10:15:39 +01:00
if (gPaintBlockedTiles && tile_element->AsPath()->IsBlockedByVehicle())
{
imageFlags = COLOUR_BRIGHT_GREEN << 19 | COLOUR_GREY << 24 | IMAGE_TYPE_REMAP;
}
// Draw wide flags as ghosts, leaving only the "walkable" paths to be drawn normally
if (gPaintWidePathsAsGhost && tile_element->AsPath()->IsWide())
{
imageFlags &= 0x7FFFF;
imageFlags |= CONSTRUCTION_MARKER;
}
int16_t x = session->MapPosition.x, y = session->MapPosition.y;
2018-11-01 13:53:50 +01:00
TileElement* surface = map_get_surface_element_at({ session->MapPosition.x, session->MapPosition.y });
uint16_t bl = height / 8;
2018-06-22 23:03:53 +02:00
if (surface == nullptr)
{
2019-01-18 20:35:43 +01:00
hasSupports = true;
2018-06-22 23:03:53 +02:00
}
else if (surface->base_height != bl)
{
2019-01-18 20:35:43 +01:00
hasSupports = true;
2018-06-22 23:03:53 +02:00
}
else
{
2018-09-16 16:17:35 +02:00
if (tile_element->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
// Diagonal path
2019-01-18 20:35:43 +01:00
if (surface->AsSurface()->GetSlope() != PathSlopeToLandSlope[tile_element->AsPath()->GetSlopeDirection()])
2018-06-22 23:03:53 +02:00
{
2019-01-18 20:35:43 +01:00
hasSupports = true;
}
2018-06-22 23:03:53 +02:00
}
else
{
2018-09-14 14:54:12 +02:00
if (surface->AsSurface()->GetSlope() != TILE_ELEMENT_SLOPE_FLAT)
2018-06-22 23:03:53 +02:00
{
2019-01-18 20:35:43 +01:00
hasSupports = true;
}
}
}
2018-06-22 23:03:53 +02:00
if (gStaffDrawPatrolAreas != 0xFFFF)
{
int32_t staffIndex = gStaffDrawPatrolAreas;
uint8_t staffType = staffIndex & 0x7FFF;
bool is_staff_list = staffIndex & 0x8000;
2017-09-02 23:31:39 +02:00
x = session->MapPosition.x;
y = session->MapPosition.y;
uint8_t patrolColour = COLOUR_LIGHT_BLUE;
2018-06-22 23:03:53 +02:00
if (!is_staff_list)
{
2019-02-28 20:28:58 +01:00
Peep* staff = GET_PEEP(staffIndex);
2018-06-22 23:03:53 +02:00
if (!staff_is_patrol_area_set(staff->staff_id, x, y))
{
patrolColour = COLOUR_GREY;
}
staffType = staff->staff_type;
}
2018-06-22 23:03:53 +02:00
if (staff_is_patrol_area_set(200 + staffType, x, y))
{
uint32_t imageId = 2618;
int32_t height2 = tile_element->base_height * 8;
2018-09-16 16:17:35 +02:00
if (tile_element->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
imageId = 2619 + ((tile_element->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 3);
height2 += 16;
}
sub_98196C(session, imageId | patrolColour << 19 | IMAGE_TYPE_REMAP, 16, 16, 1, 1, 0, height2 + 2);
}
}
2018-12-05 19:29:51 +01:00
if (session->ViewFlags & VIEWPORT_FLAG_PATH_HEIGHTS)
2018-06-22 23:03:53 +02:00
{
uint16_t height2 = 3 + tile_element->base_height * 8;
2018-09-16 16:17:35 +02:00
if (tile_element->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
height2 += 8;
}
uint32_t imageId = (SPR_HEIGHT_MARKER_BASE + height2 / 16) | COLOUR_GREY << 19 | IMAGE_TYPE_REMAP;
imageId += get_height_marker_offset();
imageId -= gMapBaseZ;
sub_98196C(session, imageId, 16, 16, 1, 1, 0, height2);
}
PathSurfaceEntry* footpathEntry = tile_element->AsPath()->GetPathEntry();
PathRailingsEntry* railingEntry = tile_element->AsPath()->GetRailingEntry();
2019-01-02 19:52:53 +01:00
if (footpathEntry != nullptr && railingEntry != nullptr)
2018-06-22 23:03:53 +02:00
{
if (railingEntry->support_type == RailingEntrySupportType::Pole)
2018-06-22 23:03:53 +02:00
{
2019-01-02 19:52:53 +01:00
path_paint_pole_support(
2019-01-18 20:35:43 +01:00
session, tile_element, height, footpathEntry, railingEntry, hasSupports, imageFlags, sceneryImageFlags);
}
2018-06-22 23:03:53 +02:00
else
{
2019-01-02 19:52:53 +01:00
path_paint_box_support(
2019-01-18 20:35:43 +01:00
session, tile_element, height, footpathEntry, railingEntry, hasSupports, imageFlags, sceneryImageFlags);
}
}
2016-10-17 23:51:18 +02:00
2016-10-24 14:06:44 +02:00
#ifdef __ENABLE_LIGHTFX__
2018-06-22 23:03:53 +02:00
if (lightfx_is_available())
{
2019-02-26 10:29:25 +01:00
if (tile_element->AsPath()->HasAddition() && !(tile_element->AsPath()->IsBroken()))
2018-06-22 23:03:53 +02:00
{
rct_scenery_entry* sceneryEntry = tile_element->AsPath()->GetAdditionEntry();
if (sceneryEntry != nullptr && sceneryEntry->path_bit.flags & PATH_BIT_FLAG_LAMP)
2018-06-22 23:03:53 +02:00
{
if (!(tile_element->AsPath()->GetEdges() & EDGE_NE))
2018-06-22 23:03:53 +02:00
{
lightfx_add_3d_light_magic_from_drawing_tile(
session->MapPosition, -16, 0, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3);
}
if (!(tile_element->AsPath()->GetEdges() & EDGE_SE))
2018-06-22 23:03:53 +02:00
{
lightfx_add_3d_light_magic_from_drawing_tile(
session->MapPosition, 0, 16, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3);
}
if (!(tile_element->AsPath()->GetEdges() & EDGE_SW))
2018-06-22 23:03:53 +02:00
{
lightfx_add_3d_light_magic_from_drawing_tile(
session->MapPosition, 16, 0, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3);
}
if (!(tile_element->AsPath()->GetEdges() & EDGE_NW))
2018-06-22 23:03:53 +02:00
{
lightfx_add_3d_light_magic_from_drawing_tile(
session->MapPosition, 0, -16, height + 23, LIGHTFX_LIGHT_TYPE_LANTERN_3);
}
}
}
}
2016-10-17 23:51:18 +02:00
#endif
}
2016-04-30 22:09:53 +02:00
void path_paint_box_support(
paint_session* session, const TileElement* tileElement, int32_t height, PathSurfaceEntry* footpathEntry,
PathRailingsEntry* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags)
2016-04-30 22:09:53 +02:00
{
2018-10-03 10:57:29 +02:00
PathElement* pathElement = tileElement->AsPath();
// Rol edges around rotation
uint8_t edges = ((tileElement->AsPath()->GetEdges() << session->CurrentRotation) & 0xF)
| (((tileElement->AsPath()->GetEdges()) << session->CurrentRotation) >> 4);
uint8_t corners = (((tileElement->AsPath()->GetCorners()) << session->CurrentRotation) & 0xF)
| (((tileElement->AsPath()->GetCorners()) << session->CurrentRotation) >> 4);
2018-06-22 23:03:53 +02:00
LocationXY16 boundBoxOffset = { stru_98D804[edges][0], stru_98D804[edges][1] };
LocationXY16 boundBoxSize = { stru_98D804[edges][2], stru_98D804[edges][3] };
uint16_t edi = edges | (corners << 4);
uint32_t imageId;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
imageId = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation)
2018-06-22 23:03:53 +02:00
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
+ 16;
}
else
{
imageId = byte_98D6E0[edi];
}
imageId += footpathEntry->image;
2018-06-22 23:03:53 +02:00
if (!session->DidPassSurface)
{
boundBoxOffset.x = 3;
boundBoxOffset.y = 3;
boundBoxSize.x = 26;
boundBoxSize.y = 26;
}
// By default, add 1 to the z bounding box to always clip above the surface
uint8_t boundingBoxZOffset = 1;
// If we are on the same tile as a straight track, add the offset 2 so we
// can clip above gravel part of the track sprite
if (session->TrackElementOnSameHeight)
{
if (session->TrackElementOnSameHeight->AsTrack()->GetTrackType() == TRACK_ELEM_FLAT)
{
boundingBoxZOffset = 2;
}
}
if (!hasSupports || !session->DidPassSurface)
2018-06-22 23:03:53 +02:00
{
sub_98197C(
session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x, boundBoxOffset.y,
height + boundingBoxZOffset);
2018-06-22 23:03:53 +02:00
}
else
{
uint32_t image_id;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
image_id = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation)
2018-06-22 23:03:53 +02:00
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
2019-01-02 19:52:53 +01:00
+ railingEntry->bridge_image + 51;
2018-06-22 23:03:53 +02:00
}
else
{
2019-01-02 19:52:53 +01:00
image_id = byte_98D8A4[edges] + railingEntry->bridge_image + 49;
}
sub_98197C(
session, image_id | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x, boundBoxOffset.y,
height + boundingBoxZOffset);
2019-01-02 19:52:53 +01:00
// TODO: Revert this when path import works correctly.
if (!pathElement->IsQueue() && !pathElement->ShouldDrawPathOverSupports())
2018-06-22 23:03:53 +02:00
{
// don't draw
2018-06-22 23:03:53 +02:00
}
else
{
sub_98199C(
session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x,
boundBoxOffset.y, height + boundingBoxZOffset);
}
}
sub_6A3F61(session, tileElement, edi, height, railingEntry, imageFlags, sceneryImageFlags, hasSupports);
uint16_t ax = 0;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
ax = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 0x3) + 1;
}
2018-06-22 23:03:53 +02:00
if (byte_98D8A4[edges] == 0)
{
2019-01-02 19:52:53 +01:00
path_a_supports_paint_setup(session, 0, ax, height, imageFlags, railingEntry, nullptr);
2018-06-22 23:03:53 +02:00
}
else
{
2019-01-02 19:52:53 +01:00
path_a_supports_paint_setup(session, 1, ax, height, imageFlags, railingEntry, nullptr);
}
height += 32;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
height += 16;
}
paint_util_set_general_support_height(session, height, 0x20);
if (pathElement->IsQueue() || (tileElement->AsPath()->GetEdgesAndCorners() != 0xFF && hasSupports))
2018-06-22 23:03:53 +02:00
{
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
return;
}
if (tileElement->AsPath()->GetEdgesAndCorners() == 0xFF)
2018-06-22 23:03:53 +02:00
{
paint_util_set_segment_support_height(session, SEGMENT_C8 | SEGMENT_CC | SEGMENT_D0 | SEGMENT_D4, 0xFFFF, 0);
return;
}
paint_util_set_segment_support_height(session, SEGMENT_C4, 0xFFFF, 0);
2018-06-22 23:03:53 +02:00
if (edges & 1)
{
paint_util_set_segment_support_height(session, SEGMENT_CC, 0xFFFF, 0);
}
2018-06-22 23:03:53 +02:00
if (edges & 2)
{
paint_util_set_segment_support_height(session, SEGMENT_D4, 0xFFFF, 0);
}
2018-06-22 23:03:53 +02:00
if (edges & 4)
{
paint_util_set_segment_support_height(session, SEGMENT_D0, 0xFFFF, 0);
}
2018-06-22 23:03:53 +02:00
if (edges & 8)
{
paint_util_set_segment_support_height(session, SEGMENT_C8, 0xFFFF, 0);
}
2016-04-30 22:09:53 +02:00
}
void path_paint_pole_support(
paint_session* session, const TileElement* tileElement, int16_t height, PathSurfaceEntry* footpathEntry,
PathRailingsEntry* railingEntry, bool hasSupports, uint32_t imageFlags, uint32_t sceneryImageFlags)
2016-04-30 22:09:53 +02:00
{
2018-10-03 10:57:29 +02:00
PathElement* pathElement = tileElement->AsPath();
// Rol edges around rotation
uint8_t edges = ((tileElement->AsPath()->GetEdges() << session->CurrentRotation) & 0xF)
| (((tileElement->AsPath()->GetEdges()) << session->CurrentRotation) >> 4);
2018-06-22 23:03:53 +02:00
LocationXY16 boundBoxOffset = { stru_98D804[edges][0], stru_98D804[edges][1] };
2018-06-22 23:03:53 +02:00
LocationXY16 boundBoxSize = { stru_98D804[edges][2], stru_98D804[edges][3] };
uint8_t corners = (((tileElement->AsPath()->GetCorners()) << session->CurrentRotation) & 0xF)
| (((tileElement->AsPath()->GetCorners()) << session->CurrentRotation) >> 4);
uint16_t edi = edges | (corners << 4);
uint32_t imageId;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
imageId = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation) & 3) + 16;
}
2018-06-22 23:03:53 +02:00
else
{
imageId = byte_98D6E0[edi];
}
imageId += footpathEntry->image;
// Below Surface
2018-06-22 23:03:53 +02:00
if (!session->DidPassSurface)
{
boundBoxOffset.x = 3;
boundBoxOffset.y = 3;
boundBoxSize.x = 26;
boundBoxSize.y = 26;
}
// By default, add 1 to the z bounding box to always clip above the surface
uint8_t boundingBoxZOffset = 1;
// If we are on the same tile as a straight track, add the offset 2 so we
// can clip above gravel part of the track sprite
if (session->TrackElementOnSameHeight)
{
if (session->TrackElementOnSameHeight->AsTrack()->GetTrackType() == TRACK_ELEM_FLAT)
{
boundingBoxZOffset = 2;
}
}
if (!hasSupports || !session->DidPassSurface)
2018-06-22 23:03:53 +02:00
{
sub_98197C(
session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x, boundBoxOffset.y,
height + boundingBoxZOffset);
}
2018-06-22 23:03:53 +02:00
else
{
uint32_t bridgeImage;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
bridgeImage = ((tileElement->AsPath()->GetSlopeDirection() + session->CurrentRotation)
2018-06-22 23:03:53 +02:00
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
2019-01-02 19:52:53 +01:00
+ railingEntry->bridge_image + 16;
}
2018-06-22 23:03:53 +02:00
else
{
2019-01-02 19:52:53 +01:00
bridgeImage = edges + railingEntry->bridge_image;
bridgeImage |= imageFlags;
}
sub_98197C(
session, bridgeImage | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x,
boundBoxOffset.y, height + boundingBoxZOffset);
2019-01-02 19:52:53 +01:00
// TODO: Revert this when path import works correctly.
if (pathElement->IsQueue() || pathElement->ShouldDrawPathOverSupports())
2018-06-22 23:03:53 +02:00
{
sub_98199C(
session, imageId | imageFlags, 0, 0, boundBoxSize.x, boundBoxSize.y, 0, height, boundBoxOffset.x,
boundBoxOffset.y, height + boundingBoxZOffset);
}
}
sub_6A3F61(session, tileElement, edi, height, railingEntry, imageFlags, sceneryImageFlags, hasSupports); // TODO: arguments
uint16_t ax = 0;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
ax = 8;
}
uint8_t supports[] = {
6,
8,
7,
5,
};
2018-06-22 23:03:53 +02:00
for (int8_t i = 3; i > -1; --i)
{
if (!(edges & (1 << i)))
{
2019-01-02 19:52:53 +01:00
path_b_supports_paint_setup(session, supports[i], ax, height, imageFlags, railingEntry);
}
}
height += 32;
2018-09-16 16:17:35 +02:00
if (tileElement->AsPath()->IsSloped())
2018-06-22 23:03:53 +02:00
{
height += 16;
}
paint_util_set_general_support_height(session, height, 0x20);
if (pathElement->IsQueue() || (tileElement->AsPath()->GetEdgesAndCorners() != 0xFF && hasSupports))
2018-06-22 23:03:53 +02:00
{
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
return;
}
if (tileElement->AsPath()->GetEdgesAndCorners() == 0xFF)
2018-06-22 23:03:53 +02:00
{
paint_util_set_segment_support_height(session, SEGMENT_C8 | SEGMENT_CC | SEGMENT_D0 | SEGMENT_D4, 0xFFFF, 0);
return;
}
paint_util_set_segment_support_height(session, SEGMENT_C4, 0xFFFF, 0);
2018-06-22 23:03:53 +02:00
if (edges & EDGE_NE)
{
paint_util_set_segment_support_height(session, SEGMENT_CC, 0xFFFF, 0);
}
2018-06-22 23:03:53 +02:00
if (edges & EDGE_SE)
{
paint_util_set_segment_support_height(session, SEGMENT_D4, 0xFFFF, 0);
}
2018-06-22 23:03:53 +02:00
if (edges & EDGE_SW)
{
paint_util_set_segment_support_height(session, SEGMENT_D0, 0xFFFF, 0);
}
2018-06-22 23:03:53 +02:00
if (edges & EDGE_NW)
{
paint_util_set_segment_support_height(session, SEGMENT_C8, 0xFFFF, 0);
}
2016-06-15 23:31:13 +02:00
}