mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-16 03:23:15 +01:00
implement game_command_create_ride
This commit is contained in:
@@ -911,7 +911,7 @@ static uint32 game_do_command_table[58] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x006B3F0F,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -974,7 +974,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
|
||||
game_command_place_track,
|
||||
game_command_remove_track,
|
||||
game_load_or_quit,
|
||||
game_command_emptysub,
|
||||
game_command_create_ride,
|
||||
game_command_demolish_ride,
|
||||
game_command_set_ride_status,
|
||||
game_command_set_ride_vehicles,
|
||||
|
||||
@@ -224,6 +224,8 @@ enum {
|
||||
STR_LOWER_COST_AMOUNT = 985,
|
||||
STR_COST_AMOUNT = 986,
|
||||
|
||||
STR_TOO_MANY_RIDES = 987,
|
||||
|
||||
STR_CONSTRUCTION = 990,
|
||||
|
||||
STR_STATION_PLATFORM = 991,
|
||||
|
||||
@@ -90,12 +90,15 @@ typedef utf16* utf16string;
|
||||
#define OPENRCT2_COMMIT_SHA1_SHORT ""
|
||||
|
||||
// Represent fixed point numbers. dp = decimal point
|
||||
typedef uint8 fixed8_1dp;
|
||||
typedef uint8 fixed8_2dp;
|
||||
typedef sint16 fixed16_1dp;
|
||||
typedef sint16 fixed16_2dp;
|
||||
typedef sint32 fixed32_1dp;
|
||||
typedef sint32 fixed32_2dp;
|
||||
|
||||
// Money is stored as a multiple of 0.10.
|
||||
typedef fixed8_1dp money8;
|
||||
typedef fixed16_1dp money16;
|
||||
typedef fixed32_1dp money32;
|
||||
|
||||
|
||||
378
src/ride/ride.c
378
src/ride/ride.c
@@ -143,6 +143,7 @@ static void ride_shop_connected(rct_ride* ride, int ride_idx);
|
||||
static void ride_spiral_slide_update(rct_ride *ride);
|
||||
static void ride_update(int rideIndex);
|
||||
static void ride_update_vehicle_colours(int rideIndex);
|
||||
static void sub_6DE52C(rct_ride *ride);
|
||||
|
||||
rct_ride_type *ride_get_entry(rct_ride *ride)
|
||||
{
|
||||
@@ -4707,6 +4708,383 @@ static void ride_stop_peeps_queuing(int rideIndex)
|
||||
}
|
||||
}
|
||||
|
||||
static int ride_get_empty_slot()
|
||||
{
|
||||
rct_ride *ride;
|
||||
for (int i = 0; i < MAX_RIDES; i++) {
|
||||
ride = GET_RIDE(i);
|
||||
if (ride->type == RIDE_TYPE_NULL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ride_get_default_mode(rct_ride *ride)
|
||||
{
|
||||
const rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride->subtype);
|
||||
const uint8 *availableModes = RideAvailableModes;
|
||||
|
||||
for (int i = 0; i < ride->type; i++) {
|
||||
while (*(availableModes++) != 255) {}
|
||||
}
|
||||
if (rideEntry->flags & RIDE_ENTRY_FLAG_17) {
|
||||
availableModes += 2;
|
||||
}
|
||||
return availableModes[0];
|
||||
}
|
||||
|
||||
static bool ride_with_colour_config_exists(int rideType, const track_colour *colours)
|
||||
{
|
||||
rct_ride *ride;
|
||||
int i;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->type != rideType) continue;
|
||||
if (ride->track_colour_main[0] != colours->main) continue;
|
||||
if (ride->track_colour_additional[0] != colours->additional) continue;
|
||||
if (ride->track_colour_supports[0] != colours->supports) continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ride_name_exists(char *name)
|
||||
{
|
||||
char buffer[256];
|
||||
rct_ride *ride;
|
||||
int i;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
format_string(buffer, ride->name, &ride->name_arguments);
|
||||
if (strcmp(buffer, name) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B4776
|
||||
*/
|
||||
static void ride_set_to_random_colour_preset(rct_ride *ride)
|
||||
{
|
||||
const track_colour_preset_list *colourPresets;
|
||||
const track_colour *colours;
|
||||
|
||||
colourPresets = RCT2_ADDRESS(0x0097D934, track_colour_preset_list*)[ride->type];
|
||||
|
||||
// 200 attempts to find a colour preset that hasn't already been used in the park for this ride type
|
||||
for (int i = 0; i < 200; i++) {
|
||||
int listIndex = scenario_rand() % colourPresets->count;
|
||||
colours = &colourPresets->list[listIndex];
|
||||
|
||||
if (!ride_with_colour_config_exists(ride->type, colours)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ride->track_colour_main[i] = colours->main;
|
||||
ride->track_colour_additional[i] = colours->additional;
|
||||
ride->track_colour_supports[i] = colours->supports;
|
||||
}
|
||||
ride->colour_scheme_type = 0;
|
||||
}
|
||||
|
||||
static money32 ride_get_common_price(rct_ride *forRide)
|
||||
{
|
||||
rct_ride *ride;
|
||||
int i;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->type == forRide->type && ride != forRide) {
|
||||
return ride->price;
|
||||
}
|
||||
}
|
||||
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
static money32 shop_item_get_common_price(rct_ride *forRide, int shopItem)
|
||||
{
|
||||
rct_ride_type *rideEntry;
|
||||
rct_ride *ride;
|
||||
int i;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride != forRide) {
|
||||
rideEntry = GET_RIDE_ENTRY(ride->subtype);
|
||||
if (rideEntry->shop_item == shopItem) {
|
||||
return ride->price;
|
||||
}
|
||||
if (rideEntry->shop_item_secondary == shopItem) {
|
||||
return ride->price_secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
static bool shop_item_has_common_price(int shopItem)
|
||||
{
|
||||
if (shopItem < 32) {
|
||||
return RCT2_GLOBAL(0x01358838, uint32) & (1 << shopItem);
|
||||
} else {
|
||||
return RCT2_GLOBAL(0x0135934C, uint32) & (1 << (shopItem - 32));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B3F0F
|
||||
*/
|
||||
money32 ride_create(int type, int subType, int flags, int *outRideIndex)
|
||||
{
|
||||
char rideNameBuffer[256];
|
||||
rct_ride *ride;
|
||||
rct_ride_type *rideEntry;
|
||||
int rideIndex, rideEntryIndex;
|
||||
|
||||
if (subType == 255) {
|
||||
uint8 *availableRideEntries = get_ride_entry_indices_for_ride_type(type);
|
||||
for (uint8 *rei = availableRideEntries; *rei != 255; rei++) {
|
||||
rideEntry = GET_RIDE_ENTRY(*rei);
|
||||
if (rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) {
|
||||
subType = *rei;
|
||||
goto foundRideEntry;
|
||||
}
|
||||
}
|
||||
subType = availableRideEntries[0];
|
||||
}
|
||||
|
||||
foundRideEntry:
|
||||
rideEntryIndex = subType;
|
||||
rideIndex = ride_get_empty_slot();
|
||||
if (rideIndex == -1) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_RIDES;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
*outRideIndex = rideIndex;
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY)) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||
RCT2_GLOBAL(0x009DEA5E, uint16) = 0x8000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ride = GET_RIDE(rideIndex);
|
||||
rideEntry = GET_RIDE_ENTRY(rideEntryIndex);
|
||||
ride->type = type;
|
||||
ride->subtype = rideEntryIndex;
|
||||
ride_set_to_random_colour_preset(ride);
|
||||
ride->overall_view = 0xFFFF;
|
||||
|
||||
// Ride name
|
||||
if (rideEntryIndex == 255) {
|
||||
useDefaultName:
|
||||
ride->name = STR_NONE;
|
||||
|
||||
struct {
|
||||
uint16 type_name;
|
||||
uint16 number;
|
||||
} name_args;
|
||||
name_args.type_name = 2 + ride->type;
|
||||
name_args.number = 0;
|
||||
do {
|
||||
name_args.number++;
|
||||
format_string(rideNameBuffer, 1, &name_args);
|
||||
} while (ride_name_exists(rideNameBuffer));
|
||||
ride->name = 1;
|
||||
ride->name_arguments_type_name = name_args.type_name;
|
||||
ride->name_arguments_number = name_args.number;
|
||||
} else {
|
||||
if (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME)) {
|
||||
goto useDefaultName;
|
||||
}
|
||||
ride->name = 1;
|
||||
ride->name_arguments_type_name = rideEntry->name;
|
||||
ride->name_arguments_number = 0;
|
||||
|
||||
rct_string_id rideNameStringId = 0;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ride->name_arguments_number++;
|
||||
format_string(rideNameBuffer, ride->name, &ride->name_arguments);
|
||||
|
||||
rideNameStringId = user_string_allocate(4, rideNameBuffer);
|
||||
if (rideNameStringId != 0) {
|
||||
ride->name = rideNameStringId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rideNameStringId == 0) {
|
||||
goto useDefaultName;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ride->station_starts[i] = 0xFFFF;
|
||||
ride->entrances[i] = 0xFFFF;
|
||||
ride->exits[i] = 0xFFFF;
|
||||
ride->var_066[i] = 255;
|
||||
ride->queue_time[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ride->vehicles[i] = 0xFFFF;
|
||||
}
|
||||
|
||||
ride->status = RIDE_STATUS_CLOSED;
|
||||
ride->lifecycle_flags = 0;
|
||||
ride->var_1CA = 0;
|
||||
ride->num_stations = 0;
|
||||
ride->num_vehicles = 1;
|
||||
ride->var_0CA = 32;
|
||||
ride->var_0CB = 32;
|
||||
ride->num_cars_per_train = 1;
|
||||
ride->var_0CB = 12;
|
||||
ride->min_waiting_time = 10;
|
||||
ride->max_waiting_time = 60;
|
||||
ride->depart_flags = RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH | 3;
|
||||
if (RCT2_ADDRESS(0x0097D4F2, uint16)[ride->type * 4] & 2) {
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_MUSIC;
|
||||
}
|
||||
ride->music = RCT2_ADDRESS(0x0097D4F4, uint8)[ride->type * 8];
|
||||
|
||||
ride->operation_option = (
|
||||
RCT2_GLOBAL(0x0097CF40 + 4 + (ride->type * 8), uint8) +
|
||||
RCT2_GLOBAL(0x0097CF40 + 4 + (ride->type * 8), uint8) +
|
||||
RCT2_GLOBAL(0x0097CF40 + 4 + (ride->type * 8), uint8) +
|
||||
RCT2_GLOBAL(0x0097CF40 + 5 + (ride->type * 8), uint8)
|
||||
) / 4;
|
||||
|
||||
ride->lift_hill_speed = RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4];
|
||||
|
||||
ride->measurement_index = 255;
|
||||
ride->excitement = (ride_rating)-1;
|
||||
ride->var_120 = 0;
|
||||
ride->var_122 = 0;
|
||||
ride->var_148 = 0;
|
||||
|
||||
ride->price = 0;
|
||||
ride->price_secondary = 0;
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) {
|
||||
ride->price = RCT2_GLOBAL(0x0097D4F0 + 0 + (ride->type * 8), uint8);
|
||||
ride->price_secondary = RCT2_GLOBAL(0x0097D4F0 + 1 + (ride->type * 8), uint8);
|
||||
|
||||
if (rideEntry->shop_item != 255) {
|
||||
ride->price = RCT2_ADDRESS(0x00982358, money8)[rideEntry->shop_item];
|
||||
}
|
||||
if (rideEntry->shop_item_secondary != 255) {
|
||||
ride->price = RCT2_ADDRESS(0x00982358, money8)[rideEntry->shop_item_secondary];
|
||||
}
|
||||
if (rideEntry->shop_item == 255 && (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY)) {
|
||||
ride->price = 0;
|
||||
}
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_BUILD_THE_BEST) {
|
||||
ride->price = 0;
|
||||
}
|
||||
|
||||
if (ride->type == RIDE_TYPE_TOILETS) {
|
||||
if (RCT2_GLOBAL(0x01358838, uint32) & (1 << 31)) {
|
||||
money32 price = ride_get_common_price(ride);
|
||||
if (price != MONEY32_UNDEFINED) {
|
||||
ride->price = (money16)price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rideEntry->shop_item != 255) {
|
||||
if (shop_item_has_common_price(rideEntry->shop_item)) {
|
||||
money32 price = shop_item_get_common_price(ride, rideEntry->shop_item);
|
||||
if (price != MONEY32_UNDEFINED) {
|
||||
ride->price = (money16)price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rideEntry->shop_item_secondary != 255) {
|
||||
if (shop_item_has_common_price(rideEntry->shop_item_secondary)) {
|
||||
money32 price = shop_item_get_common_price(ride, rideEntry->shop_item_secondary);
|
||||
if (price != MONEY32_UNDEFINED) {
|
||||
ride->price_secondary = (money16)price;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The next 10 variables are treated like an array of 10 items
|
||||
ride->var_124 = 0;
|
||||
ride->var_124 = 0;
|
||||
ride->var_126 = 0;
|
||||
ride->var_128 = 0;
|
||||
ride->var_12A = 0;
|
||||
ride->var_12C = 0;
|
||||
ride->var_12E = 0;
|
||||
ride->age = 0;
|
||||
ride->running_cost = 0;
|
||||
ride->var_134 = 0;
|
||||
ride->var_136 = 0;
|
||||
|
||||
ride->value = 0xFFFF;
|
||||
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->var_15D = 0;
|
||||
ride->maze_tiles = 0;
|
||||
ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
|
||||
ride->music_tune_id = 255;
|
||||
|
||||
ride->breakdown_reason = 255;
|
||||
ride->upkeep_cost = (money16)-1;
|
||||
ride->reliability = 0x64FF;
|
||||
ride->unreliability_factor = 1;
|
||||
ride->inspection_interval = RIDE_INSPECTION_EVERY_30_MINUTES;
|
||||
ride->last_inspection = 0;
|
||||
ride->downtime = 0;
|
||||
ride->var_19C = 0;
|
||||
ride->var_1A0 = 0;
|
||||
ride->no_primary_items_sold = 0;
|
||||
ride->no_secondary_items_sold = 0;
|
||||
ride->last_crash_type = RIDE_CRASH_TYPE_NONE;
|
||||
ride->income_per_hour = MONEY32_UNDEFINED;
|
||||
ride->profit = MONEY32_UNDEFINED;
|
||||
ride->connected_message_throttle = 0;
|
||||
ride->entrance_style = RIDE_ENTRANCE_STYLE_PLAIN;
|
||||
ride->num_block_brakes = 0;
|
||||
ride->guests_favourite = 0;
|
||||
|
||||
ride->num_circuits = 1;
|
||||
ride->mode = ride_get_default_mode(ride);
|
||||
ride->min_max_cars_per_train = (rideEntry->min_cars_in_train << 4) | rideEntry->max_cars_in_train;
|
||||
sub_6DE52C(ride);
|
||||
window_invalidate_by_class(WC_RIDE_LIST);
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||
RCT2_GLOBAL(0x009DEA5E, uint16) = 0x8000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B3F0F
|
||||
*/
|
||||
void game_command_create_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
|
||||
{
|
||||
*ebx = ride_create(*edx & 0xFF, (*edx >> 8) & 0xFF, *ebx & 0xFF, edi);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006B49D9
|
||||
|
||||
@@ -150,7 +150,13 @@ typedef struct {
|
||||
// 0 = closed, 1 = open, 2 = test
|
||||
uint8 status; // 0x049
|
||||
rct_string_id name; // 0x04A
|
||||
uint32 name_arguments; // 0x04C probably just for when a ride hasn't been named (e.g. Crooked House 1)
|
||||
union {
|
||||
uint32 name_arguments; // 0x04C
|
||||
struct {
|
||||
rct_string_id name_arguments_type_name; // 0x04C
|
||||
uint16 name_arguments_number; // 0x04E
|
||||
};
|
||||
};
|
||||
uint16 overall_view; // 0x050 00XX = X, XX00 = Y (* 32 + 16)
|
||||
uint16 station_starts[4]; // 0x052
|
||||
uint8 station_heights[4]; // 0x05A
|
||||
@@ -300,7 +306,7 @@ typedef struct {
|
||||
uint32 no_secondary_items_sold; // 0x1A8
|
||||
uint8 var_1AC;
|
||||
uint8 var_1AD;
|
||||
uint8 last_crash_type;
|
||||
uint8 last_crash_type; // 0x1AE
|
||||
uint8 connected_message_throttle; // 0x1AF
|
||||
money32 income_per_hour; // 0x1B0
|
||||
money32 profit; // 0x1B4
|
||||
@@ -707,6 +713,11 @@ typedef struct {
|
||||
uint8 additional_2;
|
||||
} vehicle_colour;
|
||||
|
||||
typedef struct {
|
||||
uint8 count;
|
||||
track_colour list[256];
|
||||
} track_colour_preset_list;
|
||||
|
||||
enum {
|
||||
RIDE_MEASUREMENT_FLAG_RUNNING = 1 << 0,
|
||||
RIDE_MEASUREMENT_FLAG_UNLOADING = 1 << 1,
|
||||
@@ -890,6 +901,7 @@ void ride_set_name(int rideIndex, const char *name);
|
||||
void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
int ride_get_refund_price(int ride_id);
|
||||
void game_command_create_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
|
||||
Reference in New Issue
Block a user