1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-10 09:32:29 +01:00

Close #24146: Expand plugin functionality for balloons and money effects

This commit is contained in:
Max
2025-04-19 23:23:02 +02:00
committed by GitHub
parent 57e75329cd
commit 923a38c990
11 changed files with 267 additions and 21 deletions

View File

@@ -24,6 +24,7 @@
- Feature: [#22646] New scenario files now contain a minimap image, shown in the scenario selection window.
- Feature: [#23774] Climates can now be customised using objects.
- Feature: [#23876] New park save files now contain a preview image, shown in the load/save window.
- Feature: [#24146] [Plugin] Add APIs for colouring balloons and setting the value of money effects.
- Improved: [#24078] Handrails on Wooden Roller Coaster station sprites with no platforms have been removed.
- Improved: [objects#379] Add additional colour schemes to Mine Train.
- Change: [#23932] The land rights window now checks “Land Owned” by default.

View File

@@ -1710,6 +1710,7 @@ declare global {
readonly year: number;
}
/**
* APIs for the map.
*/
@@ -1731,11 +1732,15 @@ declare global {
getAllEntities(type: "staff"): Staff[];
getAllEntities(type: "car"): Car[];
getAllEntities(type: "litter"): Litter[];
getAllEntities(type: "balloon"): Balloon[];
getAllEntities(type: "money_effect"): MoneyEffect[];
getAllEntitiesOnTile(type: EntityType, tilePos: CoordsXY): Entity[];
getAllEntitiesOnTile(type: "guest", tilePos: CoordsXY): Guest[];
getAllEntitiesOnTile(type: "staff", tilePos: CoordsXY): Staff[];
getAllEntitiesOnTile(type: "car", tilePos: CoordsXY): Car[];
getAllEntitiesOnTile(type: "litter", tilePos: CoordsXY): Litter[];
getAllEntitiesOnTile(type: "balloon", tilePos: CoordsXY): Balloon[];
getAllEntitiesOnTile(type: "money_effect", tilePos: CoordsXY): MoneyEffect[];
createEntity(type: EntityType, initializer: object): Entity;
/**
@@ -1745,6 +1750,7 @@ declare global {
* @param elementIndex The index of the track element on the tile.
*/
getTrackIterator(location: CoordsXY, elementIndex: number): TrackIterator | null;
}
type TileElementType =
@@ -3844,6 +3850,26 @@ declare global {
"empty_juice_cup" |
"empty_bowl_blue";
/**
* Represents balloon entity.
*/
interface Balloon extends Entity {
/**
* The colour of the balloon.
*/
colour: number;
}
/**
* Represents money_effect entity.
*/
interface MoneyEffect extends Entity {
/**
* The value of the money effect.
*/
value: number;
}
/**
* Network APIs
* Use `network.mode` to determine whether the current game is a client, server or in single player mode.

View File

@@ -51,25 +51,9 @@ void MoneyEffect::CreateAt(money64 value, const CoordsXYZ& effectPos, bool guest
if (moneyEffect == nullptr)
return;
moneyEffect->Value = value;
moneyEffect->GuestPurchase = (guestPurchase ? 1 : 0);
moneyEffect->SpriteData.Width = 64;
moneyEffect->SpriteData.HeightMin = 20;
moneyEffect->SpriteData.HeightMax = 30;
moneyEffect->MoveTo(effectPos);
moneyEffect->NumMovements = 0;
moneyEffect->MoveDelay = 0;
int16_t offsetX = 0;
if (!gOpenRCT2NoGraphics)
{
auto [stringId, newValue] = moneyEffect->GetStringId();
char buffer[128];
OpenRCT2::FormatStringLegacy(buffer, 128, stringId, &newValue);
offsetX = -(GfxGetStringWidth(buffer, FontStyle::Medium) / 2);
}
moneyEffect->OffsetX = offsetX;
moneyEffect->Wiggle = 0;
moneyEffect->SetValue(value);
}
/**
@@ -105,6 +89,30 @@ void MoneyEffect::Create(money64 value, const CoordsXYZ& loc)
CreateAt(-value, offsetLoc, false);
}
/**
* Set the value of the money effect
*/
void MoneyEffect::SetValue(money64 value)
{
Value = value;
SpriteData.Width = 64;
SpriteData.HeightMin = 20;
SpriteData.HeightMax = 30;
MoveDelay = 0;
NumMovements = 0;
int16_t offsetX = 0;
if (!gOpenRCT2NoGraphics)
{
auto [stringId, newValue] = GetStringId();
char buffer[128];
OpenRCT2::FormatStringLegacy(buffer, 128, stringId, &newValue);
offsetX = -(GfxGetStringWidth(buffer, FontStyle::Medium) / 2);
}
OffsetX = offsetX;
Wiggle = 0;
}
/**
*
* rct2: 0x00673232

View File

@@ -33,6 +33,7 @@ struct MoneyEffect : EntityBase
static void CreateAt(money64 value, const CoordsXYZ& effectPos, bool guestPurchase);
static void Create(money64 value, const CoordsXYZ& loc);
void SetValue(money64 value);
void Update();
std::pair<StringId, money64> GetStringId() const;
void Serialise(DataSerialiser& stream);

View File

@@ -561,9 +561,11 @@
<ClInclude Include="scenes\title\TitleSequence.h" />
<ClInclude Include="scenes\title\TitleSequenceManager.h" />
<ClInclude Include="scenes\title\TitleSequencePlayer.h" />
<ClInclude Include="scripting\bindings\entity\ScBalloon.hpp" />
<ClInclude Include="scripting\bindings\entity\ScEntity.hpp" />
<ClInclude Include="scripting\bindings\entity\ScGuest.hpp" />
<ClInclude Include="scripting\bindings\entity\ScLitter.hpp" />
<ClInclude Include="scripting\bindings\entity\ScMoneyEffect.hpp" />
<ClInclude Include="scripting\bindings\entity\ScParticle.hpp" />
<ClInclude Include="scripting\bindings\entity\ScPeep.hpp" />
<ClInclude Include="scripting\bindings\entity\ScStaff.hpp" />
@@ -600,6 +602,7 @@
<ClInclude Include="scripting\IconNames.hpp" />
<ClInclude Include="scripting\Plugin.h" />
<ClInclude Include="scripting\ScriptEngine.h" />
<ClInclude Include="scripting\SoundNames.hpp" />
<ClInclude Include="SpriteIds.h" />
<ClInclude Include="System.hpp" />
<ClInclude Include="TrackImporter.h" />
@@ -1088,8 +1091,10 @@
<ClCompile Include="scenes\title\TitleScene.cpp" />
<ClCompile Include="scenes\title\TitleSequence.cpp" />
<ClCompile Include="scenes\title\TitleSequenceManager.cpp" />
<ClCompile Include="scripting\bindings\entity\ScBalloon.cpp" />
<ClCompile Include="scripting\bindings\entity\ScGuest.cpp" />
<ClCompile Include="scripting\bindings\entity\ScLitter.cpp" />
<ClCompile Include="scripting\bindings\entity\ScMoneyEffect.cpp" />
<ClCompile Include="scripting\bindings\entity\ScParticle.cpp" />
<ClCompile Include="scripting\bindings\entity\ScStaff.cpp" />
<ClCompile Include="scripting\bindings\entity\ScVehicle.cpp" />

View File

@@ -27,9 +27,11 @@
#include "../interface/InteractiveConsole.h"
#include "../platform/Platform.h"
#include "Duktape.hpp"
#include "bindings/entity/ScBalloon.hpp"
#include "bindings/entity/ScEntity.hpp"
#include "bindings/entity/ScGuest.hpp"
#include "bindings/entity/ScLitter.hpp"
#include "bindings/entity/ScMoneyEffect.hpp"
#include "bindings/entity/ScParticle.hpp"
#include "bindings/entity/ScPeep.hpp"
#include "bindings/entity/ScStaff.hpp"
@@ -438,6 +440,8 @@ void ScriptEngine::Initialise()
ScTrackSegment::Register(ctx);
ScEntity::Register(ctx);
ScLitter::Register(ctx);
ScBalloon::Register(ctx);
ScMoneyEffect::Register(ctx);
ScVehicle::Register(ctx);
ScCrashedVehicleParticle::Register(ctx);
ScPeep::Register(ctx);

View File

@@ -0,0 +1,55 @@
/*****************************************************************************
* Copyright (c) 2014-2025 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.
*****************************************************************************/
#ifdef ENABLE_SCRIPTING
#include "ScBalloon.hpp"
#include "../../../entity/Balloon.h"
namespace OpenRCT2::Scripting
{
ScBalloon::ScBalloon(EntityId Id)
: ScEntity(Id)
{
}
void ScBalloon::Register(duk_context* ctx)
{
dukglue_set_base_class<ScEntity, ScBalloon>(ctx);
dukglue_register_property(ctx, &ScBalloon::colour_get, &ScBalloon::colour_set, "colour");
}
Balloon* ScBalloon::GetBalloon() const
{
return ::GetEntity<Balloon>(_id);
}
uint8_t ScBalloon::colour_get() const
{
auto balloon = GetBalloon();
if (balloon != nullptr)
{
return balloon->colour;
}
return 0;
}
void ScBalloon::colour_set(uint8_t value)
{
auto balloon = GetBalloon();
if (balloon != nullptr)
{
balloon->colour = value;
}
}
} // namespace OpenRCT2::Scripting
#endif

View File

@@ -0,0 +1,35 @@
/*****************************************************************************
* Copyright (c) 2014-2025 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.
*****************************************************************************/
#pragma once
#ifdef ENABLE_SCRIPTING
#include "ScEntity.hpp"
struct Balloon;
namespace OpenRCT2::Scripting
{
class ScBalloon : public ScEntity
{
public:
ScBalloon(EntityId Id);
static void Register(duk_context* ctx);
private:
Balloon* GetBalloon() const;
uint8_t colour_get() const;
void colour_set(uint8_t);
};
} // namespace OpenRCT2::Scripting
#endif

View File

@@ -0,0 +1,55 @@
/*****************************************************************************
* Copyright (c) 2014-2025 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.
*****************************************************************************/
#ifdef ENABLE_SCRIPTING
#include "ScMoneyEffect.hpp"
#include "../../../entity/MoneyEffect.h"
namespace OpenRCT2::Scripting
{
ScMoneyEffect::ScMoneyEffect(EntityId Id)
: ScEntity(Id)
{
}
void ScMoneyEffect::Register(duk_context* ctx)
{
dukglue_set_base_class<ScEntity, ScMoneyEffect>(ctx);
dukglue_register_property(ctx, &ScMoneyEffect::value_get, &ScMoneyEffect::value_set, "value");
}
MoneyEffect* ScMoneyEffect::GetMoneyEffect() const
{
return ::GetEntity<MoneyEffect>(_id);
}
money64 ScMoneyEffect::value_get() const
{
auto moneyEffect = GetMoneyEffect();
if (moneyEffect != nullptr)
{
return moneyEffect->Value;
}
return 0;
}
void ScMoneyEffect::value_set(money64 value)
{
auto moneyEffect = GetMoneyEffect();
if (moneyEffect != nullptr)
{
moneyEffect->SetValue(value);
}
}
} // namespace OpenRCT2::Scripting
#endif

View File

@@ -0,0 +1,36 @@
/*****************************************************************************
* Copyright (c) 2014-2025 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.
*****************************************************************************/
#pragma once
#ifdef ENABLE_SCRIPTING
#include "ScEntity.hpp"
struct MoneyEffect;
namespace OpenRCT2::Scripting
{
class ScMoneyEffect : public ScEntity
{
public:
ScMoneyEffect(EntityId Id);
static void Register(duk_context* ctx);
private:
MoneyEffect* GetMoneyEffect() const;
money64 value_get() const;
void value_set(money64);
};
} // namespace OpenRCT2::Scripting
#endif

View File

@@ -26,9 +26,11 @@
#include "../../../ride/TrainManager.h"
#include "../../../world/Map.h"
#include "../../Duktape.hpp"
#include "../entity/ScBalloon.hpp"
#include "../entity/ScEntity.hpp"
#include "../entity/ScGuest.hpp"
#include "../entity/ScLitter.hpp"
#include "../entity/ScMoneyEffect.hpp"
#include "../entity/ScParticle.hpp"
#include "../entity/ScStaff.hpp"
#include "../entity/ScVehicle.hpp"
@@ -108,7 +110,7 @@ namespace OpenRCT2::Scripting
{
for (auto sprite : EntityList<Balloon>())
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScEntity>(sprite->Id)));
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScBalloon>(sprite->Id)));
}
}
else if (type == "car")
@@ -144,6 +146,13 @@ namespace OpenRCT2::Scripting
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScLitter>(sprite->Id)));
}
}
else if (type == "money_effect")
{
for (auto sprite : EntityList<MoneyEffect>())
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScMoneyEffect>(sprite->Id)));
}
}
else if (type == "duck")
{
for (auto sprite : EntityList<Duck>())
@@ -227,7 +236,7 @@ namespace OpenRCT2::Scripting
{
for (auto sprite : EntityTileList<Balloon>(pos))
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScEntity>(sprite->Id)));
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScBalloon>(sprite->Id)));
}
}
else if (type == "car")
@@ -258,6 +267,13 @@ namespace OpenRCT2::Scripting
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScGuest>(sprite->Id)));
}
}
else if (type == "money_effect")
{
for (auto sprite : EntityTileList<MoneyEffect>(pos))
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScMoneyEffect>(sprite->Id)));
}
}
else if (type == "staff")
{
for (auto sprite : EntityTileList<Staff>(pos))
@@ -365,7 +381,7 @@ namespace OpenRCT2::Scripting
}
else if (type == "money_effect")
{
res = createEntityType<MoneyEffect, ScEntity>(_context, initializer);
res = createEntityType<MoneyEffect, ScMoneyEffect>(_context, initializer);
}
else if (type == "crashed_vehicle_particle")
{
@@ -385,7 +401,7 @@ namespace OpenRCT2::Scripting
}
else if (type == "balloon")
{
res = createEntityType<Balloon, ScEntity>(_context, initializer);
res = createEntityType<Balloon, ScBalloon>(_context, initializer);
}
else if (type == "duck")
{
@@ -465,6 +481,10 @@ namespace OpenRCT2::Scripting
return GetObjectAsDukValue(_context, std::make_shared<ScGuest>(spriteId));
case EntityType::Litter:
return GetObjectAsDukValue(_context, std::make_shared<ScLitter>(spriteId));
case EntityType::Balloon:
return GetObjectAsDukValue(_context, std::make_shared<ScBalloon>(spriteId));
case EntityType::MoneyEffect:
return GetObjectAsDukValue(_context, std::make_shared<ScMoneyEffect>(spriteId));
case EntityType::CrashedVehicleParticle:
return GetObjectAsDukValue(_context, std::make_shared<ScCrashedVehicleParticle>(spriteId));
default: