/** * * rct2: 0x6ba4d6 */ static void window_banner_mouseup(rct_window *w, sint32 widgetIndex) { rct_banner* banner = &gBanners[w->number]; sint32 x = banner->x << 5; sint32 y = banner->y << 5; rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); while (1){ if ((map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) && (map_element->properties.banner.index == w->number)) break; map_element++; } switch (widgetIndex) { case WIDX_CLOSE: window_close(w); break; case WIDX_BANNER_DEMOLISH: game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0); break; case WIDX_BANNER_TEXT: window_text_input_open(w, WIDX_BANNER_TEXT, STR_BANNER_TEXT, STR_ENTER_BANNER_TEXT, gBanners[w->number].string_idx, 0, 32); break; case WIDX_BANNER_NO_ENTRY: textinput_cancel(); game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->colour, GAME_COMMAND_SET_BANNER_STYLE, banner->text_colour, banner->flags ^ BANNER_FLAG_NO_ENTRY); break; } }
static void window_tile_inspector_tool_down() { short widgetIndex; rct_window* w; short x, y; int direction; window_tool_get_registers(w, widgetIndex, x, y); screen_pos_to_map_pos(&x, &y, &direction); if (x == (short)0x8000) { return; } window_tile_inspector_tile_x = x >> 5; window_tile_inspector_tile_y = y >> 5; rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); int numItems = 0; do { numItems++; } while (!map_element_is_last_for_tile(element++)); window_tile_inspector_item_count = numItems; w->scrolls[0].v_top = 0; window_invalidate(w); }
rct_map_element *banner_get_map_element(int bannerIndex) { rct_banner *banner = &gBanners[bannerIndex]; rct_map_element *mapElement = map_get_first_element_at(banner->x, banner->y); do { if (map_element_get_banner_index(mapElement) == bannerIndex) { return mapElement; } } while (!map_element_is_last_for_tile(mapElement++)); return NULL; }
rct_tile_element *banner_get_tile_element(sint32 bannerIndex) { rct_banner *banner = &gBanners[bannerIndex]; rct_tile_element *tileElement = map_get_first_element_at(banner->x, banner->y); do { if (tile_element_get_banner_index(tileElement) == bannerIndex) { return tileElement; } } while (!tile_element_is_last_for_tile(tileElement++)); return nullptr; }
/** * * rct2: 0x006D303D */ void track_design_save_select_nearby_scenery(sint32 rideIndex) { rct_map_element *mapElement; for (sint32 y = 0; y < 256; y++) { for (sint32 x = 0; x < 256; x++) { mapElement = map_get_first_element_at(x, y); do { if (track_design_save_should_select_scenery_around(rideIndex, mapElement)) { track_design_save_select_nearby_scenery_for_tile(rideIndex, x, y); break; } } while (!map_element_is_last_for_tile(mapElement++)); } } gfx_invalidate_screen(); }
/** * * rct2: 0x006D303D */ void track_design_save_select_nearby_scenery(sint32 rideIndex) { rct_tile_element *tileElement; for (sint32 y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++) { for (sint32 x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { tileElement = map_get_first_element_at(x, y); do { if (track_design_save_should_select_scenery_around(rideIndex, tileElement)) { track_design_save_select_nearby_scenery_for_tile(rideIndex, x, y); break; } } while (!(tileElement++)->IsLastForTile()); } } gfx_invalidate_screen(); }
static money32 BannerSetColour(sint16 x, sint16 y, uint8 baseHeight, uint8 direction, uint8 colour, uint8 flags) { gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; sint32 z = (baseHeight * 8); gCommandPosition.x = x + 16; gCommandPosition.y = y + 16; gCommandPosition.z = z; if (!map_can_build_at(x, y, z - 16)) { return MONEY32_UNDEFINED; } if (flags & GAME_COMMAND_FLAG_APPLY) { rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32); bool found = false; do { if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_BANNER) continue; if (tileElement->properties.banner.position != direction) continue; found = true; break; } while (!tile_element_is_last_for_tile(tileElement++)); if (!found) { return MONEY32_UNDEFINED; } auto intent = Intent(INTENT_ACTION_UPDATE_BANNER); intent.putExtra(INTENT_EXTRA_BANNER_INDEX, tileElement->properties.banner.index); context_broadcast_intent(&intent); gBanners[tileElement->properties.banner.index].colour = colour; map_invalidate_tile_zoom1(x, y, z, z + 32); } return 0; }
/** * * rct2: 0x006A614A */ static void viewport_interaction_remove_footpath(rct_tile_element *tileElement, sint32 x, sint32 y) { sint32 z; rct_window *w; rct_tile_element *tileElement2; z = tileElement->base_height; w = window_find_by_class(WC_FOOTPATH); if (w != nullptr) footpath_provisional_update(); tileElement2 = map_get_first_element_at(x / 32, y / 32); do { if (tileElement2->GetType() == TILE_ELEMENT_TYPE_PATH && tileElement2->base_height == z) { gGameCommandErrorTitle = STR_CANT_REMOVE_FOOTPATH_FROM_HERE; footpath_remove(x, y, z, GAME_COMMAND_FLAG_APPLY); break; } } while (!(tileElement2++)->IsLastForTile()); }
static void window_tile_inspector_scrollpaint() { int x = 15, y = 11 * (window_tile_inspector_item_count - 1), i = 0; rct_window *w; rct_drawpixelinfo *dpi; char buffer[256]; window_paint_get_registers(w, dpi); if (window_tile_inspector_tile_x == -1) return; rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y); do { int type = map_element_get_type(element); char *type_name; int base_height = element->base_height; int clearance_height = element->clearance_height; if ((i & 1) != 0) gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + 11, RCT2_GLOBAL(0x0141FC4A + (w->colours[1] * 8), uint8) | 0x1000000); switch (type) { case MAP_ELEMENT_TYPE_SURFACE: sprintf( buffer, "Surface (%s, %s)", language_get_string(STR_TILE_INSPECTOR_TERRAIN_START + map_element_get_terrain(element)), language_get_string(STR_TILE_INSPECTOR_TERRAIN_EDGE_START + map_element_get_terrain_edge(element)) ); type_name = buffer; break; case MAP_ELEMENT_TYPE_PATH: { // TODO: use these uint8 pathType, pathDirection; pathType = element->properties.path.type >> 2; pathDirection = element->properties.path.type & 3; } sprintf( buffer, "Path (%s)", "" // TODO: queue? has bins? has benches? e.t.c. ); type_name = buffer; break; case MAP_ELEMENT_TYPE_TRACK: type_name = "Track"; // TODO: show type? break; case MAP_ELEMENT_TYPE_SCENERY: sprintf( buffer, "Scenery (%s)", language_get_string(g_smallSceneryEntries[element->properties.scenery.type]->name) ); type_name = buffer; break; case MAP_ELEMENT_TYPE_ENTRANCE: sprintf( buffer, "Entrance (%s)", language_get_string(STR_TILE_INSPECTOR_ENTRANCE_START + element->properties.entrance.type) ); type_name = buffer; break; case MAP_ELEMENT_TYPE_FENCE: sprintf( buffer, "Fence (%s)", language_get_string(g_wallSceneryEntries[element->properties.scenery.type]->name) ); type_name = buffer; break; case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE: type_name = "Scenery multiple"; break; case MAP_ELEMENT_TYPE_BANNER: sprintf( buffer, "Banner (%d)", element->properties.banner.index ); type_name = buffer; break; } gfx_draw_string(dpi, type_name, 12, x, y); gfx_draw_string_left(dpi, 5182, &base_height, 12, x + 200, y); gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + 280, y); uint8 flags = element->flags; char j; buffer[8] = '\0'; for (j = 7; j >= 0; j--, flags >>= 1) { buffer[j] = flags & 1 ? '1' : '0'; } gfx_draw_string(dpi, buffer, 12, x + 390, y); y -= 11; i++; } while (!map_element_is_last_for_tile(element++)); }
/** * * rct2: 0x006E2712 */ void scenery_remove_ghost_tool_placement(){ sint16 x, y, z; x = RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_X, sint16); y = RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_Y, sint16); z = RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_Z, uint8); if (RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) & (1 << 0)){ RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) &= ~(1 << 0); game_do_command( x, 105 | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_MAP_ELEMENT_TYPE, uint8) << 8), y, z | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_SELECTED_OBJECT, uint8) << 8), GAME_COMMAND_REMOVE_SCENERY, 0, 0); } if (RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) & (1 << 1)){ RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) &= ~(1 << 1); rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); do{ if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH) continue; if (map_element->base_height != z) continue; game_do_command( x, 233 | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TARGET_PATH_INCLINE, uint8) << 8), y, z | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TARGET_PATH_TYPE, uint8) << 8), GAME_COMMAND_PLACE_PATH, RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_PATH_OBJECT_TYPE, uint32) & 0xFFFF0000, 0); break; } while (!map_element_is_last_for_tile(map_element++)); } if (RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) & (1 << 2)){ RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) &= ~(1 << 2); game_do_command( x, 105 | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_MAP_ELEMENT_TYPE, uint8) << 8), y, RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_WALL_ROTATION, uint8) |(z << 8), GAME_COMMAND_REMOVE_FENCE, 0, 0); } if (RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) & (1 << 3)){ RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) &= ~(1 << 3); game_do_command( x, 105 | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_ROTATION, uint8) << 8), y, z, GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0); } if (RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) & (1 << 4)){ RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) &= ~(1 << 4); game_do_command( x, 105, y, z | (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_ROTATION, uint8) << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0); } }
void fix_duplicated_banners() { // For each banner in the map, check if the banner index is in use already, and if so, create a new entry for it bool activeBanners[Util::CountOf(gBanners)]{}; rct_tile_element * tileElement; for (int y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++) { for (int x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { tileElement = map_get_first_element_at(x, y); do { // TODO: Handle walls and large-scenery that use banner indices too. Large scenery can be tricky, as they occupy // multiple tiles that should both refer to the same banner index. if (tile_element_get_type(tileElement) == TILE_ELEMENT_TYPE_BANNER) { uint8 bannerIndex = tileElement->properties.banner.index; if (activeBanners[bannerIndex]) { log_info( "Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y, tileElement->base_height); // Banner index is already in use by another banner, so duplicate it uint8 newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY); if (newBannerIndex == BANNER_NULL) { log_error("Failed to create new banner."); continue; } Guard::Assert(activeBanners[newBannerIndex] == false); // Copy over the original banner, but update the location rct_banner & newBanner = gBanners[newBannerIndex]; newBanner = gBanners[bannerIndex]; newBanner.x = x; newBanner.y = y; // Duplicate user string too rct_string_id stringIdx = newBanner.string_idx; if (is_user_string_id(stringIdx)) { utf8 buffer[USER_STRING_MAX_LENGTH]; format_string(buffer, USER_STRING_MAX_LENGTH, stringIdx, nullptr); rct_string_id newStringIdx = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); if (newStringIdx == 0) { log_error("Failed to allocate user string for banner"); continue; } newBanner.string_idx = newStringIdx; } tileElement->properties.banner.index = newBannerIndex; } // Mark banner index as in-use activeBanners[bannerIndex] = true; } } while (!tile_element_is_last_for_tile(tileElement++)); } } }
static money32 BannerPlace(sint16 x, sint16 y, uint8 pathBaseHeight, uint8 direction, uint8 colour, uint8 type, uint8 *bannerIndex, uint8 flags) { gCommandPosition.x = x + 16; gCommandPosition.y = y + 16; gCommandPosition.z = pathBaseHeight * 16; gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; if (game_is_paused() && !gCheatsBuildInPauseMode) { gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } if (!map_check_free_elements_and_reorganise(1)) { return MONEY32_UNDEFINED; } if (!map_is_location_valid(x, y)) { return MONEY32_UNDEFINED; } rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32); bool pathFound = false; do { if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_PATH) continue; if (tileElement->base_height != pathBaseHeight * 2 && tileElement->base_height != (pathBaseHeight - 1) * 2) continue; if (!(tileElement->properties.path.edges & (1 << direction))) continue; pathFound = true; break; } while (!tile_element_is_last_for_tile(tileElement++)); if (!pathFound) { gGameCommandErrorText = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; return MONEY32_UNDEFINED; } if (!map_can_build_at(x, y, pathBaseHeight * 16)) { return MONEY32_UNDEFINED; } uint8 baseHeight = (pathBaseHeight + 1) * 2; tileElement = map_get_banner_element_at(x / 32, y / 32, baseHeight, direction); if (tileElement != nullptr) { gGameCommandErrorText = STR_BANNER_SIGN_IN_THE_WAY; return MONEY32_UNDEFINED; } *bannerIndex = create_new_banner(flags); if (*bannerIndex == BANNER_NULL) { return MONEY32_UNDEFINED; } if (flags & GAME_COMMAND_FLAG_APPLY) { if (gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { LocationXYZ16 coord; coord.x = x + 16; coord.y = y + 16; coord.z = tile_element_height(coord.x, coord.y); network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); } rct_tile_element* newTileElement = tile_element_insert(x / 32, y / 32, baseHeight, 0); assert(newTileElement != nullptr); gBanners[*bannerIndex].type = type; gBanners[*bannerIndex].colour = colour; gBanners[*bannerIndex].x = x / 32; gBanners[*bannerIndex].y = y / 32; newTileElement->type = TILE_ELEMENT_TYPE_BANNER; newTileElement->clearance_height = newTileElement->base_height + 2; newTileElement->properties.banner.position = direction; newTileElement->properties.banner.flags = 0xFF; newTileElement->properties.banner.unused = 0; newTileElement->properties.banner.index = *bannerIndex; if (flags & GAME_COMMAND_FLAG_GHOST) { newTileElement->flags |= TILE_ELEMENT_FLAG_GHOST; } map_invalidate_tile_full(x, y); map_animation_create(MAP_ANIMATION_TYPE_BANNER, x, y, newTileElement->base_height); } rct_scenery_entry *bannerEntry = get_banner_entry(type); if (bannerEntry == nullptr) { return MONEY32_UNDEFINED; } if (gParkFlags & PARK_FLAGS_NO_MONEY) { return 0; } return bannerEntry->banner.price; }
/** * * rct2: 0x006BA305 */ void window_banner_open(rct_windownumber number) { rct_window* w; rct_widget *viewportWidget; // Check if window is already open w = window_bring_to_front_by_number(WC_BANNER, number); if (w != NULL) return; w = window_create_auto_pos(WW, WH, &window_banner_events, WC_BANNER, WF_NO_SCROLLING); w->widgets = window_banner_widgets; w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_BANNER_TEXT) | (1 << WIDX_BANNER_NO_ENTRY) | (1 << WIDX_BANNER_DEMOLISH) | (1 << WIDX_MAIN_COLOUR) | (1 << WIDX_TEXT_COLOUR_DROPDOWN) | (1 << WIDX_TEXT_COLOUR_DROPDOWN_BUTTON); w->number = number; window_init_scroll_widgets(w); sint32 view_x = gBanners[w->number].x << 5; sint32 view_y = gBanners[w->number].y << 5; rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32); while(1) { if ( (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) && (map_element->properties.banner.index == w->number) ) { break; } map_element++; } sint32 view_z = map_element->base_height<<3; w->frame_no = view_z; view_x += 16; view_y += 16; // Create viewport viewportWidget = &window_banner_widgets[WIDX_VIEWPORT]; viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 2, (viewportWidget->bottom - viewportWidget->top) - 2, 0, view_x, view_y, view_z, 0, -1 ); w->viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; window_invalidate(w); }
/* 0x006E2712 */ void scenery_remove_ghost_tool_placement(){ sint16 x, y, z; x = RCT2_GLOBAL(0x00F64EC4, sint16); y = RCT2_GLOBAL(0x00F64EC6, sint16); z = RCT2_GLOBAL(0x00F64F09, uint8); if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 0)){ RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 0); game_do_command( x, 105 | (RCT2_GLOBAL(0x00F64F0C, uint8) << 8), y, z | (RCT2_GLOBAL(0x00F64EDA, uint8) << 8), GAME_COMMAND_REMOVE_SCENERY, 0, 0); } if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 1)){ RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 1); rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); do{ if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH) continue; if (map_element->base_height != z) continue; game_do_command( x, 233 | (RCT2_GLOBAL(0x00F64F0F, uint8) << 8), y, z | (RCT2_GLOBAL(0x00F64F10, uint8) << 8), GAME_COMMAND_PLACE_PATH, RCT2_GLOBAL(0x00F64EAC, uint32) & 0xFFFF0000, 0); break; } while (!map_element_is_last_for_tile(map_element++)); } if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 2)){ RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 2); game_do_command( x, 105 | (RCT2_GLOBAL(0x00F64F0C, uint8) << 8), y, RCT2_GLOBAL(0x00F64F11, uint8) |(z << 8), GAME_COMMAND_REMOVE_FENCE, 0, 0); } if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 3)){ RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 3); game_do_command( x, 105 | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8), y, z, GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0); } if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 4)){ RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 4); game_do_command( x, 105, y, z | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0); } }