From f6797181b5b13ff4bc1af519ca82af94731506f7 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 13 Feb 2016 13:10:55 +0000 Subject: [PATCH 1/4] Start implementing clear_funcs --- src/world/map.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----- src/world/map.h | 4 ++- 2 files changed, 71 insertions(+), 8 deletions(-) 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); From 305ae76346a02be0c0b9fa1a60f32c0981de6f1c Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 13 Feb 2016 20:26:22 +0000 Subject: [PATCH 2/4] Implement clear funcs for remaining functions --- src/ride/ride.c | 48 ++++++++++++++++++++++- src/ride/track.c | 90 +++++++++++++++++++++++++++++++++++++++++++- src/world/footpath.c | 47 ++++++++++++++++++++++- src/world/map.c | 54 ++++++++++++++++++++++++-- 4 files changed, 229 insertions(+), 10 deletions(-) diff --git a/src/ride/ride.c b/src/ride/ride.c index 439e45b275..b9255ef503 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -45,6 +45,7 @@ #include "../world/map.h" #include "../world/map_animation.h" #include "../world/sprite.h" +#include "../world/scenery.h" #include "cable_lift.h" #include "ride.h" #include "ride_data.h" @@ -7621,6 +7622,49 @@ static void maze_entrance_hedge_replacement(int x, int y, rct_map_element *mapEl } while (!map_element_is_last_for_tile(mapElement++)); } +/** + * + * rct2: 0x0066637E + */ +int place_entrance_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(0x009E32C8, uint8*); + + 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(0x009E32B8, money32) += price; + + if (ebp[4] & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(ebp[4] & GAME_COMMAND_FLAG_APPLY)) + return 0; + + rct_xy16 location = { + .x = RCT2_GLOBAL(0x009E32C4, sint16), + .y = RCT2_GLOBAL(0x009E32C6, sint16) + }; + + 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; +} + money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 direction, uint8 flags, uint8 rideIndex, uint8 station_num, uint8 is_exit) { // Remember when in Unknown station num mode rideIndex is unknown and z is set @@ -7655,7 +7699,7 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio // Horrible hack until map_can_construct_with_clear_at is implemented. RCT2_GLOBAL(0x009E32C8, uint8*) = (&flags) - 4; - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, (void*)0x0066637E, 0xF)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &place_entrance_clear_func, 0xF)) { return MONEY32_UNDEFINED; } @@ -7758,7 +7802,7 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio // Horrible hack until map_can_construct_with_clear_at is implemented. RCT2_GLOBAL(0x009E32C8, uint8*) = (&flags) - 4; - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, (void*)0x0066637E, 0xF)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &place_entrance_clear_func, 0xF)) { return MONEY32_UNDEFINED; } diff --git a/src/ride/track.c b/src/ride/track.c index 3f604f5d93..6f12d743b5 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3395,6 +3395,49 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int *edi = rideIndex; } +/** + * + * rct2: 0x006CDE57 + */ +int place_maze_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(0x00F4412F, uint8*); + + 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(0x00F4413E, money32) += price; + + if (ebp[12] & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(ebp[12] & GAME_COMMAND_FLAG_APPLY)) + return 0; + + rct_xy16 location = { + .x = RCT2_GLOBAL(0x00F4412B, sint16), + .y = RCT2_GLOBAL(0x00F4412D, sint16) + }; + + 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; +} + money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 x, sint16 y, sint16 z) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; @@ -3458,7 +3501,7 @@ money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 RCT2_GLOBAL(0x00F4412D, uint16) = fy; RCT2_GLOBAL(0x00F4412F, uint8*) = stack_F4412F; RCT2_GLOBAL(0x00F4413E, money32) = 0; - if (!map_can_construct_with_clear_at(fx, fy, fz0, fz1, (void*)0x006CDE57, 15)) { + if (!map_can_construct_with_clear_at(fx, fy, fz0, fz1, &place_maze_clear_func, 15)) { return MONEY32_UNDEFINED; } @@ -4088,6 +4131,49 @@ static bool sub_6C4D89(int x, int y, int z, int direction, int rideIndex, int fl return !(RCT2_CALLPROC_X(0x006C4D89, x, flags | (rideIndex << 8), y, z | (direction << 8), 0, 0, 0) & 0x100); } +/** + * + * rct2: 0x006C5A4F + */ +int place_track_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(0x00F44060, uint8*); + + 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(ebp, money32) += price; + + if (ebp[20] & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(ebp[20] & GAME_COMMAND_FLAG_APPLY)) + return 0; + + rct_xy16 location = { + .x = RCT2_GLOBAL(0x00F440A2, sint16), + .y = RCT2_GLOBAL(0x00F440A4, sint16) + }; + + 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; +} + static money32 track_place(int rideIndex, int type, int originX, int originY, int originZ, int direction, int properties_1, int properties_2, int properties_3, int edx_flags, int flags) { rct_ride *ride = get_ride(rideIndex); @@ -4300,7 +4386,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in RCT2_GLOBAL(0x00F44060, void*) = &clearance_struct; if (!gCheatsDisableClearanceChecks || flags & GAME_COMMAND_FLAG_GHOST){ - if (!map_can_construct_with_clear_at(x, y, baseZ, clearanceZ, (void*)0x006C5A5F, bl)) + if (!map_can_construct_with_clear_at(x, y, baseZ, clearanceZ, &place_track_clear_func, bl)) return MONEY32_UNDEFINED; } // Again when 0x006C5A5F implemented remove this. diff --git a/src/world/footpath.c b/src/world/footpath.c index 0d5301738f..d5d8e6b1dd 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -137,6 +137,49 @@ static void loc_6A6620(int flags, int x, int y, rct_map_element *mapElement) map_invalidate_tile_full(x, y); } +/** + * + * rct2: 0x006A6733 + */ +int footpath_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(0x00F3EF7C, uint8*); + + 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(0x00F3EFD9, money32) += price; + + if (ebp[8] & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(ebp[8] & GAME_COMMAND_FLAG_APPLY)) + return 0; + + rct_xy16 location = { + .x = RCT2_GLOBAL(0x00F3EF84, sint16), + .y = RCT2_GLOBAL(0x00F3EF86, sint16) + }; + + 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; +} + static money32 footpath_element_insert(int type, int x, int y, int z, int slope, int flags, uint8 pathItemType) { rct_map_element *mapElement; @@ -165,7 +208,7 @@ static money32 footpath_element_insert(int type, int x, int y, int z, int slope, // 0x006A6733 expects the flags to be at (*0xF3EF7C) + 8 RCT2_GLOBAL(0x00F3EF7C, uint32) = (uint32)(&flags - 2); - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, (void*)0x006A6733, bl)) + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &footpath_clear_func, bl)) return MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); @@ -500,7 +543,7 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop // 0x006A6733 expects the flags to be at (*0xF3EF7C) + 8 RCT2_GLOBAL(0x00F3EF7C, uint32) = (uint32)(&flags - 2); - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, (void*)0x006A6733, bl)) + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &footpath_clear_func, bl)) return MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); diff --git a/src/world/map.c b/src/world/map.c index 3110ce24b4..9cced02f35 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -2797,7 +2797,7 @@ int map_place_scenery_clear_func(rct_map_element** map_element) { // Change so that hack is not required uint8* ebp = RCT2_GLOBAL(0x00F64F1E, uint8*); - if (!(ebp[4] & (1 << 7))) + if (!(ebp[4] & GAME_COMMAND_FLAG_7)) return 1; rct_scenery_entry* scenery = g_smallSceneryEntries[(*map_element)->properties.scenery.type]; @@ -2813,10 +2813,10 @@ int map_place_scenery_clear_func(rct_map_element** map_element) { RCT2_GLOBAL(0x00F64F26, money32) += price; - if (ebp[4] & (1 << 6)) + if (ebp[4] & GAME_COMMAND_FLAG_GHOST) return 0; - if (!(ebp[4] & (1 << 0))) + if (!(ebp[4] & GAME_COMMAND_FLAG_APPLY)) return 0; rct_xy16 location = { @@ -3472,6 +3472,52 @@ money32 map_place_fence( return ebx; } +/** + * + * rct2: 0x006B8D88 + */ +int map_place_large_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(0x00F43896, uint8*); + + if (!(ebp[12] & GAME_COMMAND_FLAG_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[12] & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(ebp[12] & GAME_COMMAND_FLAG_APPLY)) + return 0; + + rct_xy16 location = { + .x = RCT2_GLOBAL(0x00F43892, sint16), + .y = RCT2_GLOBAL(0x00F43894, sint16) + }; + + 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: 0x006B893C @@ -3616,7 +3662,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in RCT2_GLOBAL(0x00F43892, sint16) = curTile.x; RCT2_GLOBAL(0x00F43894, sint16) = curTile.y; RCT2_GLOBAL(0x00F43896, uint32) = (uint32)(ebx - 3); // this is how ebx flags var is passed to 0x006B8D88 - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(curTile.x, curTile.y, zLow, zHigh, (void*)0x006B8D88, bl)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(curTile.x, curTile.y, zLow, zHigh, &map_place_large_scenery_clear_func, bl)) { *ebx = MONEY32_UNDEFINED; return; } From 9c3055224d7f16f8ad92a3a2a7bc47d820f75e86 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 13 Feb 2016 21:01:36 +0000 Subject: [PATCH 3/4] Refactor clear funcs --- src/ride/ride.c | 59 +------------------ src/ride/track.c | 116 ++----------------------------------- src/world/footpath.c | 61 +------------------- src/world/map.c | 133 ++++++++++++++++++------------------------- src/world/map.h | 5 +- 5 files changed, 68 insertions(+), 306 deletions(-) diff --git a/src/ride/ride.c b/src/ride/ride.c index b9255ef503..6dbd2ece77 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -7622,49 +7622,6 @@ static void maze_entrance_hedge_replacement(int x, int y, rct_map_element *mapEl } while (!map_element_is_last_for_tile(mapElement++)); } -/** - * - * rct2: 0x0066637E - */ -int place_entrance_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(0x009E32C8, uint8*); - - 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(0x009E32B8, money32) += price; - - if (ebp[4] & GAME_COMMAND_FLAG_GHOST) - return 0; - - if (!(ebp[4] & GAME_COMMAND_FLAG_APPLY)) - return 0; - - rct_xy16 location = { - .x = RCT2_GLOBAL(0x009E32C4, sint16), - .y = RCT2_GLOBAL(0x009E32C6, sint16) - }; - - 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; -} - money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 direction, uint8 flags, uint8 rideIndex, uint8 station_num, uint8 is_exit) { // Remember when in Unknown station num mode rideIndex is unknown and z is set @@ -7693,13 +7650,8 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio } sint16 clear_z = z / 8 + (is_exit ? 5 : 7); - RCT2_GLOBAL(0x009E32C4, sint16) = x; - RCT2_GLOBAL(0x009E32C6, sint16) = y; - - // Horrible hack until map_can_construct_with_clear_at is implemented. - RCT2_GLOBAL(0x009E32C8, uint8*) = (&flags) - 4; - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &place_entrance_clear_func, 0xF)) { + + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, RCT2_ADDRESS(0x009E32B8, money32))) { return MONEY32_UNDEFINED; } @@ -7796,13 +7748,8 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio } sint8 clear_z = (z / 8) + (is_exit ? 5 : 7); - RCT2_GLOBAL(0x009E32C4, sint16) = x; - RCT2_GLOBAL(0x009E32C6, sint16) = y; - // Horrible hack until map_can_construct_with_clear_at is implemented. - RCT2_GLOBAL(0x009E32C8, uint8*) = (&flags) - 4; - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &place_entrance_clear_func, 0xF)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, RCT2_ADDRESS(0x009E32B8, money32))) { return MONEY32_UNDEFINED; } diff --git a/src/ride/track.c b/src/ride/track.c index 6f12d743b5..2f26e4dcf6 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3395,56 +3395,12 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int *edi = rideIndex; } -/** - * - * rct2: 0x006CDE57 - */ -int place_maze_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(0x00F4412F, uint8*); - - 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(0x00F4413E, money32) += price; - - if (ebp[12] & GAME_COMMAND_FLAG_GHOST) - return 0; - - if (!(ebp[12] & GAME_COMMAND_FLAG_APPLY)) - return 0; - - rct_xy16 location = { - .x = RCT2_GLOBAL(0x00F4412B, sint16), - .y = RCT2_GLOBAL(0x00F4412D, sint16) - }; - - 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; -} - money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 x, sint16 y, sint16 z) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, sint16) = x + 8; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, sint16) = y + 8; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, sint16) = z; - RCT2_GLOBAL(0x00F4413E, uint32) = 0; if (!sub_68B044()) { return MONEY32_UNDEFINED; } @@ -3487,6 +3443,7 @@ money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 } } + money32 cost = 0; // Clearance checks if (!gCheatsDisableClearanceChecks) { int fx = floor2(x, 32); @@ -3494,14 +3451,7 @@ money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 int fz0 = z >> 3; int fz1 = fz0 + 4; - uint8 stack_F4412F[13]; - stack_F4412F[0x0C] = flags; - - RCT2_GLOBAL(0x00F4412B, uint16) = fx; - RCT2_GLOBAL(0x00F4412D, uint16) = fy; - RCT2_GLOBAL(0x00F4412F, uint8*) = stack_F4412F; - RCT2_GLOBAL(0x00F4413E, money32) = 0; - if (!map_can_construct_with_clear_at(fx, fy, fz0, fz1, &place_maze_clear_func, 15)) { + if (!map_can_construct_with_clear_at(fx, fy, fz0, fz1, &map_place_non_scenery_clear_func, 15, flags, &cost)) { return MONEY32_UNDEFINED; } @@ -3525,6 +3475,8 @@ money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 price = (price >> 17) * 10; } + cost += price; + if (flags & GAME_COMMAND_FLAG_APPLY) { if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { rct_xyz16 coord; @@ -3558,7 +3510,7 @@ money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 } } - return price; + return cost; } /** @@ -4131,49 +4083,6 @@ static bool sub_6C4D89(int x, int y, int z, int direction, int rideIndex, int fl return !(RCT2_CALLPROC_X(0x006C4D89, x, flags | (rideIndex << 8), y, z | (direction << 8), 0, 0, 0) & 0x100); } -/** - * - * rct2: 0x006C5A4F - */ -int place_track_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(0x00F44060, uint8*); - - 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(ebp, money32) += price; - - if (ebp[20] & GAME_COMMAND_FLAG_GHOST) - return 0; - - if (!(ebp[20] & GAME_COMMAND_FLAG_APPLY)) - return 0; - - rct_xy16 location = { - .x = RCT2_GLOBAL(0x00F440A2, sint16), - .y = RCT2_GLOBAL(0x00F440A4, sint16) - }; - - 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; -} - static money32 track_place(int rideIndex, int type, int originX, int originY, int originZ, int direction, int properties_1, int properties_2, int properties_3, int edx_flags, int flags) { rct_ride *ride = get_ride(rideIndex); @@ -4374,23 +4283,10 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in _currentTrackEndX = x; _currentTrackEndY = y; - // Until 0x006C5A5F is implemented use this hacky struct. - struct{ - money32 cost; //0 - uint8 pad[0x10];//4 - uint8 flags;//14 - } clearance_struct; - clearance_struct.cost = cost; - clearance_struct.flags = flags; - - RCT2_GLOBAL(0x00F44060, void*) = &clearance_struct; - if (!gCheatsDisableClearanceChecks || flags & GAME_COMMAND_FLAG_GHOST){ - if (!map_can_construct_with_clear_at(x, y, baseZ, clearanceZ, &place_track_clear_func, bl)) + if (!map_can_construct_with_clear_at(x, y, baseZ, clearanceZ, &map_place_non_scenery_clear_func, bl, flags, &cost)) return MONEY32_UNDEFINED; } - // Again when 0x006C5A5F implemented remove this. - cost = clearance_struct.cost; //6c53dc // push baseZ and clearanceZ diff --git a/src/world/footpath.c b/src/world/footpath.c index d5d8e6b1dd..ef3ce37feb 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -137,49 +137,6 @@ static void loc_6A6620(int flags, int x, int y, rct_map_element *mapElement) map_invalidate_tile_full(x, y); } -/** - * - * rct2: 0x006A6733 - */ -int footpath_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(0x00F3EF7C, uint8*); - - 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(0x00F3EFD9, money32) += price; - - if (ebp[8] & GAME_COMMAND_FLAG_GHOST) - return 0; - - if (!(ebp[8] & GAME_COMMAND_FLAG_APPLY)) - return 0; - - rct_xy16 location = { - .x = RCT2_GLOBAL(0x00F3EF84, sint16), - .y = RCT2_GLOBAL(0x00F3EF86, sint16) - }; - - 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; -} - static money32 footpath_element_insert(int type, int x, int y, int z, int slope, int flags, uint8 pathItemType) { rct_map_element *mapElement; @@ -201,14 +158,7 @@ static money32 footpath_element_insert(int type, int x, int y, int z, int slope, zHigh += 2; } - RCT2_GLOBAL(0x00F3EF84, uint16) = x; - RCT2_GLOBAL(0x00F3EF86, uint16) = y; - - // Ugh, hack until 0x006A6733 is written - // 0x006A6733 expects the flags to be at (*0xF3EF7C) + 8 - RCT2_GLOBAL(0x00F3EF7C, uint32) = (uint32)(&flags - 2); - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &footpath_clear_func, bl)) + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &map_place_non_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F3EFD9, money32))) return MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); @@ -536,14 +486,7 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop zHigh += 2; } - RCT2_GLOBAL(0x00F3EF84, uint16) = x; - RCT2_GLOBAL(0x00F3EF86, uint16) = y; - - // Ugh, hack until 0x006A6733 is written - // 0x006A6733 expects the flags to be at (*0xF3EF7C) + 8 - RCT2_GLOBAL(0x00F3EF7C, uint32) = (uint32)(&flags - 2); - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &footpath_clear_func, bl)) + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &map_place_non_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F3EFD9, money32))) return MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); diff --git a/src/world/map.c b/src/world/map.c index 9cced02f35..d332bd8867 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1586,7 +1586,7 @@ const uint8 map_element_lower_styles[5][32] = { * * rct2: 0x00663CB9 */ -int map_set_land_height_clear_func(rct_map_element** map_element) { +int map_set_land_height_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price) { if (map_element_get_type(*map_element) == MAP_ELEMENT_TYPE_SURFACE) return 0; @@ -1736,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, &map_set_land_height_clear_func, 0xF) == false) + if(map_can_construct_with_clear_at(x, y, height, zCorner, &map_set_land_height_clear_func, 0xF, 0, NULL) == false) return MONEY32_UNDEFINED; mapElement = map_get_first_element_at(x / 32, y / 32); @@ -2788,16 +2788,13 @@ void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, /** * - * rct2: 0x006E0D6E + * rct2: 0x006E0D6E, 0x006B8D88 */ -int map_place_scenery_clear_func(rct_map_element** map_element) { +int map_place_scenery_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price) { 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] & GAME_COMMAND_FLAG_7)) + if (!(flags & GAME_COMMAND_FLAG_7)) return 1; rct_scenery_entry* scenery = g_smallSceneryEntries[(*map_element)->properties.scenery.type]; @@ -2807,24 +2804,48 @@ int map_place_scenery_clear_func(rct_map_element** map_element) { return 1; } - money32 price = scenery->small_scenery.removal_price * 10; - if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) - price = 0; + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) + *price += scenery->small_scenery.removal_price * 10; - RCT2_GLOBAL(0x00F64F26, money32) += price; - - if (ebp[4] & GAME_COMMAND_FLAG_GHOST) + if (flags & GAME_COMMAND_FLAG_GHOST) return 0; - if (!(ebp[4] & GAME_COMMAND_FLAG_APPLY)) + if (!(flags & GAME_COMMAND_FLAG_APPLY)) return 0; - rct_xy16 location = { - .x = RCT2_GLOBAL(0x00F64F22, sint16), - .y = RCT2_GLOBAL(0x00F64F24, uint16) - }; + map_invalidate_tile(x, y, (*map_element)->base_height * 8, (*map_element)->clearance_height * 8); - 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: 0x006C5A4F, 0x006CDE57, 0x006A6733, 0x0066637E + */ +int map_place_non_scenery_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price) { + if (map_element_get_type(*map_element) != MAP_ELEMENT_TYPE_SCENERY) + 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; + } + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) + *price += scenery->small_scenery.removal_price * 10; + + if (flags & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) + return 0; + + map_invalidate_tile(x, y, (*map_element)->base_height * 8, (*map_element)->clearance_height * 8); map_element_remove(*map_element); @@ -2845,6 +2866,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi uint8 rotation = *edi; int z = *ebp; uint8 scenery_type = *ebx >> 8; + uint8 flags = *ebx & 0xFF; uint8 quadrant = *edx; uint8 color1 = *edx >> 8; RCT2_GLOBAL(0x00F64F26, money32) = 0; @@ -2895,7 +2917,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi *ebx = MONEY32_UNDEFINED; return; } - if(*ebx & GAME_COMMAND_FLAG_APPLY && !(*ebx & 0x40)){ + if(flags & GAME_COMMAND_FLAG_APPLY && !(flags & 0x40)){ footpath_remove_litter(x, y, F64EC8); if(!gCheatsDisableClearanceChecks && (scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_ALLOW_WALLS)) { map_remove_walls_at(x, y, F64EC8, F64EC8 + scenery_entry->small_scenery.height); @@ -2969,10 +2991,10 @@ 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, &map_place_scenery_clear_func, bl)){ + if(gCheatsDisableClearanceChecks || map_can_construct_with_clear_at(x, y, zLow, zHigh, &map_place_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F64F26, money32))){ 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)) { + if(flags & GAME_COMMAND_FLAG_APPLY){ + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { rct_xyz16 coord; coord.x = x + 16; coord.y = y + 16; @@ -2994,7 +3016,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi if(z != 0){ new_map_element->properties.scenery.colour_1 |= 0x20; } - if(*ebx & 0x40){ + if(flags & 0x40){ new_map_element->flags |= 0x10; } map_invalidate_tile_full(x, y); @@ -3472,52 +3494,6 @@ money32 map_place_fence( return ebx; } -/** - * - * rct2: 0x006B8D88 - */ -int map_place_large_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(0x00F43896, uint8*); - - if (!(ebp[12] & GAME_COMMAND_FLAG_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[12] & GAME_COMMAND_FLAG_GHOST) - return 0; - - if (!(ebp[12] & GAME_COMMAND_FLAG_APPLY)) - return 0; - - rct_xy16 location = { - .x = RCT2_GLOBAL(0x00F43892, sint16), - .y = RCT2_GLOBAL(0x00F43894, sint16) - }; - - 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: 0x006B893C @@ -3662,7 +3638,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in RCT2_GLOBAL(0x00F43892, sint16) = curTile.x; RCT2_GLOBAL(0x00F43894, sint16) = curTile.y; RCT2_GLOBAL(0x00F43896, uint32) = (uint32)(ebx - 3); // this is how ebx flags var is passed to 0x006B8D88 - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(curTile.x, curTile.y, zLow, zHigh, &map_place_large_scenery_clear_func, bl)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(curTile.x, curTile.y, zLow, zHigh, &map_place_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F4389A, money32))) { *ebx = MONEY32_UNDEFINED; return; } @@ -4068,9 +4044,8 @@ 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, CLEAR_FUNC *clearFunc, uint8 bl) +int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl, uint8 flags, money32 *price) { - 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; @@ -4142,9 +4117,9 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUN continue; } loc_68BABC: - if (RCT2_GLOBAL(0x00F1AD40, void*) != (void*)0xFFFFFFFF) { + if (clearFunc != NULL) { int zero = 0; - if (!clearFunc(&map_element)) { + if (!clearFunc(&map_element, x, y, flags, price)) { continue; } } @@ -4153,9 +4128,9 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUN } return false; loc_68BAE6: - if (RCT2_GLOBAL(0x00F1AD40, void*) != (void*)0xFFFFFFFF) { + if (clearFunc != NULL) { int zero = 0; - if (!clearFunc(&map_element)) { + if (!clearFunc(&map_element, x, y, flags, price)) { goto loc_68B9B7; } } @@ -4175,7 +4150,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUN */ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl) { - return map_can_construct_with_clear_at(x, y, zLow, zHigh, (void*)0xFFFFFFFF, bl); + return map_can_construct_with_clear_at(x, y, zLow, zHigh, NULL, bl, 0, NULL); } /** diff --git a/src/world/map.h b/src/world/map.h index 4803dc0a61..c53728384c 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -312,8 +312,9 @@ void map_reorganise_elements(); int sub_68B044(); rct_map_element *map_element_insert(int x, int y, int z, int flags); -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); +typedef int (CLEAR_FUNC)(rct_map_element** map_element, int x, int y, uint8 flags, money32* price); +int map_place_non_scenery_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price); +int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl, uint8 flags, money32 *price); 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); From 53689349f9221a9c582db2641853ab18b46569f5 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 13 Feb 2016 21:55:00 +0000 Subject: [PATCH 4/4] Fix mistake added in refactor. Also remove redundant global variable setting --- src/world/map.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/world/map.c b/src/world/map.c index d332bd8867..666cb3a4b5 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -2988,9 +2988,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi if(z == 0){ bl |= 0xF0; } - 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, &map_place_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F64F26, money32))){ RCT2_GLOBAL(0x00F64F14, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x3; if(flags & GAME_COMMAND_FLAG_APPLY){ @@ -3001,8 +2999,8 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi coord.z = map_element_height(coord.x, coord.y); network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); } - int flags = (bl & 0xf); - rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, zLow, flags); + int collisionQuadrants = (bl & 0xf); + rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, zLow, collisionQuadrants); RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_MAP_ELEMENT, rct_map_element*) = new_map_element; uint8 type = quadrant << 6; type |= MAP_ELEMENT_TYPE_SCENERY;