mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-24 15:24:30 +01:00
Merge pull request #2629 from janisozaur/harden-game-commands
Game commands hardening
This commit is contained in:
@@ -155,6 +155,13 @@ void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* es
|
||||
int rideOrItem = (*edx >> 8) & 0xFF;
|
||||
int numWeeks = (*ebx >> 8) & 0xFF;
|
||||
|
||||
if (type < 0 || type >= countof(AdvertisingCampaignPricePerWeek))
|
||||
{
|
||||
log_warning("Invalid game command, type = %d", type);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_MARKETING * 4;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_MARKETING_CAMPAIGN) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 3048;
|
||||
|
||||
@@ -293,7 +293,13 @@ void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *e
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_WAGES * 4;
|
||||
uint8 order_id = *ebx >> 8;
|
||||
uint16 sprite_id = *edx;
|
||||
if(*ebx & GAME_COMMAND_FLAG_APPLY){
|
||||
if (sprite_id >= MAX_SPRITES)
|
||||
{
|
||||
log_warning("Invalid game command, sprite_id = %u", sprite_id);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
|
||||
rct_peep *peep = &g_sprite_list[sprite_id].peep;
|
||||
if(order_id & 0x80){ // change costume
|
||||
uint8 sprite_type = order_id & ~0x80;
|
||||
@@ -366,7 +372,19 @@ void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int
|
||||
if(*ebx & GAME_COMMAND_FLAG_APPLY){
|
||||
window_close_by_class(WC_FIRE_PROMPT);
|
||||
uint16 sprite_id = *edx;
|
||||
if (sprite_id >= MAX_SPRITES)
|
||||
{
|
||||
log_warning("Invalid game command, sprite_id = %u", sprite_id);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
rct_peep *peep = &g_sprite_list[sprite_id].peep;
|
||||
if (peep->sprite_identifier != SPRITE_IDENTIFIER_PEEP || peep->type != PEEP_TYPE_STAFF)
|
||||
{
|
||||
log_warning("Invalid game command, peep->sprite_identifier = %u, peep->type = %u", peep->sprite_identifier, peep->type);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
remove_peep_from_ride(peep);
|
||||
peep_sprite_remove(peep);
|
||||
}
|
||||
|
||||
135
src/ride/ride.c
135
src/ride/ride.c
@@ -2914,7 +2914,15 @@ static bool ride_does_vehicle_colour_exist(uint8 ride_sub_type, vehicle_colour *
|
||||
|
||||
static int ride_get_unused_preset_vehicle_colour(uint8 ride_type, uint8 ride_sub_type)
|
||||
{
|
||||
if (ride_sub_type >= 128)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride_sub_type);
|
||||
if (rideEntry == (rct_ride_type *)0xFFFFFFFF)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
vehicle_colour_preset_list *presetList = rideEntry->vehicle_preset_list;
|
||||
if (presetList->count == 255)
|
||||
return 255;
|
||||
@@ -3588,6 +3596,12 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
|
||||
|
||||
uint8 ride_id = *edx & 0xFF;
|
||||
rct_ride* ride = GET_RIDE(ride_id);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalid game command.");
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 flags = *ebx & 0xFF;
|
||||
uint8 new_value = (*ebx >> 8) & 0xFF;
|
||||
@@ -4606,6 +4620,11 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying)
|
||||
rct_xy_element trackElement, problematicTrackElement;
|
||||
|
||||
ride = GET_RIDE(rideIndex);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalid ride type for ride %u", rideIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
window_close_by_number(WC_RIDE_CONSTRUCTION, rideIndex);
|
||||
|
||||
@@ -4864,6 +4883,12 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4;
|
||||
|
||||
ride = GET_RIDE(rideIndex);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalid game command for ride %u", rideIndex);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
RCT2_GLOBAL(0x00F43484, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32);
|
||||
|
||||
switch (targetStatus) {
|
||||
@@ -4944,6 +4969,7 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
|
||||
if (nameChunkOffset < 0)
|
||||
nameChunkOffset = 2;
|
||||
nameChunkOffset *= 12;
|
||||
nameChunkOffset = min(nameChunkOffset, countof(newName) - 12);
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
|
||||
@@ -5162,6 +5188,10 @@ static int ride_get_random_colour_preset_index(uint8 ride_type)
|
||||
{
|
||||
const track_colour_preset_list *colourPresets;
|
||||
const track_colour *colours;
|
||||
if (ride_type >= 128)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
colourPresets = RCT2_ADDRESS(0x0097D934, track_colour_preset_list*)[ride_type];
|
||||
|
||||
@@ -5265,6 +5295,11 @@ money32 ride_create(int type, int subType, int flags, int *outRideIndex, int *ou
|
||||
foundRideEntry:
|
||||
rideEntryIndex = subType;
|
||||
rideIndex = ride_get_empty_slot();
|
||||
if (subType >= 128)
|
||||
{
|
||||
log_warning("Invalid request for ride type %u", subType);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
if (rideIndex == -1) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_RIDES;
|
||||
return MONEY32_UNDEFINED;
|
||||
@@ -5287,6 +5322,11 @@ foundRideEntry:
|
||||
|
||||
ride = GET_RIDE(rideIndex);
|
||||
rideEntry = GET_RIDE_ENTRY(rideEntryIndex);
|
||||
if (rideEntry == (rct_ride_type *)0xFFFFFFFF)
|
||||
{
|
||||
log_warning("Invalid request for ride %u", rideIndex);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
ride->type = type;
|
||||
ride->subtype = rideEntryIndex;
|
||||
ride_set_colour_preset(ride, *outRideColour & 0xFF);
|
||||
@@ -5596,7 +5636,13 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = 0;
|
||||
rct_ride *ride = &g_ride_list[ride_id];
|
||||
rct_ride *ride = GET_RIDE(ride_id);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalid game command for ride %u", ride_id);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
int x = 0, y = 0, z = 0;
|
||||
if(ride->overall_view != (uint16)-1){
|
||||
x = ((ride->overall_view & 0xFF) * 32) + 16;
|
||||
@@ -5724,25 +5770,61 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in
|
||||
uint8 type = *ebx >> 8;
|
||||
uint8 value = *edx >> 8;
|
||||
int index = *edi;
|
||||
rct_ride *ride = &g_ride_list[ride_id];
|
||||
if (index < 0) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
rct_ride *ride = GET_RIDE(ride_id);
|
||||
if (ride->type == RIDE_TYPE_NULL) {
|
||||
log_warning("Invalid game command, ride_id = %u", ride_id);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
*ebx = 0;
|
||||
switch(type){
|
||||
case 0:
|
||||
if (index >= countof(ride->track_colour_main)) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
ride->track_colour_main[index] = value;
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case 1:
|
||||
if (index >= countof(ride->track_colour_additional)) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
ride->track_colour_additional[index] = value;
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case 2:
|
||||
if (index >= countof(ride->vehicle_colours)) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
*((uint8*)(&ride->vehicle_colours[index])) = value;
|
||||
ride_update_vehicle_colours(ride_id);
|
||||
break;
|
||||
case 3:
|
||||
if (index >= countof(ride->vehicle_colours)) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
*((uint8*)(&ride->vehicle_colours[index]) + 1) = value;
|
||||
ride_update_vehicle_colours(ride_id);
|
||||
break;
|
||||
case 4:
|
||||
if (index >= countof(ride->track_colour_supports)) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
ride->track_colour_supports[index] = value;
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
@@ -5761,13 +5843,17 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case 7:
|
||||
if (index >= countof(ride->vehicle_colours_extended)) {
|
||||
log_warning("Invalid game command, index %d out of bounds", index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
ride->vehicle_colours_extended[index] = value;
|
||||
ride_update_vehicle_colours(ride_id);
|
||||
break;
|
||||
}
|
||||
window_invalidate_by_number(WC_RIDE, ride_id);
|
||||
}
|
||||
*ebx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5780,21 +5866,28 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
|
||||
uint8 ride_number;
|
||||
money16 price;
|
||||
rct_ride *ride;
|
||||
rct_ride_type *ride_type;
|
||||
rct_ride_type *rideEntry;
|
||||
bool secondary_price;
|
||||
|
||||
flags = *ebx;
|
||||
ride_number = (*edx & 0xFF);
|
||||
ride = GET_RIDE(ride_number);
|
||||
ride_type = gRideTypeList[ride->subtype];
|
||||
rideEntry = GET_RIDE_ENTRY(ride->subtype);
|
||||
price = *edi;
|
||||
secondary_price = (*edx >> 8);
|
||||
|
||||
if (rideEntry == (rct_ride_type *)0xFFFFFFFF)
|
||||
{
|
||||
log_warning("Invalid game command for ride %u", ride_number);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
//eax
|
||||
//ebx flags
|
||||
//ecx ecx
|
||||
//edx ride_number
|
||||
//ebp ride_type
|
||||
//ebp rideEntry
|
||||
|
||||
*ebx = 0; // for cost check - changing ride price does not cost anything
|
||||
|
||||
@@ -5803,7 +5896,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
|
||||
if (!secondary_price) {
|
||||
shop_item = 0x1F;
|
||||
if (ride->type != RIDE_TYPE_TOILETS) {
|
||||
shop_item = ride_type->shop_item;
|
||||
shop_item = rideEntry->shop_item;
|
||||
if (shop_item == 0xFF) {
|
||||
ride->price = price;
|
||||
window_invalidate_by_class(WC_RIDE);
|
||||
@@ -5818,7 +5911,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
|
||||
}
|
||||
}
|
||||
else {
|
||||
shop_item = ride_type->shop_item_secondary;
|
||||
shop_item = rideEntry->shop_item_secondary;
|
||||
if (shop_item == 0xFF) {
|
||||
shop_item = RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8);
|
||||
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) == 0) {
|
||||
@@ -5835,12 +5928,12 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
|
||||
}
|
||||
}
|
||||
ride = GET_RIDE(0);
|
||||
ride_type = gRideTypeList[ride->subtype];
|
||||
rideEntry = GET_RIDE_ENTRY(ride->subtype);
|
||||
uint8 count = 0;
|
||||
while (count < 0xFF) {
|
||||
if (ride->type != 0xFF) {
|
||||
if (ride->type != RIDE_TYPE_TOILETS || shop_item != 0x1F) {
|
||||
if (ride_type->shop_item == shop_item) {
|
||||
if (rideEntry->shop_item == shop_item) {
|
||||
ride->price = price;
|
||||
window_invalidate_by_number(WC_RIDE, count);
|
||||
}
|
||||
@@ -5850,8 +5943,8 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
|
||||
window_invalidate_by_number(WC_RIDE, count);
|
||||
}
|
||||
// If the shop item is the same or an on-ride photo
|
||||
if (ride_type->shop_item_secondary == shop_item ||
|
||||
(ride_type->shop_item_secondary == 0xFF &&
|
||||
if (rideEntry->shop_item_secondary == shop_item ||
|
||||
(rideEntry->shop_item_secondary == 0xFF &&
|
||||
(shop_item == 0x3 || shop_item == 0x20 || shop_item == 0x21 || shop_item == 0x22))) {
|
||||
|
||||
ride->price_secondary = price;
|
||||
@@ -5860,7 +5953,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
|
||||
}
|
||||
count++;
|
||||
ride++;
|
||||
ride_type = gRideTypeList[ride->subtype];
|
||||
rideEntry = GET_RIDE_ENTRY(ride->subtype);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6749,6 +6842,12 @@ void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int
|
||||
value = (*edx >> 8) & 0xFF;
|
||||
|
||||
ride = GET_RIDE(rideIndex);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalid game command for ride %u", rideIndex);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4;
|
||||
|
||||
@@ -7090,6 +7189,11 @@ void game_command_place_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int
|
||||
|
||||
money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 station_num, uint8 flags){
|
||||
rct_ride* ride = GET_RIDE(rideIndex);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalide ride id %u for entrance/exit removal", rideIndex);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_GHOST)){
|
||||
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){
|
||||
@@ -7110,6 +7214,11 @@ money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8
|
||||
|
||||
uint8 found = 0;
|
||||
rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32);
|
||||
if (mapElement == NULL)
|
||||
{
|
||||
log_warning("Invalid coordinates for entrance/exit removal x = %d, y = %d", x, y);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
do{
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
|
||||
continue;
|
||||
|
||||
@@ -3309,6 +3309,14 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int
|
||||
rideIndex = _edi & 0xFF;
|
||||
}
|
||||
|
||||
rct_ride* ride = GET_RIDE(rideIndex);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
{
|
||||
log_warning("Invalid game command for track placement, ride id = %d", rideIndex);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
money32 cost = 0;
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY)){
|
||||
RCT2_GLOBAL(0x00F44150, uint8) = 0;
|
||||
@@ -3365,7 +3373,6 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int
|
||||
if (num_circuits == 0) num_circuits = 1;
|
||||
game_do_command(0, GAME_COMMAND_FLAG_APPLY | (num_circuits << 8), 0, rideIndex | (9 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0);
|
||||
|
||||
rct_ride* ride = GET_RIDE(rideIndex);
|
||||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NOT_CUSTOM_DESIGN;
|
||||
|
||||
@@ -4511,6 +4518,11 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY,
|
||||
|
||||
uint8 found = 0;
|
||||
rct_map_element* mapElement = map_get_first_element_at(originX / 32, originY / 32);
|
||||
if (mapElement == NULL)
|
||||
{
|
||||
log_warning("Invalid coordinates for track removal. x = %d, y = %d", originX, originY);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
do{
|
||||
if (mapElement->base_height * 8 != originZ)
|
||||
continue;
|
||||
@@ -4798,6 +4810,12 @@ void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int *
|
||||
}
|
||||
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
if (mapElement == NULL)
|
||||
{
|
||||
log_warning("Invalid game command for setting brakes speed. x = %d, y = %d", x, y);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
do {
|
||||
if (mapElement->base_height * 8 != z)
|
||||
continue;
|
||||
|
||||
@@ -645,15 +645,18 @@ int map_is_location_owned(int x, int y, int z)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
// This check is to avoid throwing lots of messages in logs.
|
||||
if (x < (256 * 32) && y < (256 * 32)) {
|
||||
mapElement = map_get_surface_element_at(x / 32, y / 32);
|
||||
if (mapElement->properties.surface.ownership & OWNERSHIP_OWNED)
|
||||
return 1;
|
||||
|
||||
if (mapElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) {
|
||||
z /= 8;
|
||||
if (z < mapElement->base_height || z - 2 > mapElement->base_height)
|
||||
if (mapElement != NULL) {
|
||||
if (mapElement->properties.surface.ownership & OWNERSHIP_OWNED)
|
||||
return 1;
|
||||
|
||||
if (mapElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) {
|
||||
z /= 8;
|
||||
if (z < mapElement->base_height || z - 2 > mapElement->base_height)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,6 +711,12 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es
|
||||
money32 cost;
|
||||
|
||||
rct_scenery_entry *entry = g_smallSceneryEntries[scenery_type];
|
||||
if (entry == (rct_scenery_entry *)0xFFFFFFFF)
|
||||
{
|
||||
log_warning("Invalid game command for scenery removal, scenery_type = %u", scenery_type);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
cost = entry->small_scenery.removal_price * 10;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4;
|
||||
@@ -793,6 +802,12 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i
|
||||
|
||||
bool element_found = false;
|
||||
rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
|
||||
if (map_element == NULL)
|
||||
{
|
||||
log_warning("Invalid game command for scenery removal, x = %d, y = %d", x, y);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
do {
|
||||
if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE)
|
||||
continue;
|
||||
@@ -2128,6 +2143,11 @@ static money32 smooth_land_tile(int direction, uint8 flags, int x, int y, int ta
|
||||
|
||||
// Get height of tile
|
||||
rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5);
|
||||
if (mapElement == NULL)
|
||||
{
|
||||
log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
int baseZ = map_get_corner_height(mapElement, direction);
|
||||
|
||||
// Check if tile is same height as target tile
|
||||
@@ -2200,6 +2220,11 @@ money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop
|
||||
x = mapLeft;
|
||||
y = mapTop;
|
||||
mapElement = map_get_surface_element_at(x >> 5, y >> 5);
|
||||
if (mapElement == NULL)
|
||||
{
|
||||
log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK;
|
||||
if (slope != 0) {
|
||||
commandType = command == 0xFFFF ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND;
|
||||
@@ -3294,12 +3319,25 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry_index >= 128)
|
||||
{
|
||||
log_warning("Invalid game command for scenery placement, entry_index = %u", entry_index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sub_68B044()) {
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
|
||||
rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[entry_index];
|
||||
if (scenery_entry == (rct_scenery_entry *)0xFFFFFFFF)
|
||||
{
|
||||
log_warning("Invalid game command for scenery placement, entry_index = %u", entry_index);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
if(scenery_entry->large_scenery.var_11 != 0xFF){
|
||||
banner_id = create_new_banner(flags);
|
||||
|
||||
@@ -4284,6 +4322,10 @@ bool map_element_is_underground(rct_map_element *mapElement)
|
||||
rct_map_element *map_get_large_scenery_segment(int x, int y, int z, int direction, int sequence)
|
||||
{
|
||||
rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
if (mapElement == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
do {
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE)
|
||||
continue;
|
||||
@@ -4767,6 +4809,12 @@ void game_command_place_park_entrance(int* eax, int* ebx, int* ecx, int* edx, in
|
||||
void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {
|
||||
static char newName[128];
|
||||
|
||||
if ((*ecx >= MAX_BANNERS) || (*ecx < 0))
|
||||
{
|
||||
log_warning("Invalid game command for setting banner name, banner id = %d", *ecx);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
rct_banner* banner = &gBanners[*ecx];
|
||||
|
||||
int nameChunkIndex = *eax & 0xFFFF;
|
||||
@@ -4776,6 +4824,7 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e
|
||||
if (nameChunkOffset < 0)
|
||||
nameChunkOffset = 2;
|
||||
nameChunkOffset *= 12;
|
||||
nameChunkOffset = min(nameChunkOffset, countof(newName) - 12);
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
|
||||
@@ -4811,6 +4860,12 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e
|
||||
void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {
|
||||
static char newName[128];
|
||||
|
||||
if ((*ecx >= MAX_BANNERS) || (*ecx < 0))
|
||||
{
|
||||
log_warning("Invalid game command for setting sign name, banner id = %d", *ecx);
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
rct_banner* banner = &gBanners[*ecx];
|
||||
int x = banner->x << 5;
|
||||
int y = banner->y << 5;
|
||||
@@ -4822,6 +4877,7 @@ void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi
|
||||
if (nameChunkOffset < 0)
|
||||
nameChunkOffset = 2;
|
||||
nameChunkOffset *= 12;
|
||||
nameChunkOffset = min(nameChunkOffset, countof(newName) - 12);
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
|
||||
@@ -4866,6 +4922,12 @@ void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi
|
||||
}
|
||||
|
||||
void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {
|
||||
if ((*ecx >= MAX_BANNERS) || (*ecx < 0))
|
||||
{
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_SELECTION_OF_OBJECTS;
|
||||
*ebx = MONEY32_UNDEFINED;
|
||||
return;
|
||||
}
|
||||
rct_banner* banner = &gBanners[*ecx];
|
||||
|
||||
banner->colour = (uint8)*edx;
|
||||
|
||||
@@ -871,6 +871,7 @@ void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
|
||||
if (nameChunkOffset < 0)
|
||||
nameChunkOffset = 2;
|
||||
nameChunkOffset *= 12;
|
||||
nameChunkOffset = min(nameChunkOffset, countof(newName) - 12);
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
|
||||
RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
|
||||
|
||||
Reference in New Issue
Block a user