From 9087170cf1118cf480aefe26aa5395c46503dbf0 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Thu, 9 Mar 2017 20:30:19 +0000 Subject: [PATCH] Move functions into banner.cpp --- src/openrct2/libopenrct2.vcxproj | 4 +- src/openrct2/world/banner.c | 169 ---------- src/openrct2/world/banner.cpp | 558 +++++++++++++++++++++++++++++++ src/openrct2/world/banner.h | 2 +- src/openrct2/world/map.c | 370 -------------------- src/openrct2/world/wall.cpp | 2 +- 6 files changed, 562 insertions(+), 543 deletions(-) delete mode 100644 src/openrct2/world/banner.c create mode 100644 src/openrct2/world/banner.cpp diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 40212868c5..448829cc8d 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -336,6 +336,7 @@ + @@ -405,7 +406,6 @@ - @@ -618,4 +618,4 @@ - \ No newline at end of file + diff --git a/src/openrct2/world/banner.c b/src/openrct2/world/banner.c deleted file mode 100644 index 43b664bd20..0000000000 --- a/src/openrct2/world/banner.c +++ /dev/null @@ -1,169 +0,0 @@ -#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers -/***************************************************************************** - * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. - * - * OpenRCT2 is the work of many authors, a full list can be found in contributors.md - * For more information, visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is free software: you can redistribute it and/or modify - * 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. - * - * A full copy of the GNU General Public License can be found in licence.txt - *****************************************************************************/ -#pragma endregion - -#include "../game.h" -#include "../localisation/localisation.h" -#include "../ride/ride.h" -#include "banner.h" -#include "map.h" - -rct_banner gBanners[MAX_BANNERS]; - -/** - * - * rct2: 0x006B9CB0 - */ -void banner_init() -{ - for (sint32 i = 0; i < MAX_BANNERS; i++) { - gBanners[i].type = BANNER_NULL; - } -} - -/** - * Creates a new banner and returns the index of the banner - * If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns - * the first unused index but does NOT mark the banner as created. - * returns 0xFF on failure. - * - * rct2: 0x006BA278 - */ -sint32 create_new_banner(uint8 flags) -{ - sint32 banner_index = 0; - for (; banner_index < MAX_BANNERS; banner_index++){ - if (gBanners[banner_index].type == BANNER_NULL){ - break; - } - } - - if (banner_index == MAX_BANNERS){ - gGameCommandErrorText = STR_TOO_MANY_BANNERS_IN_GAME; - return BANNER_NULL; - } - - if (flags & GAME_COMMAND_FLAG_APPLY){ - rct_banner* banner = &gBanners[banner_index]; - - banner->flags = 0; - banner->type = 0; - banner->string_idx = STR_DEFAULT_SIGN; - banner->colour = 2; - banner->text_colour = 2; - } - return banner_index; -} - -rct_map_element *banner_get_map_element(sint32 bannerIndex) -{ - rct_banner *banner = &gBanners[bannerIndex]; - rct_map_element *mapElement = map_get_first_element_at(banner->x, banner->y); - do { - if (map_element_get_banner_index(mapElement) == bannerIndex) { - return mapElement; - } - } while (!map_element_is_last_for_tile(mapElement++)); - return NULL; -} - -/** - * - * rct2: 0x006B7EAB - */ -static sint32 banner_get_ride_index_at(sint32 x, sint32 y, sint32 z) -{ - rct_map_element *mapElement; - rct_ride *ride; - sint32 rideIndex, resultRideIndex; - - resultRideIndex = -1; - mapElement = map_get_first_element_at(x >> 5, y >> 5); - do { - if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) - continue; - - rideIndex = mapElement->properties.track.ride_index; - ride = get_ride(rideIndex); - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) - continue; - - if ((mapElement->clearance_height * 8) + 32 <= z) - continue; - - resultRideIndex = rideIndex; - } while (!map_element_is_last_for_tile(mapElement++)); - - return resultRideIndex; -} - -/** - * - * rct2: 0x006B7D86 - */ -sint32 banner_get_closest_ride_index(sint32 x, sint32 y, sint32 z) -{ - sint32 i, rideIndex; - rct_ride *ride; - - static const rct_xy16 NeighbourCheckOrder[] = { - { 32, 0 }, - { -32, 0 }, - { 0, 32 }, - { 0, -32 }, - { -32, +32 }, - { +32, -32 }, - { +32, +32 }, - { -32, +32 }, - { 0, 0 } - }; - - for (i = 0; i < countof(NeighbourCheckOrder); i++) { - rideIndex = banner_get_ride_index_at(x + NeighbourCheckOrder[i].x, y + NeighbourCheckOrder[i].y, z); - if (rideIndex != -1) { - return rideIndex; - } - } - - rideIndex = -1; - sint32 resultDistance = INT_MAX; - FOR_ALL_RIDES(i, ride) { - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) - continue; - - uint16 xy = ride->overall_view; - if (xy == 0xFFFF) - continue; - - sint32 rideX = (xy & 0xFF) * 32; - sint32 rideY = (xy >> 8) * 32; - sint32 distance = abs(x - rideX) + abs(y - rideY); - if (distance < resultDistance) { - resultDistance = distance; - rideIndex = i; - } - } - - return rideIndex; -} - -void fix_banner_count() -{ - for (sint32 banner_index = 0; banner_index < MAX_BANNERS; banner_index++){ - rct_map_element *map_element = banner_get_map_element(banner_index); - if(map_element==NULL) - gBanners[banner_index].type = BANNER_NULL; - } -} diff --git a/src/openrct2/world/banner.cpp b/src/openrct2/world/banner.cpp new file mode 100644 index 0000000000..c2d41f732e --- /dev/null +++ b/src/openrct2/world/banner.cpp @@ -0,0 +1,558 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * 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. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "../core/util.hpp" +#include "../network/network.h" + +extern "C" +{ + #include "../game.h" + #include "../localisation/localisation.h" + #include "../ride/ride.h" + #include "../interface/window.h" + #include "../util/util.h" + #include "scenery.h" + #include "banner.h" + #include "map.h" + #include "park.h" +} + +rct_banner gBanners[MAX_BANNERS]; + +extern "C" +{ + /** + * + * rct2: 0x006B9CB0 + */ + void banner_init() + { + for (sint32 i = 0; i < MAX_BANNERS; i++) { + gBanners[i].type = BANNER_NULL; + } + } + + /** + * Creates a new banner and returns the index of the banner + * If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns + * the first unused index but does NOT mark the banner as created. + * returns 0xFF on failure. + * + * rct2: 0x006BA278 + */ + sint32 create_new_banner(uint8 flags) + { + sint32 banner_index = 0; + for (; banner_index < MAX_BANNERS; banner_index++) { + if (gBanners[banner_index].type == BANNER_NULL) { + break; + } + } + + if (banner_index == MAX_BANNERS) { + gGameCommandErrorText = STR_TOO_MANY_BANNERS_IN_GAME; + return BANNER_NULL; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + rct_banner* banner = &gBanners[banner_index]; + + banner->flags = 0; + banner->type = 0; + banner->string_idx = STR_DEFAULT_SIGN; + banner->colour = 2; + banner->text_colour = 2; + } + return banner_index; + } + + rct_map_element *banner_get_map_element(sint32 bannerIndex) + { + rct_banner *banner = &gBanners[bannerIndex]; + rct_map_element *mapElement = map_get_first_element_at(banner->x, banner->y); + do { + if (map_element_get_banner_index(mapElement) == bannerIndex) { + return mapElement; + } + } while (!map_element_is_last_for_tile(mapElement++)); + return NULL; + } + + /** + * + * rct2: 0x006B7EAB + */ + static sint32 banner_get_ride_index_at(sint32 x, sint32 y, sint32 z) + { + rct_map_element *mapElement; + rct_ride *ride; + sint32 rideIndex, resultRideIndex; + + resultRideIndex = -1; + mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) + continue; + + rideIndex = mapElement->properties.track.ride_index; + ride = get_ride(rideIndex); + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) + continue; + + if ((mapElement->clearance_height * 8) + 32 <= z) + continue; + + resultRideIndex = rideIndex; + } while (!map_element_is_last_for_tile(mapElement++)); + + return resultRideIndex; + } + + /** + * + * rct2: 0x006B7D86 + */ + sint32 banner_get_closest_ride_index(sint32 x, sint32 y, sint32 z) + { + uint32 i, rideIndex; + rct_ride *ride; + + static const rct_xy16 NeighbourCheckOrder[] = { + { 32, 0 }, + { -32, 0 }, + { 0, 32 }, + { 0, -32 }, + { -32, +32 }, + { +32, -32 }, + { +32, +32 }, + { -32, +32 }, + { 0, 0 } + }; + + for (i = 0; i < Util::CountOf(NeighbourCheckOrder); i++) { + rideIndex = banner_get_ride_index_at(x + NeighbourCheckOrder[i].x, y + NeighbourCheckOrder[i].y, z); + if (rideIndex != -1) { + return rideIndex; + } + } + + rideIndex = -1; + sint32 resultDistance = INT_MAX; + FOR_ALL_RIDES(i, ride) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) + continue; + + uint16 xy = ride->overall_view; + if (xy == 0xFFFF) + continue; + + sint32 rideX = (xy & 0xFF) * 32; + sint32 rideY = (xy >> 8) * 32; + sint32 distance = abs(x - rideX) + abs(y - rideY); + if (distance < resultDistance) { + resultDistance = distance; + rideIndex = i; + } + } + + return rideIndex; + } + + void fix_banner_count() + { + for (sint32 banner_index = 0; banner_index < MAX_BANNERS; banner_index++) { + rct_map_element *map_element = banner_get_map_element(banner_index); + if (map_element == NULL) + gBanners[banner_index].type = BANNER_NULL; + } + } + + + /** + * + * rct2: 0x006BA058 + */ + void game_command_remove_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) + { + sint32 x = *eax; + sint32 y = *ecx; + uint8 base_height = *edx; + uint8 banner_position = *edx >> 8; + uint8 flags = *ebx & 0xFF; + sint32 z = base_height * 8; + gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + gCommandPosition.x = x + 16; + gCommandPosition.y = y + 16; + gCommandPosition.z = z; + + if (!(flags & GAME_COMMAND_FLAG_GHOST) && game_is_paused() && !gCheatsBuildInPauseMode) { + gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; + } + + if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, z - 16)) { + *ebx = MONEY32_UNDEFINED; + return; + } + + // Slight modification to the code so that it now checks height as well + // This was causing a bug with banners on two paths stacked. + rct_map_element* map_element = map_get_banner_element_at(x / 32, y / 32, base_height, banner_position); + if (map_element == NULL) { + *ebx = MONEY32_UNDEFINED; + return; + } + + rct_banner *banner = &gBanners[map_element->properties.banner.index]; + rct_scenery_entry *scenery_entry = get_banner_entry(banner->type); + money32 refund = 0; + if (scenery_entry != NULL && scenery_entry != (rct_scenery_entry *)-1) { + refund = -((scenery_entry->banner.price * 3) / 4); + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (gGameCommandNestLevel == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + map_element_remove_banner_entry(map_element); + map_invalidate_tile_zoom1(x, y, z, z + 32); + map_element_remove(map_element); + } + + *ebx = refund; + if (gParkFlags & PARK_FLAGS_NO_MONEY) { + *ebx = 0; + } + } + + + /** + * + * rct2: 0x006BA16A + */ + void game_command_set_banner_colour(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) + { + gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + sint32 x = *eax; + sint32 y = *ecx; + uint8 base_height = *edx; + uint8 banner_position = *edx >> 8; + uint8 colour = *ebp; + sint32 z = (base_height * 8); + gCommandPosition.x = x + 16; + gCommandPosition.y = y + 16; + gCommandPosition.z = z; + + if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) { + if (!map_is_location_owned(x, y, z - 16)) { + *ebx = MONEY32_UNDEFINED; + return; + } + } + + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + + bool found = false; + do { + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) + continue; + + if (map_element->properties.banner.position != banner_position) + continue; + + found = true; + break; + } while (!map_element_is_last_for_tile(map_element++)); + + if (found == false) { + *ebx = MONEY32_UNDEFINED; + return; + } + + rct_window* window = window_find_by_number(WC_BANNER, map_element->properties.banner.index); + if (window) { + window_invalidate(window); + } + gBanners[map_element->properties.banner.index].colour = colour; + map_invalidate_tile_zoom1(x, y, z, z + 32); + } + + *ebx = 0; + } + + /** + * + * rct2: 0x006B9E6D + */ + void game_command_place_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) + { + sint32 x = (uint16)*eax; + sint32 y = (uint16)*ecx; + uint8 base_height = *edx; + uint8 edge = *edx >> 8; + uint8 colour = *edi; + uint8 type = *ebx >> 8; + gCommandPosition.x = x + 16; + gCommandPosition.y = y + 16; + gCommandPosition.z = base_height * 16; + gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + if (game_is_paused() && !gCheatsBuildInPauseMode) { + gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; + } + + if (!map_check_free_elements_and_reorganise(1)) { + *ebx = MONEY32_UNDEFINED; + return; + } + + if (x >= 8192 || y >= 8192) { + *ebx = MONEY32_UNDEFINED; + return; + } + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + sint32 dl = base_height * 2; + sint32 ch = (base_height - 1) * 2; + + bool pathFound = false; + do { + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH) + continue; + + if (map_element->base_height != dl && map_element->base_height != ch) + continue; + + if (!(map_element->properties.path.edges & (1 << edge))) + continue; + + pathFound = true; + break; + } while (!map_element_is_last_for_tile(map_element++)); + + if (pathFound == false) { + gGameCommandErrorText = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; + *ebx = MONEY32_UNDEFINED; + return; + } + + if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !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; + + // Check to see if there is a banner in the way + do { + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) + continue; + + if (map_element->base_height != dl) + continue; + + if ((map_element->properties.banner.position & 0x3) != edge) + continue; + + gGameCommandErrorText = STR_BANNER_SIGN_IN_THE_WAY; + *ebx = MONEY32_UNDEFINED; + return; + } while (!map_element_is_last_for_tile(map_element++)); + + sint32 banner_index = create_new_banner(*ebx); + if (banner_index == BANNER_NULL) { + *ebx = MONEY32_UNDEFINED; + return; + } + *edi = banner_index; + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + if (gGameCommandNestLevel == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); + assert(new_map_element != NULL); + gBanners[banner_index].type = type; + gBanners[banner_index].colour = colour; + gBanners[banner_index].x = x / 32; + gBanners[banner_index].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 = banner_index; + if (*ebx & GAME_COMMAND_FLAG_GHOST) { + new_map_element->flags |= MAP_ELEMENT_FLAG_GHOST; + } + 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 (gParkFlags & PARK_FLAGS_NO_MONEY) { + *ebx = 0; + } + } + + void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { + static char newName[128]; + + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + log_warning("Invalid game command for setting banner name, banner id = %d", *ecx); + *ebx = MONEY32_UNDEFINED; + return; + } + rct_banner* banner = &gBanners[*ecx]; + + sint32 nameChunkIndex = *eax & 0xFFFF; + + gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; + sint32 nameChunkOffset = nameChunkIndex - 1; + if (nameChunkOffset < 0) + nameChunkOffset = 2; + nameChunkOffset *= 12; + nameChunkOffset = min(nameChunkOffset, (sint32)Util::CountOf(newName) - 12); + memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 0), edx, sizeof(uint32)); + memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 4), ebp, sizeof(uint32)); + memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 8), edi, sizeof(uint32)); + + if (nameChunkIndex != 0) { + *ebx = 0; + return; + } + + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + + utf8 *buffer = gCommonStringFormatBuffer; + utf8 *dst = buffer; + dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); + safe_strcpy(dst, newName, 32); + + rct_string_id stringId = user_string_allocate(128, buffer); + if (stringId) { + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = stringId; + user_string_free(prev_string_id); + rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx); + if (w) { + window_invalidate(w); + } + } + else { + gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; + *ebx = MONEY32_UNDEFINED; + return; + } + + *ebx = 0; + } + + void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS; + *ebx = MONEY32_UNDEFINED; + return; + } + + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + + rct_banner* banner = &gBanners[*ecx]; + + banner->colour = (uint8)*edx; + banner->text_colour = (uint8)*edi; + banner->flags = (uint8)*ebp; + + uint8 bannerIndex = *ecx & 0xFF; + + sint32 x = banner->x << 5; + sint32 y = banner->y << 5; + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + bool bannerFound = false; + do { + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) + continue; + + if (map_element->properties.banner.index != bannerIndex) + continue; + + bannerFound = true; + break; + } while (!map_element_is_last_for_tile(map_element++)); + + if (bannerFound == false) { + *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); + } + + sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour; + + utf8 buffer[256]; + format_string(buffer, 256, banner->string_idx, 0); + sint32 firstCodepoint = utf8_get_next(buffer, NULL); + if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END) { + utf8_write_codepoint(buffer, colourCodepoint); + } + else { + utf8_insert_codepoint(buffer, colourCodepoint); + } + + rct_string_id stringId = user_string_allocate(128, buffer); + if (stringId != 0) { + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = stringId; + user_string_free(prev_string_id); + rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx); + if (w) { + window_invalidate(w); + } + } + else { + gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; + *ebx = MONEY32_UNDEFINED; + return; + } + + *ebx = 0; + } + +} diff --git a/src/openrct2/world/banner.h b/src/openrct2/world/banner.h index 003d711e18..aeee30d7f0 100644 --- a/src/openrct2/world/banner.h +++ b/src/openrct2/world/banner.h @@ -40,7 +40,7 @@ enum{ BANNER_FLAG_NO_ENTRY = (1 << 0), BANNER_FLAG_IS_LARGE_SCENERY = (1 << 1), BANNER_FLAG_LINKED_TO_RIDE = (1 << 2), - BANNER_FLAG_4 = (1 << 3) + BANNER_FLAG_IS_WALL = (1 << 3) }; extern rct_banner gBanners[MAX_BANNERS]; diff --git a/src/openrct2/world/map.c b/src/openrct2/world/map.c index f9f4c7c006..44fcc1eaa5 100644 --- a/src/openrct2/world/map.c +++ b/src/openrct2/world/map.c @@ -1089,69 +1089,6 @@ void game_command_remove_large_scenery(sint32* eax, sint32* ebx, sint32* ecx, si return; } -/** - * - * rct2: 0x006BA058 - */ -void game_command_remove_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) -{ - sint32 x = *eax; - sint32 y = *ecx; - uint8 base_height = *edx; - uint8 banner_position = *edx >> 8; - uint8 flags = *ebx & 0xFF; - sint32 z = base_height * 8; - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; - gCommandPosition.x = x + 16; - gCommandPosition.y = y + 16; - gCommandPosition.z = z; - - if(!(flags & GAME_COMMAND_FLAG_GHOST) && game_is_paused() && !gCheatsBuildInPauseMode){ - gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - *ebx = MONEY32_UNDEFINED; - return; - } - - if(!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, z - 16)){ - *ebx = MONEY32_UNDEFINED; - return; - } - - // Slight modification to the code so that it now checks height as well - // This was causing a bug with banners on two paths stacked. - rct_map_element* map_element = map_get_banner_element_at(x / 32, y / 32, base_height, banner_position); - if (map_element == NULL){ - *ebx = MONEY32_UNDEFINED; - return; - } - - rct_banner *banner = &gBanners[map_element->properties.banner.index]; - rct_scenery_entry *scenery_entry = get_banner_entry(banner->type); - money32 refund = 0; - if (scenery_entry != NULL && scenery_entry != (rct_scenery_entry *)-1) { - refund = -((scenery_entry->banner.price * 3) / 4); - } - - if (flags & GAME_COMMAND_FLAG_APPLY) { - if (gGameCommandNestLevel == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { - rct_xyz16 coord; - coord.x = x + 16; - coord.y = y + 16; - coord.z = map_element_height(coord.x, coord.y); - network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); - } - - map_element_remove_banner_entry(map_element); - map_invalidate_tile_zoom1(x, y, z, z + 32); - map_element_remove(map_element); - } - - *ebx = refund; - if (gParkFlags & PARK_FLAGS_NO_MONEY) { - *ebx = 0; - } -} - /** * * rct2: 0x006E0F26 @@ -1287,61 +1224,6 @@ void game_command_set_large_scenery_colour(sint32* eax, sint32* ebx, sint32* ecx *ebx = 0; } -/** - * - * rct2: 0x006BA16A - */ -void game_command_set_banner_colour(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) -{ - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; - sint32 x = *eax; - sint32 y = *ecx; - uint8 base_height = *edx; - uint8 banner_position = *edx >> 8; - uint8 colour = *ebp; - sint32 z = (base_height * 8); - gCommandPosition.x = x + 16; - gCommandPosition.y = y + 16; - gCommandPosition.z = z; - - if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode){ - if (!map_is_location_owned(x, y, z - 16)){ - *ebx = MONEY32_UNDEFINED; - return; - } - } - - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); - - bool found = false; - do { - if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) - continue; - - if (map_element->properties.banner.position != banner_position) - continue; - - found = true; - break; - } while (!map_element_is_last_for_tile(map_element++)); - - if (found == false){ - *ebx = MONEY32_UNDEFINED; - return; - } - - rct_window* window = window_find_by_number(WC_BANNER, map_element->properties.banner.index); - if(window){ - window_invalidate(window); - } - gBanners[map_element->properties.banner.index].colour = colour; - map_invalidate_tile_zoom1(x, y, z, z + 32); - } - - *ebx = 0; -} - // This will cause clear scenery to remove paths // This should be a flag for the game command which can be set via a checkbox on the clear scenery window. // #define CLEAR_SCENERY_REMOVES_PATHS @@ -2746,126 +2628,6 @@ void game_command_set_water_height(sint32* eax, sint32* ebx, sint32* ecx, sint32 } } -/** - * - * rct2: 0x006B9E6D - */ -void game_command_place_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) -{ - sint32 x = (uint16)*eax; - sint32 y = (uint16)*ecx; - uint8 base_height = *edx; - uint8 edge = *edx >> 8; - uint8 colour = *edi; - uint8 type = *ebx >> 8; - gCommandPosition.x = x + 16; - gCommandPosition.y = y + 16; - gCommandPosition.z = base_height * 16; - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; - if (game_is_paused() && !gCheatsBuildInPauseMode) { - gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - *ebx = MONEY32_UNDEFINED; - return; - } - - if (!map_check_free_elements_and_reorganise(1)) { - *ebx = MONEY32_UNDEFINED; - return; - } - - if (x >= 8192 || y >= 8192) { - *ebx = MONEY32_UNDEFINED; - return; - } - - rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); - sint32 dl = base_height * 2; - sint32 ch = (base_height - 1) * 2; - - bool pathFound = false; - do { - if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH) - continue; - - if (map_element->base_height != dl && map_element->base_height != ch) - continue; - - if (!(map_element->properties.path.edges & (1 << edge))) - continue; - - pathFound = true; - break; - } while (!map_element_is_last_for_tile(map_element++)); - - if (pathFound == false) { - gGameCommandErrorText = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; - *ebx = MONEY32_UNDEFINED; - return; - } - - if(!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !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; - - // Check to see if there is a banner in the way - do { - if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) - continue; - - if (map_element->base_height != dl) - continue; - - if ((map_element->properties.banner.position & 0x3) != edge) - continue; - - gGameCommandErrorText = STR_BANNER_SIGN_IN_THE_WAY; - *ebx = MONEY32_UNDEFINED; - return; - } while (!map_element_is_last_for_tile(map_element++)); - - sint32 banner_index = create_new_banner(*ebx); - if(banner_index == BANNER_NULL){ - *ebx = MONEY32_UNDEFINED; - return; - } - *edi = banner_index; - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - if (gGameCommandNestLevel == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { - rct_xyz16 coord; - coord.x = x + 16; - coord.y = y + 16; - coord.z = map_element_height(coord.x, coord.y); - network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); - } - - rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); - assert(new_map_element != NULL); - gBanners[banner_index].type = type; - gBanners[banner_index].colour = colour; - gBanners[banner_index].x = x / 32; - gBanners[banner_index].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 = banner_index; - if(*ebx & GAME_COMMAND_FLAG_GHOST){ - new_map_element->flags |= MAP_ELEMENT_FLAG_GHOST; - } - 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(gParkFlags & PARK_FLAGS_NO_MONEY){ - *ebx = 0; - } -} - /** * * rct2: 0x006E0D6E, 0x006B8D88 @@ -4580,62 +4342,6 @@ void map_clear_all_elements() } } -void game_command_set_banner_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { - static char newName[128]; - - if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) - { - log_warning("Invalid game command for setting banner name, banner id = %d", *ecx); - *ebx = MONEY32_UNDEFINED; - return; - } - rct_banner* banner = &gBanners[*ecx]; - - sint32 nameChunkIndex = *eax & 0xFFFF; - - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS; - sint32 nameChunkOffset = nameChunkIndex - 1; - if (nameChunkOffset < 0) - nameChunkOffset = 2; - nameChunkOffset *= 12; - nameChunkOffset = min(nameChunkOffset, countof(newName) - 12); - memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 0), edx, sizeof(uint32)); - memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 4), ebp, sizeof(uint32)); - memcpy((void*)((uintptr_t)newName + (uintptr_t)nameChunkOffset + 8), edi, sizeof(uint32)); - - if (nameChunkIndex != 0) { - *ebx = 0; - return; - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { - *ebx = 0; - return; - } - - utf8 *buffer = gCommonStringFormatBuffer; - utf8 *dst = buffer; - dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); - safe_strcpy(dst, newName, 32); - - rct_string_id stringId = user_string_allocate(128, buffer); - if (stringId) { - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = stringId; - user_string_free(prev_string_id); - rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx); - if (w) { - window_invalidate(w); - } - } else { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - *ebx = MONEY32_UNDEFINED; - return; - } - - *ebx = 0; -} - void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { static char newName[128]; @@ -4705,82 +4411,6 @@ void game_command_set_sign_name(sint32* eax, sint32* ebx, sint32* ecx, sint32* e *ebx = 0; } -void game_command_set_banner_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { - if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) - { - gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS; - *ebx = MONEY32_UNDEFINED; - return; - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { - *ebx = 0; - return; - } - - rct_banner* banner = &gBanners[*ecx]; - - banner->colour = (uint8)*edx; - banner->text_colour = (uint8)*edi; - banner->flags = (uint8)*ebp; - - uint8 bannerIndex = *ecx & 0xFF; - - sint32 x = banner->x << 5; - sint32 y = banner->y << 5; - - rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); - bool bannerFound = false; - do { - if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) - continue; - - if (map_element->properties.banner.index != bannerIndex) - continue; - - bannerFound = true; - break; - } while (!map_element_is_last_for_tile(map_element++)); - - if (bannerFound == false) { - *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); - } - - sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour; - - utf8 buffer[256]; - format_string(buffer, 256, banner->string_idx, 0); - sint32 firstCodepoint = utf8_get_next(buffer, NULL); - if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END) { - utf8_write_codepoint(buffer, colourCodepoint); - } else { - utf8_insert_codepoint(buffer, colourCodepoint); - } - - rct_string_id stringId = user_string_allocate(128, buffer); - if (stringId != 0) { - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = stringId; - user_string_free(prev_string_id); - rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx); - if (w) { - window_invalidate(w); - } - } else { - gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT; - *ebx = MONEY32_UNDEFINED; - return; - } - - *ebx = 0; -} - void game_command_set_sign_style(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp) { uint8 bannerId = *ecx & 0xFF; rct_banner *banner = &gBanners[bannerId]; diff --git a/src/openrct2/world/wall.cpp b/src/openrct2/world/wall.cpp index 97cb3d039a..033979c107 100644 --- a/src/openrct2/world/wall.cpp +++ b/src/openrct2/world/wall.cpp @@ -476,7 +476,7 @@ static money32 WallPlace(uint8 wallType, rct_banner * banner = &gBanners[bannerIndex]; if (flags & GAME_COMMAND_FLAG_APPLY) { - banner->flags |= BANNER_FLAG_4; + banner->flags |= BANNER_FLAG_IS_WALL; banner->type = 0; banner->x = position.x / 32; banner->y = position.y / 32;