From a95357a32d3e440dcf08885e43b4b0b0a636639c Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sat, 31 Oct 2015 02:25:43 -0600 Subject: [PATCH] signs and banners editable in multiplayer --- src/game.c | 10 ++- src/game.h | 6 +- src/windows/banner.c | 53 ++--------- src/windows/sign.c | 110 ++++++----------------- src/world/map.c | 210 +++++++++++++++++++++++++++++++++++++++++++ src/world/map.h | 4 + 6 files changed, 260 insertions(+), 133 deletions(-) diff --git a/src/game.c b/src/game.c index b16a705913..f603d93422 100644 --- a/src/game.c +++ b/src/game.c @@ -404,7 +404,7 @@ static int game_check_affordability(int cost) return MONEY32_UNDEFINED; } -static GAME_COMMAND_POINTER* new_game_command_table[58]; +static GAME_COMMAND_POINTER* new_game_command_table[62]; /** * @@ -1131,7 +1131,7 @@ void game_load_or_quit_no_save_prompt() } } -static GAME_COMMAND_POINTER* new_game_command_table[58] = { +static GAME_COMMAND_POINTER* new_game_command_table[62] = { game_command_set_ride_appearance, game_command_set_land_height, game_pause_toggle, @@ -1189,5 +1189,9 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_set_large_scenery_colour, game_command_set_banner_colour, game_command_set_land_ownership, - game_command_clear_scenery + game_command_clear_scenery, + game_command_set_banner_name, + game_command_set_sign_name, + game_command_set_banner_style, + game_command_set_sign_style }; diff --git a/src/game.h b/src/game.h index ec806a8cc4..286c21fb1f 100644 --- a/src/game.h +++ b/src/game.h @@ -83,7 +83,11 @@ enum GAME_COMMAND { GAME_COMMAND_SET_LARGE_SCENERY_COLOUR, GAME_COMMAND_SET_BANNER_COLOUR, GAME_COMMAND_SET_LAND_OWNERSHIP, - GAME_COMMAND_CLEAR_SCENERY + GAME_COMMAND_CLEAR_SCENERY, + GAME_COMMAND_SET_BANNER_NAME, + GAME_COMMAND_SET_SIGN_NAME, + GAME_COMMAND_SET_BANNER_STYLE, + GAME_COMMAND_SET_SIGN_STYLE }; enum { diff --git a/src/windows/banner.c b/src/windows/banner.c index 01f6d4ec1d..d084a8de62 100644 --- a/src/windows/banner.c +++ b/src/windows/banner.c @@ -199,13 +199,7 @@ static void window_banner_mouseup(rct_window *w, int widgetIndex) break; case WIDX_BANNER_NO_ENTRY: textinput_cancel(); - banner->flags ^= BANNER_FLAG_NO_ENTRY; - window_invalidate(w); - - map_element->properties.banner.flags = 0xFF; - if (banner->flags & BANNER_FLAG_NO_ENTRY){ - map_element->properties.banner.flags &= ~(1 << map_element->properties.banner.position); - } + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->colour, GAME_COMMAND_SET_BANNER_STYLE, banner->text_colour, banner->flags ^ BANNER_FLAG_NO_ENTRY); break; } } @@ -254,35 +248,13 @@ static void window_banner_dropdown(rct_window *w, int widgetIndex, int dropdownI if (dropdownIndex == -1) break; - banner->colour = (uint8)dropdownIndex; - window_invalidate(w); + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_BANNER_STYLE, banner->text_colour, 0); break; case WIDX_TEXT_COLOR_DROPDOWN_BUTTON: if (dropdownIndex == -1) break; - banner->text_colour = dropdownIndex + 1; - - int colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour; - - uint8 buffer[256]; - format_string(buffer, banner->string_idx, 0); - int 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); - window_invalidate(w); - } else { - window_error_open(2984, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id)); - } + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->colour, GAME_COMMAND_SET_BANNER_STYLE, dropdownIndex + 1, 0); break; } } @@ -291,22 +263,9 @@ static void window_banner_dropdown(rct_window *w, int widgetIndex, int dropdownI static void window_banner_textinput(rct_window *w, int widgetIndex, char *text) { if (widgetIndex == WIDX_BANNER_TEXT && text != NULL) { - rct_banner* banner = &gBanners[w->number]; - - utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8); - utf8 *dst = buffer; - dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); - strncpy(dst, text, 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); - window_invalidate(w); - } else { - window_error_open(2984, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id)); - } + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 0)), GAME_COMMAND_SET_BANNER_NAME, *((int*)(text + 8)), *((int*)(text + 4))); + game_do_command(2, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 12)), GAME_COMMAND_SET_BANNER_NAME, *((int*)(text + 20)), *((int*)(text + 16))); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 24)), GAME_COMMAND_SET_BANNER_NAME, *((int*)(text + 32)), *((int*)(text + 28))); } } diff --git a/src/windows/sign.c b/src/windows/sign.c index d1e288a816..23f2eb85be 100644 --- a/src/windows/sign.c +++ b/src/windows/sign.c @@ -187,8 +187,10 @@ void window_sign_open(rct_windownumber number) int view_z = map_element->base_height << 3; w->frame_no = view_z; - w->list_information_type = map_element->properties.scenerymultiple.colour[0] & 0x1F; - w->var_492 = map_element->properties.scenerymultiple.colour[1] & 0x1F; + rct_banner* banner = &gBanners[w->number]; + + banner->colour = map_element->properties.scenerymultiple.colour[0] & 0x1F; + banner->text_colour = map_element->properties.scenerymultiple.colour[1] & 0x1F; w->var_48C = map_element->properties.scenerymultiple.type; view_x += 16; @@ -274,10 +276,10 @@ static void window_sign_mousedown(int widgetIndex, rct_window*w, rct_widget* wid switch (widgetIndex) { case WIDX_MAIN_COLOR: - window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, (uint8)w->list_information_type); + window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, (uint8)banner->colour); break; case WIDX_TEXT_COLOR: - window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, (uint8)w->var_492); + window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, (uint8)banner->text_colour); break; } } @@ -285,70 +287,31 @@ static void window_sign_mousedown(int widgetIndex, rct_window*w, rct_widget* wid /* rct2: 0x6B979C */ static void window_sign_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { + rct_banner *banner = &gBanners[w->number]; + switch (widgetIndex){ case WIDX_MAIN_COLOR: if (dropdownIndex == -1) return; - w->list_information_type = dropdownIndex; + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->text_colour, GAME_COMMAND_SET_SIGN_STYLE, dropdownIndex, 1); break; case WIDX_TEXT_COLOR: if (dropdownIndex == -1) return; - w->var_492 = dropdownIndex; + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_SIGN_STYLE, banner->colour, 1); break; default: return; } - rct_banner *banner = &gBanners[w->number]; - rct_map_element *mapElement = banner_get_map_element(w->number); - if (mapElement == NULL || map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) - return; - - sign_set_colour( - banner->x * 32, - banner->y * 32, - mapElement->base_height, - mapElement->type & 3, - mapElement->properties.scenerymultiple.type >> 10, - w->list_information_type & 0xFF, - w->var_492 & 0xFF - ); window_invalidate(w); } /* rct2: 0x6B9791 & 0x6E6171*/ static void window_sign_textinput(rct_window *w, int widgetIndex, char *text) { - rct_banner* banner = &gBanners[w->number]; - int x = banner->x << 5; - int y = banner->y << 5; - if (widgetIndex == WIDX_SIGN_TEXT && text != NULL) { - if (*text != 0) { - rct_string_id string_id = user_string_allocate(128, text); - if (string_id != 0) { - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = string_id; - user_string_free(prev_string_id); - - banner->flags &= ~(BANNER_FLAG_2); - gfx_invalidate_screen(); - } else { - window_error_open(2984, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id)); - } - } - else{ - int rideIndex = banner_get_closest_ride_index(x, y, 16); - if (rideIndex == -1) - return; - - banner->colour = rideIndex; - banner->flags |= BANNER_FLAG_2; - - rct_string_id prev_string_id = banner->string_idx; - banner->string_idx = 778; - user_string_free(prev_string_id); - gfx_invalidate_screen(); - } + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 0)), GAME_COMMAND_SET_SIGN_NAME, *((int*)(text + 8)), *((int*)(text + 4))); + game_do_command(2, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 12)), GAME_COMMAND_SET_SIGN_NAME, *((int*)(text + 20)), *((int*)(text + 16))); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 24)), GAME_COMMAND_SET_SIGN_NAME, *((int*)(text + 32)), *((int*)(text + 28))); } } @@ -372,8 +335,10 @@ static void window_sign_invalidate(rct_window *w) text_colour_btn->type = WWT_COLORBTN; } - main_colour_btn->image = (w->list_information_type << 19) | 0x600013C3; - text_colour_btn->image = (w->var_492 << 19) | 0x600013C3; + rct_banner* banner = &gBanners[w->number]; + + main_colour_btn->image = (banner->colour << 19) | 0x600013C3; + text_colour_btn->image = (banner->text_colour << 19) | 0x600013C3; } /* rct2: 0x006B9754 & 0x006E6134 */ @@ -468,8 +433,9 @@ void window_sign_small_open(rct_windownumber number){ int view_z = map_element->base_height << 3; w->frame_no = view_z; - w->list_information_type = map_element->properties.fence.item[1] & 0x1F; - w->var_492 = (map_element->properties.fence.item[1] >> 5) | ((map_element->flags&0x60) >> 2); + rct_banner* banner = &gBanners[w->number]; + banner->colour = map_element->properties.fence.item[1] & 0x1F; + banner->text_colour = (map_element->properties.fence.item[1] >> 5) | ((map_element->flags&0x60) >> 2); w->var_48C = map_element->properties.fence.type; view_x += 16; @@ -550,43 +516,21 @@ static void window_sign_small_mouseup(rct_window *w, int widgetIndex) /* rct2: 0x6E617C */ static void window_sign_small_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { + rct_banner* banner = &gBanners[w->number]; + switch (widgetIndex){ case WIDX_MAIN_COLOR: if (dropdownIndex == -1) return; - w->list_information_type = dropdownIndex; + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_SIGN_STYLE, banner->text_colour, 0); break; case WIDX_TEXT_COLOR: if (dropdownIndex == -1) return; - w->var_492 = dropdownIndex; + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->colour, GAME_COMMAND_SET_SIGN_STYLE, dropdownIndex, 0); break; default: return; } - rct_banner* banner = &gBanners[w->number]; - int x = banner->x << 5; - int y = banner->y << 5; - - rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); - - while (1){ - if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) { - rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type]; - if (scenery_entry->wall.var_0D != 0xFF){ - if (map_element->properties.fence.item[0] == w->number) - break; - } - } - map_element++; - } - - map_element->flags &= 0x9F; - map_element->properties.fence.item[1] = - w->list_information_type | - ((w->var_492 & 0x7) << 5); - map_element->flags |= ((w->var_492 & 0x18) << 2); - - map_invalidate_tile(x, y, map_element->base_height * 8, map_element->clearance_height * 8); window_invalidate(w); } @@ -610,6 +554,8 @@ static void window_sign_small_invalidate(rct_window *w) text_colour_btn->type = WWT_COLORBTN; } - main_colour_btn->image = (w->list_information_type << 19) | 0x600013C3; - text_colour_btn->image = (w->var_492 << 19) | 0x600013C3; + rct_banner* banner = &gBanners[w->number]; + + main_colour_btn->image = (banner->colour << 19) | 0x600013C3; + text_colour_btn->image = (banner->text_colour << 19) | 0x600013C3; } diff --git a/src/world/map.c b/src/world/map.c index 116bbc56ae..fbc12b811a 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -4716,6 +4716,216 @@ void game_command_place_park_entrance(int* eax, int* ebx, int* ecx, int* edx, in (*ebx >> 8) & 0xFF); } +void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + static char newName[128]; + + rct_banner* banner = &gBanners[*ecx]; + + int nameChunkIndex = *eax & 0xFFFF; + + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; + int nameChunkOffset = nameChunkIndex - 1; + if (nameChunkOffset < 0) + nameChunkOffset = 2; + nameChunkOffset *= 12; + RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; + RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; + RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; + + if (nameChunkIndex != 0) { + *ebx = 0; + return; + } + + utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8); + utf8 *dst = buffer; + dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); + strncpy(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 { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 2984; + *ebx = MONEY32_UNDEFINED; + return; + } + + *ebx = 0; +} + +void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + static char newName[128]; + + rct_banner* banner = &gBanners[*ecx]; + int x = banner->x << 5; + int y = banner->y << 5; + + int nameChunkIndex = *eax & 0xFFFF; + + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; + int nameChunkOffset = nameChunkIndex - 1; + if (nameChunkOffset < 0) + nameChunkOffset = 2; + nameChunkOffset *= 12; + RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; + RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; + RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; + + if (nameChunkIndex != 0) { + *ebx = 0; + return; + } + + if (newName[0] != 0) { + rct_string_id string_id = user_string_allocate(128, newName); + if (string_id != 0) { + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = string_id; + user_string_free(prev_string_id); + + banner->flags &= ~(BANNER_FLAG_2); + gfx_invalidate_screen(); + } else { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 2984; + *ebx = MONEY32_UNDEFINED; + return; + } + } + else{ + int rideIndex = banner_get_closest_ride_index(x, y, 16); + if (rideIndex == -1) { + *ebx = 0; + return; + } + + banner->colour = rideIndex; + banner->flags |= BANNER_FLAG_2; + + rct_string_id prev_string_id = banner->string_idx; + banner->string_idx = 778; + user_string_free(prev_string_id); + gfx_invalidate_screen(); + } + + *ebx = 0; +} + +void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + rct_banner* banner = &gBanners[*ecx]; + + banner->colour = (uint8)*edx; + banner->text_colour = (uint8)*edi; + + banner->flags = (uint8)*ebp; + + int x = banner->x << 5; + int y = banner->y << 5; + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + + while (1){ + if ((map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) && + (map_element->properties.banner.index == *ecx)) break; + map_element++; + } + + map_element->properties.banner.flags = 0xFF; + if (banner->flags & BANNER_FLAG_NO_ENTRY){ + map_element->properties.banner.flags &= ~(1 << map_element->properties.banner.position); + } + + int colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour; + + uint8 buffer[256]; + format_string(buffer, banner->string_idx, 0); + int 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 { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 2984; + *ebx = MONEY32_UNDEFINED; + return; + } + + *ebx = 0; +} + +void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + rct_banner *banner = &gBanners[*ecx]; + int x = banner->x << 5; + int y = banner->y << 5; + + banner->colour = (uint8)*edx; + banner->text_colour = (uint8)*edi; + + if (*ebp == 0) { // small sign + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + + while (1){ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) { + rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type]; + if (scenery_entry->wall.var_0D != 0xFF){ + if (map_element->properties.fence.item[0] == *ecx) + break; + } + } + map_element++; + } + map_element->flags &= 0x9F; + map_element->properties.fence.item[1] = + banner->colour | + ((banner->text_colour & 0x7) << 5); + map_element->flags |= ((banner->text_colour & 0x18) << 2); + + map_invalidate_tile(x, y, map_element->base_height * 8, map_element->clearance_height * 8); + } else { // large sign + rct_map_element *mapElement = banner_get_map_element(*ecx); + if (mapElement == NULL || map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 2984; + *ebx = MONEY32_UNDEFINED; + return; + } + + sign_set_colour( + banner->x * 32, + banner->y * 32, + mapElement->base_height, + mapElement->type & 3, + mapElement->properties.scenerymultiple.type >> 10, + banner->colour, + banner->text_colour + ); + } + + rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx); + if (w) { + window_invalidate(w); + } + + *ebx = 0; +} + /** * Gets the map element at x, y, z. * @param x x units, not tiles. diff --git a/src/world/map.h b/src/world/map.h index c99617a8c4..e1c4ed0aa0 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -335,6 +335,10 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi void game_command_place_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_place_park_entrance(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_sign_style(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])