static money32 BannerRemove(sint16 x, sint16 y, uint8 baseHeight, uint8 direction, uint8 flags) { sint32 z = baseHeight * 8; gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; gCommandPosition.x = x + 16; gCommandPosition.y = y + 16; gCommandPosition.z = z; if (!(flags & GAME_COMMAND_FLAG_GHOST) && game_is_paused() && !gCheatsBuildInPauseMode) { gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } if (!map_can_build_at(x, y, z - 16)) { return MONEY32_UNDEFINED; } // Slight modification to the code so that it now checks height as well // This was causing a bug with banners on two paths stacked. rct_tile_element* tileElement = map_get_banner_element_at(x / 32, y / 32, baseHeight, direction); if (tileElement == nullptr) { return MONEY32_UNDEFINED; } rct_banner *banner = &gBanners[tileElement->properties.banner.index]; rct_scenery_entry *bannerEntry = get_banner_entry(banner->type); money32 refund = 0; if (bannerEntry != nullptr) { refund = -((bannerEntry->banner.price * 3) / 4); } 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); } tile_element_remove_banner_entry(tileElement); map_invalidate_tile_zoom1(x, y, z, z + 32); tile_element_remove(tileElement); } if (gParkFlags & PARK_FLAGS_NO_MONEY) { refund = 0; } return refund; }
/** * * rct2: 0x0068A15E */ void sub_68A15E(sint32 screenX, sint32 screenY, sint16 *x, sint16 *y, sint32 *direction, rct_tile_element **tileElement) { sint16 my_x, my_y; sint32 interactionType; rct_tile_element *myTileElement; rct_viewport *viewport; get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER, &my_x, &my_y, &interactionType, &myTileElement, &viewport); if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) { *x = LOCATION_NULL; return; } sint16 originalZ = 0; if (interactionType == VIEWPORT_INTERACTION_ITEM_WATER) { originalZ = surface_get_water_height(myTileElement) << 4; } LocationXY16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY); LocationXY16 map_pos = { (sint16)(my_x + 16), (sint16)(my_y + 16) }; for (sint32 i = 0; i < 5; i++) { sint16 z = originalZ; if (interactionType != VIEWPORT_INTERACTION_ITEM_WATER) { z = tile_element_height(map_pos.x, map_pos.y); } map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); map_pos.x = Math::Clamp<sint16>(map_pos.x, my_x, my_x + 31); map_pos.y = Math::Clamp<sint16>(map_pos.y, my_y, my_y + 31); } // Determine to which edge the cursor is closest sint32 myDirection; sint32 mod_x = map_pos.x & 0x1F; sint32 mod_y = map_pos.y & 0x1F; if (mod_x < mod_y) { if (mod_x + mod_y < 32) { myDirection = 0; } else { myDirection = 1; } } else { if (mod_x + mod_y < 32) { myDirection = 3; } else { myDirection = 2; } } *x = map_pos.x & ~0x1F; *y = map_pos.y & ~0x1F; if (direction != nullptr) *direction = myDirection; if (tileElement != nullptr) *tileElement = myTileElement; }
static std::vector<paint_session> extract_paint_session(const std::string parkFileName) { core_init(); gOpenRCT2Headless = true; auto context = OpenRCT2::CreateContext(); std::vector<paint_session> sessions; log_info("Starting..."); if (context->Initialise()) { drawing_engine_init(); if (!context->LoadParkFromFile(parkFileName)) { log_error("Failed to load park!"); return {}; } gIntroState = INTRO_STATE_NONE; gScreenFlags = SCREEN_FLAGS_PLAYING; int32_t mapSize = gMapSize; int32_t resolutionWidth = (mapSize * 32 * 2); int32_t resolutionHeight = (mapSize * 32 * 1); resolutionWidth += 8; resolutionHeight += 128; rct_viewport viewport; viewport.x = 0; viewport.y = 0; viewport.width = resolutionWidth; viewport.height = resolutionHeight; viewport.view_width = viewport.width; viewport.view_height = viewport.height; viewport.var_11 = 0; viewport.flags = 0; int32_t customX = (gMapSize / 2) * 32 + 16; int32_t customY = (gMapSize / 2) * 32 + 16; int32_t x = 0, y = 0; int32_t z = tile_element_height(customX, customY) & 0xFFFF; x = customY - customX; y = ((customX + customY) / 2) - z; viewport.view_x = x - ((viewport.view_width) / 2); viewport.view_y = y - ((viewport.view_height) / 2); viewport.zoom = 0; gCurrentRotation = 0; // Ensure sprites appear regardless of rotation reset_all_sprite_quadrant_placements(); rct_drawpixelinfo dpi; dpi.x = 0; dpi.y = 0; dpi.width = resolutionWidth; dpi.height = resolutionHeight; dpi.pitch = 0; dpi.bits = (uint8_t*)malloc(dpi.width * dpi.height); log_info("Obtaining sprite data..."); viewport_render(&dpi, &viewport, 0, 0, viewport.width, viewport.height, &sessions); free(dpi.bits); drawing_engine_dispose(); } log_info("Got %u paint sessions.", std::size(sessions)); return sessions; }
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; }