Merge pull request #21514 from ZehMatt/ride-initialization

Default Ride initialization
This commit is contained in:
Michael Steenbeek 2024-03-30 23:34:20 +01:00 committed by GitHub
commit ab73fe7317
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 125 additions and 155 deletions

View File

@ -141,7 +141,6 @@ GameActions::Result RideCreateAction::Execute() const
return GameActions::Result(GameActions::Status::Unknown, STR_CANT_CREATE_NEW_RIDE_ATTRACTION, STR_UNKNOWN_OBJECT_TYPE);
}
ride->id = rideIndex;
ride->type = _rideType;
ride->subtype = rideEntryIndex;
ride->SetColourPreset(_colour1);
@ -153,7 +152,7 @@ GameActions::Result RideCreateAction::Execute() const
station.Start.SetNull();
station.Entrance.SetNull();
station.Exit.SetNull();
station.TrainAtStation = RideStation::NO_TRAIN;
station.TrainAtStation = RideStation::kNoTrain;
station.QueueTime = 0;
station.SegmentLength = 0;
station.QueueLength = 0;
@ -161,12 +160,7 @@ GameActions::Result RideCreateAction::Execute() const
station.Height = 0;
}
std::fill(std::begin(ride->vehicles), std::end(ride->vehicles), EntityId::GetNull());
ride->status = RideStatus::Closed;
ride->lifecycle_flags = 0;
ride->vehicle_change_timeout = 0;
ride->num_stations = 0;
ride->NumTrains = 1;
if (GetGameState().Cheats.DisableTrainLengthLimit)
{
@ -210,16 +204,7 @@ GameActions::Result RideCreateAction::Execute() const
ride->lift_hill_speed = rtd.LiftData.minimum_speed;
ride->measurement = {};
ride->excitement = kRideRatingUndefined;
ride->cur_num_customers = 0;
ride->num_customers_timeout = 0;
ride->chairlift_bullwheel_rotation = 0;
for (auto& price : ride->price)
{
price = 0;
}
auto& gameState = GetGameState();
if (!(gameState.ParkFlags & PARK_FLAGS_NO_MONEY))
@ -288,20 +273,9 @@ GameActions::Result RideCreateAction::Execute() const
}
}
std::fill(std::begin(ride->num_customers), std::end(ride->num_customers), 0);
ride->value = RIDE_VALUE_UNDEFINED;
ride->satisfaction = 255;
ride->satisfaction_time_out = 0;
ride->satisfaction_next = 0;
ride->popularity = 255;
ride->popularity_time_out = 0;
ride->popularity_next = 0;
ride->window_invalidate_flags = 0;
ride->total_customers = 0;
ride->total_profit = 0;
ride->num_riders = 0;
ride->slide_in_use = 0;
ride->maze_tiles = 0;
ride->build_date = GetDate().GetMonthsElapsed();
ride->music_tune_id = TUNE_ID_NULL;
@ -310,16 +284,9 @@ GameActions::Result RideCreateAction::Execute() const
ride->reliability = kRideInitialReliability;
ride->unreliability_factor = 1;
ride->inspection_interval = RIDE_INSPECTION_EVERY_30_MINUTES;
ride->last_inspection = 0;
ride->downtime = 0;
std::fill_n(ride->downtime_history, sizeof(ride->downtime_history), 0x00);
ride->no_primary_items_sold = 0;
ride->no_secondary_items_sold = 0;
ride->last_crash_type = RIDE_CRASH_TYPE_NONE;
ride->income_per_hour = kMoney64Undefined;
ride->profit = kMoney64Undefined;
ride->connected_message_throttle = 0;
ride->drops = 0;
ride->entrance_style = OBJECT_ENTRY_INDEX_NULL;
if (rtd.HasFlag(RIDE_TYPE_FLAG_HAS_ENTRANCE_EXIT))
@ -327,9 +294,6 @@ GameActions::Result RideCreateAction::Execute() const
ride->entrance_style = _entranceObjectIndex;
}
ride->num_block_brakes = 0;
ride->guests_favourite = 0;
ride->num_circuits = 1;
ride->mode = ride->GetDefaultMode();
ride->MinCarsPerTrain = rideEntry->min_cars_in_train;

View File

@ -2533,7 +2533,7 @@ void Guest::GoToRideEntrance(const Ride& ride)
bool Guest::FindVehicleToEnter(const Ride& ride, std::vector<uint8_t>& car_array)
{
uint8_t chosen_train = RideStation::NO_TRAIN;
uint8_t chosen_train = RideStation::kNoTrain;
if (ride.mode == RideMode::Dodgems || ride.mode == RideMode::Race)
{

View File

@ -916,7 +916,7 @@ namespace RCT1
{
auto& dstStation = dst->GetStation(StationIndex::FromUnderlying(i));
dstStation.Start.SetNull();
dstStation.TrainAtStation = RideStation::NO_TRAIN;
dstStation.TrainAtStation = RideStation::kNoTrain;
dstStation.Entrance.SetNull();
dstStation.Exit.SetNull();
dstStation.LastPeepInQueue = EntityId::GetNull();

View File

@ -1397,7 +1397,7 @@ namespace RCT2
auto& destStation = dst->GetStation(stationIndex);
destStation.Start.SetNull();
destStation.TrainAtStation = RideStation::NO_TRAIN;
destStation.TrainAtStation = RideStation::kNoTrain;
destStation.Entrance.SetNull();
destStation.Exit.SetNull();
destStation.LastPeepInQueue = EntityId::GetNull();

View File

@ -176,6 +176,12 @@ Ride* RideAllocateAtIndex(RideId index)
auto result = &GetGameState().Rides[idx];
assert(result->id == RideId::GetNull());
// Initialize the ride to all the defaults.
*result = Ride{};
// Because it is default initialized to zero rather than the magic constant for Null, fill the array.
std::fill(std::begin(result->vehicles), std::end(result->vehicles), EntityId::GetNull());
result->id = index;
return result;
}

View File

@ -50,20 +50,20 @@ constexpr uint16_t const MAZE_CLEARANCE_HEIGHT = 4 * COORDS_Z_STEP;
struct RideStation
{
static constexpr uint8_t kNoTrain = std::numeric_limits<uint8_t>::max();
CoordsXY Start;
uint8_t Height;
uint8_t Length;
uint8_t Depart;
uint8_t TrainAtStation;
uint8_t Height{};
uint8_t Length{};
uint8_t Depart{};
uint8_t TrainAtStation{ kNoTrain };
TileCoordsXYZD Entrance;
TileCoordsXYZD Exit;
int32_t SegmentLength; // Length of track between this station and the next.
uint16_t SegmentTime; // Time for train to reach the next station from this station.
uint8_t QueueTime;
uint16_t QueueLength;
EntityId LastPeepInQueue;
static constexpr uint8_t NO_TRAIN = std::numeric_limits<uint8_t>::max();
int32_t SegmentLength{}; // Length of track between this station and the next.
uint16_t SegmentTime{}; // Time for train to reach the next station from this station.
uint8_t QueueTime{};
uint16_t QueueLength{};
EntityId LastPeepInQueue{ EntityId::GetNull() };
int32_t GetBaseZ() const;
void SetBaseZ(int32_t newZ);
@ -113,20 +113,20 @@ enum class RideStatus : uint8_t;
*/
struct Ride
{
RideId id = RideId::GetNull();
ride_type_t type = RIDE_TYPE_NULL;
RideId id{ RideId::GetNull() };
ride_type_t type{ RIDE_TYPE_NULL };
// pointer to static info. for example, wild mouse type is 0x36, subtype is
// 0x4c.
ObjectEntryIndex subtype;
RideMode mode;
uint8_t colour_scheme_type;
VehicleColour vehicle_colours[OpenRCT2::Limits::MaxVehicleColours];
ObjectEntryIndex subtype{ OBJECT_ENTRY_INDEX_NULL };
RideMode mode{};
uint8_t colour_scheme_type{};
VehicleColour vehicle_colours[OpenRCT2::Limits::MaxVehicleColours]{};
// 0 = closed, 1 = open, 2 = test
RideStatus status;
RideStatus status{};
std::string custom_name;
uint16_t default_name_number;
uint16_t default_name_number{};
CoordsXY overall_view;
EntityId vehicles[OpenRCT2::Limits::MaxTrainsPerRide + 1]; // Points to the first car in the train
EntityId vehicles[OpenRCT2::Limits::MaxTrainsPerRide + 1]{}; // Points to the first car in the train
uint8_t depart_flags;
uint8_t num_stations;
uint8_t NumTrains;
@ -145,54 +145,54 @@ struct Ride
uint8_t NumLaps;
uint8_t launch_speed;
uint8_t speed;
uint8_t rotations;
uint8_t rotations{};
};
uint8_t boat_hire_return_direction;
uint8_t boat_hire_return_direction{};
TileCoordsXY boat_hire_return_position;
// bits 0 through 4 are the number of helix sections
// bit 5: spinning tunnel, water splash, or rapids
// bit 6: log reverser, waterfall
// bit 7: whirlpool
uint8_t special_track_elements;
uint8_t special_track_elements{};
// Divide this value by 29127 to get the human-readable max speed
// (in RCT2, display_speed = (max_speed * 9) >> 18)
int32_t max_speed;
int32_t average_speed;
uint8_t current_test_segment;
uint8_t average_speed_test_timeout;
fixed16_2dp max_positive_vertical_g;
fixed16_2dp max_negative_vertical_g;
fixed16_2dp max_lateral_g;
fixed16_2dp previous_vertical_g;
fixed16_2dp previous_lateral_g;
uint32_t testing_flags;
int32_t max_speed{};
int32_t average_speed{};
uint8_t current_test_segment{};
uint8_t average_speed_test_timeout{};
fixed16_2dp max_positive_vertical_g{};
fixed16_2dp max_negative_vertical_g{};
fixed16_2dp max_lateral_g{};
fixed16_2dp previous_vertical_g{};
fixed16_2dp previous_lateral_g{};
uint32_t testing_flags{};
// x y z map location of the current track piece during a test
// this is to prevent counting special tracks multiple times
TileCoordsXYZ CurTestTrackLocation;
// Next 3 variables are related (XXXX XYYY ZZZa aaaa)
uint16_t turn_count_default; // X = current turn count
uint16_t turn_count_banked;
uint16_t turn_count_sloped; // X = number turns > 3 elements
uint16_t turn_count_default{}; // X = current turn count
uint16_t turn_count_banked{};
uint16_t turn_count_sloped{}; // X = number turns > 3 elements
// Y is number of powered lifts, X is drops
uint8_t drops; // (YYXX XXXX)
uint8_t start_drop_height;
uint8_t highest_drop_height;
int32_t sheltered_length;
uint8_t drops{}; // (YYXX XXXX)
uint8_t start_drop_height{};
uint8_t highest_drop_height{};
int32_t sheltered_length{};
// Unused always 0? Should affect nausea
uint16_t var_11C;
uint8_t num_sheltered_sections; // (?abY YYYY)
uint16_t var_11C{};
uint8_t num_sheltered_sections{}; // (?abY YYYY)
// Customer counter in the current 960 game tick (about 30 seconds) interval
uint16_t cur_num_customers;
uint16_t cur_num_customers{};
// Counts ticks to update customer intervals, resets each 960 game ticks.
uint16_t num_customers_timeout;
uint16_t num_customers_timeout{};
// Customer count in the last 10 * 960 game ticks (sliding window)
uint16_t num_customers[OpenRCT2::Limits::CustomerHistorySize];
money64 price[RCT2::ObjectLimits::MaxShopItemsPerRideEntry];
uint16_t num_customers[OpenRCT2::Limits::CustomerHistorySize]{};
money64 price[RCT2::ObjectLimits::MaxShopItemsPerRideEntry]{};
TileCoordsXYZ ChairliftBullwheelLocation[2];
union
{
RatingTuple ratings;
RatingTuple ratings{};
struct
{
ride_rating excitement;
@ -200,39 +200,39 @@ struct Ride
ride_rating nausea;
};
};
money64 value;
uint16_t chairlift_bullwheel_rotation;
uint8_t satisfaction;
uint8_t satisfaction_time_out;
uint8_t satisfaction_next;
money64 value{};
uint16_t chairlift_bullwheel_rotation{};
uint8_t satisfaction{};
uint8_t satisfaction_time_out{};
uint8_t satisfaction_next{};
// Various flags stating whether a window needs to be refreshed
uint8_t window_invalidate_flags;
uint32_t total_customers;
money64 total_profit;
uint8_t popularity;
uint8_t popularity_time_out; // Updated every purchase and ?possibly by time?
uint8_t popularity_next; // When timeout reached this will be the next popularity
uint16_t num_riders;
uint8_t music_tune_id;
uint8_t slide_in_use;
uint8_t window_invalidate_flags{};
uint32_t total_customers{};
money64 total_profit{};
uint8_t popularity{};
uint8_t popularity_time_out{}; // Updated every purchase and ?possibly by time?
uint8_t popularity_next{}; // When timeout reached this will be the next popularity
uint16_t num_riders{};
uint8_t music_tune_id{};
uint8_t slide_in_use{};
union
{
EntityId slide_peep;
uint16_t maze_tiles;
uint16_t maze_tiles{};
};
uint8_t slide_peep_t_shirt_colour;
uint8_t spiral_slide_progress;
int32_t build_date;
money64 upkeep_cost;
EntityId race_winner;
uint32_t music_position;
uint8_t breakdown_reason_pending;
uint8_t mechanic_status;
EntityId mechanic;
StationIndex inspection_station;
uint8_t broken_vehicle;
uint8_t broken_car;
uint8_t breakdown_reason;
uint8_t slide_peep_t_shirt_colour{};
uint8_t spiral_slide_progress{};
int32_t build_date{};
money64 upkeep_cost{};
EntityId race_winner{};
uint32_t music_position{};
uint8_t breakdown_reason_pending{};
uint8_t mechanic_status{};
EntityId mechanic{ EntityId::GetNull() };
StationIndex inspection_station{ StationIndex::GetNull() };
uint8_t broken_vehicle{};
uint8_t broken_car{};
uint8_t breakdown_reason{};
union
{
struct
@ -240,52 +240,52 @@ struct Ride
uint8_t reliability_subvalue; // 0 - 255, acts like the decimals for reliability_percentage
uint8_t reliability_percentage; // Starts at 100 and decreases from there.
};
uint16_t reliability;
uint16_t reliability{};
};
// Small constant used to increase the unreliability as the game continues,
// making breakdowns more and more likely.
uint8_t unreliability_factor;
uint8_t unreliability_factor{};
// Range from [0, 100]
uint8_t downtime;
uint8_t inspection_interval;
uint8_t last_inspection;
uint8_t downtime_history[OpenRCT2::Limits::DowntimeHistorySize];
uint32_t no_primary_items_sold;
uint32_t no_secondary_items_sold;
uint8_t breakdown_sound_modifier;
uint8_t downtime{};
uint8_t inspection_interval{};
uint8_t last_inspection{};
uint8_t downtime_history[OpenRCT2::Limits::DowntimeHistorySize]{};
uint32_t no_primary_items_sold{};
uint32_t no_secondary_items_sold{};
uint8_t breakdown_sound_modifier{};
// Used to oscillate the sound when ride breaks down.
// 0 = no change, 255 = max change
uint8_t not_fixed_timeout;
uint8_t last_crash_type;
uint8_t connected_message_throttle;
money64 income_per_hour;
money64 profit;
TrackColour track_colour[OpenRCT2::Limits::NumColourSchemes];
ObjectEntryIndex music;
ObjectEntryIndex entrance_style;
uint16_t vehicle_change_timeout;
uint8_t num_block_brakes;
uint8_t lift_hill_speed;
uint32_t guests_favourite;
uint32_t lifecycle_flags;
uint16_t total_air_time;
StationIndex current_test_station;
uint8_t num_circuits;
CoordsXYZ CableLiftLoc;
EntityId cable_lift;
uint8_t not_fixed_timeout{};
uint8_t last_crash_type{};
uint8_t connected_message_throttle{};
money64 income_per_hour{};
money64 profit{};
TrackColour track_colour[OpenRCT2::Limits::NumColourSchemes]{};
ObjectEntryIndex music{ OBJECT_ENTRY_INDEX_NULL };
ObjectEntryIndex entrance_style{ OBJECT_ENTRY_INDEX_NULL };
uint16_t vehicle_change_timeout{};
uint8_t num_block_brakes{};
uint8_t lift_hill_speed{};
uint32_t guests_favourite{};
uint32_t lifecycle_flags{};
uint16_t total_air_time{};
StationIndex current_test_station{ StationIndex::GetNull() };
uint8_t num_circuits{};
CoordsXYZ CableLiftLoc{};
EntityId cable_lift{ EntityId::GetNull() };
// These two fields are used to warn users about issues.
// Such issue can be hacked rides with incompatible options set.
// They don't require export/import.
uint8_t current_issues;
uint32_t last_issue_time;
uint8_t current_issues{};
uint32_t last_issue_time{};
// TO-DO: those friend functions are temporary, find a way to not access the private fields
friend void UpdateSpiralSlide(Ride& ride);
friend void UpdateChairlift(Ride& ride);
private:
std::array<RideStation, OpenRCT2::Limits::MaxStationsPerRide> stations;
std::array<RideStation, OpenRCT2::Limits::MaxStationsPerRide> stations{};
public:
RideStation& GetStation(StationIndex stationIndex = StationIndex::FromUnderlying(0));
@ -299,9 +299,9 @@ public:
StationIndex::UnderlyingType GetStationNumber(StationIndex in) const;
public:
uint16_t inversions;
uint16_t holes;
uint8_t sheltered_eighths;
uint16_t inversions{};
uint16_t holes{};
uint8_t sheltered_eighths{};
std::unique_ptr<RideMeasurement> measurement;

View File

@ -198,7 +198,7 @@ void Ride::RemoveVehicles()
}
for (size_t i = 0; i < OpenRCT2::Limits::MaxStationsPerRide; i++)
stations[i].TrainAtStation = RideStation::NO_TRAIN;
stations[i].TrainAtStation = RideStation::kNoTrain;
// Also clean up orphaned vehicles for good measure.
for (auto* vehicle : TrainManager::View())

View File

@ -1460,7 +1460,7 @@ void Vehicle::TrainReadyToDepart(uint8_t num_peeps_on_train, uint8_t num_used_se
// Boat Hire with passengers on it.
if (curRide->status != RideStatus::Closed || (curRide->num_riders != 0 && curRide->type != RIDE_TYPE_BOAT_HIRE))
{
curRide->GetStation(current_station).TrainAtStation = RideStation::NO_TRAIN;
curRide->GetStation(current_station).TrainAtStation = RideStation::kNoTrain;
sub_state = 2;
return;
}
@ -1471,7 +1471,7 @@ void Vehicle::TrainReadyToDepart(uint8_t num_peeps_on_train, uint8_t num_used_se
uint8_t seat = ((-Pitch) / 8) & 0xF;
if (!peep[seat].IsNull())
{
curRide->GetStation(current_station).TrainAtStation = RideStation::NO_TRAIN;
curRide->GetStation(current_station).TrainAtStation = RideStation::kNoTrain;
SetState(Vehicle::Status::UnloadingPassengers);
return;
}
@ -1479,7 +1479,7 @@ void Vehicle::TrainReadyToDepart(uint8_t num_peeps_on_train, uint8_t num_used_se
if (num_peeps == 0)
return;
curRide->GetStation(current_station).TrainAtStation = RideStation::NO_TRAIN;
curRide->GetStation(current_station).TrainAtStation = RideStation::kNoTrain;
sub_state = 2;
return;
}
@ -1487,7 +1487,7 @@ void Vehicle::TrainReadyToDepart(uint8_t num_peeps_on_train, uint8_t num_used_se
if (num_peeps_on_train == 0)
return;
curRide->GetStation(current_station).TrainAtStation = RideStation::NO_TRAIN;
curRide->GetStation(current_station).TrainAtStation = RideStation::kNoTrain;
SetState(Vehicle::Status::WaitingForPassengers);
}
@ -1532,7 +1532,7 @@ void Vehicle::UpdateWaitingForPassengers()
auto& station = curRide->GetStation(current_station);
if (station.Entrance.IsNull())
{
station.TrainAtStation = RideStation::NO_TRAIN;
station.TrainAtStation = RideStation::kNoTrain;
sub_state = 2;
return;
}
@ -1543,7 +1543,7 @@ void Vehicle::UpdateWaitingForPassengers()
return;
}
if (station.TrainAtStation != RideStation::NO_TRAIN)
if (station.TrainAtStation != RideStation::kNoTrain)
return;
station.TrainAtStation = trainIndex.value();