diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index cd00f7470a..a025a57d68 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -4296,6 +4296,9 @@ STR_5984 :Blocked paths: STR_5985 :New folder STR_5986 :Type the name of the new folder. STR_5987 :Unable to create folder +STR_5988 :{SMALLFONT}{BLACK}No remaining land rights for sale +STR_5989 :{SMALLFONT}{BLACK}No remaining construction rights for sale +STR_5990 :{SMALLFONT}{BLACK}No remaining land rights or construction rights for sale ############# # Scenarios # diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index f03a065dc5..f82c024184 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -3636,6 +3636,9 @@ enum { STR_FILEBROWSER_ACTION_NEW_FOLDER = 5985, STR_FILEBROWSER_FOLDER_NAME_PROMPT = 5986, STR_UNABLE_TO_CREATE_FOLDER = 5987, + STR_NO_LAND_RIGHTS_FOR_SALE_TIP = 5988, + STR_NO_CONSTRUCTION_RIGHTS_FOR_SALE_TIP = 5989, + STR_NO_LAND_OR_CONSTRUCTION_RIGHTS_FOR_SALE_TIP = 5990, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 diff --git a/src/scenario.c b/src/scenario.c index 5bd2f30e26..0109daa7e6 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -279,6 +279,7 @@ void scenario_begin() date_reset(); duck_remove_all(); park_calculate_size(); + map_count_remaining_land_rights(); staff_reset_stats(); gLastEntranceStyle = RIDE_ENTRANCE_STYLE_PLAIN; memset(gMarketingCampaignDaysLeft, 0, 20); diff --git a/src/windows/land_rights.c b/src/windows/land_rights.c index 3d25524416..129f7e8613 100644 --- a/src/windows/land_rights.c +++ b/src/windows/land_rights.c @@ -208,6 +208,23 @@ static void window_land_rights_invalidate(rct_window *w) window_land_rights_widgets[WIDX_PREVIEW].image = gLandToolSize <= 7 ? SPR_LAND_TOOL_SIZE_0 + gLandToolSize : 0xFFFFFFFF; + + // Disable ownership and/or construction buying functions if there're no tiles left for sale + if (gLandRemainingOwnershipSales == 0) { + w->disabled_widgets |= (1 << WIDX_BUY_LAND_RIGHTS); + window_land_rights_widgets[WIDX_BUY_LAND_RIGHTS].tooltip = STR_NO_LAND_RIGHTS_FOR_SALE_TIP; + } else { + w->disabled_widgets &= ~(1 << WIDX_BUY_LAND_RIGHTS); + window_land_rights_widgets[WIDX_BUY_LAND_RIGHTS].tooltip = STR_BUY_LAND_RIGHTS_TIP; + } + + if (gLandRemainingConstructionSales == 0) { + w->disabled_widgets |= (1 << WIDX_BUY_CONSTRUCTION_RIGHTS); + window_land_rights_widgets[WIDX_BUY_CONSTRUCTION_RIGHTS].tooltip = STR_NO_CONSTRUCTION_RIGHTS_FOR_SALE_TIP; + } else { + w->disabled_widgets &= ~(1 << WIDX_BUY_CONSTRUCTION_RIGHTS); + window_land_rights_widgets[WIDX_BUY_CONSTRUCTION_RIGHTS].tooltip = STR_BUY_CONSTRUCTION_RIGHTS_TIP; + } } static void window_land_rights_paint(rct_window *w, rct_drawpixelinfo *dpi) diff --git a/src/windows/park.c b/src/windows/park.c index 1cca36b76b..5d9b21921c 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -1033,6 +1033,15 @@ static void window_park_entrance_invalidate(rct_window *w) window_park_entrance_widgets[i].bottom = height + 23; height += 24; } + + // Disable land rights button if there's no more construction/ownership for sale + if (gLandRemainingOwnershipSales == 0 && gLandRemainingConstructionSales == 0) { + w->disabled_widgets |= (1 << WIDX_BUY_LAND_RIGHTS); + window_park_entrance_widgets[WIDX_BUY_LAND_RIGHTS].tooltip = STR_NO_LAND_OR_CONSTRUCTION_RIGHTS_FOR_SALE_TIP; + } else { + w->disabled_widgets &= ~(1 << WIDX_BUY_LAND_RIGHTS); + window_park_entrance_widgets[WIDX_BUY_LAND_RIGHTS].tooltip = STR_BUY_LAND_AND_CONSTRUCTION_RIGHTS_TIP; + } } /** diff --git a/src/world/map.c b/src/world/map.c index b35d640e35..aa9ff82ac1 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -119,6 +119,9 @@ money32 gWaterToolRaiseCost; money32 gWaterToolLowerCost; money32 gLandRightsCost; +uint16 gLandRemainingOwnershipSales; +uint16 gLandRemainingConstructionSales; + rct_xyz16 gCommandPosition; uint8 gUnk9E2E28; @@ -394,6 +397,31 @@ void map_init(int size) climate_reset(CLIMATE_WARM); } +/** + * Counts the number of surface tiles that offer land ownership rights for sale, + * but haven't been bought yet. It updates gLandRemainingOwnershipSales and + * gLandRemainingConstructionSales. +*/ +void map_count_remaining_land_rights() +{ + gLandRemainingOwnershipSales = 0; + gLandRemainingConstructionSales = 0; + + for (int x = 0; x <= 255; x++) { + for (int y = 0; y <= 255; y++) { + rct_map_element *element = map_get_surface_element_at(x, y); + + uint8 flags = element->properties.surface.ownership; + + if ((flags & OWNERSHIP_AVAILABLE) && (flags & OWNERSHIP_OWNED) == 0) { + gLandRemainingOwnershipSales++; + } else if ((flags & OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE) && (flags & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) == 0) { + gLandRemainingConstructionSales++; + } + } + } +} + /** * * rct2: 0x0068AFFD diff --git a/src/world/map.h b/src/world/map.h index 6188c2f2e0..4a0afc16f0 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -384,11 +384,15 @@ extern money32 gWaterToolRaiseCost; extern money32 gWaterToolLowerCost; extern money32 gLandRightsCost; +extern uint16 gLandRemainingOwnershipSales; +extern uint16 gLandRemainingConstructionSales; + extern rct_xyz16 gCommandPosition; extern uint8 gUnk9E2E28; void map_init(int size); +void map_count_remaining_land_rights(); void map_update_tile_pointers(); rct_map_element *map_get_first_element_at(int x, int y); void map_set_tile_elements(int x, int y, rct_map_element *elements); diff --git a/src/world/park.c b/src/world/park.c index b724ff0248..a33d644e55 100644 --- a/src/world/park.c +++ b/src/world/park.c @@ -1114,14 +1114,23 @@ int map_buy_land_rights(int x0, int y0, int x1, int y1, int setting, int flags) */ void game_command_buy_land_rights(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { + int flags = *ebx & 0xFFFF; + *ebx = map_buy_land_rights( (*eax & 0xFFFF), (*ecx & 0xFFFF), (*edi & 0xFFFF), (*ebp & 0xFFFF), (*edx & 0xFF00) >> 8, - *ebx & 0xFFFF + flags ); + + // Too expensive to always call in map_buy_land_rights. + // It's already counted when the park is loaded, after + // that it should only be called for user actions. + if (flags & GAME_COMMAND_FLAG_APPLY) { + map_count_remaining_land_rights(); + } }