From 8774731f039a14cd5cdd3513a6bf0e00398a9d5c Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Thu, 22 Jan 2015 00:19:05 +0000 Subject: [PATCH] refactor map element iteration --- src/audio/audio.c | 2 +- src/editor.c | 62 +++++----- src/interface/viewport_interaction.c | 13 +- src/peep/peep.c | 53 ++++----- src/ride/ride.c | 171 ++++++++++++++------------- src/ride/ride_ratings.c | 20 ++-- src/ride/station.c | 19 +-- src/scenario.c | 24 ++-- src/windows/banner.c | 18 +-- src/windows/cheats.c | 61 ++++------ src/windows/footpath.c | 10 +- src/windows/ride.c | 2 +- src/windows/sign.c | 32 +++-- src/world/map.c | 162 +++++++++++++++---------- src/world/map.h | 15 ++- src/world/park.c | 2 +- 16 files changed, 347 insertions(+), 319 deletions(-) diff --git a/src/audio/audio.c b/src/audio/audio.c index b66978f9cb..7d3209617b 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -1431,7 +1431,7 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z) sint16 y2 = y & 0xFFE0; if (x2 < 0x1FFF && y2 < 0x1FFF) { rct_map_element* mapelement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[((y2 * 256 + x2) & 0xFFFF) / 8]; - while (mapelement->type & MAP_ELEMENT_TYPE_MASK) { + while (map_element_get_type(mapelement) != MAP_ELEMENT_TYPE_SURFACE) { mapelement++; } if ((mapelement->base_height * 8) - 5 > z) { diff --git a/src/editor.c b/src/editor.c index 491468d3e7..35f2583ce8 100644 --- a/src/editor.c +++ b/src/editor.c @@ -339,15 +339,15 @@ static void sub_666DFD() x /= 32; y /= 32; - mapElement = TILE_MAP_ELEMENT_POINTER(x + y * 256); + mapElement = map_get_first_element_at(x, y); do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) { mapElement->properties.entrance.path_type = 0; break; } } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); } /** @@ -397,10 +397,10 @@ static void sub_69F06A() */ static void sub_6A2B62() { - int i, x, y; + int i; rct_sprite *sprite; rct_ride *ride; - rct_map_element *mapElement; + map_element_iterator it; RCT2_CALLPROC_EBPSAFE(0x0069F007); @@ -429,37 +429,33 @@ static void sub_6A2B62() RCT2_CALLPROC_EBPSAFE(0x0069F3AB); // Fix paths and remove all ride track / entrance / exit - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - resetElementLoop: - mapElement = TILE_MAP_ELEMENT_POINTER(x + y * 256); - do { - switch (mapElement->type & MAP_ELEMENT_TYPE_MASK) { - case MAP_ELEMENT_TYPE_PATH: - if (mapElement->type & 1) { - mapElement->properties.path.type &= 0xF7; - mapElement->properties.path.addition_status = 255; - } - break; + map_element_iterator_begin(&it); + do { + switch (map_element_get_type(it.element)) { + case MAP_ELEMENT_TYPE_PATH: + if (it.element->type & 1) { + it.element->properties.path.type &= 0xF7; + it.element->properties.path.addition_status = 255; + } + break; - case MAP_ELEMENT_TYPE_TRACK: - RCT2_CALLPROC_EBPSAFE(0x006A7594); - sub_6A6AA7(x * 32, y * 32, mapElement); - map_element_remove(mapElement); - goto resetElementLoop; + case MAP_ELEMENT_TYPE_TRACK: + RCT2_CALLPROC_EBPSAFE(0x006A7594); + sub_6A6AA7(it.x * 32, it.y * 32, it.element); + map_element_remove(it.element); + map_element_iterator_restart_for_tile(&it); + break; - case MAP_ELEMENT_TYPE_ENTRANCE: - if (mapElement->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE) { - RCT2_CALLPROC_EBPSAFE(0x006A7594); - sub_6A6AA7(x * 32, y * 32, mapElement); - map_element_remove(mapElement); - goto resetElementLoop; - } - break; - } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + case MAP_ELEMENT_TYPE_ENTRANCE: + if (it.element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE) { + RCT2_CALLPROC_EBPSAFE(0x006A7594); + sub_6A6AA7(it.x * 32, it.y * 32, it.element); + map_element_remove(it.element); + map_element_iterator_restart_for_tile(&it); + } + break; } - } + } while (map_element_iterator_next(&it)); object_unload_all(); diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index 8e303509a7..5d51a00fab 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -190,7 +190,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info case VIEWPORT_INTERACTION_ITEM_RIDE: if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; ride = GET_RIDE(mapElement->properties.track.ride_index); @@ -199,7 +199,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1163; - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = mapElement->properties.track.type == ENTRANCE_TYPE_RIDE_ENTRANCE ? 1335 : 1337; } else if (mapElement->properties.track.type == 1 || mapElement->properties.track.type == 2 || mapElement->properties.track.type == 3) { @@ -288,7 +288,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info if (!(RCT2_ADDRESS_SCREEN_FLAGS & SCREEN_FLAGS_SCENARIO_EDITOR)) break; - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_ENTRANCE) + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE) break; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1164; @@ -397,13 +397,14 @@ static void viewport_interaction_remove_footpath(rct_map_element *mapElement, in if (w != NULL) sub_6A7831(); - mapElement2 = TILE_MAP_ELEMENT_POINTER((y / 32) * 256 + (x / 32)); + mapElement2 = map_get_first_element_at(x / 32, y / 32); do { - if ((mapElement2->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH && mapElement2->base_height == z) { + if (map_element_get_type(mapElement2) == MAP_ELEMENT_TYPE_PATH && mapElement2->base_height == z) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_REMOVE_FOOTPATH_FROM_HERE; footpath_remove(x, y, z, 1); + break; } - } while (!((mapElement2++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement2++)); } /** diff --git a/src/peep/peep.c b/src/peep/peep.c index f514a77537..e2d326b90c 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -111,8 +111,7 @@ int sub_68F3AE(rct_peep* peep){ peep->var_C4++; if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF))return 1; - uint16 ebx = (peep->next_x | (peep->next_y << 8)) >> 5; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebx); + rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32); uint8 map_type = MAP_ELEMENT_TYPE_PATH; if ((peep->next_z >> 8) & ((1 << 4) | (1 << 3))){ @@ -121,12 +120,11 @@ int sub_68F3AE(rct_peep* peep){ int z = peep->next_z & 0xFF; - for (;; map_element++){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == map_type){ + do { + if (map_element_get_type(map_element) == map_type){ if (z == map_element->base_height)return 1; } - if (map_element->flags & MAP_ELEMENT_FLAG_LAST_TILE)break; - } + } while (!map_element_is_last_for_tile(map_element++)); peep_decrement_num_riders(peep); peep->state = PEEP_STATE_FALLING; @@ -348,15 +346,13 @@ void peep_update_falling(rct_peep* peep){ // If not drowning then falling. Note: peeps 'fall' after leaving a ride/enter the park. - rct_map_element *map_element = TILE_MAP_ELEMENT_POINTER((peep->y / 32) * 256 + (peep->x /32)); + rct_map_element *map_element = map_get_first_element_at(peep->x / 32, peep->y / 32); rct_map_element *saved_map = NULL; int saved_height = 0; - for (int final_element = 0; !final_element; map_element++){ - final_element = map_element->flags & MAP_ELEMENT_FLAG_LAST_TILE; - + do { // If a path check if we are on it - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){ int height = map_height_from_slope(peep->x, peep->y, map_element->properties.surface.slope) + map_element->base_height * 8; @@ -366,7 +362,7 @@ void peep_update_falling(rct_peep* peep){ saved_map = map_element; break; } // If a surface get the height and see if we are on it - else if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SURFACE){ + else if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SURFACE){ // If the surface is water check to see if we could be drowning if (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK){ int height = (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) * 16; @@ -404,7 +400,7 @@ void peep_update_falling(rct_peep* peep){ saved_map = map_element; } // If not a path or surface go see next element else continue; - } + } while (!map_element_is_last_for_tile(map_element++)); // This will be null if peep is falling if (saved_map == NULL){ @@ -699,9 +695,9 @@ static void peep_update_mowing(rct_peep* peep){ if (peep->var_37 != 7)continue; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5); + rct_map_element *map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32); - for (; ((map_element->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE); map_element++); + for (; (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SURFACE); map_element++); if ((map_element->properties.surface.terrain & MAP_ELEMENT_SURFACE_TERRAIN_MASK) == (TERRAIN_GRASS << 5)){ map_element->properties.surface.grass_length = 0; @@ -740,10 +736,10 @@ static void peep_update_watering(rct_peep* peep){ int x = peep->next_x + RCT2_ADDRESS(0x993CCC, sint16)[peep->var_37 * 2]; int y = peep->next_y + RCT2_ADDRESS(0x993CCE, sint16)[peep->var_37 * 2]; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((x | (y << 8)) >> 5); + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); for (;; map_element++){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY){ if (abs((peep->next_z & 0xFF) - map_element->base_height) <= 4){ rct_scenery_entry* scenery_entry = g_smallSceneryEntries[map_element->properties.scenery.type]; @@ -755,7 +751,7 @@ static void peep_update_watering(rct_peep* peep){ } } } - if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){ + if (map_element_is_last_for_tile(map_element)) { peep_state_reset(peep); return; } @@ -794,27 +790,30 @@ static void peep_update_emptying_bin(rct_peep* peep){ if (peep->action_frame != 11)return; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5); + rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32); - for (;; map_element++){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){ - if ((peep->next_z & 0xFF) == map_element->base_height)break; + for (;; map_element++) { + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH) { + if ((peep->next_z & 0xFF) == map_element->base_height) + break; } - if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){ + if (map_element_is_last_for_tile(map_element)) { peep_state_reset(peep); return; } } - if ((map_element->properties.path.additions & 0xF) == 0){ + if ((map_element->properties.path.additions & 0x0F) == 0) { peep_state_reset(peep); return; } rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[(map_element->properties.path.additions & 0xF) - 1]; - if (!(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG1) - || map_element->flags&(1 << 5) - || map_element->properties.path.additions & (1 << 7)){ + if ( + !(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG1) + || map_element->flags & (1 << 5) + || map_element->properties.path.additions & (1 << 7) + ) { peep_state_reset(peep); return; } diff --git a/src/ride/ride.c b/src/ride/ride.c index 10ea7cb8b1..3deadc9142 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -266,47 +266,42 @@ money32 ride_calculate_income_per_hour(rct_ride *ride) */ rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY) { - rct_map_element *resultMapElement, *mapElement; + map_element_iterator it; + rct_map_element *resultMapElement; int foundSpecialTrackPiece; resultMapElement = (rct_map_element*)-1; foundSpecialTrackPiece = 0; - uint16 x, y; - for (x = 0; x < 256; x++) { - for (y = 0; y < 256; y++) { - // Iterate through map elements on tile - int tileIndex = (y << 8) | x; - mapElement = TILE_MAP_ELEMENT_POINTER(tileIndex); - do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK) - continue; - if (rideIndex != mapElement->properties.track.ride_index) - continue; + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_TRACK) + continue; + if (rideIndex != it.element->properties.track.ride_index) + continue; - // Found a track piece for target ride + // Found a track piece for target ride - // Check if its a ??? - int specialTrackPiece = ( - (mapElement->properties.track.type != 2 && mapElement->properties.track.type != 3) && - (RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & 0x10) - ); + // Check if its a ??? + int specialTrackPiece = ( + (it.element->properties.track.type != 2 && it.element->properties.track.type != 3) && + (RCT2_ADDRESS(0x0099BA64, uint8)[it.element->properties.track.type * 16] & 0x10) + ); - // Set result tile to this track piece if first found track or a ??? - if (resultMapElement == (rct_map_element*)-1 || specialTrackPiece) { - resultMapElement = mapElement; + // Set result tile to this track piece if first found track or a ??? + if (resultMapElement == (rct_map_element*)-1 || specialTrackPiece) { + resultMapElement = it.element; - if (outX != NULL) *outX = x * 32; - if (outY != NULL) *outY = y * 32; - } - - if (specialTrackPiece) { - foundSpecialTrackPiece = 1; - return resultMapElement; - } - } while (!(mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE) && mapElement++); + if (outX != NULL) *outX = it.x * 32; + if (outY != NULL) *outY = it.y * 32; } - } + + if (specialTrackPiece) { + foundSpecialTrackPiece = 1; + return resultMapElement; + } + } while (map_element_iterator_next(&it)); + return resultMapElement; } @@ -881,7 +876,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y) ride_remove_peeps(rideIndex); // Check if element is a station entrance or exit - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) return ride_modify_entrance_or_exit(mapElement, x, y); constructionWindow = ride_create_or_find_construction_window(rideIndex); @@ -2031,29 +2026,35 @@ void ride_check_all_reachable() * rct2: 0x006B7C59 * @return 1 if the coordinate is reachable or has no entrance, 0 otherwise */ -static int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index) { - int x = ((coordinate >> 8) & 0xFF) << 5, // cx - y = (coordinate & 0xFF) << 5; // ax - uint8 station_height = ride->station_heights[index]; - int tile_idx = ((x << 8) | y) >> 5; - rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; +static int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index) +{ + int x, y, z; + rct_map_element *mapElement; - while(1) { - uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK; - if (element_type == MAP_ELEMENT_TYPE_ENTRANCE && station_height == tile->base_height) { - break; - } else if (tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) { - return 1; - } - tile++; + x = coordinate & 0xFF; + y = (coordinate >> 8) & 0xFF; + z = ride->station_heights[index]; + mapElement = map_get_first_element_at(x, y); + + for (;;) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height) { + break; + } else if (map_element_is_last_for_tile(mapElement)) { + return 1; + } + mapElement++; } - uint8 face_direction = tile->type & 3; - y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; - x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; - tile_idx = ((x << 8) | y) >> 5; + uint8 face_direction = mapElement->type & 3; - return map_coord_is_connected(tile_idx, station_height, face_direction); + x *= 32; + y *= 32; + x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; + y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; + x /= 32; + y /= 32; + + return map_coord_is_connected(x, y, z, face_direction); } static void ride_entrance_exit_connected(rct_ride* ride, int ride_idx) @@ -2086,64 +2087,66 @@ static void ride_entrance_exit_connected(rct_ride* ride, int ride_idx) static void ride_shop_connected(rct_ride* ride, int ride_idx) { - rct_ride* ride_back = ride; + int x, y, count; + rct_map_element *mapElement; + uint16 coordinate = ride->station_starts[0]; if (coordinate == 0xFFFF) return; - int x = ((coordinate >> 8) & 0xFF) << 5, // cx - y = (coordinate & 0xFF) << 5; // ax + x = (coordinate & 0xFF); + y = (coordinate >> 8) & 0xFF; - rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[coordinate]; - - for (; ; tile++){ - uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK; - if(element_type == MAP_ELEMENT_TYPE_TRACK && tile->properties.track.ride_index == ride_idx) - break; - if(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) - return; - } + mapElement = map_get_first_element_at(x, y); + do { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK && mapElement->properties.track.ride_index == ride_idx) + break; + } while (!map_element_is_last_for_tile(mapElement++)); uint16 entrance_directions = 0; - uint8 track_type = tile->properties.track.type; - ride = &g_ride_list[tile->properties.track.ride_index]; - if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) { + uint8 track_type = mapElement->properties.track.type; + ride = &g_ride_list[mapElement->properties.track.ride_index]; + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) { entrance_directions = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16]; - } else { + } else { entrance_directions = RCT2_ADDRESS(0x0099BA64, uint8)[track_type * 16]; - } + } - - uint8 tile_direction = tile->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 tile_direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; entrance_directions <<= tile_direction; entrance_directions = ((entrance_directions >> 12) | entrance_directions) & 0xF; - // now each bit in entrance_directions stands for an entrance direction to check + // Now each bit in entrance_directions stands for an entrance direction to check if (entrance_directions == 0) return; - for (int count = 0; entrance_directions != 0; ++count) { + // Turn x, y from tiles into units + x *= 32; + y *= 32; + + for (count = 0; entrance_directions != 0; count++) { if (!(entrance_directions & 1)) { entrance_directions >>= 1; - continue; - } + continue; + } entrance_directions >>= 1; - uint8 face_direction = count ^ 2; // flip direction north<->south, east<->west + // Flip direction north<->south, east<->west + uint8 face_direction = count ^ 2; + int y2 = y - RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; int x2 = x - RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; - int tile_idx = ((x2 << 8) | y2) >> 5; - if (map_coord_is_connected(tile_idx, tile->base_height, face_direction)) - return; - } - - // name of ride is parameter of the format string - RCT2_GLOBAL(0x013CE952, uint16) = ride->name; + if (map_coord_is_connected(x2 / 32, y2 / 32, mapElement->base_height, face_direction)) + return; + } + + // Name of ride is parameter of the format string + RCT2_GLOBAL(0x013CE952, uint16) = ride->name; RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments; news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx); - ride->connected_message_throttle = 3; + ride->connected_message_throttle = 3; } #pragma endregion @@ -2242,7 +2245,7 @@ static void ride_entrance_set_map_tooltip(rct_map_element *mapElement) void ride_set_map_tooltip(rct_map_element *mapElement) { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { ride_entrance_set_map_tooltip(mapElement); } else { if ( diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 9a88f57509..0f54794a0b 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -236,11 +236,11 @@ static void ride_ratings_update_state_2() y = RCT2_GLOBAL(0x0138B586, uint16) / 32; z = RCT2_GLOBAL(0x0138B588, uint16) / 8; - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + mapElement = map_get_first_element_at(x, y); trackType = RCT2_GLOBAL(0x0138B592, uint8); do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK) + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; if (mapElement->base_height != z) continue; @@ -271,7 +271,7 @@ static void ride_ratings_update_state_2() RCT2_GLOBAL(0x0138B588, uint16) = z; RCT2_GLOBAL(0x0138B592, uint8) = mapElement->properties.track.type; } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; } @@ -333,11 +333,11 @@ static void ride_ratings_update_state_5() y = RCT2_GLOBAL(0x0138B586, uint16) / 32; z = RCT2_GLOBAL(0x0138B588, uint16) / 8; - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + mapElement = map_get_first_element_at(x, y); trackType = RCT2_GLOBAL(0x0138B592, uint8); do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK) + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; if (mapElement->base_height != z) continue; @@ -363,7 +363,7 @@ static void ride_ratings_update_state_5() RCT2_GLOBAL(0x0138B588, uint16) = z; RCT2_GLOBAL(0x0138B592, uint8) = mapElement->properties.track.type; } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; } @@ -736,15 +736,15 @@ static int ride_ratings_get_scenery_score(rct_ride *ride) for (yy = y - 5; yy <= y + 5; yy++) { for (xx = x - 5; xx <= x + 5; xx++) { // Count scenery items on this tile - mapElement = TILE_MAP_ELEMENT_POINTER(yy * 256 + xx); + mapElement = map_get_first_element_at(xx, yy); do { - if (mapElement->flags & 0x10) + if (mapElement->flags & (1 << 4)) continue; - type = mapElement->type & MAP_ELEMENT_TYPE_MASK; + type = map_element_get_type(mapElement); if (type == MAP_ELEMENT_TYPE_SCENERY || type == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) numSceneryItems++; - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); } } diff --git a/src/ride/station.c b/src/ride/station.c index 398c98892e..d2eec14bdf 100644 --- a/src/ride/station.c +++ b/src/ride/station.c @@ -294,16 +294,13 @@ rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int statio y = ride->station_starts[stationIndex] >> 8; z = ride->station_heights[stationIndex]; - // Get first element of the tile - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); - // Find the station track element + mapElement = map_get_first_element_at(x, y); do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK && z == mapElement->base_height) + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK && z == mapElement->base_height) return mapElement; - mapElement++; - } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); return NULL; } @@ -312,16 +309,12 @@ rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int { rct_map_element *mapElement; - // Get first element of the tile - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); - // Find the station track element + mapElement = map_get_first_element_at(x, y); do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height) + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height) return mapElement; - - mapElement++; - } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); return NULL; } \ No newline at end of file diff --git a/src/scenario.c b/src/scenario.c index 465957c071..81c05be655 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -676,26 +676,22 @@ unsigned int scenario_rand() */ void scenario_prepare_rides_for_save() { - int i, x, y; - rct_map_element *mapElement; + int i; rct_ride *ride; + map_element_iterator it; int isFiveCoasterObjective = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_FINISH_5_ROLLERCOASTERS; // Set all existing track to be indestructible - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); - do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK) { - if (isFiveCoasterObjective) - mapElement->flags |= 0x40; - else - mapElement->flags &= ~0x40; - } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_TRACK) { + if (isFiveCoasterObjective) + it.element->flags |= 0x40; + else + it.element->flags &= ~0x40; } - } + } while (map_element_iterator_next(&it)); // Set all existing rides to have indestructible track FOR_ALL_RIDES(i, ride) { diff --git a/src/windows/banner.c b/src/windows/banner.c index 71ed90e51e..d2facef113 100644 --- a/src/windows/banner.c +++ b/src/windows/banner.c @@ -136,13 +136,15 @@ void window_banner_open(rct_windownumber number) int view_x = gBanners[w->number].x << 5; int view_y = gBanners[w->number].y << 5; - int ebp = ((view_y << 8) | view_x) >> 5; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp); - - while(1){ - if (((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_BANNER) && - (map_element->properties.banner.index == w->number)) break; + rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32); + while(1) { + if ( + (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) && + (map_element->properties.banner.index == w->number) + ) { + break; + } map_element++; } @@ -186,10 +188,10 @@ static void window_banner_mouseup() int x = banner->x << 5; int y = banner->y << 5; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5); + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); while (1){ - if (((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_BANNER) && + if ((map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) && (map_element->properties.banner.index == w->number)) break; map_element++; } diff --git a/src/windows/cheats.c b/src/windows/cheats.c index f41e3682a5..6042dd63dd 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -288,42 +288,32 @@ static void cheat_set_grass_length(int length) static void cheat_water_plants() { - int x, y; - rct_map_element *mapElement; + map_element_iterator it; - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); - do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY) { - mapElement->properties.scenery.age = 0; - } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_SCENERY) { + it.element->properties.scenery.age = 0; } - } + } while (map_element_iterator_next(&it)); gfx_invalidate_screen(); } static void cheat_fix_vandalism() { - int x, y; - rct_map_element *mapElement; + map_element_iterator it; - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); - do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_PATH) - continue; + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) + continue; - if ((mapElement->properties.path.additions & 0x0F) == 0) - continue; + if ((it.element->properties.path.additions & 0x0F) == 0) + continue; - mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN; - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); - } - } + it.element->flags &= ~MAP_ELEMENT_FLAG_BROKEN; + } while (map_element_iterator_next(&it)); gfx_invalidate_screen(); } @@ -685,20 +675,15 @@ void window_cheats_misc_tool_down(){ // in the middle of a tile. dest_x += 16; dest_y += 16; + // Set the tile coordinate to top left of tile - int tile_y = dest_y & 0xFFE0; - int tile_x = dest_x & 0xFFE0; + int tile_x = (dest_x & 0xFFE0) >> 5; + int tile_y = (dest_y & 0xFFE0) >> 5; - ebp = ((tile_y << 8) | tile_x) >> 5; - - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp); - - while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE){ - map_element->clearance_height = 0; + rct_map_element *mapElement = map_get_first_element_at(tile_x, tile_y); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SURFACE) { + mapElement->clearance_height = 0; } - if (map_element->flags & MAP_ELEMENT_FLAG_LAST_TILE) - break; - map_element++; - } + } while (!map_element_is_last_for_tile(mapElement++)); } \ No newline at end of file diff --git a/src/windows/footpath.c b/src/windows/footpath.c index 43fbc96495..67c9790e76 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -728,7 +728,7 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY) if (x == 0x8000) return; - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SURFACE) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SURFACE) { // ? uint8 dl = ((mapElement->properties.surface.slope & 0x0F) << direction) & 0xFF; uint8 dh = dl; @@ -739,7 +739,7 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY) z += 2; } else { z = mapElement->base_height; - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) { if (mapElement->properties.path.type & 4) { if (direction == (mapElement->properties.path.type & 3)) z += 2; @@ -837,9 +837,9 @@ static rct_map_element *footpath_get_map_element_to_remove() z = (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) >> 3) & 0xFF; zLow = z - 2; - mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x]; + mapElement = map_get_first_element_at(x, y); do { - if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) { if (mapElement->base_height == z) { if (mapElement->properties.path.type & 4) if (((mapElement->properties.path.type & 3) ^ 2) != RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8)) @@ -854,7 +854,7 @@ static rct_map_element *footpath_get_map_element_to_remove() return mapElement; } } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); return NULL; } diff --git a/src/windows/ride.c b/src/windows/ride.c index fdb82255de..53e877012c 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -1225,7 +1225,7 @@ rct_window *window_ride_open_track(rct_map_element *mapElement) { int rideIndex = mapElement->properties.track.ride_index; if ( - ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) || + (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) || (RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & 0x10) ) { // Open ride window in station view diff --git a/src/windows/sign.c b/src/windows/sign.c index 49c58b1f19..8f1d4bb90e 100644 --- a/src/windows/sign.c +++ b/src/windows/sign.c @@ -169,12 +169,11 @@ void window_sign_open(rct_windownumber number) int view_x = gBanners[w->number].x << 5; int view_y = gBanners[w->number].y << 5; - int ebp = ((view_y << 8) | view_x) >> 5; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp); + rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32); while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { int ebx = map_element->properties.scenerymultiple.type; ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8; rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx]; @@ -213,7 +212,7 @@ void window_sign_open(rct_windownumber number) view_z, 0, -1 - ); + ); w->viewport->flags = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES) ? VIEWPORT_FLAG_GRIDLINES : 0; w->flags |= WF_2; @@ -234,7 +233,7 @@ static void window_sign_mouseup() rct_string_id string_id; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5); + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); switch (widgetIndex) { case WIDX_CLOSE: @@ -242,7 +241,7 @@ static void window_sign_mouseup() break; case WIDX_SIGN_DEMOLISH: while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { int ebx = map_element->properties.scenerymultiple.type; ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8; rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx]; @@ -320,10 +319,10 @@ static void window_sign_dropdown() int x = banner->x << 5; int y = banner->y << 5; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5); + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { int ebx = map_element->properties.scenerymultiple.type; ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8; rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx]; @@ -499,12 +498,11 @@ void window_sign_small_open(rct_windownumber number){ int view_x = gBanners[w->number].x << 5; int view_y = gBanners[w->number].y << 5; - int ebp = ((view_y << 8) | view_x) >> 5; - - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp); + + rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32); while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_FENCE){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) { rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope]; if (scenery_entry->wall.var_0D != 0xFF){ if (map_element->properties.fence.item[0] == w->number) @@ -538,7 +536,7 @@ void window_sign_small_open(rct_windownumber number){ view_z, 0, -1 - ); + ); w->viewport->flags = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES) ? VIEWPORT_FLAG_GRIDLINES : 0; w->flags |= WF_2; @@ -559,7 +557,7 @@ static void window_sign_small_mouseup() rct_string_id string_id; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5); + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); switch (widgetIndex) { case WIDX_CLOSE: @@ -567,7 +565,7 @@ static void window_sign_small_mouseup() break; case WIDX_SIGN_DEMOLISH: while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_FENCE){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) { rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope]; if (scenery_entry->wall.var_0D != 0xFF){ if (map_element->properties.fence.item[0] == w->number) @@ -626,10 +624,10 @@ static void window_sign_small_dropdown() int x = banner->x << 5; int y = banner->y << 5; - rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5); + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); while (1){ - if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_FENCE){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) { rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope]; if (scenery_entry->wall.var_0D != 0xFF){ if (map_element->properties.fence.item[0] == w->number) diff --git a/src/world/map.c b/src/world/map.c index 508d980c92..3e4f05a509 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -45,6 +45,61 @@ int _sub_6A876D_save_y; static void tiles_init(); static void sub_6A87BB(int x, int y); +void map_element_iterator_begin(map_element_iterator *it) +{ + it->x = 0; + it->y = 0; + it->element = map_get_first_element_at(0, 0); +} + +int map_element_iterator_next(map_element_iterator *it) +{ + if (it->element == NULL) { + it->element = map_get_first_element_at(it->x, it->y); + return 1; + } + + if (!map_element_is_last_for_tile(it->element)) { + it->element++; + return 1; + } + + if (it->x < 255) { + it->x++; + it->element = map_get_first_element_at(it->x, it->y); + return 1; + } + + if (it->y < 255) { + it->x = 0; + it->y++; + it->element = map_get_first_element_at(it->x, it->y); + return 1; + } + + return 0; +} + +void map_element_iterator_restart_for_tile(map_element_iterator *it) +{ + it->element = NULL; +} + +rct_map_element *map_get_first_element_at(int x, int y) +{ + return TILE_MAP_ELEMENT_POINTER(x + y * 256); +} + +int map_element_is_last_for_tile(rct_map_element *element) +{ + return element->flags & MAP_ELEMENT_FLAG_LAST_TILE; +} + +int map_element_get_type(rct_map_element *element) +{ + return element->type & MAP_ELEMENT_TYPE_MASK; +} + int map_element_get_terrain(rct_map_element *element) { int terrain = (element->properties.surface.terrain >> 5) & 7; @@ -89,13 +144,11 @@ void map_element_set_terrain_edge(rct_map_element *element, int terrain) rct_map_element *map_get_surface_element_at(int x, int y) { - // Get first element of the tile - rct_map_element *mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + rct_map_element *mapElement = map_get_first_element_at(x, y); // Find the first surface element - while ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE) { - // Check if last element on tile - if (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE) + while (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SURFACE) { + if (map_element_is_last_for_tile(mapElement)) return NULL; mapElement++; @@ -151,7 +204,7 @@ void map_init() */ void map_update_tile_pointers() { - int i, x, y, lastTile; + int i, x, y; for (i = 0; i < MAX_TILE_MAP_ELEMENT_POINTERS; i++) TILE_MAP_ELEMENT_POINTER(i) = TILE_UNDEFINED_MAP_ELEMENT; @@ -161,10 +214,7 @@ void map_update_tile_pointers() for (y = 0; y < 256; y++) { for (x = 0; x < 256; x++) { *tile++ = mapElement; - do { - lastTile = (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE); - mapElement++; - } while (!lastTile); + do { } while (!map_element_is_last_for_tile(mapElement++)); } } @@ -354,7 +404,7 @@ void sub_68B089() mapElement++; mapElementFirst++; - } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement - 1)); // Update next free element? mapElement = RCT2_GLOBAL(0x0140E9A4, rct_map_element*); @@ -370,34 +420,32 @@ void sub_68B089() * Checks if the tile at coordinate at height counts as connected. * @return 1 if connected, 0 otherwise */ -int map_coord_is_connected(uint16 tile_idx, uint8 height, uint8 face_direction) +int map_coord_is_connected(int x, int y, int z, uint8 faceDirection) { - rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + rct_map_element *mapElement = map_get_first_element_at(x, y); - do { - rct_map_element_path_properties props = tile->properties.path; - uint8 path_type = props.type >> 2, path_dir = props.type & 3; - uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK; + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH) + continue; - if (element_type != PATH_ROAD) - continue; + rct_map_element_path_properties props = mapElement->properties.path; + uint8 pathType = props.type >> 2; + uint8 pathDirection = props.type & 3; - if (path_type & 1) { - if (path_dir == face_direction) { - if (height == tile->base_height + 2) + if (pathType & 1) { + if (pathDirection == faceDirection) { + if (z == mapElement->base_height + 2) return 1; - } - else if ((path_dir ^ 2) == face_direction && height == tile->base_height) { + } else if ((pathDirection ^ 2) == faceDirection && z == mapElement->base_height) { return 1; } - } else { - if (height == tile->base_height) + } else { + if (z == mapElement->base_height) return 1; - } - - } while (!(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) && tile++); + } + } while (!map_element_is_last_for_tile(mapElement++)); - return 0; + return 0; } /** @@ -618,9 +666,9 @@ money32 map_clear_scenery_from_tile(int x, int y, int flags) totalCost = 0; restart_from_beginning: - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + mapElement = map_get_first_element_at(x, y); do { - type = mapElement->type & MAP_ELEMENT_TYPE_MASK; + type = map_element_get_type(mapElement); switch (type) { case MAP_ELEMENT_TYPE_PATH: #ifdef CLEAR_SCENERY_REMOVES_PATHS @@ -654,7 +702,7 @@ restart_from_beginning: break; } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } while (!map_element_is_last_for_tile(mapElement++)); return totalCost; } @@ -878,36 +926,30 @@ void sub_6A6AA7(int x, int y, rct_map_element *mapElement) */ void map_remove_all_rides() { - int x, y; - rct_map_element *mapElement; + map_element_iterator it; - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - repeat_tile: - mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); + map_element_iterator_begin(&it); + do { + switch (map_element_get_type(it.element)) { + case MAP_ELEMENT_TYPE_PATH: + if (it.element->type & 1) { + it.element->properties.path.type &= ~8; + it.element->properties.path.addition_status = 255; + } + break; + case MAP_ELEMENT_TYPE_ENTRANCE: + if (it.element->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) + break; - do { - switch (mapElement->type & MAP_ELEMENT_TYPE_MASK) { - case MAP_ELEMENT_TYPE_PATH: - if (mapElement->type & 1) { - mapElement->properties.path.type &= ~8; - mapElement->properties.path.addition_status = 255; - } - break; - case MAP_ELEMENT_TYPE_ENTRANCE: - if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) - break; - - // fall-through - case MAP_ELEMENT_TYPE_TRACK: - RCT2_CALLPROC_EBPSAFE(0x006A7594); - sub_6A6AA7(x * 32, y * 32, mapElement); - map_element_remove(mapElement); - goto repeat_tile; - } - } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + // fall-through + case MAP_ELEMENT_TYPE_TRACK: + RCT2_CALLPROC_EBPSAFE(0x006A7594); + sub_6A6AA7(it.x * 32, it.y * 32, it.element); + map_element_remove(it.element); + map_element_iterator_restart_for_tile(&it); + break; } - } + } while (map_element_iterator_next(&it)); } /** diff --git a/src/world/map.h b/src/world/map.h index 43818c664f..897885d08c 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -223,6 +223,9 @@ extern rct_xy16 *gMapSelectionTiles; void map_init(); void map_update_tile_pointers(); +rct_map_element *map_get_first_element_at(int x, int y); +int map_element_is_last_for_tile(rct_map_element *element); +int map_element_get_type(rct_map_element *element); int map_element_get_terrain(rct_map_element *element); int map_element_get_terrain_edge(rct_map_element *element); void map_element_set_terrain(rct_map_element *element, int terrain); @@ -231,7 +234,7 @@ int map_height_from_slope(int x, int y, int slope); rct_map_element *map_get_surface_element_at(int x, int y); int map_element_height(int x, int y); void sub_68B089(); -int map_coord_is_connected(uint16 coordinate, uint8 height, uint8 face_direction); +int map_coord_is_connected(int x, int y, int z, uint8 faceDirection); void map_invalidate_animations(); void sub_6A876D(); int map_is_location_owned(int x, int y, int z); @@ -258,4 +261,14 @@ void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, i #define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x])) #define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x]) +typedef struct { + int x; + int y; + rct_map_element *element; +} map_element_iterator; + +void map_element_iterator_begin(map_element_iterator *it); +int map_element_iterator_next(map_element_iterator *it); +void map_element_iterator_restart_for_tile(map_element_iterator *it); + #endif diff --git a/src/world/park.c b/src/world/park.c index 4b1e8cde19..d3725e0236 100644 --- a/src/world/park.c +++ b/src/world/park.c @@ -137,7 +137,7 @@ int park_calculate_size() for (y = 0; y < 256; y++) { for (x = 0; x < 256; x++) { mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x]; - while (mapElement->type & MAP_ELEMENT_TYPE_MASK) { + while (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SURFACE) { mapElement++; }