1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 19:13:07 +01:00

Merge pull request #16831 from IntelOrca/feature/ternary-scenery-colours

Implement tertiary colours for small and large scenery objects.
This commit is contained in:
Ted John
2022-03-20 19:24:47 +00:00
committed by GitHub
21 changed files with 169 additions and 56 deletions

View File

@@ -19,6 +19,7 @@
- Feature: [#16731] [Plugin] New API for fetching and manipulating a staff member's patrol area.
- Feature: [#16800] [Plugin] Add lift hill speed properties to API.
- Feature: [#16806] Parkobj can load sprites from RCT image archives.
- Feature: [#16831] Allow ternary colours for small and large scenery objects.
- Improved: [#3517] Cheats are now saved with the park.
- Improved: [#10150] Ride stations are now properly checked if theyre sheltered.
- Improved: [#10664, #16072] Visibility status can be modified directly in the Tile Inspector's list.

View File

@@ -571,6 +571,8 @@ public:
widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WindowWidgetType::ColourBtn;
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WindowWidgetType::ColourBtn;
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR)
widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WindowWidgetType::ColourBtn;
}
else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_WALL)
{
@@ -600,6 +602,8 @@ public:
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WindowWidgetType::ColourBtn;
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR))
widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WindowWidgetType::ColourBtn;
}
}
}
@@ -1200,8 +1204,13 @@ private:
else if (scenerySelection.SceneryType == SCENERY_TYPE_LARGE)
{
auto sceneryEntry = get_large_scenery_entry(scenerySelection.EntryIndex);
auto imageId = ImageId(
sceneryEntry->image + gWindowSceneryRotation, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
auto imageId = ImageId(sceneryEntry->image + gWindowSceneryRotation);
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR)
imageId = imageId.WithPrimary(gWindowSceneryPrimaryColour);
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
imageId = imageId.WithSecondary(gWindowScenerySecondaryColour);
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR)
imageId = imageId.WithTertiary(gWindowSceneryTertiaryColour);
gfx_draw_sprite(&dpi, imageId, { 33, 0 });
}
else if (scenerySelection.SceneryType == SCENERY_TYPE_WALL)
@@ -1258,6 +1267,10 @@ private:
imageId = imageId.WithSecondary(gWindowScenerySecondaryColour);
}
}
if (sceneryEntry->flags & SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR)
{
imageId = imageId.WithTertiary(gWindowSceneryTertiaryColour);
}
auto spriteTop = (sceneryEntry->height / 4) + 43;
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE) && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VOFFSET_CENTRE))

View File

@@ -1036,7 +1036,7 @@ static void RepaintSceneryToolDown(const ScreenCoordsXY& windowPos, rct_widgetin
uint8_t quadrant = info.Element->AsSmallScenery()->GetSceneryQuadrant();
auto repaintScenery = SmallScenerySetColourAction(
{ info.Loc, info.Element->GetBaseZ() }, quadrant, info.Element->AsSmallScenery()->GetEntryIndex(),
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
GameActions::Execute(&repaintScenery);
break;
@@ -1066,7 +1066,8 @@ static void RepaintSceneryToolDown(const ScreenCoordsXY& windowPos, rct_widgetin
auto repaintScenery = LargeScenerySetColourAction(
{ info.Loc, info.Element->GetBaseZ(), info.Element->GetDirection() },
info.Element->AsLargeScenery()->GetSequenceIndex(), gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
info.Element->AsLargeScenery()->GetSequenceIndex(), gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour,
gWindowSceneryTertiaryColour);
GameActions::Execute(&repaintScenery);
break;
@@ -1812,7 +1813,7 @@ static void WindowTopToolbarSceneryToolDown(const ScreenCoordsXY& windowPos, rct
{
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, selectedScenery,
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
auto res = GameActions::Query(&smallSceneryPlaceAction);
success = res.Error;
if (res.Error == GameActions::Status::Ok)
@@ -1835,7 +1836,7 @@ static void WindowTopToolbarSceneryToolDown(const ScreenCoordsXY& windowPos, rct
{
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, selectedScenery,
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
smallSceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
@@ -1947,7 +1948,8 @@ static void WindowTopToolbarSceneryToolDown(const ScreenCoordsXY& windowPos, rct
CoordsXYZD loc = { gridPos, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(
loc, selectedScenery, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
loc, selectedScenery, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour,
gWindowSceneryTertiaryColour);
auto res = GameActions::Query(&sceneryPlaceAction);
if (res.Error == GameActions::Status::Ok)
@@ -1972,7 +1974,7 @@ static void WindowTopToolbarSceneryToolDown(const ScreenCoordsXY& windowPos, rct
CoordsXYZD loc = { gridPos, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(
loc, selectedScenery, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour);
loc, selectedScenery, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
sceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
{
@@ -2469,12 +2471,14 @@ static void TopToolbarToolUpdateWater(const ScreenCoordsXY& screenPos)
* On success places ghost scenery and returns cost to place proper
*/
static money64 TryPlaceGhostSmallScenery(
CoordsXYZD loc, uint8_t quadrant, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour)
CoordsXYZD loc, uint8_t quadrant, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour,
colour_t tertiaryColour)
{
scenery_remove_ghost_tool_placement();
// 6e252b
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(loc, quadrant, entryIndex, primaryColour, secondaryColour);
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
loc, quadrant, entryIndex, primaryColour, secondaryColour, tertiaryColour);
smallSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
auto res = GameActions::Execute(&smallSceneryPlaceAction);
if (res.Error != GameActions::Status::Ok)
@@ -2553,12 +2557,12 @@ static money64 TryPlaceGhostWall(
}
static money64 TryPlaceGhostLargeScenery(
CoordsXYZD loc, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour)
CoordsXYZD loc, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour, colour_t tertiaryColour)
{
scenery_remove_ghost_tool_placement();
// 6e25a7
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, entryIndex, primaryColour, secondaryColour);
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, entryIndex, primaryColour, secondaryColour, tertiaryColour);
sceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
auto res = GameActions::Execute(&sceneryPlaceAction);
if (res.Error != GameActions::Status::Ok)
@@ -2710,7 +2714,7 @@ static void TopToolbarToolUpdateScenery(const ScreenCoordsXY& screenPos)
{
cost = TryPlaceGhostSmallScenery(
{ mapTile, gSceneryPlaceZ, rotation }, quadrant, selection.EntryIndex, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour);
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
if (cost != MONEY64_UNDEFINED)
break;
@@ -2866,7 +2870,7 @@ static void TopToolbarToolUpdateScenery(const ScreenCoordsXY& screenPos)
{
cost = TryPlaceGhostLargeScenery(
{ mapTile, gSceneryPlaceZ, direction }, selection.EntryIndex, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour);
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
if (cost != MONEY64_UNDEFINED)
break;

View File

@@ -20,11 +20,12 @@
#include "../world/Surface.h"
LargeSceneryPlaceAction::LargeSceneryPlaceAction(
const CoordsXYZD& loc, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour)
const CoordsXYZD& loc, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour, uint8_t tertiaryColour)
: _loc(loc)
, _sceneryType(sceneryType)
, _primaryColour(primaryColour)
, _secondaryColour(secondaryColour)
, _tertiaryColour(tertiaryColour)
{
}
@@ -34,6 +35,7 @@ void LargeSceneryPlaceAction::AcceptParameters(GameActionParameterVisitor& visit
visitor.Visit("object", _sceneryType);
visitor.Visit("primaryColour", _primaryColour);
visitor.Visit("secondaryColour", _secondaryColour);
visitor.Visit("tertiaryColour", _tertiaryColour);
}
uint16_t LargeSceneryPlaceAction::GetActionFlags() const
@@ -45,7 +47,8 @@ void LargeSceneryPlaceAction::Serialise(DataSerialiser& stream)
{
GameAction::Serialise(stream);
stream << DS_TAG(_loc) << DS_TAG(_sceneryType) << DS_TAG(_primaryColour) << DS_TAG(_secondaryColour);
stream << DS_TAG(_loc) << DS_TAG(_sceneryType) << DS_TAG(_primaryColour) << DS_TAG(_secondaryColour)
<< DS_TAG(_tertiaryColour);
}
GameActions::Result LargeSceneryPlaceAction::Query() const
@@ -62,7 +65,7 @@ GameActions::Result LargeSceneryPlaceAction::Query() const
money32 supportsCost = 0;
if (_primaryColour > TILE_ELEMENT_COLOUR_MASK || _secondaryColour > TILE_ELEMENT_COLOUR_MASK)
if (_primaryColour >= COLOUR_COUNT || _secondaryColour >= COLOUR_COUNT || _tertiaryColour >= COLOUR_COUNT)
{
log_error(
"Invalid game command for scenery placement, primaryColour = %u, secondaryColour = %u", _primaryColour,
@@ -381,6 +384,7 @@ void LargeSceneryPlaceAction::SetNewLargeSceneryElement(LargeSceneryElement& sce
sceneryElement.SetSequenceIndex(tileNum);
sceneryElement.SetPrimaryColour(_primaryColour);
sceneryElement.SetSecondaryColour(_secondaryColour);
sceneryElement.SetTertiaryColour(_tertiaryColour);
if (GetFlags() & GAME_COMMAND_FLAG_GHOST)
{

View File

@@ -27,12 +27,14 @@ private:
ObjectEntryIndex _sceneryType{ OBJECT_ENTRY_INDEX_NULL };
uint8_t _primaryColour{};
uint8_t _secondaryColour{};
uint8_t _tertiaryColour{};
public:
LargeSceneryPlaceAction() = default;
LargeSceneryPlaceAction(
const CoordsXYZD& loc, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour);
const CoordsXYZD& loc, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour,
uint8_t tertiaryColour);
void AcceptParameters(GameActionParameterVisitor& visitor) override;

View File

@@ -14,11 +14,12 @@
#include "../world/Scenery.h"
LargeScenerySetColourAction::LargeScenerySetColourAction(
const CoordsXYZD& loc, uint8_t tileIndex, uint8_t primaryColour, uint8_t secondaryColour)
const CoordsXYZD& loc, uint8_t tileIndex, uint8_t primaryColour, uint8_t secondaryColour, uint8_t tertiaryColour)
: _loc(loc)
, _tileIndex(tileIndex)
, _primaryColour(primaryColour)
, _secondaryColour(secondaryColour)
, _tertiaryColour(tertiaryColour)
{
}
@@ -31,7 +32,8 @@ void LargeScenerySetColourAction::Serialise(DataSerialiser& stream)
{
GameAction::Serialise(stream);
stream << DS_TAG(_loc) << DS_TAG(_tileIndex) << DS_TAG(_primaryColour) << DS_TAG(_secondaryColour);
stream << DS_TAG(_loc) << DS_TAG(_tileIndex) << DS_TAG(_primaryColour) << DS_TAG(_secondaryColour)
<< DS_TAG(_tertiaryColour);
}
GameActions::Result LargeScenerySetColourAction::Query() const
@@ -60,15 +62,21 @@ GameActions::Result LargeScenerySetColourAction::QueryExecute(bool isExecuting)
return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
}
if (_primaryColour > 31)
if (_primaryColour >= COLOUR_COUNT)
{
log_error("Invalid primary colour: colour = %u", _primaryColour);
return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
}
if (_secondaryColour > 31)
if (_secondaryColour >= COLOUR_COUNT)
{
log_error("Invalid primary colour: colour = %u", _secondaryColour);
log_error("Invalid secondary colour: colour = %u", _secondaryColour);
return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
}
if (_tertiaryColour >= COLOUR_COUNT)
{
log_error("Invalid tertiary colour: colour = %u", _tertiaryColour);
return GameActions::Result(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
}
@@ -135,6 +143,7 @@ GameActions::Result LargeScenerySetColourAction::QueryExecute(bool isExecuting)
{
tileElement->SetPrimaryColour(_primaryColour);
tileElement->SetSecondaryColour(_secondaryColour);
tileElement->SetTertiaryColour(_tertiaryColour);
map_invalidate_tile_full(currentTile);
}

View File

@@ -18,10 +18,12 @@ private:
uint8_t _tileIndex{};
uint8_t _primaryColour{};
uint8_t _secondaryColour{};
uint8_t _tertiaryColour{};
public:
LargeScenerySetColourAction() = default;
LargeScenerySetColourAction(const CoordsXYZD& loc, uint8_t tileIndex, uint8_t primaryColour, uint8_t secondaryColour);
LargeScenerySetColourAction(
const CoordsXYZD& loc, uint8_t tileIndex, uint8_t primaryColour, uint8_t secondaryColour, uint8_t tertiaryColour);
uint16_t GetActionFlags() const override;

View File

@@ -29,12 +29,14 @@
#include "SmallSceneryRemoveAction.h"
SmallSceneryPlaceAction::SmallSceneryPlaceAction(
const CoordsXYZD& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour)
const CoordsXYZD& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour,
uint8_t tertiaryColour)
: _loc(loc)
, _quadrant(quadrant)
, _sceneryType(sceneryType)
, _primaryColour(primaryColour)
, _secondaryColour(secondaryColour)
, _tertiaryColour(tertiaryColour)
{
}
@@ -419,6 +421,7 @@ GameActions::Result SmallSceneryPlaceAction::Execute() const
sceneryElement->SetAge(0);
sceneryElement->SetPrimaryColour(_primaryColour);
sceneryElement->SetSecondaryColour(_secondaryColour);
sceneryElement->SetTertiaryColour(_tertiaryColour);
sceneryElement->SetClearanceZ(sceneryElement->GetBaseZ() + sceneryEntry->height + 7);
sceneryElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST);
if (supportsRequired)

View File

@@ -27,11 +27,13 @@ private:
ObjectEntryIndex _sceneryType{};
uint8_t _primaryColour{};
uint8_t _secondaryColour{};
uint8_t _tertiaryColour{};
public:
SmallSceneryPlaceAction() = default;
SmallSceneryPlaceAction(
const CoordsXYZD& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour);
const CoordsXYZD& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour,
uint8_t tertiaryColour);
void AcceptParameters(GameActionParameterVisitor& visitor) override;

View File

@@ -26,12 +26,14 @@
#include "../world/TileElement.h"
SmallScenerySetColourAction::SmallScenerySetColourAction(
const CoordsXYZ& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour)
const CoordsXYZ& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour,
uint8_t tertiaryColour)
: _loc(loc)
, _quadrant(quadrant)
, _sceneryType(sceneryType)
, _primaryColour(primaryColour)
, _secondaryColour(secondaryColour)
, _tertiaryColour(tertiaryColour)
{
}
@@ -96,6 +98,7 @@ GameActions::Result SmallScenerySetColourAction::QueryExecute(bool isExecuting)
{
sceneryElement->SetPrimaryColour(_primaryColour);
sceneryElement->SetSecondaryColour(_secondaryColour);
sceneryElement->SetTertiaryColour(_tertiaryColour);
map_invalidate_tile_full(_loc);
}

View File

@@ -19,11 +19,13 @@ private:
ObjectEntryIndex _sceneryType{};
uint8_t _primaryColour{};
uint8_t _secondaryColour{};
uint8_t _tertiaryColour{};
public:
SmallScenerySetColourAction() = default;
SmallScenerySetColourAction(
const CoordsXYZ& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour);
const CoordsXYZ& loc, uint8_t quadrant, ObjectEntryIndex sceneryType, uint8_t primaryColour, uint8_t secondaryColour,
uint8_t tertiaryColour);
uint16_t GetActionFlags() const override;

View File

@@ -106,7 +106,14 @@ void LargeSceneryObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int3
{
auto screenCoords = ScreenCoordsXY{ width / 2, (height / 2) - 39 };
const auto image = ImageId(_legacyType.image, COLOUR_BORDEAUX_RED, COLOUR_YELLOW);
auto image = ImageId(_legacyType.image);
if (_legacyType.flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR)
image = image.WithPrimary(COLOUR_BORDEAUX_RED);
if (_legacyType.flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
image = image.WithSecondary(COLOUR_YELLOW);
if (_legacyType.flags & LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR)
image = image.WithTertiary(COLOUR_DARK_BROWN);
gfx_draw_sprite(dpi, image, screenCoords);
}
@@ -143,6 +150,7 @@ void LargeSceneryObject::ReadJson(IReadObjectContext* context, json_t& root)
{
{ "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR },
{ "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR },
{ "hasTertiaryColour", LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR },
{ "isAnimated", LARGE_SCENERY_FLAG_ANIMATED },
{ "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC },
{ "isTree", LARGE_SCENERY_FLAG_IS_TREE },

View File

@@ -107,6 +107,10 @@ void SmallSceneryObject::DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int3
imageId = imageId.WithSecondary(COLOUR_YELLOW);
}
}
if (_legacyType.HasFlag(SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR))
{
imageId = imageId.WithSecondary(COLOUR_DARK_BROWN);
}
auto screenCoords = ScreenCoordsXY{ width / 2, (height / 2) + (_legacyType.height / 2) };
screenCoords.y = std::min(screenCoords.y, height - 16);
@@ -260,6 +264,7 @@ void SmallSceneryObject::ReadJson(IReadObjectContext* context, json_t& root)
{ "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS },
{ "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 },
{ "isTree", SMALL_SCENERY_FLAG_IS_TREE },
{ "hasTertiaryColour", SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR },
});
// Determine shape flags from a shape string

View File

@@ -374,7 +374,18 @@ void PaintLargeScenery(paint_session& session, uint8_t direction, uint16_t heigh
}
else
{
imageTemplate = ImageId(0, tileElement.GetPrimaryColour(), tileElement.GetSecondaryColour());
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR)
{
imageTemplate = imageTemplate.WithPrimary(tileElement.GetPrimaryColour());
}
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
{
imageTemplate = imageTemplate.WithSecondary(tileElement.GetSecondaryColour());
}
if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR)
{
imageTemplate = imageTemplate.WithTertiary(tileElement.GetTertiaryColour());
}
}
auto boxlengthZ = std::min<uint8_t>(tile->z_clearance, 128) - 3;

View File

@@ -186,12 +186,19 @@ static void PaintSmallSceneryBody(
if (!(sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED)))
{
auto imageId = imageTemplate.WithIndex(baseImageIndex);
if (!imageTemplate.IsRemap() && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
if (!imageTemplate.IsRemap())
{
imageId = imageId.WithPrimary(sceneryElement.GetPrimaryColour());
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
{
imageId = imageId.WithSecondary(sceneryElement.GetSecondaryColour());
imageId = imageId.WithPrimary(sceneryElement.GetPrimaryColour());
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
{
imageId = imageId.WithSecondary(sceneryElement.GetSecondaryColour());
}
}
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR))
{
imageId = imageId.WithTertiary(sceneryElement.GetTertiaryColour());
}
}
PaintAddImageAsParent(session, imageId, offset, boxLength, boxOffset);
@@ -285,12 +292,19 @@ static void PaintSmallSceneryBody(
}
auto imageId = imageTemplate.WithIndex(imageIndex);
if (!imageTemplate.IsRemap() && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
if (!imageTemplate.IsRemap())
{
imageId = ImageId(imageIndex).WithPrimary(sceneryElement.GetPrimaryColour());
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
{
imageId = imageId.WithSecondary(sceneryElement.GetSecondaryColour());
imageId = ImageId(imageIndex).WithPrimary(sceneryElement.GetPrimaryColour());
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR))
{
imageId = imageId.WithSecondary(sceneryElement.GetSecondaryColour());
}
}
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR))
{
imageId = imageId.WithTertiary(sceneryElement.GetTertiaryColour());
}
}

View File

@@ -1086,7 +1086,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
auto smallSceneryPlace = SmallSceneryPlaceAction(
{ mapCoord.x, mapCoord.y, z, rotation }, quadrant, entryInfo->Index, scenery.primary_colour,
scenery.secondary_colour);
scenery.secondary_colour, COLOUR_DARK_BROWN);
smallSceneryPlace.SetFlags(flags);
auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&smallSceneryPlace)
@@ -1127,7 +1127,8 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
flags |= GAME_COMMAND_FLAG_REPLAY;
}
auto sceneryPlaceAction = LargeSceneryPlaceAction(
{ mapCoord.x, mapCoord.y, z, rotation }, entryInfo->Index, scenery.primary_colour, scenery.secondary_colour);
{ mapCoord.x, mapCoord.y, z, rotation }, entryInfo->Index, scenery.primary_colour, scenery.secondary_colour,
COLOUR_DARK_BROWN);
sceneryPlaceAction.SetFlags(flags);
auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&sceneryPlaceAction)
: GameActions::QueryNested(&sceneryPlaceAction);

View File

@@ -26,6 +26,11 @@ colour_t LargeSceneryElement::GetSecondaryColour() const
return Colour[1];
}
colour_t LargeSceneryElement::GetTertiaryColour() const
{
return Colour[2];
}
void LargeSceneryElement::SetPrimaryColour(colour_t newColour)
{
assert(newColour <= 31);
@@ -38,6 +43,12 @@ void LargeSceneryElement::SetSecondaryColour(colour_t newColour)
Colour[1] = newColour;
}
void LargeSceneryElement::SetTertiaryColour(colour_t newColour)
{
assert(newColour <= 31);
Colour[2] = newColour;
}
Banner* LargeSceneryElement::GetBanner() const
{
return ::GetBanner(GetBannerIndex());

View File

@@ -97,6 +97,7 @@ enum LARGE_SCENERY_FLAGS
LARGE_SCENERY_FLAG_ANIMATED = (1 << 3), // 0x8
LARGE_SCENERY_FLAG_PHOTOGENIC = (1 << 4), // 0x10
LARGE_SCENERY_FLAG_IS_TREE = (1 << 5), // 0x20
LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR = (1 << 6), // 0x40
};
enum WALL_SCENERY_FLAGS

View File

@@ -79,36 +79,48 @@ void SmallSceneryElement::IncreaseAge(const CoordsXY& sceneryPos)
colour_t SmallSceneryElement::GetPrimaryColour() const
{
return colour_1 & TILE_ELEMENT_COLOUR_MASK;
return Colour[0] & TILE_ELEMENT_COLOUR_MASK;
}
colour_t SmallSceneryElement::GetSecondaryColour() const
{
return colour_2 & TILE_ELEMENT_COLOUR_MASK;
return Colour[1] & TILE_ELEMENT_COLOUR_MASK;
}
void SmallSceneryElement::SetPrimaryColour(colour_t colour)
colour_t SmallSceneryElement::GetTertiaryColour() const
{
assert(colour <= 31);
colour_1 &= ~TILE_ELEMENT_COLOUR_MASK;
colour_1 |= colour;
return Colour[2] & TILE_ELEMENT_COLOUR_MASK;
}
void SmallSceneryElement::SetSecondaryColour(colour_t colour)
void SmallSceneryElement::SetPrimaryColour(colour_t newColour)
{
assert(colour <= 31);
colour_2 &= ~TILE_ELEMENT_COLOUR_MASK;
colour_2 |= colour;
assert(newColour <= 31);
Colour[0] &= ~TILE_ELEMENT_COLOUR_MASK;
Colour[0] |= newColour;
}
void SmallSceneryElement::SetSecondaryColour(colour_t newColour)
{
assert(newColour <= 31);
Colour[1] &= ~TILE_ELEMENT_COLOUR_MASK;
Colour[1] |= newColour;
}
void SmallSceneryElement::SetTertiaryColour(colour_t newColour)
{
assert(newColour <= 31);
Colour[2] &= ~TILE_ELEMENT_COLOUR_MASK;
Colour[2] |= newColour;
}
bool SmallSceneryElement::NeedsSupports() const
{
return static_cast<bool>(colour_1 & MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS);
return static_cast<bool>(Colour[0] & MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS);
}
void SmallSceneryElement::SetNeedsSupports()
{
colour_1 |= MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS;
Colour[0] |= MAP_ELEM_SMALL_SCENERY_COLOUR_FLAG_NEEDS_SUPPORTS;
}
SmallSceneryEntry* SmallSceneryElement::GetEntry() const

View File

@@ -45,7 +45,9 @@ enum SMALL_SCENERY_FLAGS : uint32_t
SMALL_SCENERY_FLAG_PAINT_SUPPORTS = (1 << 26), // 0x4000000; used for scenery items which are support structures
SMALL_SCENERY_FLAG27 = (1 << 27), // 0x8000000
SMALL_SCENERY_FLAG_IS_TREE = (1 << 28), // Added by OpenRCT2
// Added by OpenRCT2:
SMALL_SCENERY_FLAG_IS_TREE = (1 << 28),
SMALL_SCENERY_FLAG_HAS_TERTIARY_COLOUR = (1 << 29),
};
enum

View File

@@ -429,11 +429,10 @@ struct SmallSceneryElement : TileElementBase
private:
ObjectEntryIndex entryIndex; // 5
uint8_t age; // 7
uint8_t colour_1; // 8
uint8_t colour_2; // 9
uint8_t Colour[3]; // 8
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
uint8_t pad_0A[6];
uint8_t pad_0B[5];
#pragma clang diagnostic pop
public:
@@ -449,6 +448,8 @@ public:
void SetPrimaryColour(colour_t colour);
colour_t GetSecondaryColour() const;
void SetSecondaryColour(colour_t colour);
colour_t GetTertiaryColour() const;
void SetTertiaryColour(colour_t colour);
bool NeedsSupports() const;
void SetNeedsSupports();
void UpdateAge(const CoordsXY& sceneryPos);
@@ -483,6 +484,8 @@ public:
void SetPrimaryColour(colour_t colour);
colour_t GetSecondaryColour() const;
void SetSecondaryColour(colour_t colour);
colour_t GetTertiaryColour() const;
void SetTertiaryColour(colour_t colour);
Banner* GetBanner() const;
::BannerIndex GetBannerIndex() const;