From d2b565b283da658c2aaf97d2c326f6be3f091480 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sun, 14 Jun 2015 05:56:12 -0600 Subject: [PATCH] game_command_place_large_scenery --- src/game.c | 4 +- src/game.h | 2 +- src/localisation/string_ids.h | 1 + src/ride/track.c | 2 +- src/windows/top_toolbar.c | 6 +- src/world/banner.h | 1 + src/world/map.c | 215 ++++++++++++++++++++++++++++++++++ src/world/map.h | 1 + src/world/scenery.h | 3 +- 9 files changed, 228 insertions(+), 7 deletions(-) diff --git a/src/game.c b/src/game.c index 01a88d7c2f..4c52a69f61 100644 --- a/src/game.c +++ b/src/game.c @@ -932,7 +932,7 @@ static uint32 game_do_command_table[58] = { 0, // 40 0x006E519A, 0, - 0x006B893C, + 0, 0, 0, 0, @@ -995,7 +995,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_update_staff_colour, // 40 game_command_emptysub, game_command_remove_fence, - game_command_emptysub, + game_command_place_large_scenery, game_command_remove_large_scenery, game_command_set_current_loan, game_command_set_research_funding, diff --git a/src/game.h b/src/game.h index 1d02084846..e06a29f18b 100644 --- a/src/game.h +++ b/src/game.h @@ -67,7 +67,7 @@ enum GAME_COMMAND { GAME_COMMAND_SET_STAFF_COLOUR, // 40 GAME_COMMAND_41, GAME_COMMAND_REMOVE_FENCE, - GAME_COMMAND_43, + GAME_COMMAND_PLACE_LARGE_SCENERY, GAME_COMMAND_REMOVE_LARGE_SCENERY, GAME_COMMAND_SET_CURRENT_LOAN, // 45 GAME_COMMAND_SET_RESEARCH_FUNDING, // 46 diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index f9be204fc6..491b9524b6 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -122,6 +122,7 @@ enum { STR_SCREENSHOT = 891, STR_SCREENSHOT_SAVED_AS = 892, STR_SCREENSHOT_FAILED = 893, + STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND = 895, STR_VIEW_OPTIONS_TIP = 937, STR_ADJUST_LAND_TIP = 938, diff --git a/src/ride/track.c b/src/ride/track.c index dc47d39580..0b90178d55 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -1205,7 +1205,7 @@ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int o bl | (rotation << 8), mapCoord.y, scenery->primary_colour | (scenery->secondary_colour << 8), - GAME_COMMAND_43, + GAME_COMMAND_PLACE_LARGE_SCENERY, entry_index, z ); diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index e3c7500546..7079828796 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1503,9 +1503,11 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w for (; bl != 0; bl--){ RCT2_GLOBAL(0x009A8C29, uint8) |= 1; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 1161; + int ebx = (parameter_1 & 0xFF00) | 1; - int cost = game_do_command(grid_x, ebx, grid_y, parameter_2, GAME_COMMAND_43, parameter_3, RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16)); + int cost = game_do_command(grid_x, ebx, grid_y, parameter_2, GAME_COMMAND_PLACE_LARGE_SCENERY, parameter_3, RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16)); RCT2_GLOBAL(0x009A8C29, uint8) &= ~1; @@ -2108,7 +2110,7 @@ money32 try_place_ghost_scenery(rct_xy16 map_tile, uint32 parameter_1, uint32 pa parameter_1 | 0x69, map_tile.y, parameter_2, - GAME_COMMAND_43, + GAME_COMMAND_PLACE_LARGE_SCENERY, parameter_3, RCT2_GLOBAL(0x00F64ED4, uint16)); diff --git a/src/world/banner.h b/src/world/banner.h index c3ee3300f9..3944fd7c9c 100644 --- a/src/world/banner.h +++ b/src/world/banner.h @@ -38,6 +38,7 @@ typedef struct { enum{ BANNER_FLAG_NO_ENTRY = (1 << 0), + BANNER_FLAG_1 = (1 << 1), BANNER_FLAG_2 = (1 << 2) } BANNER_FLAGS; diff --git a/src/world/map.c b/src/world/map.c index fc4988a85e..f3e594f618 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -2122,6 +2122,221 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi *ebx = MONEY32_UNDEFINED; } +/** + * + * rct2: 0x006B893C + */ +void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + int x = (sint16)*eax; + int y = (sint16)*ecx; + int z = (sint16)*ebp; + uint8 color1 = *edx; + uint8 color2 = *edx >> 8; + uint8 flags = *ebx; + uint8 rotation = *ebx >> 8; + uint8 entry_index = *edi; + int base_height = map_element_height(x, y); + RCT2_GLOBAL(0x009DEA5E, sint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, sint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, sint16) = base_height; + RCT2_GLOBAL(0x00F64F14, uint8) = 0; + uint8 banner_id = 0xFF; + RCT2_GLOBAL(0x00F4389A, uint32) = 0; + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode){ + if(sub_68B044()){ + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[entry_index]; + if(scenery_entry->large_scenery.var_11 != 0xFF){ + banner_id = create_new_banner(flags); + if(banner_id == MAX_BANNERS){ + *ebx = MONEY32_UNDEFINED; + return; + } + if(flags & GAME_COMMAND_FLAG_APPLY){ + rct_banner* banner = &gBanners[banner_id]; + banner->flags |= BANNER_FLAG_1; + banner->type = 0; + banner->x = x / 32; + banner->y = y / 32; + int eax2 = x, ebx2 = *ebx, ecx2 = y, edx2 = z, esi2 = *esi, edi2 = *edi, ebp2 = *ebp; + RCT2_CALLFUNC_X(0x006B7D86, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); + if((uint8)eax2 != 0xFF){ + banner->colour = eax2; + banner->flags |= BANNER_FLAG_2; + } + } + } + rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; + sint16 F43884 = 0xFFFF; + do{ + if(tile->x_offset == (sint16)0xFFFF){ + break; + } + int x2 = tile->x_offset; + int y2 = tile->y_offset; + switch(rotation){ + case 0:{ + }break; + case 1:{ + int temp = x2; + x2 = y2; + y2 = -temp; + }break; + case 2:{ + x2 = -x2; + y2 = -y2; + }break; + case 3:{ + int temp = y2; + y2 = x2; + x2 = -temp; + }break; + } + x2 += x; + y2 += y; + if(x2 >= 0x1FFF || y2 >= 0x1FFF){ + tile++; + continue; + } + rct_map_element* map_element = map_get_surface_element_at(x2 / 32, y2 / 32); + int height = map_element->base_height * 8; + if(map_element->properties.scenerymultiple.type & 0xF){ + height += 16; + if(map_element->properties.scenerymultiple.type & 0x10){ + height += 16; + } + } + if(height > F43884){ + F43884 = height; + } + tile++; + }while(1); + if(z != 0){ + F43884 = z; + } + RCT2_GLOBAL(0x009DEA62, sint16) = F43884; + tile = scenery_entry->large_scenery.tiles; + uint8 tile_num = 0; + do{ + if(tile->x_offset == (sint16)0xFFFF){ + break; + } + int x2 = tile->x_offset; + int y2 = tile->y_offset; + switch(rotation){ + case 0:{ + }break; + case 1:{ + int temp = x2; + x2 = y2; + y2 = -temp; + }break; + case 2:{ + x2 = -x2; + y2 = -y2; + }break; + case 3:{ + int temp = y2; + y2 = x2; + x2 = -temp; + }break; + } + int zLow = (tile->z_offset + F43884) / 8; + int zHigh = (tile->var_6 / 8) + zLow; + int bx = tile->var_7 >> 12; + bx <<= rotation; + uint8 bl = bx; + uint8 bh = bl >> 4; + bl &= 0xF; + bl |= bh; + uint8 F43887 = bl; + x2 += x; + y2 += y; + RCT2_GLOBAL(0x00F43892, sint16) = x2; + RCT2_GLOBAL(0x00F43894, sint16) = y2; + RCT2_GLOBAL(0x00F43896, uint32) = (uint32)(ebx - 3); // this is how ebx flags var is passed to 0x006B8D88 + if(map_can_construct_with_clear_at(x2, y2, zLow, zHigh, (void*)0x006B8D88, bl)){ + if(!(RCT2_GLOBAL(0x00F1AD60, uint8) & 4) && !(RCT2_GLOBAL(0x00F1AD60, uint8) & 2)){ + int b = RCT2_GLOBAL(0x00F1AD60, uint8) & 0x3; + if(RCT2_GLOBAL(0x00F64F14, uint8) && !(RCT2_GLOBAL(0x00F64F14, uint8) & b)){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CANT_BUILD_PARTLY_ABOVE_AND_PARTLY_BELOW_GROUND; + *ebx = MONEY32_UNDEFINED; + return; + } + RCT2_GLOBAL(0x00F64F14, uint8) = b; + if(x2 >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) || y2 >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16)){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_OFF_EDGE_OF_MAP; + *ebx = MONEY32_UNDEFINED; + return; + } + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && map_is_location_owned(x2, y2, zLow * 8)){ + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + if(!(*ebx & 0x40)){ + footpath_remove_litter(x2, y2, zLow * 8); + int bh = (zHigh - zLow) * 8; + RCT2_CALLPROC_X(0x006E588E, x2, bh << 8 | flags, y2, zLow * 8, 0, 0, 0); + } + rct_map_element *new_map_element = map_element_insert(x2 / 32, y2 / 32, zLow, F43887); + map_animation_create(0xB, x2 / 32, y2 / 32, zLow); + + new_map_element->clearance_height = zHigh; + new_map_element->type = MAP_ELEMENT_TYPE_SCENERY_MULTIPLE | rotation; + int bx = tile_num; + bx <<= 10; + bx |= entry_index; + new_map_element->properties.scenerymultiple.type = bx; + new_map_element->properties.scenerymultiple.colour[0] = color1; + new_map_element->properties.scenerymultiple.colour[1] = color2; + if(banner_id != 0xFF){ + uint8 bh = banner_id; + bh &= 0xC0; + new_map_element->type |= bh; + bh = banner_id; + bh &= 0x38; + bh <<= 2; + new_map_element->properties.scenerymultiple.colour[0] |= bh; + uint8 bl = banner_id; + bl &= 7; + bl <<= 5; + new_map_element->properties.scenerymultiple.colour[1] |= bl; + } + + if(*ebx & 0x40){ + new_map_element->flags |= MAP_ELEMENT_FLAG_5; + } + if(tile_num == 0){ + RCT2_GLOBAL(0x00F64EBC, rct_map_element*) = new_map_element; + } + map_invalidate_tile_full(x2 / 32, y2 / 32); + } + }else{ + *ebx = MONEY32_UNDEFINED; + return; + } + }else{ + *ebx = MONEY32_UNDEFINED; + return; + } + }else{ + *ebx = MONEY32_UNDEFINED; + return; + } + tile++; + tile_num++; + }while(1); + *ebx = (scenery_entry->large_scenery.price * 10) + RCT2_GLOBAL(0x00F4389A, uint32); + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } + return; + } + }else{ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + } + *ebx = MONEY32_UNDEFINED; +} + /** * * rct2: 0x006EC6D7 diff --git a/src/world/map.h b/src/world/map.h index 86e451d4a9..7bc3aa8e33 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -304,6 +304,7 @@ void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x])) #define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x]) diff --git a/src/world/scenery.h b/src/world/scenery.h index 12251b2738..c35704f13d 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -68,7 +68,8 @@ typedef struct { sint16 x_offset; sint16 y_offset; sint16 z_offset; - uint8 pad_6[3]; + uint8 var_6; + uint16 var_7; } rct_large_scenery_tile; typedef struct {