1
0
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:
IntelOrca
2015-07-16 01:38:18 +01:00
parent d5f46d774b
commit 7cddad5026
5 changed files with 399 additions and 4 deletions

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;

View File

@@ -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

View File

@@ -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);