diff --git a/src/paint/map_element/scenery.c b/src/paint/map_element/scenery.c index 74afd2b868..695ede0285 100644 --- a/src/paint/map_element/scenery.c +++ b/src/paint/map_element/scenery.c @@ -16,8 +16,279 @@ #include "map_element.h" #include "../../addresses.h" +#include "../../config.h" +#include "../../game.h" +#include "../../interface/viewport.h" +#include "../../paint/paint.h" +#include "../../paint/supports.h" #include "../../world/map.h" +#include "../../world/scenery.h" +/** + * + * rct2: 0x006DFF47 + */ void scenery_paint(uint8 direction, int height, rct_map_element* mapElement) { - RCT2_CALLPROC_X(0x6DFF47, 0, 0, direction, height, (int)mapElement, 0, 0); + //RCT2_CALLPROC_X(0x6DFF47, 0, 0, direction, height, (int)mapElement, 0, 0); return; + RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8_t) = VIEWPORT_INTERACTION_ITEM_SCENERY; + rct_xyz16 boxlength; + rct_xyz16 boxoffset; + boxoffset.x = 0; + boxoffset.y = 0; + boxoffset.z = height; + int baseImageid = 0; + if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1) { + if (track_design_save_contains_map_element(mapElement)) { + baseImageid = 0x21700000; + } + } + if (mapElement->flags & MAP_ELEMENT_FLAG_GHOST) { + RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8_t) = VIEWPORT_INTERACTION_ITEM_NONE; + baseImageid = RCT2_ADDRESS(0x993CC4, uint32_t)[gConfigGeneral.construction_marker_colour]; + } + uint32 dword_F64EB0 = baseImageid; + + rct_scenery_entry *entry = get_small_scenery_entry(mapElement->properties.scenery.type); + baseImageid = entry->image + direction; + boxlength.x = 2; + boxlength.y = 2; + sint8 x_offset = 0; + sint8 y_offset = 0; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE) { + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG24) { + // 6DFFE3: + boxoffset.x = RCT2_ADDRESS(0x009A3E7C, uint16)[direction * 4]; + boxoffset.y = RCT2_ADDRESS(0x009A3E7E, uint16)[direction * 4]; + boxlength.x = RCT2_ADDRESS(0x009A3E8C, uint16)[direction * 4]; + boxlength.y = RCT2_ADDRESS(0x009A3E8E, uint16)[direction * 4]; + x_offset = 3; + y_offset = 3; + } else { + x_offset = 15; + y_offset = 15; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) { + x_offset = 3; + y_offset = 3; + boxlength.x = 26; + boxlength.y = 26; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_ALLOW_WALLS) { + x_offset = 1; + y_offset = 1; + boxlength.x = 30; + boxlength.y = 30; + } + } + } + } else { + // 6DFFC2: + uint32 ecx = ((mapElement->type >> 6) + get_current_rotation()) & 3; + x_offset = RCT2_ADDRESS(0x009A3E74, sint8)[ecx * 2]; + y_offset = RCT2_ADDRESS(0x009A3E75, sint8)[ecx * 2]; + } + // 6E0074: + boxoffset.x = x_offset; + boxoffset.y = y_offset; + boxlength.z = entry->small_scenery.height - 4; + if (boxlength.z > 0x80) { + boxlength.z = 0x80; + } + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG6) { + if (mapElement->properties.scenery.age >= 40) { + baseImageid += 4; + } + if (mapElement->properties.scenery.age >= 55) { + baseImageid += 4; + } + } + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) { + baseImageid |= ((mapElement->properties.scenery.colour_1 & 0x1F) << 19) | 0x20000000; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { + baseImageid |= ((mapElement->properties.scenery.colour_2 & 0x1F) << 24) | 0x80000000; + } + } + if (dword_F64EB0 != 0) { + baseImageid = (baseImageid & 0x7FFFF) | dword_F64EB0; + } + if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG21)) { + sub_98197C(baseImageid, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } + + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG10) { + if (dword_F64EB0 == 0) { + // Draw translucent overlay: + int image_id = (baseImageid & 0x7FFFF) + (((mapElement->properties.scenery.colour_1 & 0x1F) + 112) << 19) + 0x40000004; + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } + } + + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_ANIMATED) { + rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); + if ( !(entry->small_scenery.flags & SMALL_SCENERY_FLAG21) || (dpi->zoom_level <= 1) ) { + // 6E01A9: + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG12) { + // 6E0512: + int image_id = ((gCurrentTicks / 2) & 0xF) + entry->image + 4; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } else + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG13) { + // 6E043B: + int image_id = ((gCurrentTicks / 2) & 0xF) + entry->image + 8; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + + image_id = direction + entry->image + 4; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + + image_id = ((gCurrentTicks / 2) & 0xF) + entry->image + 24; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } else + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_IS_CLOCK) { + // 6E035C: + int si = ((RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MINUTE, uint16) + 6) * 17) / 256; + int bx = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_HOUR, uint16); + while (bx >= 12) { + bx -= 12; + } + bx = (bx * 4) + si; + if (bx >= 48) { + bx -= 48; + } + int image_id = bx + (direction * 12); + if (image_id >= 48) { + image_id -= 48; + } + + image_id = image_id + entry->image + 68; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + + image_id = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MINUTE, uint16) + (direction * 15); + if (image_id >= 60) { + image_id -= 60; + } + image_id = image_id + entry->image + 8; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } else + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG15) { + // 6E02F6: + int image_id = ((gCurrentTicks + (RCT2_GLOBAL(0x9DE568, sint16) / 4) + (RCT2_GLOBAL(0x9DE56C, sint16) / 4) / 4) & 0xF) + entry->image; + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } else { + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG16) { + // nothing + } + int esi = gCurrentTicks; + if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG22)) { + // 6E01F8: + esi += ((RCT2_GLOBAL(0x9DE568, sint16) / 4) + (RCT2_GLOBAL(0x9DE56C, sint16) / 4)); + esi += (mapElement->type & 0xC0) / 16; + } + // 6E0222: + uint16 cx = entry->small_scenery.var_14; + uint8 cl = cx & 0xFF; + esi >>= cl; + esi &= entry->small_scenery.var_16; + int image_id = 0; + if (esi < entry->small_scenery.var_18) { + image_id = ((uint8*)entry->small_scenery.var_10)[esi]; + } + image_id = (image_id * 4) + direction + entry->image; + if (entry->small_scenery.flags & (SMALL_SCENERY_FLAG21 | SMALL_SCENERY_FLAG17)) { + image_id += 4; + } + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) { + image_id |= ((mapElement->properties.scenery.colour_1 & 0x1F) << 19) | 0x20000000; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { + image_id |= ((mapElement->properties.scenery.colour_1 & 0x1F) << 24) | 0x80000000; + } + } + if (dword_F64EB0 != 0) { + image_id = (image_id & 0x7FFFF) | dword_F64EB0; + } + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG21) { + sub_98197C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } else { + sub_98199C(image_id, x_offset, y_offset, boxlength.x, boxlength.y, boxlength.z - 1, height, boxoffset.x, boxoffset.y, boxoffset.z, get_current_rotation()); + } + } + } + } + // 6E0556: Draw supports: + if (mapElement->properties.scenery.colour_1 & 0x20) { + if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG20)) { + int ax = 0; + int supportHeight = height; + if (supportHeight & 0xF) { + supportHeight &= 0xFFFFFFF0; + ax = 49; + } + uint32 supportImageColourFlags = 0x20000000; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG26) { + supportImageColourFlags = ((mapElement->properties.scenery.colour_1 & 0x1F) << 19) | 0x20000000; + } + if (dword_F64EB0 != 0) { + supportImageColourFlags = dword_F64EB0; + } + if (direction & 1) { + wooden_b_supports_paint_setup(1, ax, supportHeight, supportImageColourFlags); + } else { + wooden_b_supports_paint_setup(0, ax, supportHeight, supportImageColourFlags); + } + } + } + // 6E05D1: + height += entry->small_scenery.height; + uint16 word_F64F2A = height; + height += 7; + height &= 0xFFF8; + paint_util_set_general_support_height(height, 0x20); + // 6E05FF: + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG23) { + height = word_F64F2A; + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE) { + // 6E0825: + paint_util_set_segment_support_height(SEGMENT_C4, height, 0x20); + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) { + paint_util_set_segment_support_height(SEGMENTS_ALL & ~SEGMENT_C4, height, 0x20); + } + return; + } + if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE)) { + return; + } + // 6E075C: + paint_util_set_segment_support_height(paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, get_current_rotation()), height, 0x20); + return; + } + if (entry->small_scenery.flags & (SMALL_SCENERY_FLAG27 | SMALL_SCENERY_FLAG_FULL_TILE)) { + paint_util_set_segment_support_height(SEGMENT_C4, 0xFFFF, 0); + if (entry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) { + paint_util_set_segment_support_height(SEGMENTS_ALL & ~SEGMENT_C4, 0xFFFF, 0); + } + return; + } + if (!(entry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE)) { + return; + } + paint_util_set_segment_support_height(paint_util_rotate_segments(SEGMENT_B4 | SEGMENT_C8 | SEGMENT_CC, get_current_rotation()), 0xFFFF, 0); + return; } diff --git a/src/paint/supports.h b/src/paint/supports.h index e06e69671d..8bacef8bd7 100644 --- a/src/paint/supports.h +++ b/src/paint/supports.h @@ -20,5 +20,6 @@ #include "../common.h" bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool* underground); +bool wooden_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags); bool metal_a_supports_paint_setup(int supportType, int segment, int special, int height, uint32 imageColourFlags); #endif diff --git a/src/ride/track_design_save.c b/src/ride/track_design_save.c index d9f728dd51..d6b5c1c16b 100644 --- a/src/ride/track_design_save.c +++ b/src/ride/track_design_save.c @@ -44,6 +44,7 @@ static uint8 _trackSaveDirection; static bool track_design_save_should_select_scenery_around(int rideIndex, rct_map_element *mapElement); static void track_design_save_select_nearby_scenery_for_tile(int rideIndex, int cx, int cy); +bool track_design_save_contains_map_element(rct_map_element *mapElement); static bool track_design_save_add_map_element(int interactionType, int x, int y, rct_map_element *mapElement); static void track_design_save_remove_map_element(int interactionType, int x, int y, rct_map_element *mapElement); static bool track_design_save_copy_scenery_to_td6(rct_track_td6 *td6); diff --git a/src/world/scenery.h b/src/world/scenery.h index 06b750ba0a..121b0e9961 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -28,7 +28,9 @@ typedef struct rct_small_scenery_entry { sint16 price; // 0x0C sint16 removal_price; // 0x0E uint32 var_10; - uint8 pad_14[0x06]; + uint16 var_14; + uint16 var_16; + uint16 var_18; uint8 scenery_tab_id; // 0x1A } rct_small_scenery_entry; @@ -59,6 +61,8 @@ typedef enum { SMALL_SCENERY_FLAG23 = (1 << 23), // 0x800000 SMALL_SCENERY_FLAG24 = (1 << 24), // 0x1000000 SMALL_SCENERY_FLAG25 = (1 << 25), // 0x2000000 + SMALL_SCENERY_FLAG26 = (1 << 26), // 0x4000000 + SMALL_SCENERY_FLAG27 = (1 << 27), // 0x8000000 } SMALL_SCENERY_FLAGS; typedef struct rct_large_scenery_tile {