diff --git a/src/world/map.c b/src/world/map.c index 477ffb93d9..3110ce24b4 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1582,6 +1582,20 @@ const uint8 map_element_lower_styles[5][32] = { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0D, 0x0E, 0x00 }, }; +/** + * + * rct2: 0x00663CB9 + */ +int map_set_land_height_clear_func(rct_map_element** map_element) { + if (map_element_get_type(*map_element) == MAP_ELEMENT_TYPE_SURFACE) + return 0; + + if (map_element_get_type(*map_element) == MAP_ELEMENT_TYPE_SCENERY) + return 0; + + return 1; +} + static money32 map_set_land_height(int flags, int x, int y, int height, int style, int selectionType) { if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { @@ -1722,7 +1736,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } - if(map_can_construct_with_clear_at(x, y, height, zCorner, RCT2_ADDRESS(0x663CB9, void), 0xF) == false) + if(map_can_construct_with_clear_at(x, y, height, zCorner, &map_set_land_height_clear_func, 0xF) == false) return MONEY32_UNDEFINED; mapElement = map_get_first_element_at(x / 32, y / 32); @@ -2772,6 +2786,52 @@ void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, *ebx = MONEY32_UNDEFINED; } +/** + * + * rct2: 0x006E0D6E + */ +int map_place_scenery_clear_func(rct_map_element** map_element) { + if (map_element_get_type(*map_element) != MAP_ELEMENT_TYPE_SCENERY) + return 1; + + // Change so that hack is not required + uint8* ebp = RCT2_GLOBAL(0x00F64F1E, uint8*); + + if (!(ebp[4] & (1 << 7))) + return 1; + + rct_scenery_entry* scenery = g_smallSceneryEntries[(*map_element)->properties.scenery.type]; + + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) { + if (scenery->small_scenery.height > 64) + return 1; + } + + money32 price = scenery->small_scenery.removal_price * 10; + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) + price = 0; + + RCT2_GLOBAL(0x00F64F26, money32) += price; + + if (ebp[4] & (1 << 6)) + return 0; + + if (!(ebp[4] & (1 << 0))) + return 0; + + rct_xy16 location = { + .x = RCT2_GLOBAL(0x00F64F22, sint16), + .y = RCT2_GLOBAL(0x00F64F24, uint16) + }; + + map_invalidate_tile(location.x, location.y, (*map_element)->base_height * 8, (*map_element)->clearance_height * 8); + + map_element_remove(*map_element); + + (*map_element)--; + return 0; +} + /** * * rct2: 0x006E08F4 @@ -2787,6 +2847,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi uint8 scenery_type = *ebx >> 8; uint8 quadrant = *edx; uint8 color1 = *edx >> 8; + RCT2_GLOBAL(0x00F64F26, money32) = 0; int F64F1D = 0; int F64EC8 = z; int base_height = map_element_height(x, y); @@ -2908,7 +2969,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi RCT2_GLOBAL(0x00F64F22, uint16) = x; RCT2_GLOBAL(0x00F64F24, uint16) = y; RCT2_GLOBAL(0x00F64F1E, uint32) = (uint32)(ebx - 1); //0x006E0D6E uses [F64F1E+4] to read ebx value - if(gCheatsDisableClearanceChecks || map_can_construct_with_clear_at(x, y, zLow, zHigh, (void*)0x006E0D6E, bl)){ + if(gCheatsDisableClearanceChecks || map_can_construct_with_clear_at(x, y, zLow, zHigh, &map_place_scenery_clear_func, bl)){ RCT2_GLOBAL(0x00F64F14, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x3; if(*ebx & GAME_COMMAND_FLAG_APPLY){ if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { @@ -2941,7 +3002,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi map_animation_create(2, x, y, new_map_element->base_height); } } - *ebx = (scenery_entry->small_scenery.price * 10); + *ebx = (scenery_entry->small_scenery.price * 10) + RCT2_GLOBAL(0x00F64F26, money32); if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ *ebx = 0; } @@ -3961,9 +4022,9 @@ static void map_obstruction_set_error_text(rct_map_element *mapElement) * ebp = clearFunc * bl = bl */ -int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl) +int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl) { - RCT2_GLOBAL(0x00F1AD40, void*) = clearFunc; + RCT2_GLOBAL(0x00F1AD40, CLEAR_FUNC*) = clearFunc; RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) = 1; if (x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16) || x < 32 || y < 32) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_OFF_EDGE_OF_MAP; @@ -4037,7 +4098,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle loc_68BABC: if (RCT2_GLOBAL(0x00F1AD40, void*) != (void*)0xFFFFFFFF) { int zero = 0; - if (!(RCT2_CALLFUNC_X((int)RCT2_GLOBAL(0x00F1AD40, void*), &zero, &zero, &zero, &zero, (int*)&map_element, &zero, &zero) & 0x100)) { + if (!clearFunc(&map_element)) { continue; } } @@ -4048,7 +4109,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle loc_68BAE6: if (RCT2_GLOBAL(0x00F1AD40, void*) != (void*)0xFFFFFFFF) { int zero = 0; - if (!(RCT2_CALLFUNC_X((int)RCT2_GLOBAL(0x00F1AD40, void*), &zero, &zero, &zero, &zero, (int*)&map_element, &zero, &zero) & 0x100)) { + if (!clearFunc(&map_element)) { goto loc_68B9B7; } } diff --git a/src/world/map.h b/src/world/map.h index ccb4408bc4..4803dc0a61 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -311,7 +311,9 @@ void map_invalidate_selection_rect(); void map_reorganise_elements(); int sub_68B044(); rct_map_element *map_element_insert(int x, int y, int z, int flags); -int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl); + +typedef int (CLEAR_FUNC)(rct_map_element** map_element); +int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl); int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void rotate_map_coordinates(sint16 *x, sint16 *y, int rotation); rct_xy16 coordinate_3d_to_2d(const rct_xyz16* coordinate_3d, int rotation);