Fix #5677: Balloons pass through the ground and objects (#20483)

This commit is contained in:
mrmbernardi 2023-12-26 12:28:19 +01:00 committed by GitHub
parent 191b0c4d6d
commit 98a52efb7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 98 additions and 18 deletions

View File

@ -11,6 +11,7 @@
- Change: [#20790] Default ride price set to free if park charges for entry.
- Change: [#20880] Restore removed default coaster colours.
- Change: [#21102] The money effect will now update even when the game is paused.
- Fix: [#5677] Balloons pass through the ground and objects.
- Fix: [#12299] Placing ride entrances/exits ignores the Disable Clearance Checks cheat.
- Fix: [#13473] Guests complain that the default Circus price is too high.
- Fix: [#15293] TTF fonts dont format correctly with OpenGL.

View File

@ -47,12 +47,19 @@ void Balloon::Update()
{
frame = 0;
}
if (Collides())
{
Pop(false);
return;
}
MoveTo({ x, y, z + 1 });
int32_t maxZ = 1967 - ((x ^ y) & 31);
if (z >= maxZ)
{
Pop();
Pop(true);
}
}
}
@ -67,7 +74,7 @@ void Balloon::Press()
uint32_t random = ScenarioRand();
if ((Id.ToUnderlying() & 7) || (random & 0xFFFF) < 0x2000)
{
Pop();
Pop(true);
}
else
{
@ -77,11 +84,14 @@ void Balloon::Press()
}
}
void Balloon::Pop()
void Balloon::Pop(bool playSound)
{
popped = 1;
frame = 0;
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BalloonPop, { x, y, z });
if (playSound)
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BalloonPop, { x, y, z });
}
}
void Balloon::Create(const CoordsXYZ& balloonPos, int32_t colour, bool isPopped)
@ -122,3 +132,49 @@ void Balloon::Paint(PaintSession& session, int32_t imageDirection) const
auto image = ImageId(imageId, colour);
PaintAddImageAsParent(session, image, { 0, 0, z }, { 1, 1, 0 });
}
bool Balloon::Collides() const
{
const TileElement* tileElement = MapGetFirstElementAt(CoordsXY({ x, y }));
if (tileElement == nullptr)
return false;
do
{
// the balloon has height so we add some padding to prevent it clipping through things.
int32_t balloon_top = z + COORDS_Z_STEP * 2;
if (balloon_top == tileElement->GetBaseZ())
{
return true;
}
// check for situations where guests can drop a balloon inside a covered building
bool check_ceiling = tileElement->GetType() == TileElementType::Entrance;
if (tileElement->GetType() == TileElementType::Track)
{
const TrackElement* trackElement = tileElement->AsTrack();
if (trackElement->GetRideType() == RIDE_TYPE_DODGEMS)
{
check_ceiling = true;
}
else
{
// all station platforms besides the plain and invisible ones are covered
auto style = GetRide(trackElement->GetRideIndex())->GetEntranceStyle();
if (style != RCT12_STATION_STYLE_PLAIN && style != RCT12_STATION_STYLE_INVISIBLE)
{
check_ceiling = true;
}
}
}
if (check_ceiling)
{
if (balloon_top > tileElement->GetBaseZ() && z < tileElement->GetClearanceZ())
{
return true;
}
}
} while (!(tileElement++)->IsLastForTile());
return false;
}

View File

@ -24,8 +24,9 @@ struct Balloon : EntityBase
uint8_t colour;
static void Create(const CoordsXYZ& balloonPos, int32_t colour, bool isPopped);
void Update();
void Pop();
void Pop(bool playSound);
void Press();
void Serialise(DataSerialiser& stream);
void Paint(PaintSession& session, int32_t imageDirection) const;
bool Collides() const;
};

View File

@ -34,6 +34,7 @@
#include "../drawing/Drawing.h"
#include "../drawing/Font.h"
#include "../drawing/Image.h"
#include "../entity/Balloon.h"
#include "../entity/EntityList.h"
#include "../entity/EntityRegistry.h"
#include "../entity/Staff.h"
@ -1914,6 +1915,23 @@ static int32_t ConsoleCommandProfilerStop(
return 0;
}
static int32_t ConsoleSpawnBalloon(InteractiveConsole& console, const arguments_t& argv)
{
if (argv.size() < 3)
{
console.WriteLineError("Need arguments: <x> <y> <z> <colour>");
return 1;
}
int32_t x = COORDS_XY_STEP * atof(argv[0].c_str());
int32_t y = COORDS_XY_STEP * atof(argv[1].c_str());
int32_t z = COORDS_Z_STEP * atof(argv[2].c_str());
int32_t col = 28;
if (argv.size() > 3)
col = atoi(argv[3].c_str());
Balloon::Create({ x, y, z }, col, false);
return 0;
}
using console_command_func = int32_t (*)(InteractiveConsole& console, const arguments_t& argv);
struct ConsoleCommand
{
@ -2006,6 +2024,7 @@ static constexpr ConsoleCommand console_command_table[] = {
{ "say", ConsoleCommandSay, "Say to other players.", "say <message>" },
{ "set", ConsoleCommandSet, "Sets the variable to the specified value.", "set <variable> <value>" },
{ "show_limits", ConsoleCommandShowLimits, "Shows the map data counts and limits.", "show_limits" },
{ "spawn_balloon", ConsoleSpawnBalloon, "Spawns a balloon.", "spawn_balloon <x> <y> <z> <colour>" },
{ "staff", ConsoleCommandStaff, "Staff management.", "staff <subcommand>" },
{ "terminate", ConsoleCommandTerminate, "Calls std::terminate(), for testing purposes only.", "terminate" },
{ "variables", ConsoleCommandVariables, "Lists all the variables that can be used with get and sometimes set.",

View File

@ -43,7 +43,7 @@
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "12"
#define NETWORK_STREAM_VERSION "13"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION

View File

@ -5983,3 +5983,15 @@ ResultWithMessage Ride::ChangeStatusCreateVehicles(bool isApplying, const Coords
return { true };
}
uint8_t Ride::GetEntranceStyle() const
{
if (const auto* stationObject = GetStationObject(); stationObject != nullptr)
{
return GetStationStyleFromIdentifier(stationObject->GetIdentifier());
}
else
{
return RCT12_STATION_STYLE_PLAIN;
}
}

View File

@ -411,6 +411,8 @@ public:
bool HasStation() const;
bool FindTrackGap(const CoordsXYE& input, CoordsXYE* output) const;
uint8_t GetEntranceStyle() const;
};
void UpdateSpiralSlide(Ride& ride);
void UpdateChairlift(Ride& ride);

View File

@ -83,17 +83,6 @@ static bool _trackDesignPlaceStateEntranceExitPlaced{};
static void TrackDesignPreviewClearMap();
static uint8_t TrackDesignGetEntranceStyle(const Ride& ride)
{
const auto* stationObject = ride.GetStationObject();
if (stationObject == nullptr)
return RCT12_STATION_STYLE_PLAIN;
const auto objectName = stationObject->GetIdentifier();
return GetStationStyleFromIdentifier(objectName);
}
ResultWithMessage TrackDesign::CreateTrackDesign(TrackDesignState& tds, const Ride& ride)
{
type = ride.type;
@ -134,7 +123,7 @@ ResultWithMessage TrackDesign::CreateTrackDesign(TrackDesignState& tds, const Ri
lift_hill_speed = ride.lift_hill_speed;
num_circuits = ride.num_circuits;
entrance_style = TrackDesignGetEntranceStyle(ride);
entrance_style = ride.GetEntranceStyle();
max_speed = static_cast<int8_t>(ride.max_speed / 65536);
average_speed = static_cast<int8_t>(ride.average_speed / 65536);
ride_length = ride.GetTotalLength() / 65536;