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.
This commit is contained in:
Robert Jordan 2017-11-02 20:16:30 -04:00 committed by Aaron van Geffen
parent 1443216ba0
commit 298420fd1e
17 changed files with 353 additions and 33 deletions

View file

@ -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 #

View file

@ -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.

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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;

View file

@ -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)
{

View file

@ -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, &centre_x, &centre_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

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -460,6 +460,7 @@ static std::vector<TitleCommand> 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 <No save file>");
} 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);

View file

@ -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

View file

@ -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;
}
}

View file

@ -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];

View file

@ -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();