mirror of https://github.com/OpenRCT2/OpenRCT2.git
Implement small scenery ternary colours
This commit is contained in:
parent
e9e377ac09
commit
793acf67ae
|
@ -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 they’re sheltered.
|
||||
- Improved: [#10664, #16072] Visibility status can be modified directly in the Tile Inspector's list.
|
||||
|
|
|
@ -602,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1265,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))
|
||||
|
|
|
@ -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;
|
||||
|
@ -1813,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)
|
||||
|
@ -1836,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)
|
||||
|
@ -2471,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)
|
||||
|
@ -2712,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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue