mirror of
https://github.com/OpenRCT2/OpenRCT2.git
synced 2025-01-22 10:21:57 -05:00
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:
parent
1443216ba0
commit
298420fd1e
17 changed files with 353 additions and 33 deletions
|
@ -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 #
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -721,8 +785,33 @@ static void window_title_command_editor_paint(rct_window * w, rct_drawpixelinfo
|
|||
w->widgets[WIDX_INPUT_DROPDOWN].left - w->widgets[WIDX_INPUT].left - 4);
|
||||
}
|
||||
if (command.Type == TITLE_SCRIPT_FOLLOW)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
if (mainWindow != nullptr)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
@ -640,6 +647,7 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq)
|
|||
case TITLE_SCRIPT_FOLLOW:
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -382,11 +382,21 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void FollowSprite(uint16 SpriteIndex) {
|
||||
rct_window *const MainWindow = window_get_main();
|
||||
if (MainWindow != nullptr)
|
||||
void FollowSprite(uint16 spriteIndex)
|
||||
{
|
||||
MainWindow->viewport_target_sprite = SpriteIndex;
|
||||
rct_window * w = window_get_main();
|
||||
if (w != nullptr)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue