From 305ae76346a02be0c0b9fa1a60f32c0981de6f1c Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sat, 13 Feb 2016 20:26:22 +0000 Subject: [PATCH] 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; }