From 298420fd1e85352e4e07dff7df0b6e1e7457801b Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Thu, 2 Nov 2017 20:16:30 -0400 Subject: [PATCH] Finalize follow sprite command Added new smart follow variable to window to more intuitively follow sprites that may not be directly followable at all times. Follow sprite is now canceled when dragging the screen but not scrolling. This is only relevant when testing title sequences in game. Select sprite button is now disabled in the title menu. Sprites are now identified based on their name. Excess identification information is not given as it'd clutter up the screen and is not necissary with the viewbox in the command editor. --- data/language/en-GB.txt | 10 +- distribution/changelog.txt | 1 + src/openrct2-ui/input/MouseInput.cpp | 1 + .../windows/TitleCommandEditor.cpp | 117 +++++++++++++-- src/openrct2-ui/windows/TitleEditor.cpp | 10 +- src/openrct2/Game.cpp | 7 +- src/openrct2/interface/viewport.c | 139 ++++++++++++++++++ src/openrct2/interface/viewport.h | 4 + src/openrct2/interface/window.c | 18 +++ src/openrct2/interface/window.h | 4 + src/openrct2/localisation/string_ids.h | 10 +- src/openrct2/title/TitleScreen.cpp | 3 +- src/openrct2/title/TitleSequence.cpp | 16 +- src/openrct2/title/TitleSequence.h | 7 +- src/openrct2/title/TitleSequencePlayer.cpp | 21 ++- src/openrct2/world/sprite.c | 15 ++ src/openrct2/world/sprite.h | 3 + 17 files changed, 353 insertions(+), 33 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 400338d5bf..7daad8021b 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -4488,8 +4488,14 @@ STR_6178 :Load{MOVE_X}{87}{RED}Missing scenario STR_6179 :Select STR_6180 :No scenario selected STR_6181 :{RED}Missing scenario -STR_6182 :Follow sprite -STR_6183 :Select sprite +STR_6182 :Follow{MOVE_X}{87}{STRING} +STR_6183 :Follow{MOVE_X}{87}No sprite selected +STR_6184 :Follow Sprite +STR_6185 :Select Sprite +STR_6186 :No sprite selected +STR_6187 :{MEDIUMFONT}{OUTLINE}{WINDOW_COLOUR_2}{STRING} +STR_6188 :Vomit +STR_6189 :Duck ############# # Scenarios # diff --git a/distribution/changelog.txt b/distribution/changelog.txt index f2d1a1ac9f..5bb817f62d 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Feature: [#3510] Auto-append extension if none is specified. - Feature: [#3994] Show bottom toolbar with map tooltip (theme option). +- Feature: [#4906] Add follow sprite command to title sequences. - Feature: [#5826] Add the show_limits command to show map data counts and limits. - Feature: [#6078] Game now converts mp.dat to SC21.SC4 (Mega Park) automatically. - Feature: [#6125] Path can now be placed in park entrances. diff --git a/src/openrct2-ui/input/MouseInput.cpp b/src/openrct2-ui/input/MouseInput.cpp index 210009c035..59509c7354 100644 --- a/src/openrct2-ui/input/MouseInput.cpp +++ b/src/openrct2-ui/input/MouseInput.cpp @@ -531,6 +531,7 @@ static void input_viewport_drag_begin(rct_window * w, sint32 x, sint32 y) context_get_cursor_position(&gInputDragLastX, &gInputDragLastY); context_hide_cursor(); + window_unfollow_sprite(w); // gInputFlags |= INPUT_FLAG_5; } diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index 1372e18743..966fc9ed93 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -106,7 +106,7 @@ static rct_widget window_title_command_editor_widgets[] = { { WWT_DROPDOWN_BUTTON, 1, WS+WHA+12, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_ACTION_SELECT_SCENARIO, STR_NONE }, // Select scenario { WWT_DROPDOWN_BUTTON, 1, WS, WW-WS-1, BY2-14, BY2-3, STR_TITLE_COMMAND_EDITOR_SELECT_SPRITE, STR_NONE }, // Select sprite - { WWT_VIEWPORT, 1, WS, WW-WS - 1, BY2, BY2+22, STR_NONE, STR_NONE }, // Viewport + { WWT_VIEWPORT, 1, WS, WW-WS-1, BY2, BY2+22, STR_NONE, STR_NONE }, // Viewport { WWT_DROPDOWN_BUTTON, 1, 10, 80, WH-21, WH-10, STR_OK, STR_NONE }, // OKAY { WWT_DROPDOWN_BUTTON, 1, WW-80, WW-10, WH-21, WH-10, STR_CANCEL, STR_NONE }, // Cancel @@ -173,7 +173,7 @@ static void scenario_select_callback(const utf8 * path) static sint32 get_command_info_index(sint32 index) { - for (sint32 i = 0; i < NUM_COMMANDS; i++) + for (sint32 i = 0; i < (sint32)NUM_COMMANDS; i++) { if (_window_title_command_editor_orders[i].command == index) return i; @@ -183,7 +183,7 @@ static sint32 get_command_info_index(sint32 index) static TITLE_COMMAND_ORDER get_command_info(sint32 index) { - for (sint32 i = 0; i < NUM_COMMANDS; i++) + for (sint32 i = 0; i < (sint32)NUM_COMMANDS; i++) { if (_window_title_command_editor_orders[i].command == index) return _window_title_command_editor_orders[i]; @@ -267,7 +267,7 @@ void window_title_command_editor_open(TitleSequence * sequence, sint32 index, bo window_init_scroll_widgets(window); rct_widget *const viewportWidget = &window_title_command_editor_widgets[WIDX_VIEWPORT]; - viewport_create(window, window->x + viewportWidget->left, window->y + viewportWidget->top, viewportWidget->right - viewportWidget->left, viewportWidget->bottom - viewportWidget->top, 0, 0, 0, 0, 0, -1); + viewport_create(window, window->x + viewportWidget->left + 1, window->y + viewportWidget->top + 1, viewportWidget->right - viewportWidget->left - 1, viewportWidget->bottom - viewportWidget->top - 1, 0, 0, 0, 0, 0, -1); _window_title_command_editor_index = index; _window_title_command_editor_insert = insert; @@ -293,6 +293,12 @@ void window_title_command_editor_open(TitleSequence * sequence, sint32 index, bo case TITLE_SCRIPT_WAIT: snprintf(textbox1Buffer, BUF_SIZE, "%d", command.Milliseconds); break; + case TITLE_SCRIPT_FOLLOW: + if (command.SpriteIndex != SPRITE_INDEX_NULL) + { + window_follow_sprite(window, (size_t)command.SpriteIndex); + } + break; } } @@ -391,8 +397,8 @@ static void window_title_command_editor_mousedown(rct_window * w, rct_widgetinde { case WIDX_COMMAND_DROPDOWN: { - sint32 numItems = NUM_COMMANDS; - for (sint32 i = 0; i < numItems; i++) + size_t numItems = NUM_COMMANDS; + for (size_t i = 0; i < numItems; i++) { gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; gDropdownItemsArgs[i] = _window_title_command_editor_orders[i].nameStringId; @@ -432,7 +438,8 @@ static void window_title_command_editor_mousedown(rct_window * w, rct_widgetinde widget->right - widget->left - 3); dropdown_set_checked(command.Speed - 1, true); - } else if (command.Type == TITLE_SCRIPT_LOAD) + } + else if (command.Type == TITLE_SCRIPT_LOAD) { sint32 numItems = (sint32)_sequence->NumSaves; for (sint32 i = 0; i < numItems; i++) @@ -471,6 +478,10 @@ static void window_title_command_editor_dropdown(rct_window * w, rct_widgetindex switch (widgetIndex) { case WIDX_COMMAND_DROPDOWN: + if (command.SpriteIndex != SPRITE_INDEX_NULL) + { + window_unfollow_sprite(w); + } if (dropdownIndex == get_command_info_index(command.Type)) { break; @@ -497,6 +508,9 @@ static void window_title_command_editor_dropdown(rct_window * w, rct_widgetindex break; case TITLE_SCRIPT_FOLLOW: command.SpriteIndex = SPRITE_INDEX_NULL; + command.SpriteName[0] = '\0'; + window_unfollow_sprite(w); + w->viewport->flags &= ~VIEWPORT_FOCUS_TYPE_SPRITE; break; case TITLE_SCRIPT_SPEED: command.Speed = 1; @@ -626,9 +640,56 @@ static void window_title_command_editor_tool_down(rct_window * w, rct_widgetinde if (info.type == VIEWPORT_INTERACTION_ITEM_SPRITE) { - command.SpriteIndex = info.sprite->unknown.sprite_index; - w->viewport_target_sprite = command.SpriteIndex; - w->viewport->flags |= VIEWPORT_FOCUS_TYPE_SPRITE; + uint16 spriteIndex = info.sprite->unknown.sprite_index; + uint16 spriteIdentifier = info.sprite->unknown.sprite_identifier; + bool validSprite = false; + if (spriteIdentifier == SPRITE_IDENTIFIER_PEEP) + { + validSprite = true; + rct_peep * peep = GET_PEEP(spriteIndex); + format_string(command.SpriteName, USER_STRING_MAX_LENGTH, peep->name_string_idx, &peep->id); + } + else if (spriteIdentifier == SPRITE_IDENTIFIER_VEHICLE) + { + validSprite = true; + rct_vehicle * vehicle = GET_VEHICLE(spriteIndex); + Ride * ride = get_ride(vehicle->ride); + set_format_arg(16, uint32, ride->name_arguments); + format_string(command.SpriteName, USER_STRING_MAX_LENGTH, ride->name, &ride->name_arguments); + } + else if (spriteIdentifier == SPRITE_IDENTIFIER_LITTER) + { + rct_litter * litter = &(get_sprite(spriteIndex)->litter); + if (litter->type < Util::CountOf(litterNames)) + { + validSprite = true; + format_string(command.SpriteName, USER_STRING_MAX_LENGTH, litterNames[litter->type], nullptr); + } + } + else if (spriteIdentifier == SPRITE_IDENTIFIER_MISC) + { + if (info.sprite->IsBalloon()) + { + validSprite = true; + format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_SHOP_ITEM_SINGULAR_BALLOON, nullptr); + } + else if (info.sprite->IsDuck()) + { + validSprite = true; + format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_DUCK, nullptr); + } + } + if (validSprite) + { + command.SpriteIndex = spriteIndex; + window_follow_sprite(w, (size_t)command.SpriteIndex); + } + else + { + command.SpriteIndex = SPRITE_INDEX_NULL; + command.SpriteName[0] = '\0'; + window_unfollow_sprite(w); + } tool_cancel(); window_invalidate(w); } @@ -674,17 +735,20 @@ static void window_title_command_editor_invalidate(rct_window * w) case TITLE_SCRIPT_FOLLOW: window_title_command_editor_widgets[WIDX_SELECT_SPRITE].type = WWT_DROPDOWN_BUTTON; window_title_command_editor_widgets[WIDX_VIEWPORT].type = WWT_VIEWPORT; + // Draw button pressed while the tool is active - w->pressed_widgets &= ~(1 << WIDX_SELECT_SPRITE); if (sprite_selector_tool_is_active()) w->pressed_widgets |= (1 << WIDX_SELECT_SPRITE); + else + w->pressed_widgets &= ~(1 << WIDX_SELECT_SPRITE); + break; } if ((gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) == SCREEN_FLAGS_TITLE_DEMO) - w->disabled_widgets |= (1 << WIDX_GET); + w->disabled_widgets |= (1 << WIDX_GET) | (1 << WIDX_SELECT_SPRITE); else - w->disabled_widgets &= ~(1 << WIDX_GET); + w->disabled_widgets &= ~((1 << WIDX_GET) | (1 << WIDX_SELECT_SPRITE)); } static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo * dpi) @@ -722,7 +786,32 @@ static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo } if (command.Type == TITLE_SCRIPT_FOLLOW) { - window_draw_viewport(dpi, w); + uint8 colour = COLOUR_BLACK; + rct_string_id spriteString = STR_TITLE_COMMAND_EDITOR_FORMAT_SPRITE_NAME; + if (command.SpriteIndex != SPRITE_INDEX_NULL) + { + window_draw_viewport(dpi, w); + set_format_arg(0, uintptr_t, (uintptr_t)command.SpriteName); + } + else + { + colour = w->colours[1]; + spriteString = STR_TITLE_COMMAND_EDITOR_FOLLOW_NO_SPRITE; + } + + gfx_set_dirty_blocks( + w->x + w->widgets[WIDX_VIEWPORT].left, + w->y + w->widgets[WIDX_VIEWPORT].top, + w->x + w->widgets[WIDX_VIEWPORT].right, + w->y + w->widgets[WIDX_VIEWPORT].bottom); + gfx_draw_string_left_clipped( + dpi, + spriteString, + gCommonFormatArgs, + colour, + w->x + w->widgets[WIDX_VIEWPORT].left + 2, + w->y + w->widgets[WIDX_VIEWPORT].top + 1, + w->widgets[WIDX_VIEWPORT].right - w->widgets[WIDX_VIEWPORT].left - 2); } else if (command.Type == TITLE_SCRIPT_LOAD) { diff --git a/src/openrct2-ui/windows/TitleEditor.cpp b/src/openrct2-ui/windows/TitleEditor.cpp index 87a660dd49..e24a374d2f 100644 --- a/src/openrct2-ui/windows/TitleEditor.cpp +++ b/src/openrct2-ui/windows/TitleEditor.cpp @@ -979,7 +979,15 @@ static void window_title_editor_scrollpaint_commands(rct_window * w, rct_drawpix set_format_arg(0, rct_string_id, SpeedNames[command->Speed - 1]); break; case TITLE_SCRIPT_FOLLOW: - commandName = STR_TITLE_EDITOR_COMMAND_TYPE_FOLLOW; + commandName = STR_TITLE_EDITOR_COMMAND_FOLLOW; + if (command->SpriteIndex == SPRITE_INDEX_NULL) + { + commandName = STR_TITLE_EDITOR_COMMAND_FOLLOW_NO_SPRITE; + } + else + { + set_format_arg(0, uintptr_t, (uintptr_t)command->SpriteName); + } break; case TITLE_SCRIPT_WAIT: commandName = STR_TITLE_EDITOR_COMMAND_WAIT; diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index d40a1ebd08..9c913c197e 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1345,8 +1345,13 @@ void game_load_init() { viewport_init_all(); game_create_windows(); + mainWindow = window_get_main(); + } + else + { + mainWindow = window_get_main(); + window_unfollow_sprite(mainWindow); } - mainWindow = window_get_main(); if (mainWindow != nullptr) { diff --git a/src/openrct2/interface/viewport.c b/src/openrct2/interface/viewport.c index 370199028b..f80e3bb63f 100644 --- a/src/openrct2/interface/viewport.c +++ b/src/openrct2/interface/viewport.c @@ -517,6 +517,11 @@ void viewport_update_position(rct_window * window) rct_viewport * viewport = window->viewport; if (!viewport) return; + if (window->viewport_smart_follow_sprite != SPRITE_INDEX_NULL) + { + viewport_update_smart_sprite_follow(window); + } + if (window->viewport_target_sprite != SPRITE_INDEX_NULL) { viewport_update_sprite_follow(window); @@ -620,10 +625,144 @@ void viewport_update_sprite_follow(rct_window *window) centre_2d_coordinates(sprite->unknown.x, sprite->unknown.y, sprite->unknown.z, ¢re_x, ¢re_y, window->viewport); + window->saved_view_x = centre_x; + window->saved_view_y = centre_y; viewport_move(centre_x, centre_y, window, window->viewport); } } +void viewport_update_smart_sprite_follow(rct_window * window) +{ + rct_sprite * sprite = try_get_sprite(window->viewport_smart_follow_sprite); + if (sprite == NULL) + { + window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; + window->viewport_target_sprite = SPRITE_INDEX_NULL; + } + else if (sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_PEEP) + { + rct_peep * peep = GET_PEEP(window->viewport_smart_follow_sprite); + + if (peep->type == PEEP_TYPE_GUEST) + viewport_update_smart_guest_follow(window, peep); + else if (peep->type == PEEP_TYPE_STAFF) + viewport_update_smart_staff_follow(window, peep); + } + else if (sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE) + { + rct_vehicle * vehicle = GET_VEHICLE(window->viewport_smart_follow_sprite); + viewport_update_smart_vehicle_follow(window, vehicle); + } + else if (sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_MISC || + sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_LITTER) + { + window->viewport_focus_sprite.sprite_id = window->viewport_smart_follow_sprite; + window->viewport_target_sprite = window->viewport_smart_follow_sprite; + } + else + { + window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; + window->viewport_target_sprite = SPRITE_INDEX_NULL; + } +} + +void viewport_update_smart_guest_follow(rct_window * window, rct_peep * peep) +{ + union + { + sprite_focus sprite; + coordinate_focus coordinate; + } focus = { 0 }; // The focus will be either a sprite or a coordinate. + + focus.sprite.sprite_id = window->viewport_smart_follow_sprite; + + if (peep->state == PEEP_STATE_PICKED) + { + //focus.sprite.sprite_id = SPRITE_INDEX_NULL; + window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; + window->viewport_target_sprite = SPRITE_INDEX_NULL; + return; + } + else + { + uint8 final_check = 1; + if (peep->state == PEEP_STATE_ON_RIDE + || peep->state == PEEP_STATE_ENTERING_RIDE + || (peep->state == PEEP_STATE_LEAVING_RIDE && peep->x == LOCATION_NULL)) + { + + Ride * ride = get_ride(peep->current_ride); + if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) + { + rct_vehicle * train = GET_VEHICLE(ride->vehicles[peep->current_train]); + sint32 car = peep->current_car; + + for (; car != 0; car--) + { + train = GET_VEHICLE(train->next_vehicle_on_train); + } + + focus.sprite.sprite_id = train->sprite_index; + final_check = 0; + } + } + if (peep->x == LOCATION_NULL && final_check) + { + Ride * ride = get_ride(peep->current_ride); + sint32 x = ride->overall_view.x * 32 + 16; + sint32 y = ride->overall_view.y * 32 + 16; + sint32 height = tile_element_height(x, y); + height += 32; + focus.coordinate.x = x; + focus.coordinate.y = y; + focus.coordinate.z = height; + focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; + } + else + { + focus.sprite.type |= VIEWPORT_FOCUS_TYPE_SPRITE | VIEWPORT_FOCUS_TYPE_COORDINATE; + focus.sprite.pad_486 &= 0xFFFF; + } + focus.coordinate.rotation = get_current_rotation(); + } + + window->viewport_focus_sprite = focus.sprite; + window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; +} + +void viewport_update_smart_staff_follow(rct_window * window, rct_peep * peep) +{ + sprite_focus focus = { 0 }; + + focus.sprite_id = window->viewport_smart_follow_sprite; + + if (peep->state == PEEP_STATE_PICKED) + { + //focus.sprite.sprite_id = SPRITE_INDEX_NULL; + window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; + window->viewport_target_sprite = SPRITE_INDEX_NULL; + return; + } + else + { + focus.type |= VIEWPORT_FOCUS_TYPE_SPRITE | VIEWPORT_FOCUS_TYPE_COORDINATE; + } + + window->viewport_focus_sprite = focus; + window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; +} + +void viewport_update_smart_vehicle_follow(rct_window * window, rct_vehicle * vehicle) +{ + // Can be expanded in the future if needed + sprite_focus focus = { 0 }; + + focus.sprite_id = window->viewport_smart_follow_sprite; + + window->viewport_focus_sprite = focus; + window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; +} + /** * * rct2: 0x00685C02 diff --git a/src/openrct2/interface/viewport.h b/src/openrct2/interface/viewport.h index 54d5cb1ebc..0a60d54561 100644 --- a/src/openrct2/interface/viewport.h +++ b/src/openrct2/interface/viewport.h @@ -120,6 +120,10 @@ void viewport_create(rct_window *w, sint32 x, sint32 y, sint32 width, sint32 hei void viewport_update_pointers(); void viewport_update_position(rct_window *window); void viewport_update_sprite_follow(rct_window *window); +void viewport_update_smart_sprite_follow(rct_window * window); +void viewport_update_smart_guest_follow(rct_window * window, rct_peep * peep); +void viewport_update_smart_staff_follow(rct_window * window, rct_peep * peep); +void viewport_update_smart_vehicle_follow(rct_window * window, rct_vehicle * vehicle); void viewport_render(rct_drawpixelinfo *dpi, rct_viewport *viewport, sint32 left, sint32 top, sint32 right, sint32 bottom); void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, sint16 left, sint16 top, sint16 right, sint16 bottom); diff --git a/src/openrct2/interface/window.c b/src/openrct2/interface/window.c index 3f356d6198..7805c06ed0 100644 --- a/src/openrct2/interface/window.c +++ b/src/openrct2/interface/window.c @@ -473,6 +473,7 @@ rct_window *window_create(sint32 x, sint32 y, sint32 width, sint32 height, rct_w w->var_492 = 0; w->selected_tab = 0; w->var_4AE = 0; + w->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; RCT2_NEW_WINDOW++; colour_scheme_update(w); @@ -1359,6 +1360,9 @@ void window_scroll_to_location(rct_window *w, sint32 x, sint32 y, sint32 z) }; assert(w != NULL); + + window_unfollow_sprite(w); + if (w->viewport) { sint16 height = tile_element_height(x, y); if (z < height - 16) { @@ -2683,3 +2687,17 @@ void window_init_all() gWindowNextSlot = g_window_list; } + +void window_follow_sprite(rct_window * w, size_t spriteIndex) +{ + if (spriteIndex < MAX_SPRITES || spriteIndex == SPRITE_INDEX_NULL) + { + w->viewport_smart_follow_sprite = (uint16)spriteIndex; + } +} + +void window_unfollow_sprite(rct_window * w) +{ + w->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; + w->viewport_target_sprite = SPRITE_INDEX_NULL; +} diff --git a/src/openrct2/interface/window.h b/src/openrct2/interface/window.h index 21aa8bd454..340ea30bdd 100644 --- a/src/openrct2/interface/window.h +++ b/src/openrct2/interface/window.h @@ -319,6 +319,7 @@ typedef struct rct_window { sint8 var_4B9; uint8 colours[6]; // 0x4BA uint8 visibility; // VISIBILITY_CACHE + uint16 viewport_smart_follow_sprite; // Smart following of sprites. Handles setting viewport target sprite etc } rct_window; #define RCT_WINDOW_RIGHT(w) (w->x + w->width) @@ -794,6 +795,9 @@ void window_ride_construction_keyboard_shortcut_next_track(); void window_ride_construction_keyboard_shortcut_build_current(); void window_ride_construction_keyboard_shortcut_demolish_current(); +void window_follow_sprite(rct_window * w, size_t spriteIndex); +void window_unfollow_sprite(rct_window * w); + bool sub_6CA2DF(sint32 *trackType, sint32 *trackDirection, sint32 *rideIndex, sint32 *_liftHillAndAlternativeState, sint32 *x, sint32 *y, sint32 *z, sint32 *properties); money32 place_provisional_track_piece(sint32 rideIndex, sint32 trackType, sint32 trackDirection, sint32 liftHillAndAlternativeState, sint32 x, sint32 y, sint32 z); diff --git a/src/openrct2/localisation/string_ids.h b/src/openrct2/localisation/string_ids.h index ade8ce949c..20412f8c6a 100644 --- a/src/openrct2/localisation/string_ids.h +++ b/src/openrct2/localisation/string_ids.h @@ -3831,8 +3831,14 @@ enum { STR_TITLE_COMMAND_EDITOR_NO_SCENARIO_SELECTED = 6180, STR_TITLE_COMMAND_EDITOR_MISSING_SCENARIO = 6181, - STR_TITLE_EDITOR_COMMAND_TYPE_FOLLOW = 6182, - STR_TITLE_COMMAND_EDITOR_SELECT_SPRITE = 6183, + STR_TITLE_EDITOR_COMMAND_FOLLOW = 6182, + STR_TITLE_EDITOR_COMMAND_FOLLOW_NO_SPRITE = 6183, + STR_TITLE_EDITOR_COMMAND_TYPE_FOLLOW = 6184, + STR_TITLE_COMMAND_EDITOR_SELECT_SPRITE = 6185, + STR_TITLE_COMMAND_EDITOR_FOLLOW_NO_SPRITE = 6186, + STR_TITLE_COMMAND_EDITOR_FORMAT_SPRITE_NAME = 6187, + STR_LITTER_VOMIT = 6188, + STR_DUCK = 6189, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 diff --git a/src/openrct2/title/TitleScreen.cpp b/src/openrct2/title/TitleScreen.cpp index 504b821536..37de990f2f 100644 --- a/src/openrct2/title/TitleScreen.cpp +++ b/src/openrct2/title/TitleScreen.cpp @@ -384,7 +384,8 @@ extern "C" gfx_draw_string(dpi, buffer, COLOUR_BLACK, x + 5, y + 5 - 13); // Invalidate screen area - gfx_set_dirty_blocks(x, y, x + 500, y + 30); + sint16 width = (sint16)gfx_get_string_width(buffer); + gfx_set_dirty_blocks(x, y, x + width, y + 30); // 30 is an arbitrary height to catch both strings // Write platform information snprintf(ch, 256 - (ch - buffer), "%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); diff --git a/src/openrct2/title/TitleSequence.cpp b/src/openrct2/title/TitleSequence.cpp index ed1b616ee1..094d885729 100644 --- a/src/openrct2/title/TitleSequence.cpp +++ b/src/openrct2/title/TitleSequence.cpp @@ -460,6 +460,7 @@ static std::vector LegacyScriptRead(utf8 * script, size_t scriptLe { command.Type = TITLE_SCRIPT_FOLLOW; command.SpriteIndex = atoi(part1) & 0xFFFF; + safe_strcpy(command.SpriteName, part2, USER_STRING_MAX_LENGTH); } else if (_stricmp(token, "WAIT") == 0) { @@ -513,7 +514,8 @@ static void LegacyScriptGetLine(IStream * stream, char * parts) sint32 cindex = 0; sint32 whitespace = 1; sint32 comment = 0; - sint32 load = 0; + bool load = false; + bool sprite = false; for (; part < 3;) { sint32 c = 0; @@ -531,7 +533,7 @@ static void LegacyScriptGetLine(IStream * stream, char * parts) parts[part * 128 + cindex] = 0; comment = 1; } - else if (c == ' ' && !comment && !load) + else if (c == ' ' && !comment && !load && (!sprite || part != 2)) { if (!whitespace) { @@ -540,6 +542,10 @@ static void LegacyScriptGetLine(IStream * stream, char * parts) { load = true; } + else if (part == 0 && cindex == 6 && _strnicmp(parts, "FOLLOW", 6) == 0) + { + sprite = true; + } parts[part * 128 + cindex] = 0; part++; cindex = 0; @@ -608,7 +614,8 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq) if (command->SaveIndex == 0xFF) { sb.Append("LOAD "); - } else + } + else { sb.Append("LOAD "); sb.Append(seq->Saves[command->SaveIndex]); @@ -638,8 +645,9 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq) sb.Append(buffer); break; case TITLE_SCRIPT_FOLLOW: - String::Format(buffer, sizeof(buffer), "FOLLOW %u", command->SpriteIndex); + String::Format(buffer, sizeof(buffer), "FOLLOW %u ", command->SpriteIndex); sb.Append(buffer); + sb.Append(command->SpriteName); break; case TITLE_SCRIPT_SPEED: String::Format(buffer, sizeof(buffer), "SPEED %u", command->Speed); diff --git a/src/openrct2/title/TitleSequence.h b/src/openrct2/title/TitleSequence.h index 34069a3665..5437c1db05 100644 --- a/src/openrct2/title/TitleSequence.h +++ b/src/openrct2/title/TitleSequence.h @@ -17,6 +17,7 @@ #pragma once #include "../common.h" +#include "../localisation/localisation.h" #define TITLE_COMMAND_SCENARIO_LENGTH 64 @@ -32,7 +33,11 @@ typedef struct TitleCommand }; uint8 Rotations; // ROTATE (counter-clockwise) uint8 Zoom; // ZOOM - uint16 SpriteIndex; // FOLLOW + struct // FOLLOW + { + uint16 SpriteIndex; + utf8 SpriteName[USER_STRING_MAX_LENGTH]; + }; uint8 Speed; // SPEED uint16 Milliseconds; // WAIT utf8 Scenario[TITLE_COMMAND_SCENARIO_LENGTH]; // LOADSC diff --git a/src/openrct2/title/TitleSequencePlayer.cpp b/src/openrct2/title/TitleSequencePlayer.cpp index 6ca2963aea..17e4ddfaee 100644 --- a/src/openrct2/title/TitleSequencePlayer.cpp +++ b/src/openrct2/title/TitleSequencePlayer.cpp @@ -382,11 +382,21 @@ private: } } - void FollowSprite(uint16 SpriteIndex) { - rct_window *const MainWindow = window_get_main(); - if (MainWindow != nullptr) + void FollowSprite(uint16 spriteIndex) + { + rct_window * w = window_get_main(); + if (w != nullptr) { - MainWindow->viewport_target_sprite = SpriteIndex; + window_follow_sprite(w, spriteIndex); + } + } + + void UnfollowSprite() + { + rct_window * w = window_get_main(); + if (w != nullptr) + { + window_unfollow_sprite(w); } } @@ -547,9 +557,6 @@ private: _lastScreenHeight = w->height; _viewCentreLocation.x = x; _viewCentreLocation.y = y; - - // Stop following sprites - w->viewport_target_sprite = SPRITE_INDEX_NULL; } } diff --git a/src/openrct2/world/sprite.c b/src/openrct2/world/sprite.c index 6f035ff6de..6f4285e83f 100644 --- a/src/openrct2/world/sprite.c +++ b/src/openrct2/world/sprite.c @@ -35,6 +35,21 @@ static bool _spriteFlashingList[MAX_SPRITES]; uint16 gSpriteSpatialIndex[0x10001]; +const rct_string_id litterNames[12] = { + STR_LITTER_VOMIT, + STR_LITTER_VOMIT, + STR_SHOP_ITEM_SINGULAR_EMPTY_CAN, + STR_SHOP_ITEM_SINGULAR_RUBBISH, + STR_SHOP_ITEM_SINGULAR_EMPTY_BURGER_BOX, + STR_SHOP_ITEM_SINGULAR_EMPTY_CUP, + STR_SHOP_ITEM_SINGULAR_EMPTY_BOX, + STR_SHOP_ITEM_SINGULAR_EMPTY_BOTTLE, + STR_SHOP_ITEM_SINGULAR_EMPTY_BOWL_RED, + STR_SHOP_ITEM_SINGULAR_EMPTY_DRINK_CARTON, + STR_SHOP_ITEM_SINGULAR_EMPTY_JUICE_CUP, + STR_SHOP_ITEM_SINGULAR_EMPTY_BOWL_BLUE +}; + static LocationXYZ16 _spritelocations1[MAX_SPRITES]; static LocationXYZ16 _spritelocations2[MAX_SPRITES]; diff --git a/src/openrct2/world/sprite.h b/src/openrct2/world/sprite.h index 75432314fd..1e0dc29ec4 100644 --- a/src/openrct2/world/sprite.h +++ b/src/openrct2/world/sprite.h @@ -396,6 +396,9 @@ extern uint16 gSpriteListHead[6]; extern uint16 gSpriteListCount[6]; extern uint16 gSpriteSpatialIndex[0x10001]; + +extern const rct_string_id litterNames[12]; + rct_sprite *create_sprite(uint8 bl); void reset_sprite_list(); void reset_sprite_spatial_index();