Exemplo n.º 1
0
/**
 *
 *  rct2: 0x0068563D
 */
rct_string_id research_item_get_name(const rct_research_item* researchItem)
{
    if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE)
    {
        rct_ride_entry* rideEntry = get_ride_entry(researchItem->entryIndex);
        if (rideEntry == nullptr)
        {
            return STR_EMPTY;
        }
        else
        {
            return rideEntry->naming.name;
        }
    }
    else
    {
        rct_scenery_group_entry* sceneryEntry = get_scenery_group_entry(researchItem->entryIndex);
        if (sceneryEntry == nullptr)
        {
            return STR_EMPTY;
        }
        else
        {
            return sceneryEntry->name;
        }
    }
}
Exemplo n.º 2
0
/**
 *
 *  rct2: 0x006B3EBA
 */
void window_new_ride_focus(ride_list_item rideItem)
{
	rct_window *w;
	rct_ride_entry *rideType;

	w = window_find_by_class(WC_CONSTRUCT_RIDE);
	if (w == NULL)
		return;

	rideType = get_ride_entry(rideItem.entry_index);

	if(!gConfigInterface.select_by_track_type)
		window_new_ride_set_page(w, rideType->category[0]);
	else
		window_new_ride_set_page(w, gRideCategories[rideType->ride_type[0]]);

	ride_list_item *listItem = _windowNewRideListItems;
	while (listItem->type != RIDE_TYPE_NULL) {
		if (listItem->type == rideItem.type && listItem->entry_index == rideItem.entry_index) {
			_windowNewRideHighlightedItem[0] = rideItem;
			w->new_ride.highlighted_ride_id = rideItem.ride_type_and_entry;
			window_new_ride_scroll_to_focused_ride(w);
		}
		listItem++;
	}
}
Exemplo n.º 3
0
void research_populate_list_researched()
{
    // Rides
    for (int32_t i = 0; i < MAX_RIDE_OBJECTS; i++)
    {
        rct_ride_entry* rideEntry = get_ride_entry(i);
        if (rideEntry == nullptr)
        {
            continue;
        }

        for (auto rideType : rideEntry->ride_type)
        {
            if (rideType != RIDE_TYPE_NULL)
            {
                research_insert(true, RESEARCH_ENTRY_RIDE_MASK | (rideType << 8) | i, rideEntry->category[0]);
            }
        }
    }

    // Scenery
    for (int32_t i = 0; i < MAX_SCENERY_GROUP_OBJECTS; i++)
    {
        rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(i);
        if (sceneryGroupEntry == nullptr)
        {
            continue;
        }

        research_insert(true, i, RESEARCH_CATEGORY_SCENERY_GROUP);
    }
}
Exemplo n.º 4
0
/**
 * rct2: 0x0088ABA4
 * @param (edi) direction
 * @param (al) al
 * @param (cl) cl
 * @param (ebx) image_id
 * @param (edx) height
 */
static void paint_crooked_house_structure(paint_session * session, uint8 direction, uint8 x_offset, uint8 y_offset,
                                          uint32 segment, sint32 height)
{
    const rct_tile_element * original_tile_element = static_cast<const rct_tile_element *>(session->CurrentlyDrawnItem);

    Ride * ride = get_ride(track_element_get_ride_index(original_tile_element));

    rct_ride_entry * rideEntry = get_ride_entry(ride->subtype);

    if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)
    {
        if (ride->vehicles[0] != SPRITE_INDEX_NULL)
        {
            rct_sprite * sprite         = get_sprite(ride->vehicles[0]);
            session->InteractionType    = VIEWPORT_INTERACTION_ITEM_SPRITE;
            session->CurrentlyDrawnItem = sprite;
        }
    }

    uint32 image_id = (direction + rideEntry->vehicles[0].base_image_id) | session->TrackColours[SCHEME_MISC];

    rct_crooked_house_bound_box boundBox = crooked_house_data[segment];
    sub_98197C(
        session, image_id, x_offset, y_offset, boundBox.length_x, boundBox.length_y, 127, height + 3, boundBox.offset_x,
        boundBox.offset_y, height + 3);
}
Exemplo n.º 5
0
/** At least 6 open roller coasters. */
static bool award_is_deserved_best_rollercoasters([[maybe_unused]] int32_t activeAwardTypes)
{
    int32_t i, rollerCoasters;
    Ride* ride;
    rct_ride_entry* rideEntry;

    rollerCoasters = 0;
    FOR_ALL_RIDES (i, ride)
    {
        rideEntry = get_ride_entry(ride->subtype);
        if (rideEntry == nullptr)
        {
            continue;
        }

        if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED))
        {
            continue;
        }

        if (!ride_entry_has_category(rideEntry, RIDE_CATEGORY_ROLLERCOASTER))
        {
            continue;
        }

        rollerCoasters++;
    }
Exemplo n.º 6
0
static void paint_swinging_inverter_ship_structure(rct_ride * ride, uint8 direction, sint8 axisOffset, uint16 height)
{
	rct_map_element * savedMapElement = g_currently_drawn_item;

	rct_ride_entry * rideType = get_ride_entry(ride->subtype);
	rct_vehicle * vehicle = NULL;

	sint8 xOffset = !(direction & 1) ? axisOffset : 0;
	sint8 yOffset = (direction & 1) ? axisOffset : 0;

	if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK
	    && ride->vehicles[0] != SPRITE_INDEX_NULL) {
		vehicle = GET_VEHICLE(ride->vehicles[0]);

		gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_SPRITE;
		g_currently_drawn_item = vehicle;
	}

	uint32 vehicleImageId = rideType->vehicles[0].base_image_id + swinging_inverter_ship_base_sprite_offset[direction];
	if (vehicle != NULL) {
		sint32 rotation = (sint8) vehicle->vehicle_sprite_type;
		if (rotation != 0) {
			vehicleImageId = rideType->vehicles[0].base_image_id + swinging_inverter_ship_animating_base_sprite_offset[direction];

			if (direction & 2) {
				rotation = -rotation;
			}
			if (rotation < 0) {
				rotation += 72;
			}

			vehicleImageId += (rotation - 1) << 1;
		}
	}

	uint32 colourFlags = gTrackColours[SCHEME_MISC];
	if (colourFlags == 0x20000000) {
		colourFlags = ride->vehicle_colours[0].body_colour << 19 | ride->vehicle_colours[0].trim_colour << 24 | 0xA0000000;
	}

	swinging_inverter_ship_bound_box boundBox = swinging_inverter_ship_bounds[direction];
	vehicleImageId = vehicleImageId | colourFlags;
	uint32 frameImageId = swinging_inverter_ship_frame_sprites[direction] | gTrackColours[SCHEME_TRACK];

	if (direction & 2) {
		sub_98197C(vehicleImageId, xOffset, yOffset, boundBox.length_x, boundBox.length_y, 127, height, boundBox.offset_x, boundBox.offset_y, height, get_current_rotation());
		sub_98199C(frameImageId, xOffset, yOffset, boundBox.length_x, boundBox.length_y, 127, height, boundBox.offset_x, boundBox.offset_y, height, get_current_rotation());
	} else {
		sub_98197C(frameImageId, xOffset, yOffset, boundBox.length_x, boundBox.length_y, 127, height, boundBox.offset_x, boundBox.offset_y, height, get_current_rotation());
		sub_98199C(vehicleImageId, xOffset, yOffset, boundBox.length_x, boundBox.length_y, 127, height, boundBox.offset_x, boundBox.offset_y, height, get_current_rotation());
	}

	g_currently_drawn_item = savedMapElement;
	gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE;
}
Exemplo n.º 7
0
void research_insert_ride_entry(uint8_t entryIndex, bool researched)
{
    rct_ride_entry* rideEntry = get_ride_entry(entryIndex);
    uint8_t category = rideEntry->category[0];
    for (auto rideType : rideEntry->ride_type)
    {
        if (rideType != RIDE_TYPE_NULL)
        {
            research_insert(researched, RESEARCH_ENTRY_RIDE_MASK | (rideType << 8) | entryIndex, category);
        }
    }
}
Exemplo n.º 8
0
/**
 * rct2: 0x0076F72C
 */
static void paint_haunted_house_structure(paint_session * session, uint8 rideIndex, uint8 direction, sint8 xOffset,
                                          sint8 yOffset, uint8 part, uint16 height)
{
    const rct_tile_element * savedTileElement = static_cast<const rct_tile_element *>(session->CurrentlyDrawnItem);

    uint8 frameNum = 0;

    Ride *           ride      = get_ride(rideIndex);
    rct_ride_entry * rideEntry = get_ride_entry(ride->subtype);

    uint32 baseImageId = rideEntry->vehicles[0].base_image_id;

    if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK && ride->vehicles[0] != SPRITE_INDEX_NULL)
    {
        session->InteractionType    = VIEWPORT_INTERACTION_ITEM_SPRITE;
        rct_vehicle * vehicle       = GET_VEHICLE(ride->vehicles[0]);
        session->CurrentlyDrawnItem = vehicle;
        frameNum                    = vehicle->vehicle_sprite_type;
    }

    uint32                  imageId  = (baseImageId + direction) | session->TrackColours[SCHEME_MISC];
    haunted_house_bound_box boundBox = haunted_house_data[part];
    sub_98197C(
        session, imageId, xOffset, yOffset, boundBox.length_x, boundBox.length_y, 127, height, boundBox.offset_x,
        boundBox.offset_y, height);

    rct_drawpixelinfo * dpi = session->Unk140E9A8;
    if (dpi->zoom_level == 0 && frameNum != 0)
    {
        switch (direction)
        {
        case 0:
            imageId = baseImageId + 3 + frameNum;
            break;
        case 1:
            imageId = baseImageId + 21 + frameNum;
            break;
        case 2:
            imageId = baseImageId + 39 + frameNum;
            break;
        case 3:
            imageId = baseImageId + 57 + frameNum;
            break;
        }
        imageId = imageId | session->TrackColours[SCHEME_MISC];
        sub_98199C(
            session, imageId, xOffset, yOffset, boundBox.length_x, boundBox.length_y, 127, height, boundBox.offset_x,
            boundBox.offset_y, height);
    }

    session->CurrentlyDrawnItem = savedTileElement;
    session->InteractionType    = VIEWPORT_INTERACTION_ITEM_RIDE;
}
Exemplo n.º 9
0
bool marketing_is_campaign_type_applicable(sint32 campaignType)
{
    sint32         i;
    Ride           * ride;
    rct_ride_entry * rideEntry;

    switch (campaignType)
    {
    case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE:
    case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
        if (!park_entry_price_unlocked())
            return false;
        return true;

    case ADVERTISING_CAMPAIGN_RIDE_FREE:
        if (!park_ride_prices_unlocked())
            return false;

        // fall-through
    case ADVERTISING_CAMPAIGN_RIDE:
        // Check if any rides exist
        FOR_ALL_RIDES(i, ride)
        {
            if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE)
            {
                return true;
            }
        }
        return false;

    case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
        // Check if any food or drink stalls exist
        FOR_ALL_RIDES(i, ride)
        {
            rideEntry = get_ride_entry(ride->subtype);
            if (rideEntry == nullptr)
            {
                continue;
            }
            if (
                shop_item_is_food_or_drink(rideEntry->shop_item) ||
                shop_item_is_food_or_drink(rideEntry->shop_item_secondary)
                )
            {
                return true;
            }
        }
        return false;

    default:
        return true;
    }
Exemplo n.º 10
0
/**
 *
 *  rct2: 0x0069E320
 */
static void window_new_campaign_get_shop_items()
{
    int32_t i, numItems;
    Ride* ride;

    uint64_t items = 0;
    FOR_ALL_RIDES (i, ride)
    {
        rct_ride_entry* rideEntry = get_ride_entry(ride->subtype);
        if (rideEntry == nullptr)
        {
            continue;
        }
        uint8_t itemType = rideEntry->shop_item;
        if (itemType != SHOP_ITEM_NONE && shop_item_is_food_or_drink(itemType))
            items |= 1ULL << itemType;
    }
Exemplo n.º 11
0
bool marketing_is_campaign_type_applicable(int campaignType)
{
	int i;
	rct_ride *ride;
	rct_ride_entry *rideEntry;

	switch (campaignType) {
	case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE:
	case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
		if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY)
			return false;
		return true;

	case ADVERTISING_CAMPAIGN_RIDE_FREE:
		if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY))
			return false;

		// fall-through
	case ADVERTISING_CAMPAIGN_RIDE:
		// Check if any rides exist
		FOR_ALL_RIDES(i, ride) {
			if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE) {
				return true;
			}
		}
		return false;

	case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
		// Check if any food or drink stalls exist
		FOR_ALL_RIDES(i, ride) {
			rideEntry = get_ride_entry(ride->subtype);
			if (rideEntry == NULL) {
				continue;
			}
			if (
				shop_item_is_food_or_drink(rideEntry->shop_item) ||
				shop_item_is_food_or_drink(rideEntry->shop_item_secondary)
			) {
				return true;
			}
		}
		return false;

	default:
		return true;
	}
Exemplo n.º 12
0
/** rct2: 0x00768A3B */
static void paint_space_rings_structure(rct_ride * ride, uint8 direction,  uint32 segment, sint32 height)
{
    rct_map_element * savedMapElement = g_currently_drawn_item;

    uint32 vehicleIndex = (segment - direction) & 0x3;

    if (ride->num_stations == 0 || vehicleIndex < ride->num_vehicles) {
        rct_ride_entry * ride_type = get_ride_entry(ride->subtype);
        rct_vehicle * vehicle = NULL;

        sint32 frameNum = direction;

        uint32 baseImageId = ride_type->vehicles[0].base_image_id;

        if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK
            && ride->vehicles[0] != SPRITE_INDEX_NULL) {
            gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_SPRITE;
            vehicle = GET_VEHICLE(ride->vehicles[vehicleIndex]);
            g_currently_drawn_item = vehicle;
            frameNum += (sint8) vehicle->vehicle_sprite_type * 4;
        }

        uint32 imageColourFlags = gTrackColours[SCHEME_MISC];
        if ((ride->colour_scheme_type & 3) != RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN) {
            vehicleIndex = 0;
        }

        if (imageColourFlags == IMAGE_TYPE_REMAP) {
            imageColourFlags = SPRITE_ID_PALETTE_COLOUR_2(ride->vehicle_colours[vehicleIndex].body_colour, ride->vehicle_colours[0].trim_colour);
        }

        uint32 imageId = (baseImageId + frameNum) | imageColourFlags;
        sub_98197C(imageId, 0, 0, 20, 20, 23, height, -10, -10, height, get_current_rotation());

        if (vehicle != NULL && vehicle->num_peeps > 0) {
            rct_peep * rider = GET_PEEP(vehicle->peep[0]);
            imageColourFlags = SPRITE_ID_PALETTE_COLOUR_2(rider->tshirt_colour, rider->trousers_colour);
            imageId = ((baseImageId & 0x7FFFF) + 352 + frameNum) | imageColourFlags;
            sub_98199C(imageId, 0, 0, 20, 20, 23, height, -10, -10, height, get_current_rotation());
        }
    }

    g_currently_drawn_item = savedMapElement;
    gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE;
}
Exemplo n.º 13
0
/**
 * rct2: 0x0088ABA4
 * @param (edi) direction
 * @param (al) al
 * @param (cl) cl
 * @param (ebx) image_id
 * @param (edx) height
 */
static void sub_88ABA4(uint8 direction, uint8 x_offset, uint8 y_offset, uint32 segment, int height) {
	rct_map_element *original_map_element = g_currently_drawn_item;

	rct_ride *ride = get_ride(original_map_element->properties.track.ride_index);

	rct_ride_entry *ride_type = get_ride_entry(ride->subtype);

	if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) {
		if (ride->vehicles[0] != (uint16)-1) {
			rct_sprite *sprite = get_sprite(ride->vehicles[0]);
			gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_SPRITE;
			g_currently_drawn_item = sprite;
		}
	}


	uint32 image_id = (direction + ride_type->vehicles[0].base_image_id) | gTrackColours[SCHEME_MISC];

	rct_crooked_house_bound_box boundBox = crooked_house_data[segment];
	sub_98197C(image_id, x_offset, y_offset, boundBox.length_x, boundBox.length_y, 127, height + 3, boundBox.offset_x, boundBox.offset_y, height + 3, get_current_rotation());
}
Exemplo n.º 14
0
static rct_string_id window_editor_inventions_list_prepare_name(const rct_research_item* researchItem, bool withGap)
{
    rct_string_id drawString;
    rct_string_id stringId = research_item_get_name(researchItem);

    if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE && !RideGroupManager::RideTypeIsIndependent(researchItem->baseRideType))
    {
        drawString = withGap ? STR_INVENTIONS_LIST_RIDE_AND_VEHICLE_NAME_DRAG : STR_WINDOW_COLOUR_2_STRINGID_STRINGID;
        rct_string_id rideGroupName = get_ride_naming(researchItem->baseRideType, get_ride_entry(researchItem->entryIndex))
                                          .name;
        set_format_arg(0, rct_string_id, rideGroupName);
        set_format_arg(2, rct_string_id, stringId);
    }
    else
    {
        drawString = STR_WINDOW_COLOUR_2_STRINGID;
        set_format_arg(0, rct_string_id, stringId);
    }

    return drawString;
}
Exemplo n.º 15
0
/**
 *
 *  rct2: 0x006CF2D6
 */
static void window_track_list_invalidate(rct_window *w)
{
	rct_ride_entry *entry;
	rct_string_id stringId;

	colour_scheme_update(w);

	entry = get_ride_entry(_window_track_list_item.entry_index);

	stringId = entry->name;
	if (!(entry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) || rideTypeShouldLoseSeparateFlag(entry))
		stringId = _window_track_list_item.type + 2;

	RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = stringId;
	if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
		window_track_list_widgets[WIDX_TITLE].image = STR_TRACK_DESIGNS;
		window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT;
	} else {
		window_track_list_widgets[WIDX_TITLE].image = STR_SELECT_DESIGN;
		window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP;
	}

	if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) || w->track_list.var_482 != 0) {
		w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW;
		w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
		window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN;
		window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_FLATBTN;
		if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0)
			w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
		else
			w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
	} else {
		w->pressed_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
		w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
		window_track_list_widgets[WIDX_ROTATE].type = WWT_EMPTY;
		window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_EMPTY;
	}
}
Exemplo n.º 16
0
/**
 *
 *  rct2: 0x00685675
 */
void research_populate_list_random()
{
    research_reset_items();

    // Rides
    for (int32_t i = 0; i < MAX_RIDE_OBJECTS; i++)
    {
        rct_ride_entry* rideEntry = get_ride_entry(i);
        if (rideEntry == nullptr)
        {
            continue;
        }

        int32_t researched = (scenario_rand() & 0xFF) > 128;
        for (auto rideType : rideEntry->ride_type)
        {
            if (rideType != RIDE_TYPE_NULL)
            {
                research_insert(researched, RESEARCH_ENTRY_RIDE_MASK | (rideType << 8) | i, rideEntry->category[0]);
            }
        }
    }

    // Scenery
    for (int32_t i = 0; i < MAX_SCENERY_GROUP_OBJECTS; i++)
    {
        rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(i);
        if (sceneryGroupEntry == nullptr)
        {
            continue;
        }

        int32_t researched = (scenario_rand() & 0xFF) > 85;
        research_insert(researched, i, RESEARCH_CATEGORY_SCENERY_GROUP);
    }
}
Exemplo n.º 17
0
/**
 *
 *  rct2: 0x006852F4
 */
static void window_editor_inventions_list_drag_open(rct_research_item* researchItem)
{
    char buffer[256], *ptr;
    int32_t stringWidth;
    rct_window* w;

    window_close_by_class(WC_EDITOR_INVENTION_LIST_DRAG);
    _editorInventionsListDraggedItem = researchItem;
    rct_string_id stringId = research_item_get_name(researchItem);

    ptr = buffer;
    if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE && !RideGroupManager::RideTypeIsIndependent(researchItem->baseRideType))
    {
        const auto rideEntry = get_ride_entry(researchItem->entryIndex);
        const rct_string_id rideGroupName = get_ride_naming(researchItem->baseRideType, rideEntry).name;
        rct_string_id args[] = {
            rideGroupName,
            stringId,
        };
        format_string(ptr, 256, STR_INVENTIONS_LIST_RIDE_AND_VEHICLE_NAME, &args);
    }
    else
    {
        format_string(ptr, 256, stringId, nullptr);
    }

    stringWidth = gfx_get_string_width(buffer);
    window_editor_inventions_list_drag_widgets[0].right = stringWidth;

    w = window_create(
        gTooltipCursorX - (stringWidth / 2), gTooltipCursorY - 7, stringWidth, 14, &window_editor_inventions_list_drag_events,
        WC_EDITOR_INVENTION_LIST_DRAG, WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_NO_SNAPPING);
    w->widgets = window_editor_inventions_list_drag_widgets;
    w->colours[1] = COLOUR_WHITE;
    input_window_position_begin(w, 0, gTooltipCursorX, gTooltipCursorY);
}
Exemplo n.º 18
0
/**
 *
 *  rct2: 0x006CF2D6
 */
static void window_track_list_invalidate(rct_window *w)
{
    rct_string_id stringId = STR_NONE;
    rct_ride_entry *entry = get_ride_entry(_window_track_list_item.entry_index);

    if (entry != NULL && entry != (rct_ride_entry*)-1) {
        rct_ride_name rideName = get_ride_naming(_window_track_list_item.type, entry);
        stringId = rideName.name;
    }

    set_format_arg(0, rct_string_id, stringId);
    if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
        window_track_list_widgets[WIDX_TITLE].text = STR_TRACK_DESIGNS;
        window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT;
    } else {
        window_track_list_widgets[WIDX_TITLE].text = STR_SELECT_DESIGN;
        window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP;
    }

    if ((gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) || w->selected_list_item != 0) {
        w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW;
        w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
        window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN;
        window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_FLATBTN;
        if (gTrackDesignSceneryToggle) {
            w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
        } else {
            w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
        }
    } else {
        w->pressed_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
        w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW);
        window_track_list_widgets[WIDX_ROTATE].type = WWT_EMPTY;
        window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_EMPTY;
    }
}
Exemplo n.º 19
0
/**
 *
 *  rct2: 0x0076750D
 */
static void top_spin_paint_vehicle(
    paint_session *          session,
    sint8                    al,
    sint8                    cl,
    uint8                    rideIndex,
    uint8                    direction,
    sint32                   height,
    const rct_tile_element * tileElement)
{
    uint16 boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ;
    // As we will be drawing a vehicle we need to backup the tileElement that
    // is assigned to the drawings.
    const rct_tile_element * curTileElement = static_cast<const rct_tile_element *>(session->CurrentlyDrawnItem);

    height += 3;

    Ride *           ride      = get_ride(rideIndex);
    rct_ride_entry * rideEntry = get_ride_entry(ride->subtype);
    rct_vehicle *    vehicle   = nullptr;

    uint8 seatRotation = 0;
    sint8 armRotation  = 0;

    if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK && ride->vehicles[0] != SPRITE_INDEX_NULL)
    {
        vehicle = GET_VEHICLE(ride->vehicles[0]);

        session->InteractionType    = VIEWPORT_INTERACTION_ITEM_SPRITE;
        session->CurrentlyDrawnItem = vehicle;

        armRotation  = vehicle->vehicle_sprite_type;
        seatRotation = vehicle->bank_rotation;
    }

    boundBoxOffsetX = al + 16;
    boundBoxOffsetY = cl + 16;
    boundBoxOffsetZ = height;

    // di
    uint8 lengthX = 24;
    // si
    uint8 lengthY = 24;

    uint32 image_id = session->TrackColours[SCHEME_MISC];
    if (image_id == IMAGE_TYPE_REMAP)
    {
        image_id = SPRITE_ID_PALETTE_COLOUR_2(ride->track_colour_main[0], ride->track_colour_supports[0]);
    }

    image_id += (direction & 1) << 1;
    image_id += rideEntry->vehicles[0].base_image_id;
    // Left back bottom support
    image_id += 572;
    sub_98197C(session, image_id, al, cl, lengthX, lengthY, 90, height, boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ);

    image_id = session->TrackColours[SCHEME_MISC];
    if (image_id == IMAGE_TYPE_REMAP)
    {
        image_id = SPRITE_ID_PALETTE_COLOUR_2(ride->track_colour_main[0], ride->track_colour_additional[0]);
    }

    sint32 var_1F = armRotation;
    if (direction & 2)
    {
        var_1F = -var_1F;
        if (var_1F != 0)
            var_1F += 48;
    }
    image_id += var_1F;
    image_id += (direction & 1) * 48;
    image_id += rideEntry->vehicles[0].base_image_id;
    // Left hand arm
    image_id += 380;

    sub_98199C(session, image_id, al, cl, lengthX, lengthY, 90, height, boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ);

    uint32 seatImageId;

    if (vehicle != nullptr && vehicle->restraints_position >= 64)
    {
        // Open Restraints
        image_id = (vehicle->restraints_position - 64) >> 6;
        image_id += direction * 3;
        image_id += rideEntry->vehicles[0].base_image_id;
        image_id += 64;
        seatImageId = image_id;
    }
Exemplo n.º 20
0
void research_fix()
{
    // Fix invalid research items
    for (int32_t i = 0; i < MAX_RESEARCH_ITEMS; i++)
    {
        rct_research_item* researchItem = &gResearchItems[i];
        if (researchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR)
            continue;
        if (researchItem->rawValue == RESEARCHED_ITEMS_END)
        {
            if (i == MAX_RESEARCH_ITEMS - 1)
            {
                (--researchItem)->rawValue = RESEARCHED_ITEMS_END;
            }
            (++researchItem)->rawValue = RESEARCHED_ITEMS_END_2;
            break;
        }
        if (researchItem->rawValue == RESEARCHED_ITEMS_END_2)
            break;
        if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE)
        {
            rct_ride_entry* rideEntry = get_ride_entry(researchItem->entryIndex);
            if (rideEntry == nullptr)
            {
                research_remove(researchItem);
                i--;
            }
        }
        else
        {
            rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem->rawValue);
            if (sceneryGroupEntry == nullptr)
            {
                research_remove(researchItem);
                i--;
            }
        }
    }

    research_update_uncompleted_types();
    if (gResearchUncompletedCategories == 0)
        gResearchProgressStage = RESEARCH_STAGE_FINISHED_ALL;

    // Sometimes ride entries are not in the research table.
    // If all research is done, simply insert all of them as researched.
    // For good measure, also include scenery groups.
    if (gResearchProgressStage == RESEARCH_STAGE_FINISHED_ALL)
    {
        for (uint8_t i = 0; i < MAX_RIDE_OBJECTS; i++)
        {
            const rct_ride_entry* rideEntry = get_ride_entry(i);

            if (rideEntry != nullptr)
            {
                research_insert_ride_entry(i, true);
                ride_entry_set_invented(i);

                for (uint8_t j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++)
                {
                    uint32_t rideType = rideEntry->ride_type[j];
                    if (rideType != RIDE_TYPE_NULL)
                    {
                        ride_type_set_invented(rideEntry->ride_type[j]);
                    }
                }
            }
        }

        for (uint8_t i = 0; i < MAX_SCENERY_GROUP_OBJECTS; i++)
        {
            const rct_scenery_group_entry* groupEntry = get_scenery_group_entry(i);

            if (groupEntry != nullptr)
                research_insert_scenery_group_entry(i, true);
        }
    }
}
Exemplo n.º 21
0
/**
 *	rct2: 0x006B6F3E
 *
 * Note: When the user has selection by track type enabled, the categories are determined by the track type, not those in the rct_ride_entry.
 */
static void window_new_ride_populate_list()
{
	uint8 currentCategory = _windowNewRideCurrentTab;
	ride_list_item *nextListItem = _windowNewRideListItems;

	// For each ride type in the view order list
	for (int i = 0; i < countof(RideTypeViewOrder); i++) {
		uint8 rideType = RideTypeViewOrder[i];
		if (rideType == RIDE_TYPE_NULL)
			continue;

		if(gConfigInterface.select_by_track_type) {
			if(gRideCategories[rideType]!=currentCategory)
				continue;
		}

		char preferredVehicleName[9];
		safe_strcpy(preferredVehicleName, "        ", sizeof(preferredVehicleName));

		if (ride_type_is_invented(rideType)) {
			int dh = 0;
			uint8 *rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(rideType);

			// For each ride entry for this ride type
			while (*rideEntryIndexPtr != 255) {
				uint8 rideEntryIndex = *rideEntryIndexPtr++;
				char rideEntryName[9];
				memcpy(rideEntryName,object_entry_groups[OBJECT_TYPE_RIDE].entries[rideEntryIndex].name,8);
				rideEntryName[8]=0;

				// Skip if vehicle type is not invented yet
				if (!ride_entry_is_invented(rideEntryIndex))
					continue;

				// Ride entries
				rct_ride_entry *rideEntry = get_ride_entry(rideEntryIndex);

				// Check if ride is in this category
				if (!gConfigInterface.select_by_track_type && (currentCategory != rideEntry->category[0] && currentCategory != rideEntry->category[1]))
					continue;

				// Skip if the vehicle isn't the preferred vehicle for this generic track type
				if (gConfigInterface.select_by_track_type && (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) || rideTypeShouldLoseSeparateFlag(rideEntry))) {
					if (strcmp(preferredVehicleName, "        \0") == 0) {
						safe_strcpy(preferredVehicleName, rideEntryName, sizeof(preferredVehicleName));
						preferredVehicleName[8] = 0;
					} else {
						if (vehicle_preference_compare(rideType, preferredVehicleName, rideEntryName) == 1) {
							safe_strcpy(preferredVehicleName, rideEntryName, sizeof(preferredVehicleName));
							preferredVehicleName[8] = 0;
						} else {
							continue;
						}
					}
				}

				if ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) && !rideTypeShouldLoseSeparateFlag(rideEntry)) {
					dh &= ~4;
					nextListItem->type = rideType;
					nextListItem->entry_index = rideEntryIndex;
					nextListItem++;
				} else if (!(dh & 1)) {
					dh |= 5;
					nextListItem->type = rideType;
					nextListItem->entry_index = rideEntryIndex;
					nextListItem++;
				} else if (dh & 4) {
					if (rideType == rideEntry->ride_type[0]) {
						nextListItem--;
						nextListItem->type = rideType;
						nextListItem->entry_index = rideEntryIndex;
						nextListItem++;
					}
				}
			}
		}
	}

	nextListItem->type = 255;
	nextListItem->entry_index = 255;
	_trackSelectionByType = gConfigInterface.select_by_track_type;
}
Exemplo n.º 22
0
/**
 *
 *  rct2: 0x006D3B1F
 */
static void window_install_track_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
    window_draw_widgets(w, dpi);

    // Track preview
    rct_widget* widget = &window_install_track_widgets[WIDX_TRACK_PREVIEW];
    int32_t x = w->x + widget->left + 1;
    int32_t y = w->y + widget->top + 1;
    int32_t colour = ColourMapA[w->colours[0]].darkest;
    gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);

    rct_g1_element g1temp = {};
    g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
    g1temp.width = 370;
    g1temp.height = 217;
    g1temp.flags = G1_FLAG_BMP;
    gfx_set_g1_element(SPR_TEMP, &g1temp);
    gfx_draw_sprite(dpi, SPR_TEMP, x, y, 0);

    x = w->x + (widget->left + widget->right) / 2;
    y = w->y + widget->bottom - 12;

    // Warnings
    rct_track_td6* td6 = _trackDesign;
    if (td6->track_flags & TRACK_DESIGN_FLAG_SCENERY_UNAVAILABLE)
    {
        if (!gTrackDesignSceneryToggle)
        {
            // Scenery not available
            gfx_draw_string_centred_clipped(
                dpi, STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE, nullptr, COLOUR_BLACK, x, y, 368);
            y -= LIST_ROW_HEIGHT;
        }
    }

    // Information
    x = w->x + widget->left + 1;
    y = w->y + widget->bottom + 4;
    // 0x006D3CF1 -- 0x006d3d71 missing

    // Track design name & type
    auto trackName = _trackName.c_str();
    gfx_draw_string_left(dpi, STR_TRACK_DESIGN_NAME, &trackName, COLOUR_BLACK, x - 1, y);
    y += LIST_ROW_HEIGHT;

    rct_ride_name rideName;
    rct_string_id friendlyTrackName;

    void* objectEntry = object_manager_load_object(&td6->vehicle_object);
    if (objectEntry != nullptr)
    {
        int32_t groupIndex = object_manager_get_loaded_object_entry_index(objectEntry);
        rideName = get_ride_naming(td6->type, get_ride_entry(groupIndex));
        friendlyTrackName = rideName.name;
    }
    else
    {
        // Fall back on the technical track name if the vehicle object cannot be loaded
        friendlyTrackName = RideNaming[td6->type].name;
    }

    gfx_draw_string_left(dpi, STR_TRACK_DESIGN_TYPE, &friendlyTrackName, COLOUR_BLACK, x, y);
    y += LIST_ROW_HEIGHT + 4;

    // Stats
    fixed32_2dp rating = td6->excitement * 10;
    gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, COLOUR_BLACK, x, y);
    y += LIST_ROW_HEIGHT;

    rating = td6->intensity * 10;
    gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, COLOUR_BLACK, x, y);
    y += LIST_ROW_HEIGHT;

    rating = td6->nausea * 10;
    gfx_draw_string_left(dpi, STR_TRACK_LIST_NAUSEA_RATING, &rating, COLOUR_BLACK, x, y);
    y += LIST_ROW_HEIGHT + 4;

    if (td6->type != RIDE_TYPE_MAZE)
    {
        if (td6->type == RIDE_TYPE_MINI_GOLF)
        {
            // Holes
            uint16_t holes = td6->holes & 0x1F;
            gfx_draw_string_left(dpi, STR_HOLES, &holes, COLOUR_BLACK, x, y);
            y += LIST_ROW_HEIGHT;
        }
        else
        {
            // Maximum speed
            uint16_t speed = ((td6->max_speed << 16) * 9) >> 18;
            gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, COLOUR_BLACK, x, y);
            y += LIST_ROW_HEIGHT;

            // Average speed
            speed = ((td6->average_speed << 16) * 9) >> 18;
            gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &speed, COLOUR_BLACK, x, y);
            y += LIST_ROW_HEIGHT;
        }

        // Ride length
        set_format_arg(0, rct_string_id, STR_RIDE_LENGTH_ENTRY);
        set_format_arg(2, uint16_t, td6->ride_length);
        gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, gCommonFormatArgs, COLOUR_BLACK, x, y, 214);
        y += LIST_ROW_HEIGHT;
    }

    if (ride_type_has_flag(td6->type, RIDE_TYPE_FLAG_HAS_G_FORCES))
    {
        // Maximum positive vertical Gs
        int32_t gForces = td6->max_positive_vertical_g * 32;
        gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, COLOUR_BLACK, x, y);
        y += LIST_ROW_HEIGHT;

        // Maximum negative vertical Gs
        gForces = td6->max_negative_vertical_g * 32;
        gfx_draw_string_left(dpi, STR_MAX_NEGATIVE_VERTICAL_G, &gForces, COLOUR_BLACK, x, y);
        y += LIST_ROW_HEIGHT;

        // Maximum lateral Gs
        gForces = td6->max_lateral_g * 32;
        gfx_draw_string_left(dpi, STR_MAX_LATERAL_G, &gForces, COLOUR_BLACK, x, y);
        y += LIST_ROW_HEIGHT;

        // If .TD6
        if (td6->version_and_colour_scheme / 4 >= 2)
        {
            if (td6->total_air_time != 0)
            {
                // Total air time
                int32_t airTime = td6->total_air_time * 25;
                gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &airTime, COLOUR_BLACK, x, y);
                y += LIST_ROW_HEIGHT;
            }
        }
    }

    if (ride_type_has_flag(td6->type, RIDE_TYPE_FLAG_HAS_DROPS))
    {
        // Drops
        uint16_t drops = td6->drops & 0x3F;
        gfx_draw_string_left(dpi, STR_DROPS, &drops, COLOUR_BLACK, x, y);
        y += LIST_ROW_HEIGHT;

        // Drop height is multiplied by 0.75
        gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &drops, COLOUR_BLACK, x, y);
        y += LIST_ROW_HEIGHT;
    }

    if (td6->type != RIDE_TYPE_MINI_GOLF)
    {
        uint16_t inversions = td6->inversions & 0x1F;
        if (inversions != 0)
        {
            // Inversions
            gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, COLOUR_BLACK, x, y);
            y += LIST_ROW_HEIGHT;
        }
    }
    y += 4;

    if (td6->space_required_x != 0xFF)
    {
        // Space required
        set_format_arg(0, uint16_t, td6->space_required_x);
        set_format_arg(2, uint16_t, td6->space_required_y);
        gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, gCommonFormatArgs, COLOUR_BLACK, x, y);
        y += LIST_ROW_HEIGHT;
    }

    if (td6->cost != 0)
    {
        gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &td6->cost, COLOUR_BLACK, x, y);
    }
}
Exemplo n.º 23
0
/**
 *
 *  rct2: 0x006850BD
 */
static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex)
{
    // Draw background
    uint8_t paletteIndex = ColourMapA[w->colours[1]].mid_light;
    gfx_clear(dpi, paletteIndex);

    rct_research_item* researchItem = gResearchItems;
    int32_t researchItemEndMarker;

    if (scrollIndex == 1)
    {
        // Skip pre-researched items
        for (; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
        {
        }
        researchItem++;
        researchItemEndMarker = RESEARCHED_ITEMS_END;
    }
    else
    {
        researchItemEndMarker = RESEARCHED_ITEMS_SEPARATOR;
    }

    int16_t boxWidth = (w->widgets[WIDX_RESEARCH_ORDER_SCROLL].right - w->widgets[WIDX_RESEARCH_ORDER_SCROLL].left);
    int16_t columnSplitOffset = boxWidth / 2;
    int32_t itemY = -SCROLLABLE_ROW_HEIGHT;
    do
    {
        itemY += SCROLLABLE_ROW_HEIGHT;
        if (itemY + SCROLLABLE_ROW_HEIGHT < dpi->y || itemY >= dpi->y + dpi->height)
            continue;

        if (w->research_item == researchItem)
        {
            int32_t top, bottom;
            if (_editorInventionsListDraggedItem == nullptr)
            {
                // Highlight
                top = itemY;
                bottom = itemY + SCROLLABLE_ROW_HEIGHT - 1;
            }
            else
            {
                // Drop horizontal rule
                top = itemY - 1;
                bottom = itemY;
            }

            gfx_filter_rect(dpi, 0, top, boxWidth, bottom, PALETTE_DARKEN_1);
        }

        if (researchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR || researchItem->rawValue == RESEARCHED_ITEMS_END)
            continue;

        if (researchItem == _editorInventionsListDraggedItem)
            continue;

        utf8 groupNameBuffer[256], vehicleNameBuffer[256];
        utf8* groupNamePtr = groupNameBuffer;
        utf8* vehicleNamePtr = vehicleNameBuffer;

        uint8_t colour;
        if (research_item_is_always_researched(researchItem))
        {
            if (w->research_item == researchItem && _editorInventionsListDraggedItem == nullptr)
                gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK;
            else
                gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_DARK;
            colour = w->colours[1] | COLOUR_FLAG_INSET;
        }
        else
        {
            // TODO: this is actually just a black colour.
            colour = COLOUR_BRIGHT_GREEN | COLOUR_FLAG_TRANSLUCENT;
            gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;

            groupNamePtr = utf8_write_codepoint(groupNamePtr, colour);
            vehicleNamePtr = utf8_write_codepoint(vehicleNamePtr, colour);
        }

        rct_string_id itemNameId = research_item_get_name(researchItem);

        if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE
            && !RideGroupManager::RideTypeIsIndependent(researchItem->baseRideType))
        {
            const auto rideEntry = get_ride_entry(researchItem->entryIndex);
            const rct_string_id rideGroupName = get_ride_naming(researchItem->baseRideType, rideEntry).name;
            format_string(
                groupNamePtr, std::size(groupNameBuffer), STR_INVENTIONS_LIST_RIDE_AND_VEHICLE_NAME, (void*)&rideGroupName);
            format_string(vehicleNamePtr, std::size(vehicleNameBuffer), itemNameId, nullptr);
        }
        else
        {
            format_string(groupNamePtr, std::size(groupNameBuffer), itemNameId, nullptr);
            vehicleNamePtr = nullptr;
        }

        // Draw group name
        gfx_clip_string(groupNameBuffer, columnSplitOffset);
        gfx_draw_string(dpi, groupNameBuffer, colour, 1, itemY);

        // Draw vehicle name
        if (vehicleNamePtr)
        {
            gfx_clip_string(vehicleNameBuffer, columnSplitOffset - 11);
            gfx_draw_string(dpi, vehicleNameBuffer, colour, columnSplitOffset + 1, itemY);
        }
    } while (researchItem++->rawValue != researchItemEndMarker);
}
Exemplo n.º 24
0
/**
 *
 *  rct2: 0x006848D4
 */
void research_finish_item(rct_research_item* researchItem)
{
    gResearchLastItem = *researchItem;
    research_invalidate_related_windows();

    if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE)
    {
        // Ride
        uint32_t base_ride_type = researchItem->baseRideType;
        int32_t rideEntryIndex = researchItem->entryIndex;
        rct_ride_entry* rideEntry = get_ride_entry(rideEntryIndex);

        if (rideEntry != nullptr && base_ride_type != RIDE_TYPE_NULL)
        {
            bool ride_group_was_invented_before = false;
            bool ride_type_was_invented_before = ride_type_is_invented(base_ride_type);
            rct_string_id availabilityString;

            // Determine if the ride group this entry belongs to was invented before.
            if (RideGroupManager::RideTypeHasRideGroups(base_ride_type))
            {
                const RideGroup* rideGroup = RideGroupManager::GetRideGroup(base_ride_type, rideEntry);

                if (rideGroup->IsInvented())
                {
                    ride_group_was_invented_before = true;
                }
            }

            ride_type_set_invented(base_ride_type);
            openrct2_assert(
                base_ride_type < std::size(RideTypePossibleTrackConfigurations), "Invalid base_ride_type = %d", base_ride_type);

            ride_entry_set_invented(rideEntryIndex);

            bool seenRideEntry[MAX_RIDE_OBJECTS]{};

            rct_research_item* researchItem2 = gResearchItems;
            for (; researchItem2->rawValue != RESEARCHED_ITEMS_END; researchItem2++)
            {
                if (researchItem2->rawValue != RESEARCHED_ITEMS_SEPARATOR && researchItem2->type == RESEARCH_ENTRY_TYPE_RIDE)
                {
                    uint8_t index = researchItem2->entryIndex;
                    seenRideEntry[index] = true;
                }
            }

            // RCT2 made non-separated vehicles available at once, by removing all but one from research.
            // To ensure old files keep working, look for ride entries not in research, and make them available as well.
            for (int32_t i = 0; i < MAX_RIDE_OBJECTS; i++)
            {
                if (!seenRideEntry[i])
                {
                    rct_ride_entry* rideEntry2 = get_ride_entry(i);
                    if (rideEntry2 != nullptr)
                    {
                        for (uint8_t j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++)
                        {
                            if (rideEntry2->ride_type[j] == base_ride_type)
                            {
                                ride_entry_set_invented(i);
                                break;
                            }
                        }
                    }
                }
            }

            // If a vehicle should be listed separately (maze, mini golf, flat rides, shops)
            if (RideGroupManager::RideTypeIsIndependent(base_ride_type))
            {
                availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE;
                set_format_arg(0, rct_string_id, rideEntry->naming.name);
            }
            // If a vehicle is the first to be invented for its ride group, show the ride group name.
            else if (
                !ride_type_was_invented_before
                || (RideGroupManager::RideTypeHasRideGroups(base_ride_type) && !ride_group_was_invented_before))
            {
                rct_ride_name naming = get_ride_naming(base_ride_type, rideEntry);
                availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE;
                set_format_arg(0, rct_string_id, naming.name);
            }
            // If the vehicle should not be listed separately and it isn't the first to be invented for its ride group,
            // report it as a new vehicle for the existing ride group.
            else
            {
                availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_VEHICLE_AVAILABLE;
                rct_ride_name baseRideNaming = get_ride_naming(base_ride_type, rideEntry);

                set_format_arg(0, rct_string_id, baseRideNaming.name);
                set_format_arg(2, rct_string_id, rideEntry->naming.name);
            }

            if (!gSilentResearch)
            {
                if (gConfigNotifications.ride_researched)
                {
                    news_item_add_to_queue(NEWS_ITEM_RESEARCH, availabilityString, researchItem->rawValue);
                }
            }

            research_invalidate_related_windows();
        }
    }
    else
    {
        // Scenery
        rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem->entryIndex);
        if (sceneryGroupEntry != nullptr)
        {
            scenery_group_set_invented(researchItem->entryIndex);

            set_format_arg(0, rct_string_id, sceneryGroupEntry->name);

            if (!gSilentResearch)
            {
                if (gConfigNotifications.ride_researched)
                {
                    news_item_add_to_queue(
                        NEWS_ITEM_RESEARCH, STR_NEWS_ITEM_RESEARCH_NEW_SCENERY_SET_AVAILABLE, researchItem->rawValue);
                }
            }

            research_invalidate_related_windows();
            init_scenery();
        }
    }
}