mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #9437 from Gymnasiast/nog-eens-research
Move research to vectors
This commit is contained in:
commit
e11f2d965a
|
@ -84,7 +84,7 @@ static void window_editor_inventions_list_drag_cursor(rct_window *w, rct_widgeti
|
|||
static void window_editor_inventions_list_drag_moved(rct_window* w, int32_t x, int32_t y);
|
||||
static void window_editor_inventions_list_drag_paint(rct_window *w, rct_drawpixelinfo *dpi);
|
||||
|
||||
static rct_string_id window_editor_inventions_list_prepare_name(const rct_research_item * researchItem, bool withGap);
|
||||
static rct_string_id window_editor_inventions_list_prepare_name(const ResearchItem * researchItem, bool withGap);
|
||||
|
||||
// 0x0098177C
|
||||
static rct_window_event_list window_editor_inventions_list_events = {
|
||||
|
@ -152,7 +152,7 @@ static rct_window_event_list window_editor_inventions_list_drag_events = {
|
|||
|
||||
#pragma endregion
|
||||
|
||||
static rct_research_item *_editorInventionsListDraggedItem;
|
||||
static ResearchItem _editorInventionsListDraggedItem;
|
||||
|
||||
static constexpr const rct_string_id EditorInventionsResearchCategories[] = {
|
||||
STR_RESEARCH_NEW_TRANSPORT_RIDES,
|
||||
|
@ -165,8 +165,8 @@ static constexpr const rct_string_id EditorInventionsResearchCategories[] = {
|
|||
};
|
||||
// clang-format on
|
||||
|
||||
static void window_editor_inventions_list_drag_open(rct_research_item* researchItem);
|
||||
static void move_research_item(rct_research_item* beforeItem);
|
||||
static void window_editor_inventions_list_drag_open(ResearchItem* researchItem);
|
||||
static void move_research_item(ResearchItem* beforeItem, int32_t scrollIndex);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -196,72 +196,47 @@ static void research_rides_setup()
|
|||
*
|
||||
* rct2: 0x006855E7
|
||||
*/
|
||||
static void move_research_item(rct_research_item* beforeItem)
|
||||
static void move_research_item(ResearchItem* beforeItem, int32_t scrollIndex)
|
||||
{
|
||||
rct_window* w;
|
||||
rct_research_item *researchItem, draggedItem;
|
||||
|
||||
if (_editorInventionsListDraggedItem + 1 == beforeItem)
|
||||
return;
|
||||
|
||||
// Back up the dragged item
|
||||
draggedItem = *_editorInventionsListDraggedItem;
|
||||
|
||||
// Remove dragged item from list
|
||||
researchItem = _editorInventionsListDraggedItem;
|
||||
do
|
||||
{
|
||||
*researchItem = *(researchItem + 1);
|
||||
researchItem++;
|
||||
} while (researchItem->rawValue != RESEARCHED_ITEMS_END_2);
|
||||
// At end of this researchItem points to the end of the list
|
||||
|
||||
if (beforeItem > _editorInventionsListDraggedItem)
|
||||
beforeItem--;
|
||||
|
||||
// Add dragged item to list
|
||||
do
|
||||
{
|
||||
*researchItem = *(researchItem - 1);
|
||||
researchItem--;
|
||||
} while (researchItem != beforeItem);
|
||||
|
||||
*researchItem = draggedItem;
|
||||
|
||||
w = window_find_by_class(WC_EDITOR_INVENTION_LIST);
|
||||
auto w = window_find_by_class(WC_EDITOR_INVENTION_LIST);
|
||||
if (w != nullptr)
|
||||
{
|
||||
w->research_item = nullptr;
|
||||
w->Invalidate();
|
||||
}
|
||||
|
||||
research_remove(&_editorInventionsListDraggedItem);
|
||||
|
||||
auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented;
|
||||
if (beforeItem != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < researchList.size(); i++)
|
||||
{
|
||||
if (researchList[i].Equals(beforeItem))
|
||||
{
|
||||
researchList.insert((researchList.begin() + i), _editorInventionsListDraggedItem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Still not found? Append to end of list.
|
||||
researchList.push_back(_editorInventionsListDraggedItem);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068558E
|
||||
*/
|
||||
static rct_research_item* window_editor_inventions_list_get_item_from_scroll_y(int32_t scrollIndex, int32_t y)
|
||||
static ResearchItem* window_editor_inventions_list_get_item_from_scroll_y(int32_t scrollIndex, int32_t y)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
|
||||
researchItem = gResearchItems;
|
||||
|
||||
if (scrollIndex != 0)
|
||||
{
|
||||
// Skip pre-researched items
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
|
||||
{
|
||||
}
|
||||
researchItem++;
|
||||
}
|
||||
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR && researchItem->rawValue != RESEARCHED_ITEMS_END;
|
||||
researchItem++)
|
||||
auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented;
|
||||
for (auto& researchItem : researchList)
|
||||
{
|
||||
y -= SCROLLABLE_ROW_HEIGHT;
|
||||
if (y < 0)
|
||||
{
|
||||
return researchItem;
|
||||
return &researchItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,35 +247,21 @@ static rct_research_item* window_editor_inventions_list_get_item_from_scroll_y(i
|
|||
*
|
||||
* rct2: 0x006855BB
|
||||
*/
|
||||
static rct_research_item* window_editor_inventions_list_get_item_from_scroll_y_include_seps(int32_t scrollIndex, int32_t y)
|
||||
static ResearchItem* window_editor_inventions_list_get_item_from_scroll_y_include_seps(int32_t scrollIndex, int32_t y)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
|
||||
researchItem = gResearchItems;
|
||||
|
||||
if (scrollIndex != 0)
|
||||
{
|
||||
// Skip pre-researched items
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
|
||||
{
|
||||
}
|
||||
researchItem++;
|
||||
}
|
||||
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR && researchItem->rawValue != RESEARCHED_ITEMS_END;
|
||||
researchItem++)
|
||||
auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented;
|
||||
for (auto& researchItem : researchList)
|
||||
{
|
||||
y -= SCROLLABLE_ROW_HEIGHT;
|
||||
if (y < 0)
|
||||
{
|
||||
return researchItem;
|
||||
return &researchItem;
|
||||
}
|
||||
}
|
||||
|
||||
return researchItem;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static rct_research_item* get_research_item_at(int32_t x, int32_t y)
|
||||
static ResearchItem* get_research_item_at(int32_t x, int32_t y, int32_t* outScrollId)
|
||||
{
|
||||
rct_window* w = window_find_by_class(WC_EDITOR_INVENTION_LIST);
|
||||
if (w != nullptr && w->x <= x && w->y < y && w->x + w->width > x && w->y + w->height > y)
|
||||
|
@ -310,18 +271,19 @@ static rct_research_item* get_research_item_at(int32_t x, int32_t y)
|
|||
if (widgetIndex == WIDX_PRE_RESEARCHED_SCROLL || widgetIndex == WIDX_RESEARCH_ORDER_SCROLL)
|
||||
{
|
||||
gPressedWidget.widget_index = widgetIndex;
|
||||
int32_t outX, outY, outScrollArea, outScrollId;
|
||||
widget_scroll_get_part(w, widget, x, y, &outX, &outY, &outScrollArea, &outScrollId);
|
||||
int32_t outX, outY, outScrollArea;
|
||||
widget_scroll_get_part(w, widget, x, y, &outX, &outY, &outScrollArea, outScrollId);
|
||||
if (outScrollArea == SCROLL_PART_VIEW)
|
||||
{
|
||||
outScrollId = outScrollId == 0 ? 0 : 1;
|
||||
*outScrollId = *outScrollId == 0 ? 0 : 1;
|
||||
|
||||
int32_t scrollY = y - (w->y + widget->top) + w->scrolls[outScrollId].v_top + 5;
|
||||
return window_editor_inventions_list_get_item_from_scroll_y_include_seps(outScrollId, scrollY);
|
||||
int32_t scrollY = y - (w->y + widget->top) + w->scrolls[*outScrollId].v_top + 5;
|
||||
return window_editor_inventions_list_get_item_from_scroll_y_include_seps(*outScrollId, scrollY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*outScrollId = -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -348,7 +310,7 @@ rct_window* window_editor_inventions_list_open()
|
|||
w->var_4AE = 0;
|
||||
w->selected_tab = 0;
|
||||
w->research_item = nullptr;
|
||||
_editorInventionsListDraggedItem = nullptr;
|
||||
_editorInventionsListDraggedItem.rawValue = -1;
|
||||
|
||||
w->min_width = WW;
|
||||
w->min_height = WH;
|
||||
|
@ -427,13 +389,13 @@ static void window_editor_inventions_list_update(rct_window* w)
|
|||
window_event_invalidate_call(w);
|
||||
widget_invalidate(w, WIDX_TAB_1);
|
||||
|
||||
if (_editorInventionsListDraggedItem == nullptr)
|
||||
if (_editorInventionsListDraggedItem.IsInventedEndMarker())
|
||||
return;
|
||||
|
||||
if (window_find_by_class(WC_EDITOR_INVENTION_LIST_DRAG) != nullptr)
|
||||
return;
|
||||
|
||||
_editorInventionsListDraggedItem = nullptr;
|
||||
_editorInventionsListDraggedItem.rawValue = -1;
|
||||
w->Invalidate();
|
||||
}
|
||||
|
||||
|
@ -443,22 +405,14 @@ static void window_editor_inventions_list_update(rct_window* w)
|
|||
*/
|
||||
static void window_editor_inventions_list_scrollgetheight(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
|
||||
*height = 0;
|
||||
|
||||
// Count / skip pre-researched items
|
||||
for (researchItem = gResearchItems; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
|
||||
*height += SCROLLABLE_ROW_HEIGHT;
|
||||
|
||||
if (scrollIndex == 1)
|
||||
if (scrollIndex == 0)
|
||||
{
|
||||
researchItem++;
|
||||
|
||||
// Count non pre-researched items
|
||||
*height = 0;
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_END; researchItem++)
|
||||
*height += SCROLLABLE_ROW_HEIGHT;
|
||||
*height += (int32_t)gResearchItemsInvented.size() * SCROLLABLE_ROW_HEIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
*height += (int32_t)gResearchItemsUninvented.size() * SCROLLABLE_ROW_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,14 +422,14 @@ static void window_editor_inventions_list_scrollgetheight(rct_window* w, int32_t
|
|||
*/
|
||||
static void window_editor_inventions_list_scrollmousedown(rct_window* w, int32_t scrollIndex, int32_t x, int32_t y)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
ResearchItem* researchItem;
|
||||
|
||||
researchItem = window_editor_inventions_list_get_item_from_scroll_y(scrollIndex, y);
|
||||
if (researchItem == nullptr)
|
||||
return;
|
||||
|
||||
// Disallow picking up always-researched items
|
||||
if (researchItem->rawValue < RESEARCHED_ITEMS_END_2 || research_item_is_always_researched(researchItem))
|
||||
if (research_item_is_always_researched(researchItem))
|
||||
return;
|
||||
|
||||
w->Invalidate();
|
||||
|
@ -488,7 +442,7 @@ static void window_editor_inventions_list_scrollmousedown(rct_window* w, int32_t
|
|||
*/
|
||||
static void window_editor_inventions_list_scrollmouseover(rct_window* w, int32_t scrollIndex, int32_t x, int32_t y)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
ResearchItem* researchItem;
|
||||
|
||||
researchItem = window_editor_inventions_list_get_item_from_scroll_y(scrollIndex, y);
|
||||
if (researchItem != w->research_item)
|
||||
|
@ -511,7 +465,7 @@ static void window_editor_inventions_list_scrollmouseover(rct_window* w, int32_t
|
|||
static void window_editor_inventions_list_cursor(
|
||||
rct_window* w, rct_widgetindex widgetIndex, int32_t x, int32_t y, int32_t* cursorId)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
ResearchItem* researchItem;
|
||||
int32_t scrollIndex;
|
||||
|
||||
switch (widgetIndex)
|
||||
|
@ -528,8 +482,7 @@ static void window_editor_inventions_list_cursor(
|
|||
|
||||
// Use the open hand as cursor for items that can be picked up
|
||||
researchItem = window_editor_inventions_list_get_item_from_scroll_y(scrollIndex, y);
|
||||
if (researchItem != nullptr && researchItem->rawValue >= RESEARCHED_ITEMS_END_2
|
||||
&& !research_item_is_always_researched(researchItem))
|
||||
if (researchItem != nullptr && !research_item_is_always_researched(researchItem))
|
||||
{
|
||||
*cursorId = CURSOR_HAND_OPEN;
|
||||
}
|
||||
|
@ -589,7 +542,7 @@ static void window_editor_inventions_list_invalidate(rct_window* w)
|
|||
static void window_editor_inventions_list_paint(rct_window* w, rct_drawpixelinfo* dpi)
|
||||
{
|
||||
rct_widget* widget;
|
||||
rct_research_item* researchItem;
|
||||
ResearchItem* researchItem;
|
||||
rct_string_id stringId;
|
||||
int32_t x, y, width;
|
||||
|
||||
|
@ -616,8 +569,8 @@ static void window_editor_inventions_list_paint(rct_window* w, rct_drawpixelinfo
|
|||
dpi, w->x + widget->left + 1, w->y + widget->top + 1, w->x + widget->right - 1, w->y + widget->bottom - 1,
|
||||
ColourMapA[w->colours[1]].darkest);
|
||||
|
||||
researchItem = _editorInventionsListDraggedItem;
|
||||
if (researchItem == nullptr)
|
||||
researchItem = &_editorInventionsListDraggedItem;
|
||||
if (researchItem->IsInventedEndMarker())
|
||||
researchItem = w->research_item;
|
||||
// If the research item is null or a list separator.
|
||||
if (researchItem == nullptr || researchItem->rawValue < 0)
|
||||
|
@ -676,36 +629,21 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
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
|
||||
|
||||
const auto& researchList = scrollIndex == 0 ? gResearchItemsInvented : gResearchItemsUninvented;
|
||||
for (const auto& researchItem : researchList)
|
||||
{
|
||||
itemY += SCROLLABLE_ROW_HEIGHT;
|
||||
if (itemY + SCROLLABLE_ROW_HEIGHT < dpi->y || itemY >= dpi->y + dpi->height)
|
||||
continue;
|
||||
|
||||
if (w->research_item == researchItem)
|
||||
if (w->research_item == &researchItem)
|
||||
{
|
||||
int32_t top, bottom;
|
||||
if (_editorInventionsListDraggedItem == nullptr)
|
||||
if (_editorInventionsListDraggedItem.IsInventedEndMarker())
|
||||
{
|
||||
// Highlight
|
||||
top = itemY;
|
||||
|
@ -721,10 +659,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
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)
|
||||
if (researchItem.Equals(&_editorInventionsListDraggedItem))
|
||||
continue;
|
||||
|
||||
utf8 groupNameBuffer[256], vehicleNameBuffer[256];
|
||||
|
@ -732,9 +667,9 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
utf8* vehicleNamePtr = vehicleNameBuffer;
|
||||
|
||||
uint8_t colour;
|
||||
if (research_item_is_always_researched(researchItem))
|
||||
if (research_item_is_always_researched(&researchItem))
|
||||
{
|
||||
if (w->research_item == researchItem && _editorInventionsListDraggedItem == nullptr)
|
||||
if (w->research_item == &researchItem && _editorInventionsListDraggedItem.IsInventedEndMarker())
|
||||
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK;
|
||||
else
|
||||
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_DARK;
|
||||
|
@ -750,13 +685,13 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
vehicleNamePtr = utf8_write_codepoint(vehicleNamePtr, colour);
|
||||
}
|
||||
|
||||
rct_string_id itemNameId = research_item_get_name(researchItem);
|
||||
rct_string_id itemNameId = research_item_get_name(&researchItem);
|
||||
|
||||
if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE
|
||||
&& !RideGroupManager::RideTypeIsIndependent(researchItem->baseRideType))
|
||||
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;
|
||||
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);
|
||||
|
@ -777,7 +712,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
gfx_clip_string(vehicleNameBuffer, columnSplitOffset - 11);
|
||||
gfx_draw_string(dpi, vehicleNameBuffer, colour, columnSplitOffset + 1, itemY);
|
||||
}
|
||||
} while (researchItem++->rawValue != researchItemEndMarker);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region Drag item
|
||||
|
@ -786,14 +721,14 @@ static void window_editor_inventions_list_scrollpaint(rct_window* w, rct_drawpix
|
|||
*
|
||||
* rct2: 0x006852F4
|
||||
*/
|
||||
static void window_editor_inventions_list_drag_open(rct_research_item* researchItem)
|
||||
static void window_editor_inventions_list_drag_open(ResearchItem* researchItem)
|
||||
{
|
||||
char buffer[256], *ptr;
|
||||
int32_t stringWidth;
|
||||
rct_window* w;
|
||||
|
||||
window_close_by_class(WC_EDITOR_INVENTION_LIST_DRAG);
|
||||
_editorInventionsListDraggedItem = researchItem;
|
||||
_editorInventionsListDraggedItem = *researchItem;
|
||||
rct_string_id stringId = research_item_get_name(researchItem);
|
||||
|
||||
ptr = buffer;
|
||||
|
@ -833,7 +768,8 @@ static void window_editor_inventions_list_drag_cursor(
|
|||
rct_window* inventionListWindow = window_find_by_class(WC_EDITOR_INVENTION_LIST);
|
||||
if (inventionListWindow != nullptr)
|
||||
{
|
||||
rct_research_item* researchItem = get_research_item_at(x, y);
|
||||
int32_t scrollId;
|
||||
ResearchItem* researchItem = get_research_item_at(x, y, &scrollId);
|
||||
if (researchItem != inventionListWindow->research_item)
|
||||
{
|
||||
inventionListWindow->Invalidate();
|
||||
|
@ -849,20 +785,23 @@ static void window_editor_inventions_list_drag_cursor(
|
|||
*/
|
||||
static void window_editor_inventions_list_drag_moved(rct_window* w, int32_t x, int32_t y)
|
||||
{
|
||||
rct_research_item* researchItem;
|
||||
ResearchItem* researchItem;
|
||||
|
||||
int32_t scrollId;
|
||||
// Skip always researched items, so that the dragged item gets placed underneath them
|
||||
do
|
||||
{
|
||||
researchItem = get_research_item_at(x, y);
|
||||
researchItem = get_research_item_at(x, y, &scrollId);
|
||||
y += LIST_ROW_HEIGHT;
|
||||
} while (researchItem != nullptr && researchItem->rawValue >= 0 && research_item_is_always_researched(researchItem));
|
||||
} while (researchItem != nullptr && research_item_is_always_researched(researchItem));
|
||||
|
||||
if (researchItem != nullptr)
|
||||
move_research_item(researchItem);
|
||||
if (scrollId != -1)
|
||||
{
|
||||
move_research_item(researchItem, scrollId);
|
||||
}
|
||||
|
||||
window_close(w);
|
||||
_editorInventionsListDraggedItem = nullptr;
|
||||
_editorInventionsListDraggedItem.rawValue = -1;
|
||||
window_invalidate_by_class(WC_EDITOR_INVENTION_LIST);
|
||||
}
|
||||
|
||||
|
@ -877,11 +816,11 @@ static void window_editor_inventions_list_drag_paint(rct_window* w, rct_drawpixe
|
|||
|
||||
x = w->x;
|
||||
y = w->y + 2;
|
||||
drawString = window_editor_inventions_list_prepare_name(_editorInventionsListDraggedItem, true);
|
||||
drawString = window_editor_inventions_list_prepare_name(&_editorInventionsListDraggedItem, true);
|
||||
gfx_draw_string_left(dpi, drawString, gCommonFormatArgs, COLOUR_BLACK | COLOUR_FLAG_OUTLINE, x, y);
|
||||
}
|
||||
|
||||
static rct_string_id window_editor_inventions_list_prepare_name(const rct_research_item* researchItem, bool withGap)
|
||||
static rct_string_id window_editor_inventions_list_prepare_name(const ResearchItem* researchItem, bool withGap)
|
||||
{
|
||||
rct_string_id drawString;
|
||||
rct_string_id stringId = research_item_get_name(researchItem);
|
||||
|
|
|
@ -292,7 +292,7 @@ static void remove_selected_objects_from_research(const rct_object_entry* instal
|
|||
|
||||
for (auto rideType : rideEntry->ride_type)
|
||||
{
|
||||
rct_research_item tmp = {};
|
||||
ResearchItem tmp = {};
|
||||
tmp.type = RESEARCH_ENTRY_TYPE_RIDE;
|
||||
tmp.entryIndex = entry_index;
|
||||
tmp.baseRideType = rideType;
|
||||
|
@ -301,7 +301,7 @@ static void remove_selected_objects_from_research(const rct_object_entry* instal
|
|||
}
|
||||
else if (entry_type == OBJECT_TYPE_SCENERY_GROUP)
|
||||
{
|
||||
rct_research_item tmp = {};
|
||||
ResearchItem tmp = {};
|
||||
tmp.type = RESEARCH_ENTRY_TYPE_SCENERY;
|
||||
tmp.entryIndex = entry_index;
|
||||
research_remove(&tmp);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
struct rct_research_item;
|
||||
struct ResearchItem;
|
||||
struct rct_object_entry;
|
||||
|
||||
/**
|
||||
|
@ -79,7 +79,7 @@ struct rct_window
|
|||
{ // 0x494
|
||||
uint32_t highlighted_item;
|
||||
uint16_t ride_colour;
|
||||
rct_research_item* research_item;
|
||||
ResearchItem* research_item;
|
||||
rct_object_entry* object_entry;
|
||||
const scenario_index_entry* highlighted_scenario;
|
||||
struct
|
||||
|
|
|
@ -46,13 +46,15 @@ uint8_t gResearchFundingLevel;
|
|||
uint8_t gResearchPriorities;
|
||||
uint16_t gResearchProgress;
|
||||
uint8_t gResearchProgressStage;
|
||||
rct_research_item gResearchLastItem;
|
||||
ResearchItem gResearchLastItem;
|
||||
uint8_t gResearchExpectedMonth;
|
||||
uint8_t gResearchExpectedDay;
|
||||
rct_research_item gResearchNextItem;
|
||||
ResearchItem gResearchNextItem;
|
||||
|
||||
// 0x01358844[500]
|
||||
rct_research_item gResearchItems[MAX_RESEARCH_ITEMS];
|
||||
ResearchItem gResearchItems[MAX_RESEARCH_ITEMS];
|
||||
std::vector<ResearchItem> gResearchItemsUninvented;
|
||||
std::vector<ResearchItem> gResearchItemsInvented;
|
||||
|
||||
// 0x00EE787C
|
||||
uint8_t gResearchUncompletedCategories;
|
||||
|
@ -69,9 +71,8 @@ bool gSilentResearch = false;
|
|||
*/
|
||||
void research_reset_items()
|
||||
{
|
||||
gResearchItems[0].rawValue = RESEARCHED_ITEMS_SEPARATOR;
|
||||
gResearchItems[1].rawValue = RESEARCHED_ITEMS_END;
|
||||
gResearchItems[2].rawValue = RESEARCHED_ITEMS_END_2;
|
||||
gResearchItemsUninvented.clear();
|
||||
gResearchItemsInvented.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,13 +82,10 @@ void research_reset_items()
|
|||
void research_update_uncompleted_types()
|
||||
{
|
||||
int32_t uncompletedResearchTypes = 0;
|
||||
rct_research_item* researchItem = gResearchItems;
|
||||
while (researchItem++->rawValue != RESEARCHED_ITEMS_SEPARATOR)
|
||||
;
|
||||
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_END; researchItem++)
|
||||
for (auto const& researchItem : gResearchItemsUninvented)
|
||||
{
|
||||
uncompletedResearchTypes |= (1 << researchItem->category);
|
||||
uncompletedResearchTypes |= (1 << researchItem.category);
|
||||
}
|
||||
|
||||
gResearchUncompletedCategories = uncompletedResearchTypes;
|
||||
|
@ -127,64 +125,62 @@ static void research_invalidate_related_windows()
|
|||
window_invalidate_by_class(WC_RESEARCH);
|
||||
}
|
||||
|
||||
static void research_mark_as_fully_completed()
|
||||
{
|
||||
gResearchProgress = 0;
|
||||
gResearchProgressStage = RESEARCH_STAGE_FINISHED_ALL;
|
||||
research_invalidate_related_windows();
|
||||
// Reset funding to 0 if no more rides.
|
||||
auto gameAction = ParkSetResearchFundingAction(gResearchPriorities, 0);
|
||||
GameActions::Execute(&gameAction);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00684BE5
|
||||
*/
|
||||
static void research_next_design()
|
||||
{
|
||||
rct_research_item *firstUnresearchedItem, *researchItem, tmp;
|
||||
int32_t ignoreActiveResearchTypes;
|
||||
|
||||
// Skip already researched items
|
||||
firstUnresearchedItem = gResearchItems;
|
||||
while (firstUnresearchedItem->rawValue != RESEARCHED_ITEMS_SEPARATOR)
|
||||
if (gResearchItemsUninvented.empty())
|
||||
{
|
||||
firstUnresearchedItem++;
|
||||
research_mark_as_fully_completed();
|
||||
return;
|
||||
}
|
||||
|
||||
ignoreActiveResearchTypes = 0;
|
||||
researchItem = firstUnresearchedItem;
|
||||
ResearchItem researchItem;
|
||||
|
||||
bool ignoreActiveResearchTypes = false;
|
||||
auto it = gResearchItemsUninvented.begin();
|
||||
for (;;)
|
||||
{
|
||||
researchItem++;
|
||||
if (researchItem->rawValue == RESEARCHED_ITEMS_END)
|
||||
researchItem = *it;
|
||||
if (it == gResearchItemsUninvented.end())
|
||||
{
|
||||
if (!ignoreActiveResearchTypes)
|
||||
{
|
||||
ignoreActiveResearchTypes = 1;
|
||||
researchItem = firstUnresearchedItem;
|
||||
ignoreActiveResearchTypes = true;
|
||||
it = gResearchItemsUninvented.begin();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
gResearchProgress = 0;
|
||||
gResearchProgressStage = RESEARCH_STAGE_FINISHED_ALL;
|
||||
research_invalidate_related_windows();
|
||||
// Reset funding to 0 if no more rides.
|
||||
auto gameAction = ParkSetResearchFundingAction(gResearchPriorities, 0);
|
||||
GameActions::Execute(&gameAction);
|
||||
research_mark_as_fully_completed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (ignoreActiveResearchTypes || (gResearchPriorities & (1 << researchItem->category)))
|
||||
else if (ignoreActiveResearchTypes || (gResearchPriorities & (1 << researchItem.category)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
gResearchNextItem = *researchItem;
|
||||
gResearchNextItem = researchItem;
|
||||
gResearchProgress = 0;
|
||||
gResearchProgressStage = RESEARCH_STAGE_DESIGNING;
|
||||
|
||||
// Bubble research item up until it is above the researched items separator
|
||||
do
|
||||
{
|
||||
tmp = *researchItem;
|
||||
*researchItem = *(researchItem - 1);
|
||||
*(researchItem - 1) = tmp;
|
||||
researchItem--;
|
||||
} while ((researchItem + 1)->rawValue != RESEARCHED_ITEMS_SEPARATOR);
|
||||
gResearchItemsUninvented.erase(it);
|
||||
gResearchItemsInvented.push_back(researchItem);
|
||||
|
||||
research_invalidate_related_windows();
|
||||
}
|
||||
|
@ -193,7 +189,7 @@ static void research_next_design()
|
|||
*
|
||||
* rct2: 0x006848D4
|
||||
*/
|
||||
void research_finish_item(rct_research_item* researchItem)
|
||||
void research_finish_item(ResearchItem* researchItem)
|
||||
{
|
||||
gResearchLastItem = *researchItem;
|
||||
research_invalidate_related_windows();
|
||||
|
@ -229,15 +225,15 @@ void research_finish_item(rct_research_item* researchItem)
|
|||
ride_entry_set_invented(rideEntryIndex);
|
||||
|
||||
bool seenRideEntry[MAX_RIDE_OBJECTS]{};
|
||||
|
||||
rct_research_item* researchItem2 = gResearchItems;
|
||||
for (; researchItem2->rawValue != RESEARCHED_ITEMS_END; researchItem2++)
|
||||
for (auto const& researchItem3 : gResearchItemsUninvented)
|
||||
{
|
||||
if (researchItem2->rawValue != RESEARCHED_ITEMS_SEPARATOR && researchItem2->type == RESEARCH_ENTRY_TYPE_RIDE)
|
||||
{
|
||||
uint8_t index = researchItem2->entryIndex;
|
||||
seenRideEntry[index] = true;
|
||||
}
|
||||
uint8_t index = researchItem3.entryIndex;
|
||||
seenRideEntry[index] = true;
|
||||
}
|
||||
for (auto const& researchItem3 : gResearchItemsInvented)
|
||||
{
|
||||
uint8_t index = researchItem3.entryIndex;
|
||||
seenRideEntry[index] = true;
|
||||
}
|
||||
|
||||
// RCT2 made non-separated vehicles available at once, by removing all but one from research.
|
||||
|
@ -386,54 +382,12 @@ void research_update()
|
|||
}
|
||||
}
|
||||
|
||||
void research_process_random_items()
|
||||
{
|
||||
rct_research_item* research = gResearchItems;
|
||||
for (; research->rawValue != RESEARCHED_ITEMS_END; research++)
|
||||
{
|
||||
}
|
||||
|
||||
research++;
|
||||
for (; research->rawValue != RESEARCHED_ITEMS_END_2; research += 2)
|
||||
{
|
||||
if (scenario_rand() & 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rct_research_item* edx = nullptr;
|
||||
rct_research_item* ebp = nullptr;
|
||||
rct_research_item* inner_research = gResearchItems;
|
||||
do
|
||||
{
|
||||
if (research->rawValue == inner_research->rawValue)
|
||||
{
|
||||
edx = inner_research;
|
||||
}
|
||||
if ((research + 1)->rawValue == inner_research->rawValue)
|
||||
{
|
||||
ebp = inner_research;
|
||||
}
|
||||
} while ((inner_research++)->rawValue != RESEARCHED_ITEMS_END);
|
||||
assert(edx != nullptr);
|
||||
edx->rawValue = research->rawValue;
|
||||
assert(ebp != nullptr);
|
||||
ebp->rawValue = (research + 1)->rawValue;
|
||||
|
||||
uint8_t cat = edx->category;
|
||||
edx->category = ebp->category;
|
||||
ebp->category = cat;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00684AC3
|
||||
*/
|
||||
void research_reset_current_item()
|
||||
{
|
||||
research_process_random_items();
|
||||
|
||||
set_every_ride_type_not_invented();
|
||||
set_every_ride_entry_not_invented();
|
||||
|
||||
|
@ -441,9 +395,9 @@ void research_reset_current_item()
|
|||
set_all_scenery_items_invented();
|
||||
set_all_scenery_groups_not_invented();
|
||||
|
||||
for (rct_research_item* research = gResearchItems; research->rawValue != RESEARCHED_ITEMS_SEPARATOR; research++)
|
||||
for (auto& researchItem : gResearchItemsInvented)
|
||||
{
|
||||
research_finish_item(research);
|
||||
research_finish_item(&researchItem);
|
||||
}
|
||||
|
||||
gResearchLastItem.rawValue = RESEARCHED_ITEMS_SEPARATOR;
|
||||
|
@ -455,29 +409,9 @@ void research_reset_current_item()
|
|||
*
|
||||
* rct2: 0x006857FA
|
||||
*/
|
||||
static void research_insert_unresearched(int32_t rawValue, int32_t category)
|
||||
static void research_insert_unresearched(int32_t rawValue, uint8_t category)
|
||||
{
|
||||
rct_research_item *researchItem, *researchItem2;
|
||||
|
||||
researchItem = gResearchItems;
|
||||
do
|
||||
{
|
||||
if (researchItem->rawValue == RESEARCHED_ITEMS_END)
|
||||
{
|
||||
// Insert slot
|
||||
researchItem2 = researchItem;
|
||||
while (researchItem2->rawValue != RESEARCHED_ITEMS_END_2)
|
||||
{
|
||||
researchItem2++;
|
||||
}
|
||||
memmove(researchItem + 1, researchItem, (researchItem2 - researchItem + 1) * sizeof(rct_research_item));
|
||||
|
||||
// Place new item
|
||||
researchItem->rawValue = rawValue;
|
||||
researchItem->category = category;
|
||||
break;
|
||||
}
|
||||
} while (rawValue != (researchItem++)->rawValue);
|
||||
gResearchItemsUninvented.push_back({ rawValue, category });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -486,52 +420,37 @@ static void research_insert_unresearched(int32_t rawValue, int32_t category)
|
|||
*/
|
||||
static void research_insert_researched(int32_t rawValue, uint8_t category)
|
||||
{
|
||||
rct_research_item *researchItem, *researchItem2;
|
||||
|
||||
researchItem = gResearchItems;
|
||||
// First check to make sure that entry is not already accounted for
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_END; researchItem++)
|
||||
ResearchItem item = { rawValue, category };
|
||||
if (item.Exists())
|
||||
{
|
||||
if ((researchItem->rawValue & 0xFFFFFF) == (rawValue & 0xFFFFFF))
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
researchItem = gResearchItems;
|
||||
do
|
||||
{
|
||||
if (researchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR)
|
||||
{
|
||||
// Insert slot
|
||||
researchItem2 = researchItem;
|
||||
while (researchItem2->rawValue != RESEARCHED_ITEMS_END_2)
|
||||
{
|
||||
researchItem2++;
|
||||
}
|
||||
memmove(researchItem + 1, researchItem, (researchItem2 - researchItem + 1) * sizeof(rct_research_item));
|
||||
|
||||
// Place new item
|
||||
researchItem->rawValue = rawValue;
|
||||
researchItem->category = category;
|
||||
break;
|
||||
}
|
||||
} while (rawValue != (researchItem++)->rawValue);
|
||||
gResearchItemsInvented.push_back(item);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006857CF
|
||||
*/
|
||||
void research_remove(rct_research_item* researchItem)
|
||||
void research_remove(ResearchItem* researchItem)
|
||||
{
|
||||
for (rct_research_item* researchItem2 = gResearchItems; researchItem2->rawValue != RESEARCHED_ITEMS_END; researchItem2++)
|
||||
for (auto it = gResearchItemsUninvented.begin(); it != gResearchItemsUninvented.end(); it++)
|
||||
{
|
||||
if (researchItem2->rawValue == researchItem->rawValue)
|
||||
auto& researchItem2 = *it;
|
||||
if (researchItem2.Equals(researchItem))
|
||||
{
|
||||
do
|
||||
{
|
||||
*researchItem2 = *(researchItem2 + 1);
|
||||
} while (researchItem2++->rawValue != RESEARCHED_ITEMS_END_2);
|
||||
gResearchItemsUninvented.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto it = gResearchItemsInvented.begin(); it != gResearchItemsInvented.end(); it++)
|
||||
{
|
||||
auto& researchItem2 = *it;
|
||||
if (researchItem2.Equals(researchItem))
|
||||
{
|
||||
gResearchItemsInvented.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -773,7 +692,7 @@ void set_every_ride_entry_not_invented()
|
|||
*
|
||||
* rct2: 0x0068563D
|
||||
*/
|
||||
rct_string_id research_item_get_name(const rct_research_item* researchItem)
|
||||
rct_string_id research_item_get_name(const ResearchItem* researchItem)
|
||||
{
|
||||
if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE)
|
||||
{
|
||||
|
@ -821,54 +740,76 @@ rct_string_id research_get_friendly_base_ride_type_name(uint8_t trackType, rct_r
|
|||
*
|
||||
* rct2: 0x00685A79
|
||||
* Do not use the research list outside of the inventions list window with the flags
|
||||
* Clears flags like "always researched".
|
||||
*/
|
||||
void research_remove_flags()
|
||||
{
|
||||
for (rct_research_item* research = gResearchItems; research->rawValue != RESEARCHED_ITEMS_END_2; research++)
|
||||
for (auto& researchItem : gResearchItemsUninvented)
|
||||
{
|
||||
// Clear the always researched flags.
|
||||
if (research->rawValue > RESEARCHED_ITEMS_SEPARATOR)
|
||||
{
|
||||
research->flags = 0;
|
||||
}
|
||||
researchItem.flags = 0;
|
||||
}
|
||||
for (auto& researchItem : gResearchItemsInvented)
|
||||
{
|
||||
researchItem.flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void research_fix()
|
||||
{
|
||||
// Fix invalid research items
|
||||
for (int32_t i = 0; i < MAX_RESEARCH_ITEMS; i++)
|
||||
for (auto it = gResearchItemsInvented.begin(); it != gResearchItemsInvented.end();)
|
||||
{
|
||||
rct_research_item* researchItem = &gResearchItems[i];
|
||||
if (researchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR)
|
||||
continue;
|
||||
if (researchItem->rawValue == RESEARCHED_ITEMS_END)
|
||||
auto& researchItem = *it;
|
||||
if (researchItem.type == RESEARCH_ENTRY_TYPE_RIDE)
|
||||
{
|
||||
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);
|
||||
rct_ride_entry* rideEntry = get_ride_entry(researchItem.entryIndex);
|
||||
if (rideEntry == nullptr)
|
||||
{
|
||||
research_remove(researchItem);
|
||||
i--;
|
||||
it = gResearchItemsInvented.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem->rawValue);
|
||||
rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem.rawValue);
|
||||
if (sceneryGroupEntry == nullptr)
|
||||
{
|
||||
research_remove(researchItem);
|
||||
i--;
|
||||
it = gResearchItemsInvented.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = gResearchItemsUninvented.begin(); it != gResearchItemsUninvented.end();)
|
||||
{
|
||||
auto& researchItem = *it;
|
||||
if (researchItem.type == RESEARCH_ENTRY_TYPE_RIDE)
|
||||
{
|
||||
rct_ride_entry* rideEntry = get_ride_entry(researchItem.entryIndex);
|
||||
if (rideEntry == nullptr)
|
||||
{
|
||||
it = gResearchItemsUninvented.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem.rawValue);
|
||||
if (sceneryGroupEntry == nullptr)
|
||||
{
|
||||
it = gResearchItemsUninvented.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -914,51 +855,18 @@ void research_fix()
|
|||
|
||||
void research_items_make_all_unresearched()
|
||||
{
|
||||
rct_research_item *researchItem, *nextResearchItem, researchItemTemp;
|
||||
|
||||
int32_t sorted;
|
||||
do
|
||||
{
|
||||
sorted = 1;
|
||||
for (researchItem = gResearchItems; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
|
||||
{
|
||||
if (research_item_is_always_researched(researchItem))
|
||||
continue;
|
||||
|
||||
nextResearchItem = researchItem + 1;
|
||||
if (nextResearchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR
|
||||
|| research_item_is_always_researched(nextResearchItem))
|
||||
{
|
||||
// Bubble up always researched item or separator
|
||||
researchItemTemp = *researchItem;
|
||||
*researchItem = *nextResearchItem;
|
||||
*nextResearchItem = researchItemTemp;
|
||||
sorted = 0;
|
||||
|
||||
if (researchItem->rawValue == RESEARCHED_ITEMS_SEPARATOR)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!sorted);
|
||||
gResearchItemsUninvented.insert(
|
||||
gResearchItemsUninvented.end(), std::make_move_iterator(gResearchItemsInvented.begin()),
|
||||
std::make_move_iterator(gResearchItemsInvented.end()));
|
||||
gResearchItemsInvented.clear();
|
||||
}
|
||||
|
||||
void research_items_make_all_researched()
|
||||
{
|
||||
rct_research_item *researchItem, researchItemTemp;
|
||||
|
||||
// Find separator
|
||||
for (researchItem = gResearchItems; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
|
||||
{
|
||||
}
|
||||
|
||||
// Move separator below all items
|
||||
for (; (researchItem + 1)->rawValue != RESEARCHED_ITEMS_END; researchItem++)
|
||||
{
|
||||
// Swap separator with research item
|
||||
researchItemTemp = *researchItem;
|
||||
*researchItem = *(researchItem + 1);
|
||||
*(researchItem + 1) = researchItemTemp;
|
||||
}
|
||||
gResearchItemsInvented.insert(
|
||||
gResearchItemsInvented.end(), std::make_move_iterator(gResearchItemsUninvented.begin()),
|
||||
std::make_move_iterator(gResearchItemsUninvented.end()));
|
||||
gResearchItemsUninvented.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -967,52 +875,41 @@ void research_items_make_all_researched()
|
|||
*/
|
||||
void research_items_shuffle()
|
||||
{
|
||||
rct_research_item *researchItem, *researchOrderBase, researchItemTemp;
|
||||
int32_t i, numNonResearchedItems;
|
||||
|
||||
// Skip pre-researched items
|
||||
for (researchItem = gResearchItems; researchItem->rawValue != RESEARCHED_ITEMS_SEPARATOR; researchItem++)
|
||||
{
|
||||
}
|
||||
researchItem++;
|
||||
researchOrderBase = researchItem;
|
||||
|
||||
// Count non pre-researched items
|
||||
numNonResearchedItems = 0;
|
||||
for (; researchItem->rawValue != RESEARCHED_ITEMS_END; researchItem++)
|
||||
numNonResearchedItems++;
|
||||
|
||||
// Shuffle list
|
||||
for (i = 0; i < numNonResearchedItems; i++)
|
||||
{
|
||||
int32_t ri = util_rand() % numNonResearchedItems;
|
||||
if (ri == i)
|
||||
continue;
|
||||
|
||||
researchItemTemp = researchOrderBase[i];
|
||||
researchOrderBase[i] = researchOrderBase[ri];
|
||||
researchOrderBase[ri] = researchItemTemp;
|
||||
}
|
||||
std::shuffle(std::begin(gResearchItemsUninvented), std::end(gResearchItemsUninvented), std::default_random_engine{});
|
||||
}
|
||||
|
||||
bool research_item_is_always_researched(rct_research_item* researchItem)
|
||||
bool research_item_is_always_researched(const ResearchItem* researchItem)
|
||||
{
|
||||
return (researchItem->flags
|
||||
& (RESEARCH_ENTRY_FLAG_RIDE_ALWAYS_RESEARCHED | RESEARCH_ENTRY_FLAG_SCENERY_SET_ALWAYS_RESEARCHED))
|
||||
!= 0;
|
||||
}
|
||||
|
||||
bool rct_research_item::IsInventedEndMarker() const
|
||||
bool ResearchItem::IsInventedEndMarker() const
|
||||
{
|
||||
return rawValue == RESEARCHED_ITEMS_SEPARATOR;
|
||||
}
|
||||
|
||||
bool rct_research_item::IsUninventedEndMarker() const
|
||||
bool ResearchItem::Equals(const ResearchItem* otherItem) const
|
||||
{
|
||||
return rawValue == RESEARCHED_ITEMS_END;
|
||||
return (entryIndex == otherItem->entryIndex && baseRideType == otherItem->baseRideType && type == otherItem->type);
|
||||
}
|
||||
|
||||
bool rct_research_item::IsRandomEndMarker() const
|
||||
bool ResearchItem::Exists() const
|
||||
{
|
||||
return rawValue == RESEARCHED_ITEMS_END_2;
|
||||
for (auto const& researchItem : gResearchItemsUninvented)
|
||||
{
|
||||
if (researchItem.Equals(this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (auto const& researchItem : gResearchItemsInvented)
|
||||
{
|
||||
if (researchItem.Equals(this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
|
||||
struct rct_ride_entry;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct rct_research_item
|
||||
struct ResearchItem
|
||||
{
|
||||
// Bit 16 (0: scenery entry, 1: ride entry)
|
||||
union
|
||||
|
@ -33,11 +32,9 @@ struct rct_research_item
|
|||
uint8_t category;
|
||||
|
||||
bool IsInventedEndMarker() const;
|
||||
bool IsRandomEndMarker() const;
|
||||
bool IsUninventedEndMarker() const;
|
||||
bool Equals(const ResearchItem* otherItem) const;
|
||||
bool Exists() const;
|
||||
};
|
||||
assert_struct_size(rct_research_item, 5);
|
||||
#pragma pack(pop)
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -100,10 +97,11 @@ extern uint16_t gResearchProgress;
|
|||
extern uint8_t gResearchProgressStage;
|
||||
extern uint8_t gResearchExpectedMonth;
|
||||
extern uint8_t gResearchExpectedDay;
|
||||
extern rct_research_item gResearchLastItem;
|
||||
extern rct_research_item gResearchNextItem;
|
||||
extern ResearchItem gResearchLastItem;
|
||||
extern ResearchItem gResearchNextItem;
|
||||
|
||||
extern rct_research_item gResearchItems[MAX_RESEARCH_ITEMS];
|
||||
extern std::vector<ResearchItem> gResearchItemsUninvented;
|
||||
extern std::vector<ResearchItem> gResearchItemsInvented;
|
||||
extern uint8_t gResearchUncompletedCategories;
|
||||
extern bool gSilentResearch;
|
||||
|
||||
|
@ -113,11 +111,10 @@ void research_update();
|
|||
void research_reset_current_item();
|
||||
void research_populate_list_random();
|
||||
void research_populate_list_researched();
|
||||
void research_process_random_items();
|
||||
|
||||
void research_finish_item(rct_research_item* researchItem);
|
||||
void research_finish_item(ResearchItem* researchItem);
|
||||
void research_insert(int32_t researched, int32_t rawValue, uint8_t category);
|
||||
void research_remove(rct_research_item* researchItem);
|
||||
void research_remove(ResearchItem* researchItem);
|
||||
|
||||
void research_insert_ride_entry(uint8_t entryIndex, bool researched);
|
||||
void research_insert_scenery_group_entry(uint8_t entryIndex, bool researched);
|
||||
|
@ -139,7 +136,7 @@ void set_every_ride_type_invented();
|
|||
void set_every_ride_type_not_invented();
|
||||
void set_every_ride_entry_invented();
|
||||
void set_every_ride_entry_not_invented();
|
||||
rct_string_id research_item_get_name(const rct_research_item* researchItem);
|
||||
rct_string_id research_item_get_name(const ResearchItem* researchItem);
|
||||
rct_string_id research_get_friendly_base_ride_type_name(uint8_t trackType, rct_ride_entry* rideEntry);
|
||||
void research_remove_flags();
|
||||
void research_fix();
|
||||
|
@ -147,4 +144,4 @@ void research_fix();
|
|||
void research_items_make_all_unresearched();
|
||||
void research_items_make_all_researched();
|
||||
void research_items_shuffle();
|
||||
bool research_item_is_always_researched(rct_research_item* researchItem);
|
||||
bool research_item_is_always_researched(const ResearchItem* researchItem);
|
||||
|
|
|
@ -2496,7 +2496,7 @@ private:
|
|||
uint8_t researchItem = src->Assoc & 0x000000FF;
|
||||
uint8_t researchType = (src->Assoc & 0x00FF0000) >> 16;
|
||||
|
||||
rct_research_item tmpResearchItem = {};
|
||||
ResearchItem tmpResearchItem = {};
|
||||
ConvertResearchEntry(&tmpResearchItem, researchItem, researchType);
|
||||
dst->Assoc = (uint32_t)tmpResearchItem.rawValue;
|
||||
}
|
||||
|
@ -2540,7 +2540,7 @@ private:
|
|||
gTotalRideValueForMoney = _s4.total_ride_value_for_money;
|
||||
}
|
||||
|
||||
void ConvertResearchEntry(rct_research_item* dst, uint8_t srcItem, uint8_t srcType)
|
||||
void ConvertResearchEntry(ResearchItem* dst, uint8_t srcItem, uint8_t srcType)
|
||||
{
|
||||
dst->rawValue = RESEARCHED_ITEMS_SEPARATOR;
|
||||
if (srcType == RCT1_RESEARCH_TYPE_RIDE)
|
||||
|
|
|
@ -915,3 +915,18 @@ void RCT12BannerElement::SetAllowedEdges(uint8_t newEdges)
|
|||
flags &= ~0b00001111;
|
||||
flags |= (newEdges & 0b00001111);
|
||||
}
|
||||
|
||||
bool RCT12ResearchItem::IsInventedEndMarker() const
|
||||
{
|
||||
return rawValue == RCT12_RESEARCHED_ITEMS_SEPARATOR;
|
||||
}
|
||||
|
||||
bool RCT12ResearchItem::IsUninventedEndMarker() const
|
||||
{
|
||||
return rawValue == RCT12_RESEARCHED_ITEMS_END;
|
||||
}
|
||||
|
||||
bool RCT12ResearchItem::IsRandomEndMarker() const
|
||||
{
|
||||
return rawValue == RCT12_RESEARCHED_ITEMS_END_2;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,13 @@ enum class RCT12TrackDesignVersion : uint8_t
|
|||
unknown
|
||||
};
|
||||
|
||||
// Everything before this point has been researched
|
||||
#define RCT12_RESEARCHED_ITEMS_SEPARATOR (-1)
|
||||
// Everything before this point and after separator still requires research
|
||||
#define RCT12_RESEARCHED_ITEMS_END (-2)
|
||||
// Extra end of list entry. Leftover from RCT1.
|
||||
#define RCT12_RESEARCHED_ITEMS_END_2 (-3)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* Maze Element entry size: 0x04 */
|
||||
|
@ -658,6 +665,28 @@ struct RCT12MapAnimation
|
|||
};
|
||||
assert_struct_size(RCT12MapAnimation, 6);
|
||||
|
||||
struct RCT12ResearchItem
|
||||
{
|
||||
// Bit 16 (0: scenery entry, 1: ride entry)
|
||||
union
|
||||
{
|
||||
int32_t rawValue;
|
||||
struct
|
||||
{
|
||||
uint8_t entryIndex;
|
||||
uint8_t baseRideType;
|
||||
uint8_t type; // 0: scenery entry, 1: ride entry
|
||||
uint8_t flags;
|
||||
};
|
||||
};
|
||||
uint8_t category;
|
||||
|
||||
bool IsInventedEndMarker() const;
|
||||
bool IsRandomEndMarker() const;
|
||||
bool IsUninventedEndMarker() const;
|
||||
};
|
||||
assert_struct_size(RCT12ResearchItem, 5);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
bool is_user_string_id(rct_string_id stringId);
|
||||
|
|
|
@ -848,7 +848,18 @@ void S6Exporter::ExportResearchedSceneryItems()
|
|||
|
||||
void S6Exporter::ExportResearchList()
|
||||
{
|
||||
std::memcpy(_s6.research_items, gResearchItems, sizeof(_s6.research_items));
|
||||
size_t i = 0;
|
||||
for (const auto& researchItem : gResearchItemsInvented)
|
||||
{
|
||||
_s6.research_items[i++] = RCT12ResearchItem{ researchItem.rawValue, researchItem.category };
|
||||
}
|
||||
_s6.research_items[i++] = { RCT12_RESEARCHED_ITEMS_SEPARATOR, 0 };
|
||||
for (const auto& researchItem : gResearchItemsUninvented)
|
||||
{
|
||||
_s6.research_items[i++] = RCT12ResearchItem{ researchItem.rawValue, researchItem.category };
|
||||
}
|
||||
_s6.research_items[i++] = { RCT12_RESEARCHED_ITEMS_END, 0 };
|
||||
_s6.research_items[i] = { RCT12_RESEARCHED_ITEMS_END_2, 0 };
|
||||
}
|
||||
|
||||
void S6Exporter::ExportMarketingCampaigns()
|
||||
|
|
|
@ -850,7 +850,25 @@ public:
|
|||
|
||||
void ImportResearchList()
|
||||
{
|
||||
std::memcpy(gResearchItems, _s6.research_items, sizeof(_s6.research_items));
|
||||
bool invented = true;
|
||||
for (size_t i = 0; i < sizeof(_s6.research_items); i++)
|
||||
{
|
||||
if (_s6.research_items[i].IsInventedEndMarker())
|
||||
{
|
||||
invented = false;
|
||||
continue;
|
||||
}
|
||||
else if (_s6.research_items[i].IsUninventedEndMarker() || _s6.research_items[i].IsRandomEndMarker())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
RCT12ResearchItem* ri = &_s6.research_items[i];
|
||||
if (invented)
|
||||
gResearchItemsInvented.push_back(ResearchItem{ ri->rawValue, ri->category });
|
||||
else
|
||||
gResearchItemsUninvented.push_back(ResearchItem{ ri->rawValue, ri->category });
|
||||
}
|
||||
}
|
||||
|
||||
void ImportBanner(Banner* dst, const RCT12Banner* src)
|
||||
|
|
|
@ -238,7 +238,7 @@ struct rct_s6_data
|
|||
uint8_t last_entrance_style;
|
||||
uint8_t rct1_water_colour;
|
||||
uint8_t pad_01358842[2];
|
||||
rct_research_item research_items[MAX_RESEARCH_ITEMS];
|
||||
RCT12ResearchItem research_items[MAX_RESEARCH_ITEMS];
|
||||
uint16_t map_base_z;
|
||||
char scenario_name[64];
|
||||
char scenario_description[256];
|
||||
|
|
Loading…
Reference in New Issue