diff --git a/src/map.c b/src/map.c index 1e2dc405bd..57a305981b 100644 --- a/src/map.c +++ b/src/map.c @@ -123,34 +123,135 @@ void map_update_tile_pointers() } /** - * + * Return the absolute height of an element, given its (x,y) coordinates + * * rct2: 0x00662783 * UNFINISHED */ -int sub_662783(int x, int y) +int map_element_height(int x, int y) { int i; rct_map_element *mapElement; + // Off the map if (x >= 8192 || y >= 8192) return 16; - x &= 0xFFFFFFE0; - y &= 0xFFFFFFE0; + // Find the tile the element is on + int x_tile = x & 0xFFFFFFE0; + int y_tile = y & 0xFFFFFFE0; - i = ((y * 256) + x) / 8; + i = ((y_tile * 256) + x_tile) / 32; mapElement = TILE_MAP_ELEMENT_POINTER(i); while (mapElement->type & MAP_ELEMENT_TYPE_MASK) { mapElement++; } - uint32 result = + uint32 height = ((mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) << 20) | (mapElement->base_height << 3); - uint32 ebx = (mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK) & ~0x16; - // slope logic + uint32 slope = (mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK); + uint8 extra_height = (slope & 0x10) >> 4; // 0x10 is the 5th bit - sets slope to double height + slope &= 0xF; - return result; + uint8 quad, quad_2; // which quadrant the element is in? + + uint8 xl, yl; + + uint8 TILE_SIZE = 31; + + xl = x & 0x1f; + yl = y & 0x1f; + + // slope logic + // slope == 0 is flat, and slope == 15 is not used + + // One corner up + if ((slope == 1) || (slope == 2) || (slope == 4) || (slope == 8)) { + switch(slope) { + case 1: // NE corner up + quad = xl + yl - TILE_SIZE; + break; + case 2: // SE corner up + quad = xl - yl; + break; + case 4: // SW corner up + quad = TILE_SIZE - yl - xl; + break; + case 8: // NW corner up + quad = xl - yl; + break; + } + if (quad > 0) { + height += quad / 2; + } + } + + // One side up + switch(slope) { + case 3: // E side up + height += xl / 2; + break; + case 6: // S side up + height += (TILE_SIZE - yl) / 2; + break; + case 9: // N side up + height += yl / 2; + height++; + break; + case 12: // W side up + height += (TILE_SIZE - xl) / 2; + break; + } + + // One corner down + if ((slope == 7) || (slope == 11) || (slope == 13) || (slope == 14)) { + switch(slope) { + case 7: // NW corner down + quad = xl + TILE_SIZE - yl; + quad_2 = xl - yl; + break; + case 11: // SW corner down + quad = xl + yl; + quad_2 = xl + yl - TILE_SIZE; + break; + case 13: // SE corner down + quad = TILE_SIZE - xl + yl; + quad_2 = xl - yl; + break; + case 14: // NE corner down + quad = (TILE_SIZE - xl) + (TILE_SIZE - yl); + quad_2 = TILE_SIZE - yl - xl; + break; + } + height += 0x10; + if (extra_height) { + height += quad / 2; + height++; + } + if (quad_2 < 0) { + height += quad_2 / 2; + height += 0xFF00; + } + } + + // Valleys + if (slope == 5) { // NW-SE valley + quad = xl + yl; + if (quad > TILE_SIZE + 1) { + quad = TILE_SIZE - xl - yl; + if (quad > 0) { + height += quad / 2; + } + } + } else if (slope == 10) { // NE-SW valley + if (xl > yl) { + quad = xl - yl; + height += quad / 2; + } + } + + return height; } diff --git a/src/map.h b/src/map.h index 8a42517699..5d0f1a655b 100644 --- a/src/map.h +++ b/src/map.h @@ -184,5 +184,6 @@ enum { void map_init(); void map_update_tile_pointers(); +int map_element_height(int x, int y); #endif diff --git a/src/news_item.c b/src/news_item.c index f09f7f19c8..3f50fbfd96 100644 --- a/src/news_item.c +++ b/src/news_item.c @@ -184,17 +184,9 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * *x = SPRITE_LOCATION_NULL; break; } - { - uint32 eax, ebx, ecx, edx, esi, edi, ebp; - eax = (ride->var_050 & 0xFF) * 32 + 16; - ecx = (ride->var_050 >> 8) * 32 + 16; - RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - if (edx & 0xFFFF0000) - edx >>= 16; - *x = eax; - *y = ecx; - *z = edx; - } + *x = (ride->var_050 & 0xFF) * 32 + 16; + *y = (ride->var_050 >> 8) * 32 + 16; + *z = map_element_height(*x, *y); break; case NEWS_ITEM_PEEP_ON_RIDE: peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[subject]); @@ -233,16 +225,10 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * *z = peep->z; break; case NEWS_ITEM_BLANK: - { - uint32 eax, ebx, ecx, edx, esi, edi, ebp; - eax = subject; - ecx = subject >> 16; - RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - *x = eax; - *y = ecx; - *z = edx; - } - break; + *x = subject; + *y = subject >> 16; + *z = map_element_height(x, y); + break; default: *x = SPRITE_LOCATION_NULL; break; diff --git a/src/news_item.h b/src/news_item.h index be8dd55e42..de12b44e22 100644 --- a/src/news_item.h +++ b/src/news_item.h @@ -22,6 +22,7 @@ #define _NEWS_ITEM_H_ #include "rct2.h" +#include "map.h" enum { NEWS_ITEM_NULL, diff --git a/src/title.c b/src/title.c index 61d2e78f52..6a85e4e6c0 100644 --- a/src/title.c +++ b/src/title.c @@ -152,7 +152,7 @@ static void title_update_showcase() { rct_window* w; uint8 script_opcode, script_operand; - short x, y; + short x, y, z; int i, _edx; if (_scriptWaitCounter <= 0) { @@ -201,18 +201,12 @@ static void title_update_showcase() case TITLE_SCRIPT_LOCATION: x = (*_currentScript++) * 32 + 16; y = (*_currentScript++) * 32 + 16; - - // Set location - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ecx = y; - RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - _edx = edx; + z = map_element_height(x, y); // Update viewport w = window_get_main(); if (w != NULL) { - window_scroll_to_location(w, x, y, _edx); + window_scroll_to_location(w, x, y, z); w->flags &= ~0x08; viewport_update_position(w); }