static void mapgen_place_tree(sint32 type, sint32 x, sint32 y) { sint32 surfaceZ; rct_map_element *mapElement; rct_scenery_entry *sceneryEntry = get_small_scenery_entry(type); surfaceZ = map_element_height(x * 32 + 16, y * 32 + 16) / 8; mapElement = map_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8)); assert(mapElement != NULL); mapElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3); mapElement->type = MAP_ELEMENT_TYPE_SCENERY | (util_rand() & 3); mapElement->properties.scenery.type = type; mapElement->properties.scenery.age = 0; mapElement->properties.scenery.colour_1 = COLOUR_YELLOW; }
/** * Randomly places a selection of preset trees on the map. Picks the right tree for the terrain it is placing it on. */ static void mapgen_place_trees() { sint32 numGrassTreeIds = 0, numDesertTreeIds = 0, numSnowTreeIds = 0; sint32 *grassTreeIds = (sint32*)malloc(countof(GrassTrees) * sizeof(sint32)); sint32 *desertTreeIds = (sint32*)malloc(countof(DesertTrees) * sizeof(sint32)); sint32 *snowTreeIds = (sint32*)malloc(countof(SnowTrees) * sizeof(sint32)); for (sint32 i = 0; i < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]; i++) { rct_scenery_entry *sceneryEntry = get_small_scenery_entry(i); rct_object_entry_extended *entry = &object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[i]; if (sceneryEntry == (rct_scenery_entry*)-1 || sceneryEntry == NULL) continue; sint32 j; for (j = 0; j < countof(GrassTrees); j++) if (strncmp(GrassTrees[j], entry->name, 8) == 0) break; if (j != countof(GrassTrees)) { grassTreeIds[numGrassTreeIds++] = i; continue; } for (j = 0; j < countof(DesertTrees); j++) if (strncmp(DesertTrees[j], entry->name, 8) == 0) break; if (j != countof(DesertTrees)) { desertTreeIds[numDesertTreeIds++] = i; continue; } for (j = 0; j < countof(SnowTrees); j++) if (strncmp(SnowTrees[j], entry->name, 8) == 0) break; if (j != countof(SnowTrees)) { snowTreeIds[numSnowTreeIds++] = i; continue; } } sint32 availablePositionsCount = 0; struct { sint32 x; sint32 y; } tmp, *pos, *availablePositions; availablePositions = malloc(256 * 256 * sizeof(tmp)); // Create list of available tiles for (sint32 y = 1; y < gMapSize - 1; y++) { for (sint32 x = 1; x < gMapSize - 1; x++) { rct_map_element *mapElement = map_get_surface_element_at(x, y); // Exclude water tiles if ((mapElement->properties.surface.terrain & 0x1F) != 0) continue; pos = &availablePositions[availablePositionsCount++]; pos->x = x; pos->y = y; } } // Shuffle list for (sint32 i = 0; i < availablePositionsCount; i++) { sint32 rindex = util_rand() % availablePositionsCount; if (rindex == i) continue; tmp = availablePositions[i]; availablePositions[i] = availablePositions[rindex]; availablePositions[rindex] = tmp; } // Place trees float treeToLandRatio = (10 + (util_rand() % 30)) / 100.0f; sint32 numTrees = max(4, (sint32)(availablePositionsCount * treeToLandRatio)); for (sint32 i = 0; i < numTrees; i++) { pos = &availablePositions[i]; sint32 type = -1; rct_map_element *mapElement = map_get_surface_element_at(pos->x, pos->y); switch (map_element_get_terrain(mapElement)) { case TERRAIN_GRASS: case TERRAIN_DIRT: case TERRAIN_GRASS_CLUMPS: if (numGrassTreeIds == 0) break; type = grassTreeIds[util_rand() % numGrassTreeIds]; break; case TERRAIN_SAND: case TERRAIN_SAND_DARK: case TERRAIN_SAND_LIGHT: if (numDesertTreeIds == 0) break; if (util_rand() % 4 == 0) type = desertTreeIds[util_rand() % numDesertTreeIds]; break; case TERRAIN_ICE: if (numSnowTreeIds == 0) break; type = snowTreeIds[util_rand() % numSnowTreeIds]; break; } if (type != -1) mapgen_place_tree(type, pos->x, pos->y); } free(availablePositions); free(grassTreeIds); free(desertTreeIds); free(snowTreeIds); }
/** * * rct2: 0x006DFF47 */ void scenery_paint(uint8 direction, sint32 height, rct_map_element* mapElement) { //RCT2_CALLPROC_X(0x6DFF47, 0, 0, direction, height, (sint32)mapElement, 0, 0); return; gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_SCENERY; rct_xyz16 boxlength; rct_xyz16 boxoffset; boxoffset.x = 0; boxoffset.y = 0; boxoffset.z = height; sint32 baseImageid = 0; const sint32 rotation = get_current_rotation(); if (gTrackDesignSaveMode) { if (!track_design_save_contains_map_element(mapElement)) { baseImageid = 0x21700000; } } if (mapElement->flags & MAP_ELEMENT_FLAG_GHOST) { gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_NONE; baseImageid = construction_markers[gConfigGeneral.construction_marker_colour]; } uint32 dword_F64EB0 = baseImageid; rct_scenery_entry *entry = get_small_scenery_entry(mapElement->properties.scenery.type); baseImageid = entry->image + direction; boxlength.x = 2; boxlength.y = 2; sint8 x_offset = 0; sint8 y_offset = 0; if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE) { if (entry->small_scenery.flags & SMALL_SCENERY_FLAG24) { // 6DFFE3: boxoffset.x = offsets[direction].x; boxoffset.y = offsets[direction].y; boxlength.x = lengths[direction].x; boxlength.y = lengths[direction].y; x_offset = 3; y_offset = 3; } else { x_offset = 15; y_offset = 15; if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) { x_offset = 3; y_offset = 3; boxlength.x = 26; boxlength.y = 26; if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_ALLOW_WALLS) { x_offset = 1; y_offset = 1; boxlength.x = 30; boxlength.y = 30; } } boxoffset.x = x_offset; boxoffset.y = y_offset; } } else { // 6DFFC2: uint8 ecx = (map_element_get_scenery_quadrant(mapElement) + rotation) & 3; x_offset = ScenerySubTileOffsets[ecx].x; y_offset = ScenerySubTileOffsets[ecx].y; boxoffset.x = x_offset; boxoffset.y = y_offset; } // 6E007F: boxlength.z = entry->small_scenery.height - 4; if (boxlength.z > 128 || boxlength.z < 0) { boxlength.z = 128; } if (entry->small_scenery.flags & SMALL_SCENERY_FLAG6) { if (mapElement->properties.scenery.age >= 40) { baseImageid += 4; } if (mapElement->properties.scenery.age >= 55) { baseImageid += 4; } } if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) { baseImageid |= ((mapElement->properties.scenery.colour_1 & 0x1F) << 19) | 0x20000000; if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { baseImageid |= ((mapElement->properties.scenery.colour_2 & 0x1F) << 24) | 0x80000000; } } if (dword_F64EB0 != 0) { baseImageid = (baseImageid & 0x7FFFF) | dword_F64EB0; } if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG21)) { sub_98197C(baseImageid, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_GLASS) { if (dword_F64EB0 == 0) { // Draw translucent overlay: // TODO: Name palette entries sint32 image_id = (baseImageid & 0x7FFFF) + (GlassPaletteIds[(mapElement->properties.scenery.colour_1 & 0x1F)] << 19) + 0x40000004; sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } } if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_ANIMATED) { rct_drawpixelinfo* dpi = unk_140E9A8; if ( (entry->small_scenery.flags & SMALL_SCENERY_FLAG21) || (dpi->zoom_level <= 1) ) { // 6E01A9: if (entry->small_scenery.flags & SMALL_SCENERY_FLAG12) { // 6E0512: sint32 image_id = ((gCurrentTicks / 2) & 0xF) + entry->image + 4; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } else if (entry->small_scenery.flags & SMALL_SCENERY_FLAG13) { // 6E043B: sint32 image_id = ((gCurrentTicks / 2) & 0xF) + entry->image + 8; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); image_id = direction + entry->image + 4; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); image_id = ((gCurrentTicks / 2) & 0xF) + entry->image + 24; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } else if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_IS_CLOCK) { // 6E035C: sint32 minuteImageOffset = ((gRealTimeOfDay.minute + 6) * 17) / 256; sint32 timeImageBase = gRealTimeOfDay.hour; while (timeImageBase >= 12) { timeImageBase -= 12; } timeImageBase = (timeImageBase * 4) + minuteImageOffset; if (timeImageBase >= 48) { timeImageBase -= 48; } sint32 image_id = timeImageBase + (direction * 12); if (image_id >= 48) { image_id -= 48; } image_id = image_id + entry->image + 68; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); image_id = gRealTimeOfDay.minute + (direction * 15); if (image_id >= 60) { image_id -= 60; } image_id = image_id + entry->image + 8; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } else if (entry->small_scenery.flags & SMALL_SCENERY_FLAG15) { // 6E02F6: sint32 image_id = gCurrentTicks; image_id += gUnk9DE568 / 4; image_id += gUnk9DE56C / 4; image_id = (image_id / 4) & 15; image_id += entry->image; if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } else { if (entry->small_scenery.flags & SMALL_SCENERY_FLAG16) { // nothing } sint32 esi = gCurrentTicks; if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG22)) { // 6E01F8: esi += ((gUnk9DE568 / 4) + (gUnk9DE56C / 4)); esi += (mapElement->type & 0xC0) / 16; } // 6E0222: uint16 cx = entry->small_scenery.var_14; uint8 cl = cx & 0xFF; esi >>= cl; esi &= entry->small_scenery.var_16; sint32 image_id = 0; if (esi < entry->small_scenery.var_18) { image_id = entry->small_scenery.var_10[esi]; } image_id = (image_id * 4) + direction + entry->image; if (entry->small_scenery.flags & (SMALL_SCENERY_FLAG21 | SMALL_SCENERY_FLAG17)) { image_id += 4; } if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) { image_id |= ((mapElement->properties.scenery.colour_1 & 0x1F) << 19) | 0x20000000; if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { image_id |= ((mapElement->properties.scenery.colour_2 & 0x1F) << 24) | 0x80000000; } } if (dword_F64EB0 != 0) { image_id = (image_id & 0x7FFFF) | dword_F64EB0; } if (entry->small_scenery.flags & SMALL_SCENERY_FLAG21) { sub_98197C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } else { sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, rotation); } } } }
/** * * rct2: 0x006EDE88 */ sint32 viewport_interaction_get_item_right(sint32 x, sint32 y, viewport_interaction_info *info) { rct_tile_element *tileElement; rct_scenery_entry *sceneryEntry; rct_banner *banner; Ride *ride; sint32 i, stationIndex; // No click input for title screen or track manager if (gScreenFlags & (SCREEN_FLAGS_TITLE_DEMO | SCREEN_FLAGS_TRACK_MANAGER)) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; // if ((gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) && gS6Info.editor_step != EDITOR_STEP_ROLLERCOASTER_DESIGNER) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; LocationXY16 mapCoord = {}; get_map_coordinates_from_pos(x, y, ~(VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER), &mapCoord.x, &mapCoord.y, &info->type, &info->tileElement, nullptr); info->x = mapCoord.x; info->y = mapCoord.y; tileElement = info->tileElement; switch (info->type) { case VIEWPORT_INTERACTION_ITEM_SPRITE: if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || tileElement->type != 0) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; tileElement += 6; ride = get_ride(tileElement->type); if (ride->status == RIDE_STATUS_CLOSED) { set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY); set_map_tooltip_format_arg(2, rct_string_id, ride->name); set_map_tooltip_format_arg(4, uint32, ride->name_arguments); } return info->type; case VIEWPORT_INTERACTION_ITEM_RIDE: if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; ride = get_ride(tile_element_get_ride_index(tileElement)); if (ride->status != RIDE_STATUS_CLOSED) return info->type; set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY); if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE) { rct_string_id stringId; if (tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_ENTRANCE) { if (ride->num_stations > 1) { stringId = STR_RIDE_STATION_X_ENTRANCE; } else { stringId = STR_RIDE_ENTRANCE; } } else { if (ride->num_stations > 1) { stringId = STR_RIDE_STATION_X_EXIT; } else { stringId = STR_RIDE_EXIT; } } set_map_tooltip_format_arg(2, rct_string_id, stringId); } else if (track_element_is_station(tileElement)) { rct_string_id stringId; if (ride->num_stations > 1) { stringId = STR_RIDE_STATION_X; } else { stringId = STR_RIDE_STATION; } set_map_tooltip_format_arg(2, rct_string_id, stringId); } else { if (!gCheatsSandboxMode && !map_is_location_owned(info->x, info->y, tileElement->base_height << 4)) { return info->type = VIEWPORT_INTERACTION_ITEM_NONE; } set_map_tooltip_format_arg(2, rct_string_id, ride->name); set_map_tooltip_format_arg(4, uint32, ride->name_arguments); return info->type; } set_map_tooltip_format_arg(4, rct_string_id, ride->name); set_map_tooltip_format_arg(6, uint32, ride->name_arguments); set_map_tooltip_format_arg(10, rct_string_id, RideComponentNames[RideNameConvention[ride->type].station].capitalised); stationIndex = tile_element_get_station(tileElement); for (i = stationIndex; i >= 0; i--) if (ride->station_starts[i].xy == RCT_XY8_UNDEFINED) stationIndex--; stationIndex++; set_map_tooltip_format_arg(12, uint16, stationIndex); return info->type; case VIEWPORT_INTERACTION_ITEM_WALL: sceneryEntry = get_wall_entry(tileElement->properties.scenery.type); if (sceneryEntry->wall.scrolling_mode != 255) { set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY); set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); return info->type; } break; case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY: sceneryEntry = get_large_scenery_entry(scenery_large_get_type(tileElement)); if (sceneryEntry->large_scenery.scrolling_mode != 255) { set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY); set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); return info->type; } break; case VIEWPORT_INTERACTION_ITEM_BANNER: banner = &gBanners[tileElement->properties.banner.index]; sceneryEntry = get_banner_entry(banner->type); set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_MODIFY); set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); return info->type; } if (!(input_test_flag(INPUT_FLAG_6)) || !(input_test_flag(INPUT_FLAG_TOOL_ACTIVE))) { if (window_find_by_class(WC_RIDE_CONSTRUCTION) == nullptr && window_find_by_class(WC_FOOTPATH) == nullptr) { return info->type = VIEWPORT_INTERACTION_ITEM_NONE; } } switch (info->type) { case VIEWPORT_INTERACTION_ITEM_SCENERY: sceneryEntry = get_small_scenery_entry(tileElement->properties.scenery.type); set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_REMOVE); set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); return info->type; case VIEWPORT_INTERACTION_ITEM_FOOTPATH: set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_REMOVE); set_map_tooltip_format_arg(2, rct_string_id, STR_FOOTPATH_MAP_TIP); if (footpath_element_is_queue(tileElement)) set_map_tooltip_format_arg(2, rct_string_id, STR_QUEUE_LINE_MAP_TIP); return info->type; case VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM: sceneryEntry = get_footpath_item_entry(footpath_element_get_path_scenery_index(tileElement)); set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_REMOVE); if (tileElement->flags & TILE_ELEMENT_FLAG_BROKEN) { set_map_tooltip_format_arg(2, rct_string_id, STR_BROKEN); set_map_tooltip_format_arg(4, rct_string_id, sceneryEntry->name); } else { set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); } return info->type; case VIEWPORT_INTERACTION_ITEM_PARK: if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) break; if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) break; set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_REMOVE); set_map_tooltip_format_arg(2, rct_string_id, STR_OBJECT_SELECTION_PARK_ENTRANCE); return info->type; case VIEWPORT_INTERACTION_ITEM_WALL: sceneryEntry = get_wall_entry(tileElement->properties.scenery.type); set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_REMOVE); set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); return info->type; case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY: sceneryEntry = get_large_scenery_entry(tileElement->properties.scenery.type & 0x3FF); set_map_tooltip_format_arg(0, rct_string_id, STR_MAP_TOOLTIP_STRINGID_CLICK_TO_REMOVE); set_map_tooltip_format_arg(2, rct_string_id, sceneryEntry->name); return info->type; } return info->type = VIEWPORT_INTERACTION_ITEM_NONE; }