diff --git a/src/map.c b/src/map.c index 1e2dc405bd..38064fe979 100644 --- a/src/map.c +++ b/src/map.c @@ -123,34 +123,148 @@ 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 + // Remove the extra height bit + slope &= 0xF; - return result; + uint8 quad, quad_extra; // which quadrant the element is in? + // quad_extra is for extra height tiles + + uint8 xl, yl; // coordinates across this tile + + uint8 TILE_SIZE = 31; + + xl = x & 0x1f; + yl = y & 0x1f; + + // Slope logic: + // Each of the four bits in slope represents that corner being raised + // slope == 15 (all four bits) is not used and slope == 0 is flat + // If the extra_height bit is set, then the slope goes up two z-levels + + // We arbitrarily take the SW corner to be closest to the viewer + + // 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 the element is in the quadrant with the slope, raise its height + 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_extra = xl + TILE_SIZE - yl; + quad = xl - yl; + break; + case 11: // SW corner down + quad_extra = xl + yl; + quad = xl + yl - TILE_SIZE; + break; + case 13: // SE corner down + quad_extra = TILE_SIZE - xl + yl; + quad = xl - yl; + break; + case 14: // NE corner down + quad_extra = (TILE_SIZE - xl) + (TILE_SIZE - yl); + quad = TILE_SIZE - yl - xl; + break; + } + + if (extra_height) { + height += quad_extra / 2; + height++; + return height; + } + // This tile is essentially at the next height level + height += 0x10; + // so we move *down* the slope + if (quad < 0) { + height += quad / 2; + height += 0xFF00; + } + } + + // Valleys + if ((slope == 5) || (slope == 10)) { + switch (slope) { + case 5: // NW-SE valley + if (xl + yl <= TILE_SIZE + 1) { + return height; + } + quad = TILE_SIZE - xl - yl; + break; + case 10: // NE-SW valley + quad = xl - yl; + break; + } + if (quad > 0) { + 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..4e862d599b 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/peep.h b/src/peep.h index 76f993fb3c..c75f065118 100644 --- a/src/peep.h +++ b/src/peep.h @@ -8,12 +8,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * You should have received a copy of the GNU General Public License * along with this program. If not, see . *****************************************************************************/ 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); }