From 4f567094551c7ebe7ba0d422015075b53f6ae405 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sun, 1 Nov 2015 14:58:46 +0000 Subject: [PATCH] implement more sub_6DAB4C --- src/ride/track.c | 24 +++++++++++++ src/ride/track.h | 1 + src/ride/vehicle.c | 53 +++++++++++++++++++++++++++-- src/world/map.c | 84 +++++++++++++++++++++++++++++----------------- src/world/map.h | 1 + 5 files changed, 131 insertions(+), 32 deletions(-) diff --git a/src/ride/track.c b/src/ride/track.c index e367b6b9c3..3a77514fb5 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -4922,6 +4922,30 @@ bool track_element_is_lift_hill(rct_map_element *trackElement) return trackElement->type & 0x80; } +/** + * Checks if a track element is recognised as the beginning of a block. + * A beginning of a block can be the end of a station, the end of a lift hill, + * or a block brake. + */ +bool track_element_is_block_start(rct_map_element *trackElement) +{ + switch (trackElement->properties.track.type) { + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_CABLE_LIFT_HILL: + case 216: + return true; + case TRACK_ELEM_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_60_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT: + if (track_element_is_lift_hill(trackElement)) { + return true; + } + break; + } + return false; +} + bool track_element_is_cable_lift(rct_map_element *trackElement) { return trackElement->properties.track.colour & TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; } diff --git a/src/ride/track.h b/src/ride/track.h index 5690767666..a973cba0c4 100644 --- a/src/ride/track.h +++ b/src/ride/track.h @@ -547,6 +547,7 @@ void track_get_back(rct_xy_element *input, rct_xy_element *output); void track_get_front(rct_xy_element *input, rct_xy_element *output); bool track_element_is_lift_hill(rct_map_element *trackElement); +bool track_element_is_block_start(rct_map_element *trackElement); bool track_element_is_cable_lift(rct_map_element *trackElement); void track_element_set_cable_lift(rct_map_element *trackElement); diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index ae7f47c742..f27dbbed00 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -917,9 +917,58 @@ loc_6DAEB9: } loc_6DB06B: + regs.ax = vehicle->var_34 + 1; + regs.ecx = vehicle->var_CD; + regs.ecx = RCT2_ADDRESS(0x008B8F30, uint32)[regs.ecx]; + regs.edi = RCT2_GLOBAL(regs.ecx + (vehicle->track_type * 4), uint32); + if (regs.ax < RCT2_GLOBAL(regs.edi - 2, uint16)) { + goto loc_6DB59A; + } + + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_end; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_end; + rct_map_element *mapElement = map_get_track_element_at_of_type_seq( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z >> 3, + trackType, + 0 + ); + if (trackType == TRACK_ELEM_CABLE_LIFT_HILL && vehicle == RCT2_GLOBAL(0x00F64E04, rct_vehicle*)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= 0x800; + } + + if (!track_element_is_block_start(mapElement)) { + goto loc_6DB2BD; + } + + if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) { + goto loc_6DB2BD; + } + RCT2_GLOBAL(regs.edi + 1, uint8) |= 0x20; + if (trackType == 216 || trackType == TRACK_ELEM_END_STATION) { + if (!(rideEntry->vehicles[0].var_14 & (1 << 3))) { + sound_play_panned(SOUND_49, 0x8001, vehicle->track_x, vehicle->track_y, vehicle->track_z); + } + } + map_invalidate_tile(vehicle->track_x, vehicle->track_z, mapElement->base_height * 8, mapElement->clearance_height * 8); + +loc_6DB1B0: regs.esi = vehicle; - regs.edi = vehicle->track_type; - RCT2_CALLFUNC_Y(0x006DB06B, ®s); + regs.edi = mapElement; + RCT2_CALLFUNC_Y(0x006DB1B0, ®s); + goto end; + +loc_6DB2BD: + regs.eax = trackType; + regs.esi = vehicle; + regs.edi = mapElement; + RCT2_CALLFUNC_Y(0x006DB2BD, ®s); + goto end; + +loc_6DB59A: + regs.esi = vehicle; + RCT2_CALLFUNC_Y(0x006DB59A, ®s); goto end; loc_6DBA13: diff --git a/src/world/map.c b/src/world/map.c index 640851372f..42a80537f3 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -897,7 +897,7 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i } *ebx = scenery_entry->large_scenery.removal_price * 10; - if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY || + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY || calculate_cost == false){ *ebx = 0; } @@ -985,7 +985,7 @@ void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int // Previously it would do a search for type of bh (set from calling function) instead of just small scenery // Unsure if this was a mistake. rct_map_element* map_element = map_get_small_scenery_element_at(x, y, base_height, scenery_type); - + if (map_element == NULL) { *ebx = 0; return; @@ -1053,7 +1053,7 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type]; map_element->properties.fence.item[1] &= 0xE0; map_element->properties.fence.item[1] |= color1; - map_element->properties.fence.item[1] &= 0x1F; + map_element->properties.fence.item[1] &= 0x1F; map_element->flags &= 0x9F; map_element->properties.fence.item[1] |= (color2 & 0x7) * 32; map_element->flags |= (color2 & 0x18) * 4; @@ -1093,7 +1093,7 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed *ebx = 0; return; } - + if((flags & GAME_COMMAND_FLAG_GHOST) && !(map_element->flags & MAP_ELEMENT_FLAG_GHOST)){ *ebx = 0; return; @@ -1134,10 +1134,10 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed if(flags & GAME_COMMAND_FLAG_APPLY){ rct_map_element* mapElement = map_get_large_scenery_segment( - currentTile.x, - currentTile.y, - base_height, - map_element_direction, + currentTile.x, + currentTile.y, + base_height, + map_element_direction, i); mapElement->properties.scenerymultiple.colour[0] &= 0xE0; @@ -1567,7 +1567,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl return MONEY32_UNDEFINED; } } - + //Uncomment to use vanilla code /* registers regs = {0}; @@ -1581,7 +1581,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl regs.ebp = 0; RCT2_CALLFUNC_Y(0x006639FE, ®s); return regs.ebx; */ - + RCT2_GLOBAL(0x9E2E18, money32) = MONEY(0, 0); if(flags & GAME_COMMAND_FLAG_APPLY) { @@ -1589,10 +1589,10 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl map_remove_walls_at(x, y, height * 8 - 16, height * 8 + 32); } RCT2_GLOBAL(0x9E2E18, money32) += MONEY(20, 0); - + //Check for obstructing scenery - rct_map_element *mapElement = map_get_first_element_at(x / 32, y / 32); - do{ + rct_map_element *mapElement = map_get_first_element_at(x / 32, y / 32); + do{ if(map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY) continue; if(height > mapElement->clearance_height) @@ -1609,7 +1609,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl if(flags & GAME_COMMAND_FLAG_APPLY) map_element_remove(mapElement--); }while(!map_element_is_last_for_tile(mapElement++)); - + //Check for ride support limits if(gCheatsDisableSupportLimits==false) { @@ -1653,7 +1653,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } } - + zCorner = height; if(style & 0xF) { @@ -1663,14 +1663,14 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl zCorner += 2; } } - + if(map_can_construct_with_clear_at(x, y, height, zCorner, RCT2_ADDRESS(0x663CB9, void), 0xF) == false) return MONEY32_UNDEFINED; - + mapElement = map_get_first_element_at(x / 32, y / 32); - do{ + do{ int elementType = map_element_get_type(mapElement); - + if(elementType == MAP_ELEMENT_TYPE_FENCE) continue; if(elementType == MAP_ELEMENT_TYPE_SCENERY) @@ -1694,7 +1694,7 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl return MONEY32_UNDEFINED; } }while(!map_element_is_last_for_tile(mapElement++)); - + if(flags & GAME_COMMAND_FLAG_APPLY) { surfaceElement = map_get_surface_element_at(x / 32, y / 32); @@ -3323,7 +3323,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in } } - + sint16 maxHeight = 0xFFFF; for (rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; tile->x_offset != -1; @@ -3335,7 +3335,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in }; rotate_map_coordinates(&curTile.x, &curTile.y, rotation); - + curTile.x += x; curTile.y += y; @@ -3440,8 +3440,8 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in new_map_element->clearance_height = zHigh; new_map_element->type = MAP_ELEMENT_TYPE_SCENERY_MULTIPLE | rotation; - new_map_element->properties.scenerymultiple.type = - (tile_num << 10) | + new_map_element->properties.scenerymultiple.type = + (tile_num << 10) | entry_index; new_map_element->properties.scenerymultiple.colour[0] = color1; @@ -4895,7 +4895,7 @@ void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* *ebx = MONEY32_UNDEFINED; return; } - + map_element->properties.banner.flags = 0xFF; if (banner->flags & BANNER_FLAG_NO_ENTRY){ map_element->properties.banner.flags &= ~(1 << map_element->properties.banner.position); @@ -4930,7 +4930,7 @@ void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* *ebx = 0; } -void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { +void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { uint8 bannerId = *ecx & 0xFF; rct_banner *banner = &gBanners[bannerId]; int x = banner->x << 5; @@ -4938,9 +4938,9 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es uint8 mainColour = (uint8)*edx; uint8 textColour = (uint8)*edi; - + if (*ebp == 0) { // small sign - + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); bool fence_found = false; do{ @@ -4998,7 +4998,7 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es } /** - * Gets the map element at x, y, z. + * Gets the track element at x, y, z. * @param x x units, not tiles. * @param y y units, not tiles. * @param z Base height. @@ -5017,10 +5017,11 @@ rct_map_element *map_get_track_element_at(int x, int y, int z) } /** - * Gets the map element at x, y, z. + * Gets the track element at x, y, z that is the given track type. * @param x x units, not tiles. * @param y y units, not tiles. * @param z Base height. + * @param trackType */ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int trackType) { @@ -5035,3 +5036,26 @@ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int track return NULL; } + +/** + * Gets the track element at x, y, z that is the given track type and sequence. + * @param x x units, not tiles. + * @param y y units, not tiles. + * @param z Base height. + * @param trackType + * @param sequence + */ +rct_map_element *map_get_track_element_at_of_type_seq(int x, int y, int z, int trackType, int sequence) +{ + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (mapElement->base_height != z) continue; + if (mapElement->properties.track.type != trackType) continue; + if ((mapElement->properties.track.sequence & 0x0F) != sequence) continue; + + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + + return NULL; +} diff --git a/src/world/map.h b/src/world/map.h index 705df960c5..892dea6b13 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -392,5 +392,6 @@ bool map_large_scenery_get_origin( rct_map_element *map_get_track_element_at(int x, int y, int z); rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int trackType); +rct_map_element *map_get_track_element_at_of_type_seq(int x, int y, int z, int trackType, int sequence); #endif