diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 23aa81e252..3eb265eb3c 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3635,4 +3635,5 @@ STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} STR_5300 :{SMALLFONT}{BLACK}Quick fire staff STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan -STR_5302 :Clear loan \ No newline at end of file +STR_5302 :Clear loan +STR_5303 :Allow building in pause mode diff --git a/src/config.c b/src/config.c index d514091732..1653d10fa7 100644 --- a/src/config.c +++ b/src/config.c @@ -199,6 +199,7 @@ config_property_definition _cheatDefinitions[] = { { offsetof(cheat_configuration, disable_brakes_failure), "disable_brakes_failure", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(cheat_configuration, disable_all_breakdowns), "disable_all_breakdowns", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(cheat_configuration, unlock_all_prices), "unlock_all_prices", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(cheat_configuration, build_in_pause_mode), "build_in_pause_mode", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, }; config_property_definition _twitchDefinitions[] = { diff --git a/src/config.h b/src/config.h index cb75fbbdc5..84b1e76c49 100644 --- a/src/config.h +++ b/src/config.h @@ -156,6 +156,7 @@ typedef struct { uint8 disable_brakes_failure; uint8 disable_all_breakdowns; uint8 unlock_all_prices; + uint8 build_in_pause_mode; } cheat_configuration; typedef struct { diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 7ff6d556e2..5ec188a446 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1018,6 +1018,7 @@ enum { STR_CHEAT_REMOVE_LITTER = 2756, STR_CHEAT_WIN_SCENARIO = 2766, STR_CHEAT_UNLOCK_PRICES = 5157, + STR_CHEAT_BUILD_IN_PAUSE_MODE = 5303, // Rides STR_CHEAT_RENEW_RIDES = 5123, diff --git a/src/ride/ride.c b/src/ride/ride.c index 4a6cc985d4..b46e7f85f6 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -4125,7 +4125,7 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi RCT2_GLOBAL(0x009DEA60, uint16) = y; RCT2_GLOBAL(0x009DEA62, uint16) = z; } - if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8)){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) && !gConfigCheat.build_in_pause_mode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -4471,4 +4471,4 @@ bool ride_is_powered_launched(rct_ride *ride) ride->mode == RIDE_MODE_POWERED_LAUNCH_PASSTROUGH || ride->mode == RIDE_MODE_POWERED_LAUNCH || ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED; -} \ No newline at end of file +} diff --git a/src/ride/track.c b/src/ride/track.c index 290255e600..bc686e0c2e 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -20,6 +20,7 @@ #include "../addresses.h" #include "../audio/audio.h" +#include "../config.h" #include "../game.h" #include "../interface/viewport.h" #include "../localisation/localisation.h" @@ -3181,8 +3182,8 @@ void game_command_place_track(int* eax, int* ebx, int* ecx, int* edx, int* esi, RCT2_GLOBAL(0x009DEA62, sint16) = z; if (!(flags & (1 << 3))){ - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){ - RCT2_GLOBAL(0x00141E9AC, rct_string_id) = 2214; + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + RCT2_GLOBAL(0x00141E9AC, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; } @@ -3426,4 +3427,4 @@ static void track_save_select_nearby_scenery_for_tile(int rideIndex, int cx, int static void track_save_add_map_element(int mapElementSelectType, int x, int y, rct_map_element *mapElement) { RCT2_CALLPROC_X(0x006D2B3C, x, mapElementSelectType, y, (int)mapElement, 0, 0, 0); -} \ No newline at end of file +} diff --git a/src/windows/cheats.c b/src/windows/cheats.c index 9e22b4c0e4..b2c57d2ce0 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -82,7 +82,8 @@ enum WINDOW_CHEATS_WIDGET_IDX { WIDX_FIX_ALL, WIDX_FAST_LIFT_HILL, WIDX_DISABLE_BRAKES_FAILURE, - WIDX_DISABLE_ALL_BREAKDOWNS + WIDX_DISABLE_ALL_BREAKDOWNS, + WIDX_BUILD_IN_PAUSE_MODE }; #pragma region MEASUREMENTS @@ -179,6 +180,7 @@ static rct_widget window_cheats_rides_widgets[] = { { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(8),OHPL(8), STR_CHEAT_410_HILL_LIFT, STR_NONE }, // 410 km/h lift hill { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(6),OHPL(6), STR_CHEAT_DISABLE_BRAKES_FAILURE,STR_NONE }, // Disable brakes failure { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(7),OHPL(7), STR_CHEAT_DISABLE_BREAKDOWNS, STR_NONE }, // Disable all breakdowns + { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(5),OHPL(5), STR_CHEAT_BUILD_IN_PAUSE_MODE, STR_NONE }, // Build in pause mode { WIDGETS_END }, }; @@ -337,7 +339,7 @@ static uint32 window_cheats_page_enabled_widgets[] = { (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_TAB_3) | (1 << WIDX_TAB_4) | (1 << WIDX_HIGH_MONEY) | (1 << WIDX_PARK_ENTRANCE_FEE) | (1 << WIDX_CLEAR_LOAN), (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_TAB_3) | (1 << WIDX_TAB_4) | (1 << WIDX_HAPPY_GUESTS) | (1 << WIDX_TRAM_GUESTS) | (1 << WIDX_NAUSEA_GUESTS) | (1 << WIDX_EXPLODE_GUESTS), (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_TAB_3) | (1 << WIDX_TAB_4) | (1 << WIDX_FREEZE_CLIMATE) | (1 << WIDX_OPEN_CLOSE_PARK) | (1 << WIDX_ZERO_CLEARANCE) | (1 << WIDX_WEATHER_SUN) | (1 << WIDX_WEATHER_THUNDER) | (1 << WIDX_CLEAR_GRASS) | (1 << WIDX_MOWED_GRASS) | (1 << WIDX_WATER_PLANTS) | (1 << WIDX_FIX_VANDALISM) | (1 << WIDX_REMOVE_LITTER) | (1 << WIDX_WIN_SCENARIO) | (1 << WIDX_UNLOCK_ALL_PRICES) | (1 << WIDX_SANDBOX_MODE), - (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_TAB_3) | (1 << WIDX_TAB_4) | (1 << WIDX_RENEW_RIDES) | (1 << WIDX_REMOVE_SIX_FLAGS) | (1 << WIDX_MAKE_DESTRUCTIBLE) | (1 << WIDX_FIX_ALL) | (1 << WIDX_FAST_LIFT_HILL) | (1 << WIDX_DISABLE_BRAKES_FAILURE) | (1 << WIDX_DISABLE_ALL_BREAKDOWNS) + (1 << WIDX_CLOSE) | (1 << WIDX_TAB_1) | (1 << WIDX_TAB_2) | (1 << WIDX_TAB_3) | (1 << WIDX_TAB_4) | (1 << WIDX_RENEW_RIDES) | (1 << WIDX_REMOVE_SIX_FLAGS) | (1 << WIDX_MAKE_DESTRUCTIBLE) | (1 << WIDX_FIX_ALL) | (1 << WIDX_FAST_LIFT_HILL) | (1 << WIDX_DISABLE_BRAKES_FAILURE) | (1 << WIDX_DISABLE_ALL_BREAKDOWNS) | (1 << WIDX_BUILD_IN_PAUSE_MODE) }; static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w); @@ -740,6 +742,10 @@ static void window_cheats_rides_mouseup() config_save_default(); window_invalidate(w); break; + case WIDX_BUILD_IN_PAUSE_MODE: + gConfigCheat.build_in_pause_mode ^= 1; + config_save_default(); + window_invalidate(w); } } @@ -782,6 +788,7 @@ static void window_cheats_invalidate() widget_set_checkbox_value(w, WIDX_FAST_LIFT_HILL, gConfigCheat.fast_lift_hill); widget_set_checkbox_value(w, WIDX_DISABLE_BRAKES_FAILURE, gConfigCheat.disable_brakes_failure); widget_set_checkbox_value(w, WIDX_DISABLE_ALL_BREAKDOWNS, gConfigCheat.disable_all_breakdowns); + widget_set_checkbox_value(w, WIDX_BUILD_IN_PAUSE_MODE, gConfigCheat.build_in_pause_mode); break; } diff --git a/src/windows/new_ride.c b/src/windows/new_ride.c index 0255441f89..8eb74fba1e 100644 --- a/src/windows/new_ride.c +++ b/src/windows/new_ride.c @@ -654,8 +654,9 @@ static void window_new_ride_scrollmousedown() window_scrollmouse_get_registers(w, scrollIndex, x, y); - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) - return; + // Made it impossible to click a ride in pause mode. Since the UI now stays responsive in pause mode, always allow clicking a ride. + /*if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) + return;*/ item = window_new_ride_scroll_get_ride_list_item_at(w, x, y); if (item.type == 255 && item.entry_index == 255) diff --git a/src/windows/track_list.c b/src/windows/track_list.c index 77228d4252..5da75b2c36 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -293,8 +293,9 @@ static void window_track_list_scrollmousedown() if (w->track_list.var_484 & 1) return; - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) - return; + // Made it impossible to click a design in pause mode. Since the UI now stays responsive in pause mode, always allow clicking a design. + /*if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) + return;*/ i = window_track_list_get_list_item_index_from_position(x, y); if (i != -1) @@ -628,4 +629,4 @@ static void window_track_list_scrollpaint() i++; trackDesignItem += 128; } -} \ No newline at end of file +} diff --git a/src/windows/track_place.c b/src/windows/track_place.c index d55cd5f994..f4b71dd56f 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -485,7 +485,7 @@ static void window_track_place_toolupdate() // Get base Z position z = window_track_place_get_base_z(x, y); - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode) { window_track_place_clear_provisional(); // Try increasing Z until a feasible placement is found @@ -630,4 +630,4 @@ static void window_track_place_paint() if (_window_track_place_last_cost != MONEY32_UNDEFINED) if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, 0, &_window_track_place_last_cost); -} \ No newline at end of file +} diff --git a/src/world/footpath.c b/src/world/footpath.c index 04e33da2c4..d9c475515e 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -26,6 +26,7 @@ #include "map.h" #include "scenery.h" #include "../cheats.h" +#include "../config.h" void footpath_interrupt_peeps(int x, int y, int z); @@ -296,7 +297,7 @@ static money32 footpath_place_real(int type, int x, int y, int z, int slope, int RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; RCT2_GLOBAL(0x009DEA62, uint16) = z * 8; - if (!(flags & FOOTPATH_CONSTRUCTION_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(0x009DEA6E, uint8) != 0) { + if (!(flags & FOOTPATH_CONSTRUCTION_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -357,7 +358,7 @@ money32 footpath_remove_real(int x, int y, int z, int flags) RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; RCT2_GLOBAL(0x009DEA62, uint16) = z * 8; - if (!(flags & FOOTPATH_CONSTRUCTION_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(0x009DEA6E, uint8) != 0) { + if (!(flags & FOOTPATH_CONSTRUCTION_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } diff --git a/src/world/map.c b/src/world/map.c index 781f1ba1b3..1a765ddf59 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -34,6 +34,7 @@ #include "park.h" #include "scenery.h" #include "../cheats.h" +#include "../config.h" const rct_xy16 TileDirectionDelta[] = { { -32, 0 }, @@ -651,7 +652,7 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es RCT2_GLOBAL(0x009DEA60, uint32) = y + 16; RCT2_GLOBAL(0x009DEA62, uint32) = base_height * 8; - if (!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + if (!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -711,7 +712,7 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i 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) { + if (!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -843,7 +844,7 @@ void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; RCT2_GLOBAL(0x009DEA62, uint16) = z; - if(!(*ebx & 0x40) && RCT2_GLOBAL(0x009DEA6E, uint8) != 0){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -1319,7 +1320,7 @@ money32 map_change_surface_style(int x0, int y0, int x1, int y1, uint8 surfaceSt money32 cost = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { cost += RCT2_GLOBAL(0x009E32B4, uint32); return (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) ? 0 : cost; } @@ -1437,7 +1438,7 @@ const uint8 map_element_lower_styles[5][32] = { static money32 sub_66397F(int flags, int x, int y, int height, int style, int selectionType) { - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -1809,7 +1810,7 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, uint8 direction = *edx; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; - if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -1865,7 +1866,7 @@ void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, RCT2_GLOBAL(0x009DEA60, uint32) = y + 16; RCT2_GLOBAL(0x009DEA62, uint32) = base_height * 16; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; - if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0){ + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode){ if(sub_68B044() && x < 8192 && y < 8192){ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); int dl = base_height * 2; @@ -1963,7 +1964,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi } RCT2_GLOBAL(0x009DEA5E, uint16) += 16; RCT2_GLOBAL(0x009DEA60, uint16) += 16; - if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0){ + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode){ if(sub_68B044()){ if(RCT2_GLOBAL(0x009D8150, uint8) & 1 || (x <= RCT2_GLOBAL(0x01358836, uint16) && y <= RCT2_GLOBAL(0x01358836, uint16))){ rct_scenery_entry* scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks[scenery_type]; diff --git a/src/world/park.c b/src/world/park.c index f87e239317..f75ec52b63 100644 --- a/src/world/park.c +++ b/src/world/park.c @@ -33,6 +33,7 @@ #include "../world/map.h" #include "park.h" #include "sprite.h" +#include "../config.h" /** * In a difficult guest generation scenario, no guests will be generated if over this value. @@ -1133,7 +1134,7 @@ int map_buy_land_rights(int x0, int y0, int x1, int y1, int setting, int flags) // Game command modified to accept selection size totalCost = 0; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) { + if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode) { for (y = y0; y <= y1; y += 32) { for (x = x0; x <= x1; x += 32) { cost = map_buy_land_rights_for_tile(x, y, setting, flags);