|
|
|
|
@@ -7,6 +7,8 @@
|
|
|
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "../Paint.h"
|
|
|
|
|
|
|
|
|
|
#include "../../Context.h"
|
|
|
|
|
#include "../../Game.h"
|
|
|
|
|
#include "../../GameState.h"
|
|
|
|
|
@@ -14,6 +16,8 @@
|
|
|
|
|
#include "../../drawing/LightFX.h"
|
|
|
|
|
#include "../../interface/Viewport.h"
|
|
|
|
|
#include "../../localisation/Localisation.h"
|
|
|
|
|
#include "../../object/EntranceObject.h"
|
|
|
|
|
#include "../../object/ObjectManager.h"
|
|
|
|
|
#include "../../object/StationObject.h"
|
|
|
|
|
#include "../../ride/RideData.h"
|
|
|
|
|
#include "../../ride/TrackDesign.h"
|
|
|
|
|
@@ -22,34 +26,64 @@
|
|
|
|
|
#include "../../world/Footpath.h"
|
|
|
|
|
#include "../../world/Park.h"
|
|
|
|
|
#include "../../world/TileInspector.h"
|
|
|
|
|
#include "../Paint.h"
|
|
|
|
|
#include "../Supports.h"
|
|
|
|
|
#include "Paint.TileElement.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* rct2: 0x0066508C, 0x00665540
|
|
|
|
|
*/
|
|
|
|
|
static void ride_entrance_exit_paint(
|
|
|
|
|
paint_session* session, uint8_t direction, int32_t height, const EntranceElement& tile_element)
|
|
|
|
|
{
|
|
|
|
|
uint8_t is_exit = tile_element.GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT;
|
|
|
|
|
using namespace OpenRCT2;
|
|
|
|
|
|
|
|
|
|
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
|
|
|
|
static void PaintRideEntranceExitScrollingText(
|
|
|
|
|
paint_session* session, const EntranceElement& entranceEl, const StationObject& stationObj, Direction direction,
|
|
|
|
|
int32_t height)
|
|
|
|
|
{
|
|
|
|
|
if (stationObj.ScrollingMode == SCROLLING_MODE_NONE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (entranceEl.GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto ride = get_ride(entranceEl.GetRideIndex());
|
|
|
|
|
if (ride == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto ft = Formatter();
|
|
|
|
|
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_NAME);
|
|
|
|
|
if (ride->status == RideStatus::Open && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
|
|
|
|
|
{
|
|
|
|
|
if (tile_element.GetRideIndex() != gTrackDesignSaveRideIndex)
|
|
|
|
|
return;
|
|
|
|
|
ride->FormatNameTo(ft);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_CLOSED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char text[256];
|
|
|
|
|
if (gConfigGeneral.upper_case_banners)
|
|
|
|
|
{
|
|
|
|
|
format_string_to_upper(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
format_string(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
auto stringWidth = gfx_get_string_width(text, FontSpriteBase::TINY);
|
|
|
|
|
auto scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
|
|
|
|
|
|
|
|
|
PaintAddImageAsChild(
|
|
|
|
|
session, scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, stationObj.ScrollingMode, COLOUR_BLACK), 0,
|
|
|
|
|
0, 28, 28, 51, height + stationObj.Height, 2, 2, height + stationObj.Height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void PaintRideEntranceExitLightEffects(paint_session* session, int32_t height, const EntranceElement& entranceEl)
|
|
|
|
|
{
|
|
|
|
|
#ifdef __ENABLE_LIGHTFX__
|
|
|
|
|
if (lightfx_is_available())
|
|
|
|
|
{
|
|
|
|
|
if (!is_exit)
|
|
|
|
|
if (entranceEl.GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE)
|
|
|
|
|
{
|
|
|
|
|
lightfx_add_3d_light_magic_from_drawing_tile(session->MapPosition, 0, 0, height + 45, LightType::Lantern3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (tile_element.GetDirection())
|
|
|
|
|
switch (entranceEl.GetDirection())
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
lightfx_add_3d_light_magic_from_drawing_tile(session->MapPosition, 16, 0, height + 16, LightType::Lantern2);
|
|
|
|
|
@@ -66,8 +100,18 @@ static void ride_entrance_exit_paint(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto ride = get_ride(tile_element.GetRideIndex());
|
|
|
|
|
static void PaintRideEntranceExit(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& entranceEl)
|
|
|
|
|
{
|
|
|
|
|
auto rideIndex = entranceEl.GetRideIndex();
|
|
|
|
|
if ((gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
|
|
|
|
&& (rideIndex != gTrackDesignSaveRideIndex))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto ride = get_ride(rideIndex);
|
|
|
|
|
if (ride == nullptr)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
@@ -79,44 +123,28 @@ static void ride_entrance_exit_paint(
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t colour_1, colour_2;
|
|
|
|
|
uint32_t transparant_image_id = 0, image_id = 0;
|
|
|
|
|
if (stationObj->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT)
|
|
|
|
|
session->InteractionType = ViewportInteractionItem::Ride;
|
|
|
|
|
|
|
|
|
|
PaintRideEntranceExitLightEffects(session, height, entranceEl);
|
|
|
|
|
|
|
|
|
|
auto hasGlass = (stationObj->Flags & STATION_OBJECT_FLAGS::IS_TRANSPARENT) != 0;
|
|
|
|
|
auto colourPrimary = ride->track_colour[0].main;
|
|
|
|
|
auto colourSecondary = ride->track_colour[0].additional;
|
|
|
|
|
auto imageTemplate = ImageId(0, colourPrimary, colourSecondary);
|
|
|
|
|
ImageId glassImageTemplate;
|
|
|
|
|
if (hasGlass)
|
|
|
|
|
{
|
|
|
|
|
colour_1 = EnumValue(GlassPaletteIds[ride->track_colour[0].main]);
|
|
|
|
|
transparant_image_id = (colour_1 << 19) | IMAGE_TYPE_TRANSPARENT;
|
|
|
|
|
glassImageTemplate = ImageId().WithTransparancy(colourPrimary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
colour_1 = ride->track_colour[0].main;
|
|
|
|
|
colour_2 = ride->track_colour[0].additional;
|
|
|
|
|
image_id = (colour_1 << 19) | (colour_2 << 24) | IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS;
|
|
|
|
|
|
|
|
|
|
session->InteractionType = ViewportInteractionItem::Ride;
|
|
|
|
|
uint32_t entranceImageId = 0;
|
|
|
|
|
|
|
|
|
|
if (tile_element.IsGhost())
|
|
|
|
|
if (entranceEl.IsGhost())
|
|
|
|
|
{
|
|
|
|
|
session->InteractionType = ViewportInteractionItem::None;
|
|
|
|
|
image_id = CONSTRUCTION_MARKER;
|
|
|
|
|
entranceImageId = image_id;
|
|
|
|
|
if (transparant_image_id)
|
|
|
|
|
transparant_image_id = image_id;
|
|
|
|
|
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
|
|
|
|
}
|
|
|
|
|
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&tile_element)))
|
|
|
|
|
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&entranceEl)))
|
|
|
|
|
{
|
|
|
|
|
image_id = CONSTRUCTION_MARKER;
|
|
|
|
|
entranceImageId = image_id;
|
|
|
|
|
if (transparant_image_id)
|
|
|
|
|
transparant_image_id = image_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_exit)
|
|
|
|
|
{
|
|
|
|
|
image_id |= stationObj->BaseImageId + direction + 8;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
image_id |= stationObj->BaseImageId + direction;
|
|
|
|
|
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Format modified to stop repeated code
|
|
|
|
|
@@ -124,250 +152,206 @@ static void ride_entrance_exit_paint(
|
|
|
|
|
// Each entrance is split into 2 images for drawing
|
|
|
|
|
// Certain entrance styles have another 2 images to draw for coloured windows
|
|
|
|
|
|
|
|
|
|
int8_t ah = is_exit ? 0x23 : 0x33;
|
|
|
|
|
|
|
|
|
|
int16_t lengthY = (direction & 1) ? 28 : 2;
|
|
|
|
|
int16_t lengthX = (direction & 1) ? 2 : 28;
|
|
|
|
|
|
|
|
|
|
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { lengthX, lengthY, ah }, { 2, 2, height });
|
|
|
|
|
|
|
|
|
|
if (transparant_image_id)
|
|
|
|
|
{
|
|
|
|
|
if (is_exit)
|
|
|
|
|
{
|
|
|
|
|
transparant_image_id |= stationObj->BaseImageId + direction + 24;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
transparant_image_id |= stationObj->BaseImageId + direction + 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PaintAddImageAsChild(session, transparant_image_id, 0, 0, lengthX, lengthY, ah, height, 2, 2, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_id += 4;
|
|
|
|
|
auto isExit = entranceEl.GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT;
|
|
|
|
|
auto lengthY = (direction & 1) ? 28 : 2;
|
|
|
|
|
auto lengthX = (direction & 1) ? 2 : 28;
|
|
|
|
|
auto lengthZ = isExit ? 35 : 51;
|
|
|
|
|
|
|
|
|
|
// Back
|
|
|
|
|
ImageIndex imageIndex = isExit ? stationObj->BaseImageId + direction + 8 : stationObj->BaseImageId + direction;
|
|
|
|
|
ImageIndex glassImageIndex = isExit ? stationObj->BaseImageId + direction + 24 : stationObj->BaseImageId + direction + 16;
|
|
|
|
|
PaintAddImageAsParent(
|
|
|
|
|
session, image_id, { 0, 0, height }, { lengthX, lengthY, ah },
|
|
|
|
|
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ }, { 2, 2, height });
|
|
|
|
|
if (hasGlass)
|
|
|
|
|
{
|
|
|
|
|
PaintAddImageAsChild(
|
|
|
|
|
session, glassImageTemplate.WithIndex(glassImageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ },
|
|
|
|
|
{ 2, 2, height });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Front
|
|
|
|
|
imageIndex += 4;
|
|
|
|
|
PaintAddImageAsParent(
|
|
|
|
|
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ },
|
|
|
|
|
{ (direction & 1) ? 28 : 2, (direction & 1) ? 2 : 28, height });
|
|
|
|
|
|
|
|
|
|
if (transparant_image_id)
|
|
|
|
|
if (hasGlass)
|
|
|
|
|
{
|
|
|
|
|
transparant_image_id += 4;
|
|
|
|
|
glassImageIndex += 4;
|
|
|
|
|
PaintAddImageAsChild(
|
|
|
|
|
session, transparant_image_id, 0, 0, lengthX, lengthY, ah, height, (direction & 1) ? 28 : 2,
|
|
|
|
|
(direction & 1) ? 2 : 28, height);
|
|
|
|
|
session, glassImageTemplate.WithIndex(glassImageIndex), { 0, 0, height }, { lengthX, lengthY, lengthZ },
|
|
|
|
|
{ (direction & 1) ? 28 : 2, (direction & 1) ? 2 : 28, height });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (direction & 1)
|
|
|
|
|
paint_util_push_tunnel_rotated(session, direction, height, TUNNEL_SQUARE_FLAT);
|
|
|
|
|
|
|
|
|
|
if (!entranceEl.IsGhost())
|
|
|
|
|
PaintRideEntranceExitScrollingText(session, entranceEl, *stationObj, direction, height);
|
|
|
|
|
|
|
|
|
|
auto supportsImageTemplate = imageTemplate;
|
|
|
|
|
if (!entranceEl.IsGhost())
|
|
|
|
|
{
|
|
|
|
|
paint_util_push_tunnel_right(session, height, TUNNEL_SQUARE_FLAT);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
paint_util_push_tunnel_left(session, height, TUNNEL_SQUARE_FLAT);
|
|
|
|
|
supportsImageTemplate = ImageId().WithPrimary(COLOUR_SATURATED_BROWN);
|
|
|
|
|
}
|
|
|
|
|
wooden_a_supports_paint_setup(session, direction & 1, 0, height, supportsImageTemplate.ToUInt32());
|
|
|
|
|
|
|
|
|
|
if (!is_exit && !(tile_element.IsGhost()) && tile_element.GetRideIndex() != RIDE_ID_NULL
|
|
|
|
|
&& stationObj->ScrollingMode != SCROLLING_MODE_NONE)
|
|
|
|
|
{
|
|
|
|
|
auto ft = Formatter();
|
|
|
|
|
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_NAME);
|
|
|
|
|
|
|
|
|
|
if (ride->status == RideStatus::Open && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
|
|
|
|
|
{
|
|
|
|
|
ride->FormatNameTo(ft);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ft.Add<rct_string_id>(STR_RIDE_ENTRANCE_CLOSED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utf8 entrance_string[256];
|
|
|
|
|
if (gConfigGeneral.upper_case_banners)
|
|
|
|
|
{
|
|
|
|
|
format_string_to_upper(entrance_string, sizeof(entrance_string), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
format_string(entrance_string, sizeof(entrance_string), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t stringWidth = gfx_get_string_width(entrance_string, FontSpriteBase::TINY);
|
|
|
|
|
uint16_t scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
|
|
|
|
|
|
|
|
|
PaintAddImageAsChild(
|
|
|
|
|
session, scrolling_text_setup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, stationObj->ScrollingMode, COLOUR_BLACK),
|
|
|
|
|
0, 0, 0x1C, 0x1C, 0x33, height + stationObj->Height, 2, 2, height + stationObj->Height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_id = entranceImageId;
|
|
|
|
|
if (image_id == 0)
|
|
|
|
|
{
|
|
|
|
|
image_id = SPRITE_ID_PALETTE_COLOUR_1(COLOUR_SATURATED_BROWN);
|
|
|
|
|
}
|
|
|
|
|
wooden_a_supports_paint_setup(session, direction & 1, 0, height, image_id);
|
|
|
|
|
|
|
|
|
|
height += isExit ? 40 : 56;
|
|
|
|
|
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
|
|
|
|
|
|
|
|
|
|
height += is_exit ? 40 : 56;
|
|
|
|
|
paint_util_set_general_support_height(session, height, 0x20);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* rct2: 0x006658ED
|
|
|
|
|
*/
|
|
|
|
|
static void park_entrance_paint(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& tile_element)
|
|
|
|
|
static void PaintParkEntranceScrollingText(
|
|
|
|
|
paint_session* session, const EntranceObject& entrance, Direction direction, int32_t height)
|
|
|
|
|
{
|
|
|
|
|
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
|
|
|
|
if ((direction + 1) & (1 << 1))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto scrollingMode = entrance.GetScrollingMode();
|
|
|
|
|
if (scrollingMode == SCROLLING_MODE_NONE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto ft = Formatter();
|
|
|
|
|
if (gParkFlags & PARK_FLAGS_PARK_OPEN)
|
|
|
|
|
{
|
|
|
|
|
const auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark();
|
|
|
|
|
auto name = park.Name.c_str();
|
|
|
|
|
ft.Add<rct_string_id>(STR_STRING);
|
|
|
|
|
ft.Add<const char*>(name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ft.Add<rct_string_id>(STR_BANNER_TEXT_CLOSED);
|
|
|
|
|
ft.Add<uint32_t>(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char text[256];
|
|
|
|
|
if (gConfigGeneral.upper_case_banners)
|
|
|
|
|
{
|
|
|
|
|
format_string_to_upper(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
format_string(text, sizeof(text), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto stringWidth = gfx_get_string_width(text, FontSpriteBase::TINY);
|
|
|
|
|
auto scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
|
|
|
|
auto imageIndex = scrolling_text_setup(
|
|
|
|
|
session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode + direction / 2, COLOUR_BLACK);
|
|
|
|
|
auto textHeight = height + entrance.GetTextHeight();
|
|
|
|
|
PaintAddImageAsChild(session, ImageId(imageIndex), { 0, 0, textHeight }, { 28, 28, 47 }, { 2, 2, textHeight });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void PaintParkEntranceLightEffects(paint_session* session)
|
|
|
|
|
{
|
|
|
|
|
#ifdef __ENABLE_LIGHTFX__
|
|
|
|
|
if (lightfx_is_available())
|
|
|
|
|
{
|
|
|
|
|
lightfx_add_3d_light_magic_from_drawing_tile(session->MapPosition, 0, 0, 155, LightType::Lantern3);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void PaintParkEntrance(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& entranceEl)
|
|
|
|
|
{
|
|
|
|
|
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
PaintParkEntranceLightEffects(session);
|
|
|
|
|
|
|
|
|
|
session->InteractionType = ViewportInteractionItem::ParkEntrance;
|
|
|
|
|
uint32_t image_id, ghost_id = 0;
|
|
|
|
|
if (tile_element.IsGhost())
|
|
|
|
|
|
|
|
|
|
ImageId imageTemplate;
|
|
|
|
|
if (entranceEl.IsGhost())
|
|
|
|
|
{
|
|
|
|
|
session->InteractionType = ViewportInteractionItem::None;
|
|
|
|
|
ghost_id = CONSTRUCTION_MARKER;
|
|
|
|
|
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
|
|
|
|
}
|
|
|
|
|
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&tile_element)))
|
|
|
|
|
else if (OpenRCT2::TileInspector::IsElementSelected(reinterpret_cast<const TileElement*>(&entranceEl)))
|
|
|
|
|
{
|
|
|
|
|
ghost_id = CONSTRUCTION_MARKER;
|
|
|
|
|
imageTemplate = ImageId().WithRemap(FilterPaletteID::Palette44);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Index to which part of the entrance
|
|
|
|
|
// Middle, left, right
|
|
|
|
|
uint8_t part_index = tile_element.GetSequenceIndex();
|
|
|
|
|
const PathSurfaceDescriptor* surfaceDescriptor = nullptr;
|
|
|
|
|
|
|
|
|
|
// The left and right of the park entrance often have this set to 127.
|
|
|
|
|
// So only attempt to get the footpath type if we're dealing with the middle bit of the entrance.
|
|
|
|
|
if (part_index == 0)
|
|
|
|
|
auto& objManager = GetContext()->GetObjectManager();
|
|
|
|
|
auto entrance = reinterpret_cast<EntranceObject*>(objManager.GetLoadedObject(ObjectType::ParkEntrance, 0));
|
|
|
|
|
auto sequence = entranceEl.GetSequenceIndex();
|
|
|
|
|
switch (sequence)
|
|
|
|
|
{
|
|
|
|
|
surfaceDescriptor = tile_element.GetPathSurfaceDescriptor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rct_entrance_type* entrance;
|
|
|
|
|
uint8_t di = ((direction / 2 + part_index / 2) & 1) ? 0x1A : 0x20;
|
|
|
|
|
|
|
|
|
|
switch (part_index)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
case EntranceSequence::Centre:
|
|
|
|
|
{
|
|
|
|
|
// Footpath
|
|
|
|
|
auto surfaceDescriptor = entranceEl.GetPathSurfaceDescriptor();
|
|
|
|
|
if (surfaceDescriptor != nullptr)
|
|
|
|
|
{
|
|
|
|
|
image_id = (surfaceDescriptor->Image + 5 * (1 + (direction & 1))) | ghost_id;
|
|
|
|
|
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 32, 0x1C, 0 }, { 0, 2, height });
|
|
|
|
|
auto imageIndex = (surfaceDescriptor->Image + 5 * (1 + (direction & 1)));
|
|
|
|
|
PaintAddImageAsParent(
|
|
|
|
|
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { 32, 28, 0 }, { 0, 2, height });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entrance = static_cast<rct_entrance_type*>(object_entry_get_chunk(ObjectType::ParkEntrance, 0));
|
|
|
|
|
if (entrance == nullptr)
|
|
|
|
|
// Entrance
|
|
|
|
|
if (entrance != nullptr)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
image_id = (entrance->image_id + direction * 3) | ghost_id;
|
|
|
|
|
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 0x1C, 0x1C, 0x2F }, { 2, 2, height + 32 });
|
|
|
|
|
auto imageIndex = entrance->GetImage(sequence, direction);
|
|
|
|
|
PaintAddImageAsParent(
|
|
|
|
|
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { 28, 28, 47 }, { 2, 2, height + 32 });
|
|
|
|
|
|
|
|
|
|
if ((direction + 1) & (1 << 1))
|
|
|
|
|
break;
|
|
|
|
|
if (ghost_id != 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
auto ft = Formatter();
|
|
|
|
|
|
|
|
|
|
if (gParkFlags & PARK_FLAGS_PARK_OPEN)
|
|
|
|
|
{
|
|
|
|
|
const auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark();
|
|
|
|
|
auto name = park.Name.c_str();
|
|
|
|
|
ft.Add<rct_string_id>(STR_STRING);
|
|
|
|
|
ft.Add<const char*>(name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ft.Add<rct_string_id>(STR_BANNER_TEXT_CLOSED);
|
|
|
|
|
ft.Add<uint32_t>(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utf8 park_name[256];
|
|
|
|
|
if (gConfigGeneral.upper_case_banners)
|
|
|
|
|
{
|
|
|
|
|
format_string_to_upper(park_name, sizeof(park_name), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
format_string(park_name, sizeof(park_name), STR_BANNER_TEXT_FORMAT, ft.Data());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t stringWidth = gfx_get_string_width(park_name, FontSpriteBase::TINY);
|
|
|
|
|
uint16_t scroll = stringWidth > 0 ? (gCurrentTicks / 2) % stringWidth : 0;
|
|
|
|
|
|
|
|
|
|
if (entrance->scrolling_mode == SCROLLING_MODE_NONE)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
int32_t stsetup = scrolling_text_setup(
|
|
|
|
|
session, STR_BANNER_TEXT_FORMAT, ft, scroll, entrance->scrolling_mode + direction / 2, COLOUR_BLACK);
|
|
|
|
|
int32_t text_height = height + entrance->text_height;
|
|
|
|
|
PaintAddImageAsChild(session, stsetup, 0, 0, 0x1C, 0x1C, 0x2F, text_height, 2, 2, text_height);
|
|
|
|
|
if (!entranceEl.IsGhost())
|
|
|
|
|
PaintParkEntranceScrollingText(session, *entrance, direction, height);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
entrance = static_cast<rct_entrance_type*>(object_entry_get_chunk(ObjectType::ParkEntrance, 0));
|
|
|
|
|
if (entrance == nullptr)
|
|
|
|
|
}
|
|
|
|
|
case EntranceSequence::Left:
|
|
|
|
|
case EntranceSequence::Right:
|
|
|
|
|
if (entrance != nullptr)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
auto imageIndex = entrance->GetImage(sequence, direction);
|
|
|
|
|
auto y = ((direction / 2 + sequence / 2) & 1) ? 26 : 32;
|
|
|
|
|
PaintAddImageAsParent(
|
|
|
|
|
session, imageTemplate.WithIndex(imageIndex), { 0, 0, height }, { 26, y, 79 }, { 3, 3, height });
|
|
|
|
|
}
|
|
|
|
|
image_id = (entrance->image_id + part_index + direction * 3) | ghost_id;
|
|
|
|
|
PaintAddImageAsParent(session, image_id, { 0, 0, height }, { 0x1A, di, 0x4F }, { 3, 3, height });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_id = ghost_id;
|
|
|
|
|
if (image_id == 0)
|
|
|
|
|
auto supportsImageTemplate = imageTemplate;
|
|
|
|
|
if (!entranceEl.IsGhost())
|
|
|
|
|
{
|
|
|
|
|
image_id = SPRITE_ID_PALETTE_COLOUR_1(COLOUR_SATURATED_BROWN);
|
|
|
|
|
supportsImageTemplate = ImageId().WithPrimary(COLOUR_SATURATED_BROWN);
|
|
|
|
|
}
|
|
|
|
|
wooden_a_supports_paint_setup(session, direction & 1, 0, height, image_id);
|
|
|
|
|
wooden_a_supports_paint_setup(session, direction & 1, 0, height, supportsImageTemplate.ToUInt32());
|
|
|
|
|
|
|
|
|
|
paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
|
|
|
|
|
paint_util_set_general_support_height(session, height + 80, 0x20);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* rct2: 0x00664FD4
|
|
|
|
|
*/
|
|
|
|
|
static void PaintHeightMarkers(paint_session* session, const EntranceElement& entranceEl, int32_t height)
|
|
|
|
|
{
|
|
|
|
|
if (PaintShouldShowHeightMarkers(session, VIEWPORT_FLAG_PATH_HEIGHTS))
|
|
|
|
|
{
|
|
|
|
|
if (entranceEl.GetDirections() & 0xF)
|
|
|
|
|
{
|
|
|
|
|
auto heightMarkerBaseZ = entranceEl.GetBaseZ() + 3;
|
|
|
|
|
ImageIndex baseImageIndex = SPR_HEIGHT_MARKER_BASE;
|
|
|
|
|
baseImageIndex += heightMarkerBaseZ / 16;
|
|
|
|
|
baseImageIndex += get_height_marker_offset();
|
|
|
|
|
baseImageIndex -= gMapBaseZ;
|
|
|
|
|
auto imageId = ImageId(baseImageIndex, COLOUR_GREY);
|
|
|
|
|
PaintAddImageAsParent(session, imageId, { 16, 16, height }, { 1, 1, 0 }, { 31, 31, heightMarkerBaseZ + 64 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PaintEntrance(paint_session* session, uint8_t direction, int32_t height, const EntranceElement& entranceElement)
|
|
|
|
|
{
|
|
|
|
|
session->InteractionType = ViewportInteractionItem::Label;
|
|
|
|
|
|
|
|
|
|
if (PaintShouldShowHeightMarkers(session, VIEWPORT_FLAG_PATH_HEIGHTS))
|
|
|
|
|
{
|
|
|
|
|
if (entranceElement.GetDirections() & 0xF)
|
|
|
|
|
{
|
|
|
|
|
int32_t z = entranceElement.GetBaseZ() + 3;
|
|
|
|
|
uint32_t image_id = 0x20101689 + get_height_marker_offset() + (z / 16);
|
|
|
|
|
image_id -= gMapBaseZ;
|
|
|
|
|
|
|
|
|
|
PaintAddImageAsParent(session, image_id, { 16, 16, height }, { 1, 1, 0 }, { 31, 31, z + 64 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PaintHeightMarkers(session, entranceElement, height);
|
|
|
|
|
switch (entranceElement.GetEntranceType())
|
|
|
|
|
{
|
|
|
|
|
case ENTRANCE_TYPE_RIDE_ENTRANCE:
|
|
|
|
|
case ENTRANCE_TYPE_RIDE_EXIT:
|
|
|
|
|
ride_entrance_exit_paint(session, direction, height, entranceElement);
|
|
|
|
|
PaintRideEntranceExit(session, direction, height, entranceElement);
|
|
|
|
|
break;
|
|
|
|
|
case ENTRANCE_TYPE_PARK_ENTRANCE:
|
|
|
|
|
park_entrance_paint(session, direction, height, entranceElement);
|
|
|
|
|
PaintParkEntrance(session, direction, height, entranceElement);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|