mirror of https://github.com/OpenRCT2/OpenRCT2.git
Create or delete banners when tile elements are changed by plugins (#21627)
This commit is contained in:
parent
919cef7f55
commit
f4156e9043
|
@ -66,6 +66,7 @@
|
|||
- Fix: [#21434] Number of guests overflows in objective text.
|
||||
- Fix: [#21522] Supports for 3×3 turns and 45 degree turns on the Hybrid Coaster and Wooden Roller Coaster not drawn correctly.
|
||||
- Fix: [#21543] Crash with creating a TrackIterator with invalid arguments.
|
||||
- Fix: [#21627] [Plugin] Banners are properly created or deleted when tile elements are changed by plugins.
|
||||
- Fix: [#21635] Tile inspector hotkey can set wall slope for non-slopeable objects.
|
||||
- Fix: [#21641] Crash when creating track iterator from an invalid tile element.
|
||||
- Fix: [#21652] Dialog window to confirm overwriting files does not apply the theme colours correctly.
|
||||
|
|
|
@ -46,7 +46,7 @@ using namespace OpenRCT2;
|
|||
// It is used for making sure only compatible builds get connected, even within
|
||||
// single OpenRCT2 version.
|
||||
|
||||
constexpr uint8_t kNetworkStreamVersion = 0;
|
||||
constexpr uint8_t kNetworkStreamVersion = 1;
|
||||
|
||||
const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion);
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace OpenRCT2
|
|||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 87;
|
||||
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 88;
|
||||
|
||||
// Versions marking breaking changes.
|
||||
static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# include "../../../common.h"
|
||||
# include "../../../core/Guard.hpp"
|
||||
# include "../../../entity/EntityRegistry.h"
|
||||
# include "../../../object/LargeSceneryEntry.h"
|
||||
# include "../../../ride/Track.h"
|
||||
# include "../../../world/Footpath.h"
|
||||
# include "../../../world/Scenery.h"
|
||||
|
@ -195,6 +196,13 @@ namespace OpenRCT2::Scripting
|
|||
auto first = GetFirstElement();
|
||||
if (index < GetNumElements(first))
|
||||
{
|
||||
auto element = &first[index];
|
||||
if (element->GetType() != TileElementType::LargeScenery
|
||||
|| element->AsLargeScenery()->GetEntry()->scrolling_mode == SCROLLING_MODE_NONE
|
||||
|| ScTileElement::GetOtherLargeSceneryElement(_coords, element->AsLargeScenery()) == nullptr)
|
||||
{
|
||||
element->RemoveBannerEntry();
|
||||
}
|
||||
TileElementRemove(&first[index]);
|
||||
MapInvalidateTileFull(_coords);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
# include "../../../common.h"
|
||||
# include "../../../core/Guard.hpp"
|
||||
# include "../../../entity/EntityRegistry.h"
|
||||
# include "../../../object/LargeSceneryEntry.h"
|
||||
# include "../../../object/WallSceneryEntry.h"
|
||||
# include "../../../ride/Ride.h"
|
||||
# include "../../../ride/RideData.h"
|
||||
# include "../../../ride/Track.h"
|
||||
|
@ -63,6 +65,7 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
void ScTileElement::type_set(std::string value)
|
||||
{
|
||||
RemoveBannerEntryIfNeeded();
|
||||
if (value == "surface")
|
||||
_element->SetType(TileElementType::Surface);
|
||||
else if (value == "footpath")
|
||||
|
@ -85,7 +88,7 @@ namespace OpenRCT2::Scripting
|
|||
scriptEngine.LogPluginInfo("Element type not recognised!");
|
||||
return;
|
||||
}
|
||||
|
||||
CreateBannerEntryIfNeeded();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
@ -537,8 +540,10 @@ namespace OpenRCT2::Scripting
|
|||
{
|
||||
case TileElementType::LargeScenery:
|
||||
{
|
||||
RemoveBannerEntryIfNeeded();
|
||||
auto* el = _element->AsLargeScenery();
|
||||
el->SetSequenceIndex(value.as_uint());
|
||||
CreateBannerEntryIfNeeded();
|
||||
Invalidate();
|
||||
break;
|
||||
}
|
||||
|
@ -1194,15 +1199,19 @@ namespace OpenRCT2::Scripting
|
|||
}
|
||||
case TileElementType::LargeScenery:
|
||||
{
|
||||
RemoveBannerEntryIfNeeded();
|
||||
auto* el = _element->AsLargeScenery();
|
||||
el->SetEntryIndex(index);
|
||||
CreateBannerEntryIfNeeded();
|
||||
Invalidate();
|
||||
break;
|
||||
}
|
||||
case TileElementType::Wall:
|
||||
{
|
||||
RemoveBannerEntryIfNeeded();
|
||||
auto* el = _element->AsWall();
|
||||
el->SetEntryIndex(index);
|
||||
CreateBannerEntryIfNeeded();
|
||||
Invalidate();
|
||||
break;
|
||||
}
|
||||
|
@ -2140,6 +2149,129 @@ namespace OpenRCT2::Scripting
|
|||
MapInvalidateTileFull(_coords);
|
||||
}
|
||||
|
||||
const LargeSceneryElement* ScTileElement::GetOtherLargeSceneryElement(
|
||||
const CoordsXY& loc, const LargeSceneryElement* const largeScenery)
|
||||
{
|
||||
const auto* const largeEntry = largeScenery->GetEntry();
|
||||
const auto direction = largeScenery->GetDirection();
|
||||
const auto sequenceIndex = largeScenery->GetSequenceIndex();
|
||||
const auto* tiles = largeEntry->tiles;
|
||||
const auto& tile = tiles[sequenceIndex];
|
||||
const auto rotatedFirstTile = CoordsXYZ{
|
||||
CoordsXY{ tile.x_offset, tile.y_offset }.Rotate(direction),
|
||||
tile.z_offset,
|
||||
};
|
||||
|
||||
const auto firstTile = CoordsXYZ{ loc, largeScenery->GetBaseZ() } - rotatedFirstTile;
|
||||
for (int32_t i = 0; tiles[i].x_offset != -1; i++)
|
||||
{
|
||||
const auto rotatedCurrentTile = CoordsXYZ{ CoordsXY{ tiles[i].x_offset, tiles[i].y_offset }.Rotate(direction),
|
||||
tiles[i].z_offset };
|
||||
|
||||
const auto currentTile = firstTile + rotatedCurrentTile;
|
||||
|
||||
const TileElement* tileElement = MapGetFirstElementAt(currentTile);
|
||||
if (tileElement != nullptr)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (tileElement->GetType() != TileElementType::LargeScenery)
|
||||
continue;
|
||||
if (tileElement->GetDirection() != direction)
|
||||
continue;
|
||||
if (tileElement->GetBaseZ() != currentTile.z)
|
||||
continue;
|
||||
|
||||
if (tileElement->AsLargeScenery() == largeScenery)
|
||||
continue;
|
||||
if (tileElement->AsLargeScenery()->GetEntryIndex() != largeScenery->GetEntryIndex())
|
||||
continue;
|
||||
if (tileElement->AsLargeScenery()->GetSequenceIndex() != i)
|
||||
continue;
|
||||
|
||||
return tileElement->AsLargeScenery();
|
||||
} while (!(tileElement++)->IsLastForTile());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ScTileElement::RemoveBannerEntryIfNeeded()
|
||||
{
|
||||
// check if other element still uses the banner entry
|
||||
if (_element->GetType() == TileElementType::LargeScenery
|
||||
&& _element->AsLargeScenery()->GetEntry()->scrolling_mode != SCROLLING_MODE_NONE
|
||||
&& GetOtherLargeSceneryElement(_coords, _element->AsLargeScenery()) != nullptr)
|
||||
return;
|
||||
// remove banner entry (if one exists)
|
||||
_element->RemoveBannerEntry();
|
||||
}
|
||||
|
||||
void ScTileElement::CreateBannerEntryIfNeeded()
|
||||
{
|
||||
// check if creation is needed
|
||||
switch (_element->GetType())
|
||||
{
|
||||
case TileElementType::Banner:
|
||||
break;
|
||||
case TileElementType::Wall:
|
||||
{
|
||||
auto wallEntry = _element->AsWall()->GetEntry();
|
||||
if (wallEntry->scrolling_mode == SCROLLING_MODE_NONE)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
case TileElementType::LargeScenery:
|
||||
{
|
||||
auto largeScenery = _element->AsLargeScenery();
|
||||
auto largeSceneryEntry = largeScenery->GetEntry();
|
||||
if (largeSceneryEntry == nullptr || largeSceneryEntry->scrolling_mode == SCROLLING_MODE_NONE)
|
||||
return;
|
||||
|
||||
auto otherElement = GetOtherLargeSceneryElement(_coords, largeScenery);
|
||||
if (otherElement != nullptr)
|
||||
{
|
||||
largeScenery->SetBannerIndex(otherElement->GetBannerIndex());
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// create banner entry and initialise it
|
||||
auto* banner = CreateBanner();
|
||||
if (banner == nullptr)
|
||||
GetContext()->GetScriptEngine().LogPluginInfo("No free banners available.");
|
||||
else
|
||||
{
|
||||
banner->text = {};
|
||||
banner->colour = 0;
|
||||
banner->text_colour = 0;
|
||||
banner->flags = 0;
|
||||
if (_element->GetType() == TileElementType::Wall)
|
||||
banner->flags = BANNER_FLAG_IS_WALL;
|
||||
if (_element->GetType() == TileElementType::LargeScenery)
|
||||
banner->flags = BANNER_FLAG_IS_LARGE_SCENERY;
|
||||
banner->type = 0;
|
||||
banner->position = TileCoordsXY(_coords);
|
||||
|
||||
if (_element->GetType() == TileElementType::Wall || _element->GetType() == TileElementType::LargeScenery)
|
||||
{
|
||||
RideId rideIndex = BannerGetClosestRideIndex({ _coords, _element->BaseHeight });
|
||||
if (!rideIndex.IsNull())
|
||||
{
|
||||
banner->ride_index = rideIndex;
|
||||
banner->flags |= BANNER_FLAG_LINKED_TO_RIDE;
|
||||
}
|
||||
}
|
||||
|
||||
_element->SetBannerIndex(banner->id);
|
||||
}
|
||||
}
|
||||
|
||||
void ScTileElement::Register(duk_context* ctx)
|
||||
{
|
||||
// All
|
||||
|
|
|
@ -210,7 +210,12 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
void Invalidate();
|
||||
|
||||
void RemoveBannerEntryIfNeeded();
|
||||
void CreateBannerEntryIfNeeded();
|
||||
|
||||
public:
|
||||
static const LargeSceneryElement* GetOtherLargeSceneryElement(
|
||||
const CoordsXY& loc, const LargeSceneryElement* const largeScenery);
|
||||
static void Register(duk_context* ctx);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue