diff --git a/src/game.c b/src/game.c index 16a1e44c3a..fef2cb6850 100644 --- a/src/game.c +++ b/src/game.c @@ -924,7 +924,7 @@ static uint32 game_do_command_table[58] = { 0x006D13FE, 0, 0x006CDEE4, - 0x006B9E6D, // 50 + 0, // 50 0, 0, 0, @@ -987,7 +987,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_start_campaign, game_command_emptysub, - game_command_emptysub, // 50 + game_command_place_banner, // 50 game_command_remove_banner, game_command_set_scenery_colour, game_command_set_fence_colour, diff --git a/src/game.h b/src/game.h index f7b09ca991..a60d5cd648 100644 --- a/src/game.h +++ b/src/game.h @@ -74,7 +74,7 @@ enum GAME_COMMAND { GAME_COMMAND_47, GAME_COMMAND_START_MARKETING_CAMPAIGN, // 48 GAME_COMMAND_49, - GAME_COMMAND_50, // New banner? (possibly scenery) + GAME_COMMAND_PLACE_BANNER, // New banner? (possibly scenery) GAME_COMMAND_REMOVE_BANNER, // Remove banner GAME_COMMAND_52, GAME_COMMAND_53, diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index f1fef1b95e..e9da964f74 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -319,6 +319,7 @@ enum { STR_BUILD_FOOTPATH_TIP = 1173, + STR_BANNER_SIGN_IN_THE_WAY = 1174, STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH = 1175, STR_CANT_BUILD_FOOTPATH_HERE = 1176, STR_CANT_REMOVE_FOOTPATH_FROM_HERE = 1177, @@ -739,6 +740,8 @@ enum { STR_CANT_DEMOLISH_RIDE = 2248, + STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS = 2252, + STR_RESEARCH_TRANSPORT_RIDES = 2253, STR_RESEARCH_GENTLE_RIDES = 2254, STR_RESEARCH_ROLLER_COASTERS = 2255, diff --git a/src/object.c b/src/object.c index 6b8bc5a6f5..7f2be9d177 100644 --- a/src/object.c +++ b/src/object.c @@ -909,8 +909,9 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk; + // skip over large scenery tiles while (*((uint16*)chunk) != 0xFFFF){ - chunk += 9; + chunk += sizeof(rct_large_scenery_tile); } chunk += 2; diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 90af8a665f..887915cb48 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1416,8 +1416,8 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w int cost; { - int esi = 0, eax = grid_x, ecx = grid_y, edx = parameter_2, ebx = (parameter_1 & 0xFF00) | 1; - cost = game_do_command_p(GAME_COMMAND_50, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); + int esi = 0, eax = grid_x, ecx = grid_y, edx = grid_z; + game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); } if (ebx == MONEY32_UNDEFINED)return; diff --git a/src/world/map.c b/src/world/map.c index e80a6f12a2..db832b1768 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -29,6 +29,7 @@ #include "banner.h" #include "climate.h" #include "map.h" +#include "map_animation.h" #include "park.h" #include "scenery.h" @@ -797,19 +798,20 @@ void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi map_element->properties.banner.position != banner_position){ map_element++; if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ - *ebx = 0; + *ebx = MONEY32_UNDEFINED; return; } } + rct_banner *banner = &gBanners[map_element->properties.banner.index]; + uint8 banner_type = banner->type; if(*ebx & GAME_COMMAND_FLAG_APPLY){ window_close_by_number(WC_BANNER, map_element->properties.banner.index); - rct_banner *banner = &gBanners[map_element->properties.banner.index]; user_string_free(banner->string_idx); banner->type = BANNER_NULL; map_invalidate_tile(x, y, z, z + 32); map_element_remove(map_element); } - rct_scenery_entry *scenery_entry = object_entry_groups[OBJECT_TYPE_BANNERS].chunks[map_element->properties.banner.index]; + rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[banner_type]; *ebx = (scenery_entry->banner.price * -3) / 4; if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ *ebx = 0; @@ -1667,6 +1669,90 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, *ebx = 0; } +/** + * + * rct2: 0x006B9E6D + */ +void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int x = (uint16)*eax; + int y = (uint16)*ecx; + uint8 base_height = *edx; + uint8 edge = *edx >> 8; + uint8 colour = *edi; + uint8 type = *ebx >> 8; + RCT2_GLOBAL(0x009DEA5E, uint32) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint32) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint32) = base_height * 16; + RCT2_GLOBAL(0x141F56C, uint8) = 12; + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0){ + if(sub_68B044() && x < 8192 && y < 8192){ + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + int dl = base_height * 2; + int ch = (base_height - 1) * 2; + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH || + (map_element->base_height != dl && map_element->base_height != ch) || + !(map_element->properties.path.edges & (1 << edge))){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; + *ebx = MONEY32_UNDEFINED; + return; + } + } + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !map_is_location_owned(x, y, base_height * 16)){ + *ebx = MONEY32_UNDEFINED; + return; + } + map_element = map_get_first_element_at(x / 32, y / 32); + dl = (base_height + 1) * 2; + while(map_element->type != MAP_ELEMENT_TYPE_BANNER || + map_element->base_height != dl || + (map_element->properties.banner.position & 0x3) != edge){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + uint8 a = sub_6BA278(*ebx); + if(a == 0xFF){ + *ebx = MONEY32_UNDEFINED; + return; + } + *edi = a; + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); + gBanners[a].type = type; + gBanners[a].colour = colour; + gBanners[a].x = x / 32; + gBanners[a].y = y / 32; + new_map_element->type = MAP_ELEMENT_TYPE_BANNER; + new_map_element->clearance_height = new_map_element->base_height + 2; + new_map_element->properties.banner.position = edge; + new_map_element->properties.banner.flags = 0xFF; + new_map_element->properties.banner.unused = 0; + new_map_element->properties.banner.index = a; + if(*ebx & 0x40){ + new_map_element->flags |= 0x10; + } + map_invalidate_tile_full(x, y); + map_animation_create(0x0A, x, y, new_map_element->base_height); + } + rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[type]; + *ebx = scenery_entry->banner.price; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } + return; + } + } + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_BANNER_SIGN_IN_THE_WAY; + *ebx = MONEY32_UNDEFINED; + return; + } + }else{ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + } + *ebx = MONEY32_UNDEFINED; +} + /** * * rct2: 0x006EC6D7 @@ -1860,6 +1946,17 @@ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl) return map_can_construct_with_clear_at(x, y, zLow, zHigh, (void*)0xFFFFFFFF, bl); } +/** + * + * rct2: 0x006BA278 + */ +int sub_6BA278(int ebx) +{ + int eax, ecx, edx, esi, edi, ebp; + RCT2_CALLFUNC_X(0x006BA278, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return eax; +} + /** * * rct2: 0x006E5935 diff --git a/src/world/map.h b/src/world/map.h index 8d66ede404..963ecd07f3 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -273,6 +273,7 @@ int sub_68B044(); rct_map_element *map_element_insert(int x, int y, int z, int flags); int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl); int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); +int sub_6BA278(int ebx); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); @@ -288,6 +289,7 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #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]) diff --git a/src/world/map_animation.c b/src/world/map_animation.c index b481cb0029..3a31fe5d82 100644 --- a/src/world/map_animation.c +++ b/src/world/map_animation.c @@ -48,7 +48,7 @@ void map_animation_create(int type, int x, int y, int z) { rct_map_animation *aobj = &gAnimatedObjects[0]; int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16); - for (; numAnimatedObjects > 0; aobj++) { + for (int i = 0; i < numAnimatedObjects; i++, aobj++) { if (aobj->x != x) continue; if (aobj->y != y)