1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-21 14:02:59 +01:00
Files
OpenRCT2/src/openrct2/paint/tile_element/Paint.Wall.cpp
2019-07-29 20:01:49 +01:00

453 lines
15 KiB
C++

/*****************************************************************************
* 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.
*****************************************************************************/
#include "../../Game.h"
#include "../../common.h"
#include "../../config/Config.h"
#include "../../drawing/Drawing.h"
#include "../../interface/Colour.h"
#include "../../interface/Viewport.h"
#include "../../localisation/Localisation.h"
#include "../../ride/Track.h"
#include "../../ride/TrackDesign.h"
#include "../../world/Banner.h"
#include "../../world/Map.h"
#include "../../world/Scenery.h"
#include "../../world/Wall.h"
#include "../Paint.h"
#include "Paint.TileElement.h"
static constexpr const uint8_t byte_9A406C[] = {
2, 2, 22, 26, 30, 34, 34, 34, 34, 34, 30, 26, 22, 2, 6, 2, 2, 2, 6, 10, 14, 18, 18, 18, 18, 18, 14, 10, 6, 2, 22, 2,
};
static constexpr const uint8_t byte_9A408C[] = {
0, 0, 4, 8, 12, 16, 16, 16, 16, 16, 12, 8, 4, 0, 20, 0, 0, 0, 20, 24, 28, 32, 32, 32, 32, 32, 28, 24, 20, 0, 4, 0,
};
static constexpr const uint8_t byte_9A40AC[] = {
2, 2, 6, 10, 14, 18, 18, 18, 18, 18, 14, 10, 6, 2, 22, 2, 2, 2, 22, 26, 30, 34, 34, 34, 34, 34, 30, 26, 22, 2, 6, 2,
};
static constexpr const uint8_t byte_9A40CC[] = {
0, 0, 20, 24, 28, 32, 32, 32, 32, 32, 28, 24, 20, 0, 4, 0, 0, 0, 4, 8, 12, 16, 16, 16, 16, 16, 12, 8, 4, 0, 20, 0,
};
static void fence_paint_door(
paint_session* session, uint32_t imageId, rct_scenery_entry* sceneryEntry, uint32_t imageColourFlags,
uint32_t tertiaryColour, uint32_t dword_141F710, LocationXYZ16 offset, LocationXYZ16 boundsR1, LocationXYZ16 boundsR1_,
LocationXYZ16 boundsR2, LocationXYZ16 boundsR2_, LocationXYZ16 boundsL1, LocationXYZ16 boundsL1_)
{
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
{
imageId |= imageColourFlags;
}
if (dword_141F710 != 0)
{
imageId = (imageId & 0x7FFFF) | dword_141F710;
}
if (sceneryEntry->wall.flags & WALL_SCENERY_IS_BANNER)
{
paint_struct* ps;
ps = sub_98197C(
session, imageId, (int8_t)offset.x, (int8_t)offset.y, boundsR1.x, boundsR1.y, (int8_t)boundsR1.z, offset.z,
boundsR1_.x, boundsR1_.y, boundsR1_.z);
if (ps != nullptr)
{
ps->tertiary_colour = tertiaryColour;
}
ps = sub_98197C(
session, imageId + 1, (int8_t)offset.x, (int8_t)offset.y, boundsR2.x, boundsR2.y, (int8_t)boundsR2.z, offset.z,
boundsR2_.x, boundsR2_.y, boundsR2_.z);
if (ps != nullptr)
{
ps->tertiary_colour = tertiaryColour;
}
}
else
{
paint_struct* ps;
ps = sub_98197C(
session, imageId, (int8_t)offset.x, (int8_t)offset.y, boundsL1.x, boundsL1.y, (int8_t)boundsL1.z, offset.z,
boundsL1_.x, boundsL1_.y, boundsL1_.z);
if (ps != nullptr)
{
ps->tertiary_colour = tertiaryColour;
}
ps = sub_98199C(
session, imageId + 1, (int8_t)offset.x, (int8_t)offset.y, boundsL1.x, boundsL1.y, (int8_t)boundsL1.z, offset.z,
boundsL1_.x, boundsL1_.y, boundsL1_.z);
if (ps != nullptr)
{
ps->tertiary_colour = tertiaryColour;
}
}
}
static void fence_paint_wall(
paint_session* session, uint32_t frameNum, const rct_scenery_entry* sceneryEntry, uint32_t dword_141F710,
uint32_t imageColourFlags, uint32_t dword_141F718, uint32_t tertiaryColour, uint32_t imageOffset, LocationXYZ16 offset,
LocationXYZ16 bounds, LocationXYZ16 boundsOffset)
{
uint32_t baseImageId = sceneryEntry->image + imageOffset + frameNum;
uint32_t imageId = baseImageId;
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_GLASS)
{
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
{
imageId |= imageColourFlags;
}
if (dword_141F710 != 0)
{
imageId = (imageId & 0x7FFFF) | dword_141F710;
}
sub_98197C(
session, imageId, (int8_t)offset.x, (int8_t)offset.y, bounds.x, bounds.y, (int8_t)bounds.z, offset.z,
boundsOffset.x, boundsOffset.y, boundsOffset.z);
if (dword_141F710 == 0)
{
imageId = baseImageId + dword_141F718;
sub_98199C(
session, imageId, (int8_t)offset.x, (int8_t)offset.y, bounds.x, bounds.y, (int8_t)bounds.z, offset.z,
boundsOffset.x, boundsOffset.y, boundsOffset.z);
}
}
else
{
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)
{
imageId |= imageColourFlags;
}
if (dword_141F710 != 0)
{
imageId = (imageId & 0x7FFFF) | dword_141F710;
}
paint_struct* paint = sub_98197C(
session, imageId, (int8_t)offset.x, (int8_t)offset.y, bounds.x, bounds.y, (int8_t)bounds.z, offset.z,
boundsOffset.x, boundsOffset.y, boundsOffset.z);
if (paint != nullptr)
{
paint->tertiary_colour = tertiaryColour;
}
}
}
/**
* rct2: 0x006E44B0
* @param direction (cl)
* @param height (dx)
* @param tile_element (esi)
*/
void fence_paint(paint_session* session, uint8_t direction, int32_t height, const TileElement* tile_element)
{
session->InteractionType = VIEWPORT_INTERACTION_ITEM_WALL;
rct_scenery_entry* sceneryEntry = tile_element->AsWall()->GetEntry();
if (sceneryEntry == nullptr)
{
return;
}
uint32_t frameNum = 0;
if (sceneryEntry->wall.flags2 & WALL_SCENERY_2_ANIMATED)
{
frameNum = (gCurrentTicks & 7) * 2;
}
int32_t primaryColour = tile_element->AsWall()->GetPrimaryColour();
uint32_t imageColourFlags = primaryColour << 19 | IMAGE_TYPE_REMAP;
uint32_t dword_141F718 = imageColourFlags + 0x23800006;
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR)
{
uint8_t secondaryColour = tile_element->AsWall()->GetSecondaryColour();
imageColourFlags |= secondaryColour << 24 | IMAGE_TYPE_REMAP_2_PLUS;
}
uint32_t tertiaryColour = 0;
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR)
{
tertiaryColour = tile_element->AsWall()->GetTertiaryColour();
imageColourFlags &= 0x0DFFFFFFF;
}
paint_util_set_general_support_height(session, 8 * tile_element->clearance_height, 0x20);
uint32_t dword_141F710 = 0;
if (gTrackDesignSaveMode || (session->ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
{
if (!track_design_save_contains_tile_element(tile_element))
{
dword_141F710 = SPRITE_ID_PALETTE_COLOUR_1(PALETTE_46);
}
}
if (tile_element->IsGhost())
{
session->InteractionType = VIEWPORT_INTERACTION_ITEM_NONE;
dword_141F710 = CONSTRUCTION_MARKER;
}
// Save tile_element
uint8_t ah = sceneryEntry->wall.height * 8 - 2;
if (sceneryEntry->wall.flags & WALL_SCENERY_IS_DOOR)
{
LocationXYZ16 offset;
LocationXYZ16 boundsR1, boundsR1_, boundsR2, boundsR2_, boundsL1, boundsL1_;
uint8_t animationFrame = tile_element->AsWall()->GetAnimationFrame();
// Add the direction as well
if (tile_element->AsWall()->AnimationIsBackwards())
animationFrame |= (1 << 4);
uint32_t imageId;
switch (direction)
{
case 0:
imageId = sceneryEntry->image + byte_9A406C[animationFrame];
boundsR1 = { 1, 3, static_cast<int16_t>(ah - 5) };
boundsR1_ = { 1, 1, static_cast<int16_t>(height + 1) };
boundsR2 = { 1, 28, 3 };
boundsR2_ = { 1, 1, static_cast<int16_t>(height + ah - 9) };
boundsL1 = { 1, 28, ah };
boundsL1_ = { 1, 1, static_cast<int16_t>(height + 1) };
offset = { 0, 0, static_cast<int16_t>(height) };
fence_paint_door(
session, imageId, sceneryEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1,
boundsR1_, boundsR2, boundsR2_, boundsL1, boundsL1_);
break;
case 1:
imageId = sceneryEntry->image + byte_9A408C[animationFrame];
boundsR1 = { 3, 3, static_cast<int16_t>(ah - 5) };
boundsR1_ = { 1, 30, static_cast<int16_t>(height + 1) };
boundsR2 = { 29, 3, 2 };
boundsR2_ = { 1, 30, static_cast<int16_t>(height + ah - 8) };
boundsL1 = { 29, 1, ah };
boundsL1_ = { 2, 30, static_cast<int16_t>(height + 1) };
offset = { 1, 31, static_cast<int16_t>(height) };
fence_paint_door(
session, imageId, sceneryEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1,
boundsR1_, boundsR2, boundsR2_, boundsL1, boundsL1_);
break;
case 2:
imageId = sceneryEntry->image + byte_9A40AC[animationFrame];
boundsR1 = { 3, 3, static_cast<int16_t>(ah - 5) };
boundsR1_ = { 30, 1, static_cast<int16_t>(height + 1) };
boundsR2 = { 3, 29, 2 };
boundsR2_ = { 30, 1, static_cast<int16_t>(height + ah - 8) };
boundsL1 = { 1, 29, ah };
boundsL1_ = { 30, 2, static_cast<int16_t>(height + 1) };
offset = { 31, 0, static_cast<int16_t>(height) };
fence_paint_door(
session, imageId, sceneryEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1,
boundsR1_, boundsR2, boundsR2_, boundsL1, boundsL1_);
break;
case 3:
imageId = sceneryEntry->image + byte_9A40CC[animationFrame];
boundsR1 = { 3, 1, static_cast<int16_t>(ah - 5) };
boundsR1_ = { 1, 1, static_cast<int16_t>(height + 1) };
boundsR2 = { 28, 1, 3 };
boundsR2_ = { 1, 1, static_cast<int16_t>(height + ah - 9) };
boundsL1 = { 28, 1, ah };
boundsL1_ = { 1, 1, static_cast<int16_t>(height + 1) };
offset = { 2, 1, static_cast<int16_t>(height) };
fence_paint_door(
session, imageId, sceneryEntry, imageColourFlags, tertiaryColour, dword_141F710, offset, boundsR1,
boundsR1_, boundsR2, boundsR2_, boundsL1, boundsL1_);
break;
}
return;
}
uint32_t imageOffset = 0;
LocationXYZ16 offset = { 0, 0, 0 }, bounds = { 0, 0, 0 }, boundsOffset = { 0, 0, 0 };
switch (direction)
{
case 0:
if (tile_element->AsWall()->GetSlope() == 2)
{
imageOffset = 3;
}
else if (tile_element->AsWall()->GetSlope() == 1)
{
imageOffset = 5;
}
else
{
imageOffset = 1;
}
offset = { 0, 0, static_cast<int16_t>(height) };
bounds = { 1, 28, ah };
boundsOffset = { 1, 1, static_cast<int16_t>(height + 1) };
break;
case 1:
if (tile_element->AsWall()->GetSlope() == 2)
{
imageOffset = 2;
}
else if (tile_element->AsWall()->GetSlope() == 1)
{
imageOffset = 4;
}
else
{
imageOffset = 0;
}
if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_GLASS)
{
if (sceneryEntry->wall.flags & WALL_SCENERY_IS_BANNER)
{
imageOffset += 12;
}
}
else
{
if (sceneryEntry->wall.flags & WALL_SCENERY_IS_BANNER)
{
imageOffset += 6;
}
}
offset = { 1, 31, static_cast<int16_t>(height) };
bounds = { 29, 1, ah };
boundsOffset = { 2, 30, static_cast<int16_t>(height + 1) };
break;
case 2:
if (tile_element->AsWall()->GetSlope() == 2)
{
imageOffset = 5;
}
else if (tile_element->AsWall()->GetSlope() == 1)
{
imageOffset = 3;
}
else
{
imageOffset = 1;
}
if (sceneryEntry->wall.flags & WALL_SCENERY_IS_BANNER)
{
imageOffset += 6;
}
offset = { 31, 0, static_cast<int16_t>(height) };
bounds = { 1, 29, ah };
boundsOffset = { 30, 2, static_cast<int16_t>(height + 1) };
break;
case 3:
if (tile_element->AsWall()->GetSlope() == 2)
{
imageOffset = 4;
}
else if (tile_element->AsWall()->GetSlope() == 1)
{
imageOffset = 2;
}
else
{
imageOffset = 0;
}
offset = { 2, 1, static_cast<int16_t>(height) };
bounds = { 28, 1, ah };
boundsOffset = { 1, 1, static_cast<int16_t>(height + 1) };
break;
}
fence_paint_wall(
session, frameNum, sceneryEntry, dword_141F710, imageColourFlags, dword_141F718, tertiaryColour, imageOffset, offset,
bounds, boundsOffset);
if (sceneryEntry->wall.scrolling_mode == SCROLLING_MODE_NONE)
{
return;
}
if (direction != 0 && direction != 3)
{
return;
}
auto secondaryColour = tile_element->AsWall()->GetSecondaryColour();
if (dword_141F710 != 0)
{
secondaryColour = COLOUR_GREY;
}
if (direction == 0)
{
secondaryColour = ColourMapA[secondaryColour].light;
}
else
{
secondaryColour = ColourMapA[secondaryColour].mid_dark;
}
uint16_t scrollingMode = sceneryEntry->wall.scrolling_mode + ((direction + 1) & 0x3);
auto banner = tile_element->AsWall()->GetBanner();
if (banner != nullptr && !banner->IsNull())
{
banner->FormatTextTo(gCommonFormatArgs);
utf8 signString[256];
if (gConfigGeneral.upper_case_banners)
{
format_string_to_upper(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, gCommonFormatArgs);
}
else
{
format_string(signString, sizeof(signString), STR_SCROLLING_SIGN_TEXT, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;
uint16_t string_width = gfx_get_string_width(signString);
uint16_t scroll = (gCurrentTicks / 2) % string_width;
sub_98199C(
session, scrolling_text_setup(session, STR_SCROLLING_SIGN_TEXT, scroll, scrollingMode, secondaryColour), 0, 0, 1, 1,
13, height + 8, boundsOffset.x, boundsOffset.y, boundsOffset.z);
}
}