diff --git a/src/game.c b/src/game.c index 984294fb10..0fefa3b726 100644 --- a/src/game.c +++ b/src/game.c @@ -918,7 +918,7 @@ static uint32 game_do_command_table[58] = { 0x006E519A, 0, 0x006B893C, - 0x006B8E1B, + 0, 0, 0, 0x006D13FE, @@ -981,7 +981,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_remove_fence, game_command_emptysub, - game_command_emptysub, + game_command_remove_large_scenery, game_command_set_current_loan, game_command_set_research_funding, game_command_emptysub, diff --git a/src/game.h b/src/game.h index 7e7e509106..0feb19c63d 100644 --- a/src/game.h +++ b/src/game.h @@ -68,7 +68,7 @@ enum GAME_COMMAND { GAME_COMMAND_41, GAME_COMMAND_REMOVE_FENCE, GAME_COMMAND_43, - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, GAME_COMMAND_SET_CURRENT_LOAN, // 45 GAME_COMMAND_SET_RESEARCH_FUNDING, // 46 GAME_COMMAND_47, diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index a7ece92671..0cd579746d 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -512,7 +512,7 @@ static void viewport_interaction_remove_large_scenery(rct_map_element *mapElemen 1 | ((mapElement->type & 0x3) << 8), y, mapElement->base_height | ((mapElement->properties.scenerymultiple.type >> 10) << 8), - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0 ); diff --git a/src/object.c b/src/object.c index 4be671b373..6b8bc5a6f5 100644 --- a/src/object.c +++ b/src/object.c @@ -907,7 +907,7 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* chunk += 1038; } - scenery_type->large_scenery.var_0C = (uint32)chunk; + scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk; while (*((uint16*)chunk) != 0xFFFF){ chunk += 9; @@ -937,7 +937,7 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; scenery_type->name = 0; scenery_type->image = 0; - scenery_type->large_scenery.var_0C = 0; + scenery_type->large_scenery.tiles = 0; scenery_type->large_scenery.scenery_tab_id = 0; scenery_type->large_scenery.var_12 = 0; scenery_type->large_scenery.var_16 = 0; diff --git a/src/windows/sign.c b/src/windows/sign.c index 39aee6746d..c77defa2c8 100644 --- a/src/windows/sign.c +++ b/src/windows/sign.c @@ -256,7 +256,7 @@ static void window_sign_mouseup() 1 | ((map_element->type&0x3) << 8), y, map_element->base_height | ((map_element->properties.scenerymultiple.type >> 10) << 8), - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0); break; diff --git a/src/world/map.c b/src/world/map.c index 088d625ff4..a790c84410 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -641,6 +641,133 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es *ebx = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost); } +/** + * + * rct2: 0x006B8E1B + */ +void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + uint8 base_height = *edx; + uint8 scenerymultiple_index = *edx >> 8; + uint8 map_element_direction = *ebx >> 8; + int x = *eax; + int y = *ecx; + int z = map_element_height(x, y); + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + + if (!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; + } + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE || + map_element->base_height != base_height || + map_element->properties.scenerymultiple.type >> 10 != scenerymultiple_index || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + *ebx = 0; + return; + } + int ecx2 = map_element->properties.scenerymultiple.type >> 10; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.scenerymultiple.type & 0x3FF]; + if(scenery_entry->large_scenery.var_11 != 0xFF){ + uint8 banner_num = map_element->type & MAP_ELEMENT_QUADRANT_MASK; + banner_num |= (map_element->properties.scenerymultiple.colour[0] & 0xE0) >> 2; + banner_num |= (map_element->properties.scenerymultiple.colour[1] & 0xE0) >> 5; + if(gBanners[banner_num].type != BANNER_NULL){ + window_close_by_number(WC_BANNER, banner_num); + gBanners[banner_num].type = BANNER_NULL; + user_string_free(gBanners[banner_num].string_idx); + } + } + int x2 = scenery_entry->large_scenery.tiles[ecx2].x_offset; + int y2 = scenery_entry->large_scenery.tiles[ecx2].y_offset; + int z2 = (base_height * 8) - scenery_entry->large_scenery.tiles[ecx2].z_offset; + switch(map_element->type & MAP_ELEMENT_DIRECTION_MASK){ + case MAP_ELEMENT_DIRECTION_WEST: + break; + case MAP_ELEMENT_DIRECTION_NORTH:{ + int temp = x2; + x2 = y2; + y2 = -temp; + }break; + case MAP_ELEMENT_DIRECTION_EAST: + x2 = -x2; + y2 = -y2; + break; + case MAP_ELEMENT_DIRECTION_SOUTH:{ + int temp = y2; + y2 = x2; + x2 = -temp; + }break; + } + x2 = -x2 + x; + y2 = -y2 + y; + int i = 0; + while(1){ + if(scenery_entry->large_scenery.tiles[i].x_offset == -1){ + *ebx = scenery_entry->large_scenery.removal_price * 10; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } + return; + } + int x3 = scenery_entry->large_scenery.tiles[i].x_offset; + int y3 = scenery_entry->large_scenery.tiles[i].y_offset; + int z3 = scenery_entry->large_scenery.tiles[i].z_offset; + switch(map_element->type & MAP_ELEMENT_DIRECTION_MASK){ + case MAP_ELEMENT_DIRECTION_WEST: + break; + case MAP_ELEMENT_DIRECTION_NORTH:{ + int temp = x3; + x3 = y3; + y3 = -temp; + }break; + case MAP_ELEMENT_DIRECTION_EAST: + x3 = -x3; + y3 = -y3; + break; + case MAP_ELEMENT_DIRECTION_SOUTH:{ + int temp = y3; + y3 = x3; + x3 = -temp; + }break; + } + x3 += x2; + y3 += y2; + z3 += z2; + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_owned(x3, y3, z3)){ + *ebx = MONEY32_UNDEFINED; + return; + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_map_element* map_element = map_get_first_element_at(x3 / 32, y3 / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction || + map_element->properties.scenerymultiple.type >> 10 != i || + map_element->base_height != base_height){ + map_element++; + } + map_invalidate_tile_full(x3, y3); + map_element_remove(map_element); + } + } + i++; + } +} + money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -1218,8 +1345,8 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, return; } } - rct_object_entry_extended* object_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_object_entry_extended*)[map_element->properties.fence.slope]; - if((uint8)object_entry->checksum != 0xFF){ + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + if(scenery_entry->wall.var_0D != 0xFF){ rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; if(banner->type != BANNER_NULL){ window_close_by_number(WC_BANNER, map_element->properties.fence.item[0]); diff --git a/src/world/map.h b/src/world/map.h index dc91f3046e..adfbca7701 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -275,6 +275,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); diff --git a/src/world/scenery.h b/src/world/scenery.h index e94337fec8..7b4765f1e7 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -58,12 +58,19 @@ typedef enum { SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000 } SMALL_SCENERY_FLAGS; +typedef struct { + sint16 x_offset; + sint16 y_offset; + sint16 z_offset; + uint8 pad_6[3]; +} rct_large_scenery_tile; + typedef struct { uint8 tool_id; // 0x06 uint8 flags; // 0x07 sint16 price; // 0x08 sint16 removal_price; // 0x0A - uint32 var_0C; + rct_large_scenery_tile* tiles; // 0x0C uint8 scenery_tab_id; // 0x10 uint8 var_11; uint32 var_12;