diff --git a/src/openrct2-ui/title/TitleSequencePlayer.cpp b/src/openrct2-ui/title/TitleSequencePlayer.cpp index 5ba6b092d4..e3a877fc3d 100644 --- a/src/openrct2-ui/title/TitleSequencePlayer.cpp +++ b/src/openrct2-ui/title/TitleSequencePlayer.cpp @@ -457,7 +457,7 @@ private: auto intent = Intent(INTENT_ACTION_REFRESH_NEW_RIDES); context_broadcast_intent(&intent); scenery_set_default_placement_configuration(); - news_item_init_queue(); + News::InitQueue(); load_palette(); gScreenAge = 0; gGameSpeed = 1; diff --git a/src/openrct2-ui/windows/GameBottomToolbar.cpp b/src/openrct2-ui/windows/GameBottomToolbar.cpp index 3f262389f9..8032f53668 100644 --- a/src/openrct2-ui/windows/GameBottomToolbar.cpp +++ b/src/openrct2-ui/windows/GameBottomToolbar.cpp @@ -157,7 +157,7 @@ rct_window* window_game_bottom_toolbar_open() */ static void window_game_bottom_toolbar_mouseup(rct_window* w, rct_widgetindex widgetIndex) { - NewsItem* newsItem; + News::Item* newsItem; switch (widgetIndex) { @@ -173,27 +173,27 @@ static void window_game_bottom_toolbar_mouseup(rct_window* w, rct_widgetindex wi context_open_window_view(WV_PARK_RATING); break; case WIDX_MIDDLE_INSET: - if (news_item_is_queue_empty()) + if (News::IsQueueEmpty()) { context_open_window(WC_RECENT_NEWS); } else { - news_item_close_current(); + News::CloseCurrentItem(); } break; case WIDX_NEWS_SUBJECT: - newsItem = news_item_get(0); - news_item_open_subject(newsItem->Type, newsItem->Assoc); + newsItem = News::GetItem(0); + News::OpenSubject(newsItem->Type, newsItem->Assoc); break; case WIDX_NEWS_LOCATE: - if (news_item_is_queue_empty()) + if (News::IsQueueEmpty()) break; { - newsItem = news_item_get(0); + newsItem = News::GetItem(0); - auto subjectLoc = news_item_get_subject_location(newsItem->Type, newsItem->Assoc); + auto subjectLoc = News::GetSubjectLocation(newsItem->Type, newsItem->Assoc); if (subjectLoc == std::nullopt) break; @@ -300,7 +300,7 @@ static void window_game_bottom_toolbar_invalidate(rct_window* w) window_game_bottom_toolbar_widgets[WIDX_LEFT_INSET].type = WWT_EMPTY; window_game_bottom_toolbar_widgets[WIDX_RIGHT_INSET].type = WWT_EMPTY; - if (news_item_is_queue_empty()) + if (News::IsQueueEmpty()) { if (!(theme_get_flags() & UITHEME_FLAG_USE_FULL_BOTTOM_TOOLBAR)) { @@ -321,7 +321,7 @@ static void window_game_bottom_toolbar_invalidate(rct_window* w) } else { - NewsItem* newsItem = news_item_get(0); + News::Item* newsItem = News::GetItem(0); window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].type = WWT_IMGBTN; window_game_bottom_toolbar_widgets[WIDX_MIDDLE_INSET].type = WWT_PLACEHOLDER; window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].type = WWT_FLATBTN; @@ -332,7 +332,7 @@ static void window_game_bottom_toolbar_invalidate(rct_window* w) w->disabled_widgets &= ~(1 << WIDX_NEWS_LOCATE); // Find out if the news item is no longer valid - auto subjectLoc = news_item_get_subject_location(newsItem->Type, newsItem->Assoc); + auto subjectLoc = News::GetSubjectLocation(newsItem->Type, newsItem->Assoc); if (subjectLoc == std::nullopt) w->disabled_widgets |= (1 << WIDX_NEWS_LOCATE); @@ -396,7 +396,7 @@ static void window_game_bottom_toolbar_paint(rct_window* w, rct_drawpixelinfo* d window_game_bottom_toolbar_draw_left_panel(dpi, w); window_game_bottom_toolbar_draw_right_panel(dpi, w); - if (!news_item_is_queue_empty()) + if (!News::IsQueueEmpty()) { window_game_bottom_toolbar_draw_news_item(dpi, w); } @@ -568,11 +568,11 @@ static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo* dpi, static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo* dpi, rct_window* w) { int32_t width; - NewsItem* newsItem; + News::Item* newsItem; rct_widget* middleOutsetWidget; middleOutsetWidget = &window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET]; - newsItem = news_item_get(0); + newsItem = News::GetItem(0); // Current news item gfx_fill_rect_inset( diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index 7577c4c7e2..9ac13b8f57 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -660,7 +660,7 @@ static void window_new_ride_mouseup(rct_window* w, rct_widgetindex widgetIndex) window_close(w); break; case WIDX_LAST_DEVELOPMENT_BUTTON: - news_item_open_subject(News::ItemType::Research, gResearchLastItem->rawValue); + News::OpenSubject(News::ItemType::Research, gResearchLastItem->rawValue); break; case WIDX_RESEARCH_FUNDING_BUTTON: context_open_window_view(WV_FINANCES_RESEARCH); diff --git a/src/openrct2-ui/windows/News.cpp b/src/openrct2-ui/windows/News.cpp index b6f9d28aa0..d0a6bb8542 100644 --- a/src/openrct2-ui/windows/News.cpp +++ b/src/openrct2-ui/windows/News.cpp @@ -156,11 +156,11 @@ static void window_news_update(rct_window* w) return; if (w->news.var_482 == 1) { - news_item_open_subject(newsItem.Type, newsItem.Assoc); + News::OpenSubject(newsItem.Type, newsItem.Assoc); } else if (w->news.var_482 > 1) { - auto subjectLoc = news_item_get_subject_location(newsItem.Type, newsItem.Assoc); + auto subjectLoc = News::GetSubjectLocation(newsItem.Type, newsItem.Assoc); if (subjectLoc != std::nullopt && (w = window_get_main()) != nullptr) { window_scroll_to_location(w, *subjectLoc); @@ -276,7 +276,7 @@ static void window_news_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32 int32_t press = 0; if (w->news.var_480 != -1) { - news_item_is_valid_idx(w->news.var_480 + NEWS_ITEM_HISTORY_START); + News::IsValidIndex(w->news.var_480 + News::ItemHistoryStart); if (i == w->news.var_480 && w->news.var_482 == 1) press = INSET_RECT_FLAG_BORDER_INSET; } @@ -352,7 +352,7 @@ static void window_news_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32 int32_t press = 0; if (w->news.var_480 != -1) { - news_item_is_valid_idx(w->news.var_480 + NEWS_ITEM_HISTORY_START); + News::IsValidIndex(w->news.var_480 + News::ItemHistoryStart); if (i == w->news.var_480 && w->news.var_482 == 2) press = 0x20; } diff --git a/src/openrct2-ui/windows/Research.cpp b/src/openrct2-ui/windows/Research.cpp index 0805d3027e..ae3486454f 100644 --- a/src/openrct2-ui/windows/Research.cpp +++ b/src/openrct2-ui/windows/Research.cpp @@ -282,7 +282,7 @@ static void window_research_development_mouseup(rct_window* w, rct_widgetindex w window_research_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_LAST_DEVELOPMENT_BUTTON: - news_item_open_subject(News::ItemType::Research, gResearchLastItem->rawValue); + News::OpenSubject(News::ItemType::Research, gResearchLastItem->rawValue); break; } } diff --git a/src/openrct2/Editor.cpp b/src/openrct2/Editor.cpp index 2e277c32d3..33156e953b 100644 --- a/src/openrct2/Editor.cpp +++ b/src/openrct2/Editor.cpp @@ -140,7 +140,7 @@ namespace Editor gS6Info.editor_step = EDITOR_STEP_OBJECTIVE_SELECTION; gS6Info.category = SCENARIO_CATEGORY_OTHER; viewport_init_all(); - news_item_init_queue(); + News::InitQueue(); context_open_window_view(WV_EDITOR_MAIN); FinaliseMainView(); gScreenAge = 0; @@ -364,7 +364,7 @@ namespace Editor climate_reset(gClimate); - news_item_init_queue(); + News::InitQueue(); } /** diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 05e43eb200..ee182cc724 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -387,9 +387,9 @@ void game_convert_strings_to_utf8() void game_convert_news_items_to_utf8() { - for (int32_t i = 0; i < MAX_NEWS_ITEMS; i++) + for (int32_t i = 0; i < News::MaxItems; i++) { - NewsItem* newsItem = news_item_get(i); + News::Item* newsItem = News::GetItem(i); if (!str_is_null_or_empty(newsItem->Text)) { diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index d6bce9d87c..82168bd6c2 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -62,7 +62,7 @@ void GameState::InitAll(int32_t mapSize) staff_reset_modes(); date_reset(); climate_reset(CLIMATE_COOL_AND_WET); - news_item_init_queue(); + News::InitQueue(); gInMapInitCode = false; @@ -298,7 +298,7 @@ void GameState::UpdateLogic() research_update(); ride_ratings_update_all(); ride_measurements_update(); - news_item_update_current(); + News::UpdateCurrentItem(); map_animation_invalidate_all(); vehicle_sounds_update(); diff --git a/src/openrct2/ReplayManager.cpp b/src/openrct2/ReplayManager.cpp index 60eb5e24e3..9c1fc82c18 100644 --- a/src/openrct2/ReplayManager.cpp +++ b/src/openrct2/ReplayManager.cpp @@ -339,7 +339,7 @@ namespace OpenRCT2 _currentRecording.reset(); - NewsItem* news = news_item_add_to_queue_raw(News::ItemType::Blank, "Replay recording stopped", 0); + News::Item* news = News::AddItemToQueue(News::ItemType::Blank, "Replay recording stopped", 0); news->SetFlags(News::ItemFlags::HasButton); // Has no subject. return result; @@ -467,7 +467,7 @@ namespace OpenRCT2 // During normal playback we pause the game if stopped. if (_mode == ReplayMode::PLAYING) { - NewsItem* news = news_item_add_to_queue_raw(News::ItemType::Blank, "Replay playback complete", 0); + News::Item* news = News::AddItemToQueue(News::ItemType::Blank, "Replay playback complete", 0); news->SetFlags(News::ItemFlags::HasButton); // Has no subject. } diff --git a/src/openrct2/actions/RideDemolishAction.hpp b/src/openrct2/actions/RideDemolishAction.hpp index add287499d..8ccb3c9cf0 100644 --- a/src/openrct2/actions/RideDemolishAction.hpp +++ b/src/openrct2/actions/RideDemolishAction.hpp @@ -141,7 +141,7 @@ private: sub_6CB945(ride); ride_clear_leftover_entrances(ride); - news_item_disable_news(News::ItemType::Ride, _rideIndex); + News::DisableNewsItems(News::ItemType::Ride, _rideIndex); for (BannerIndex i = 0; i < MAX_BANNERS; i++) { diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index e134d5b4e0..76d4057614 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1677,7 +1677,7 @@ static int32_t cc_add_news_item([[maybe_unused]] InteractiveConsole& console, [[ auto type = atoi(argv[0].c_str()); auto msg = argv[1].c_str(); auto assoc = atoi(argv[2].c_str()); - news_item_add_to_queue_raw(static_cast(type), msg, assoc); + News::AddItemToQueue(static_cast(type), msg, assoc); return 0; } diff --git a/src/openrct2/management/Award.cpp b/src/openrct2/management/Award.cpp index 787125b17c..f9dd4e8b24 100644 --- a/src/openrct2/management/Award.cpp +++ b/src/openrct2/management/Award.cpp @@ -636,7 +636,7 @@ void award_update_all() gCurrentAwards[freeAwardEntryIndex].Time = 5; if (gConfigNotifications.park_award) { - news_item_add_to_queue(News::ItemType::Award, AwardNewsStrings[awardType], 0); + News::AddItemToQueue(News::ItemType::Award, AwardNewsStrings[awardType], 0); } window_invalidate_by_class(WC_PARK_INFORMATION); } diff --git a/src/openrct2/management/Marketing.cpp b/src/openrct2/management/Marketing.cpp index bcbef43f02..0e1c75261a 100644 --- a/src/openrct2/management/Marketing.cpp +++ b/src/openrct2/management/Marketing.cpp @@ -85,7 +85,7 @@ static void marketing_raise_finished_notification(const MarketingCampaign& campa ft.Add(ShopItems[campaign.ShopItemType].Naming.Plural); } - news_item_add_to_queue(News::ItemType::Money, MarketingCampaignNames[campaign.Type][2], 0); + News::AddItemToQueue(News::ItemType::Money, MarketingCampaignNames[campaign.Type][2], 0); } } diff --git a/src/openrct2/management/NewsItem.cpp b/src/openrct2/management/NewsItem.cpp index 0b7464d0d4..f4da9a7765 100644 --- a/src/openrct2/management/NewsItem.cpp +++ b/src/openrct2/management/NewsItem.cpp @@ -24,21 +24,21 @@ #include "../world/Location.hpp" #include "../world/Sprite.h" -NewsItemQueues gNewsItems; +News::ItemQueues gNewsItems; -NewsItem& NewsItemQueues::Current() +News::Item& News::ItemQueues::Current() { return Recent.front(); } -const NewsItem& NewsItemQueues::Current() const +const News::Item& News::ItemQueues::Current() const { return Recent.front(); } -bool news_item_is_valid_idx(int32_t index) +bool News::IsValidIndex(int32_t index) { - if (index >= MAX_NEWS_ITEMS) + if (index >= News::MaxItems) { log_error("Tried to get news item past MAX_NEWS."); return false; @@ -46,17 +46,17 @@ bool news_item_is_valid_idx(int32_t index) return true; } -NewsItem* news_item_get(int32_t index) +News::Item* News::GetItem(int32_t index) { return gNewsItems.At(index); } -NewsItem& NewsItemQueues::operator[](size_t index) +News::Item& News::ItemQueues::operator[](size_t index) { - return const_cast(const_cast(*this)[index]); + return const_cast(const_cast(*this)[index]); } -const NewsItem& NewsItemQueues::operator[](size_t index) const +const News::Item& News::ItemQueues::operator[](size_t index) const { if (index < Recent.capacity()) return Recent[index]; @@ -64,14 +64,14 @@ const NewsItem& NewsItemQueues::operator[](size_t index) const return Archived[index - Recent.capacity()]; } -NewsItem* NewsItemQueues::At(int32_t index) +News::Item* News::ItemQueues::At(int32_t index) { - return const_cast(const_cast(*this).At(index)); + return const_cast(const_cast(*this).At(index)); } -const NewsItem* NewsItemQueues::At(int32_t index) const +const News::Item* News::ItemQueues::At(int32_t index) const { - if (news_item_is_valid_idx(index)) + if (News::IsValidIndex(index)) { return &(*this)[index]; } @@ -81,12 +81,12 @@ const NewsItem* NewsItemQueues::At(int32_t index) const } } -bool news_item_is_queue_empty() +bool News::IsQueueEmpty() { return gNewsItems.IsEmpty(); } -bool NewsItemQueues::IsEmpty() const +bool News::ItemQueues::IsEmpty() const { return Recent.empty(); } @@ -95,13 +95,13 @@ bool NewsItemQueues::IsEmpty() const * * rct2: 0x0066DF32 */ -void NewsItemQueues::Clear() +void News::ItemQueues::Clear() { Recent.clear(); Archived.clear(); } -void news_item_init_queue() +void News::InitQueue() { gNewsItems.Clear(); assert(gNewsItems.IsEmpty()); @@ -116,12 +116,12 @@ void news_item_init_queue() context_broadcast_intent(&intent); } -uint16_t NewsItemQueues::IncrementTicks() +uint16_t News::ItemQueues::IncrementTicks() { return ++Current().Ticks; } -static void news_item_tick_current() +static void TickCurrent() { int32_t ticks = gNewsItems.IncrementTicks(); // Only play news item sound when in normal playing mode @@ -132,7 +132,7 @@ static void news_item_tick_current() } } -int32_t NewsItemQueues::RemoveTime() const +int32_t News::ItemQueues::RemoveTime() const { if (!Recent[5].IsEmpty() && !Recent[4].IsEmpty() && !Recent[3].IsEmpty() && !Recent[2].IsEmpty()) { @@ -141,7 +141,7 @@ int32_t NewsItemQueues::RemoveTime() const return 320; } -bool NewsItemQueues::CurrentShouldBeArchived() const +bool News::ItemQueues::CurrentShouldBeArchived() const { return Current().Ticks >= RemoveTime(); } @@ -150,7 +150,7 @@ bool NewsItemQueues::CurrentShouldBeArchived() const * * rct2: 0x0066E252 */ -void news_item_update_current() +void News::UpdateCurrentItem() { // Check if there is a current news item if (gNewsItems.IsEmpty()) @@ -160,7 +160,7 @@ void news_item_update_current() context_broadcast_intent(&intent); // Update the current news item - news_item_tick_current(); + TickCurrent(); // Removal of current news item if (gNewsItems.CurrentShouldBeArchived()) @@ -171,12 +171,12 @@ void news_item_update_current() * * rct2: 0x0066E377 */ -void news_item_close_current() +void News::CloseCurrentItem() { gNewsItems.ArchiveCurrent(); } -void NewsItemQueues::ArchiveCurrent() +void News::ItemQueues::ArchiveCurrent() { // Check if there is a current message if (IsEmpty()) @@ -201,7 +201,7 @@ void NewsItemQueues::ArchiveCurrent() * * rct2: 0x0066BA74 */ -std::optional news_item_get_subject_location(News::ItemType type, int32_t subject) +std::optional News::GetSubjectLocation(News::ItemType type, int32_t subject) { std::optional subjectLoc{ std::nullopt }; @@ -281,7 +281,7 @@ std::optional news_item_get_subject_location(News::ItemType type, int return subjectLoc; } -NewsItem* NewsItemQueues::FirstOpenOrNewSlot() +News::Item* News::ItemQueues::FirstOpenOrNewSlot() { for (auto emptySlots = Recent.capacity() - Recent.size(); emptySlots < 2; ++emptySlots) { @@ -301,19 +301,19 @@ NewsItem* NewsItemQueues::FirstOpenOrNewSlot() * * rct2: 0x0066DF55 */ -NewsItem* news_item_add_to_queue(News::ItemType type, rct_string_id string_id, uint32_t assoc) +News::Item* News::AddItemToQueue(News::ItemType type, rct_string_id string_id, uint32_t assoc) { utf8 buffer[256]; void* args = gCommonFormatArgs; // overflows possible? format_string(buffer, 256, string_id, args); - return news_item_add_to_queue_raw(type, buffer, assoc); + return News::AddItemToQueue(type, buffer, assoc); } -NewsItem* news_item_add_to_queue_raw(News::ItemType type, const utf8* text, uint32_t assoc) +News::Item* News::AddItemToQueue(News::ItemType type, const utf8* text, uint32_t assoc) { - NewsItem* newsItem = gNewsItems.FirstOpenOrNewSlot(); + News::Item* newsItem = gNewsItems.FirstOpenOrNewSlot(); newsItem->Type = type; newsItem->Flags = 0; newsItem->Assoc = assoc; @@ -331,7 +331,7 @@ NewsItem* news_item_add_to_queue_raw(News::ItemType type, const utf8* text, uint * rct2: 0x0066EBE6 * */ -void news_item_open_subject(News::ItemType type, int32_t subject) +void News::OpenSubject(News::ItemType type, int32_t subject) { switch (type) { @@ -416,7 +416,7 @@ void news_item_open_subject(News::ItemType type, int32_t subject) * * rct2: 0x0066E407 */ -void news_item_disable_news(News::ItemType type, uint32_t assoc) +void News::DisableNewsItems(News::ItemType type, uint32_t assoc) { // TODO: write test invalidating windows gNewsItems.ForeachRecentNews([type, assoc](auto& newsItem) { @@ -440,22 +440,22 @@ void news_item_disable_news(News::ItemType type, uint32_t assoc) }); } -void news_item_add_to_queue_custom(NewsItem* newNewsItem) +void News::AddItemToQueue(News::Item* newNewsItem) { - NewsItem* newsItem = gNewsItems.FirstOpenOrNewSlot(); + News::Item* newsItem = gNewsItems.FirstOpenOrNewSlot(); *newsItem = *newNewsItem; } -void news_item_remove(int32_t index) +void News::RemoveItem(int32_t index) { - if (index < 0 || index >= MAX_NEWS_ITEMS) + if (index < 0 || index >= News::MaxItems) return; // News item is already null, no need to remove it if (gNewsItems[index].Type == News::ItemType::Null) return; - size_t newsBoundary = index < NEWS_ITEM_HISTORY_START ? NEWS_ITEM_HISTORY_START : MAX_NEWS_ITEMS; + size_t newsBoundary = index < News::ItemHistoryStart ? News::ItemHistoryStart : News::MaxItems; for (size_t i = index; i < newsBoundary - 1; i++) { gNewsItems[i] = gNewsItems[i + 1]; diff --git a/src/openrct2/management/NewsItem.h b/src/openrct2/management/NewsItem.h index 55d12c0d38..ed034a5fbe 100644 --- a/src/openrct2/management/NewsItem.h +++ b/src/openrct2/management/NewsItem.h @@ -47,265 +47,265 @@ namespace News { HasButton = 1 << 0, }; + + /** + * A single news item / message. + */ + struct Item + { + News::ItemType Type; + uint8_t Flags; + uint32_t Assoc; + uint16_t Ticks; + uint16_t MonthYear; + uint8_t Day; + utf8 Text[256]; + + constexpr bool IsEmpty() const noexcept + { + return Type == News::ItemType::Null; + } + + constexpr uint8_t GetTypeProperties() const + { + switch (Type) + { + case News::ItemType::Blank: + return News::ItemTypeProperty::HasLocation; + case News::ItemType::Money: + case News::ItemType::Research: + case News::ItemType::Peeps: + case News::ItemType::Award: + case News::ItemType::Graph: + return News::ItemTypeProperty::HasSubject; + case News::ItemType::Ride: + case News::ItemType::PeepOnRide: + case News::ItemType::Peep: + return News::ItemTypeProperty::HasLocation | News::ItemTypeProperty::HasSubject; + case News::ItemType::Null: + case News::ItemType::Count: + default: + return 0; + } + } + + void SetFlags(uint8_t flag) + { + Flags |= flag; + } + + constexpr bool TypeHasSubject() const + { + return this->GetTypeProperties() & News::ItemTypeProperty::HasSubject; + } + + constexpr bool TypeHasLocation() const + { + return this->GetTypeProperties() & News::ItemTypeProperty::HasLocation; + } + + constexpr bool HasButton() const noexcept + { + return Flags & News::ItemFlags::HasButton; + } + }; + + constexpr int32_t ItemHistoryStart = 11; + constexpr int32_t MaxItemsArchive = 50; + constexpr int32_t MaxItems = News::ItemHistoryStart + News::MaxItemsArchive; + + template class ItemQueue + { + public: + static_assert(N > 0, "Cannot instantiate News::ItemQueue with size=0"); + + using value_type = typename std::array::value_type; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using iterator = typename std::array::iterator; + using const_iterator = typename std::array::const_iterator; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + ItemQueue() + { + Queue[0].Type = News::ItemType::Null; + } + + constexpr iterator begin() noexcept + { + return std::begin(Queue); + } + constexpr const_iterator begin() const noexcept + { + return cbegin(); + } + constexpr const_iterator cbegin() const noexcept + { + return std::cbegin(Queue); + } + iterator end() noexcept + { + return std::find_if(std::begin(Queue), std::end(Queue), [](const_reference item) { return item.IsEmpty(); }); + } + const_iterator end() const noexcept + { + return cend(); + } + const_iterator cend() const noexcept + { + return std::find_if(std::cbegin(Queue), std::cend(Queue), [](const_reference item) { return item.IsEmpty(); }); + } + + constexpr bool empty() const noexcept + { + return Queue[0].IsEmpty(); + } + + size_type size() const noexcept + { + return std::distance(cbegin(), cend()); + } + + reference front() noexcept + { + return *begin(); + } + const_reference front() const noexcept + { + return *cbegin(); + } + reference back() noexcept + { + return *end(); + } + const_reference back() const noexcept + { + return *cend(); + } + + void pop_front() + { + std::move(std::begin(Queue) + 1, std::end(Queue), std::begin(Queue)); + Queue[N - 1].Type = News::ItemType::Null; + } + + void push_back(const_reference item) + { + auto it = end(); + if (!std::distance(it, std::end(Queue))) + { + // Reached queue max size, need to free some space + pop_front(); + Queue[N - 1] = item; + } + else + { + *it = item; + ++it; + if (std::distance(it, std::end(Queue))) + it->Type = News::ItemType::Null; + } + } + + reference operator[](size_type n) noexcept + { + return Queue[n]; + } + const_reference operator[](size_type n) const noexcept + { + return Queue[n]; + } + + constexpr size_type capacity() const noexcept + { + return N; + } + + void clear() noexcept + { + front().Type = News::ItemType::Null; + } + + private: + std::array Queue; + }; + + struct ItemQueues + { + News::Item& operator[](size_t index); + const News::Item& operator[](size_t index) const; + News::Item* At(int32_t index); + const News::Item* At(int32_t index) const; + bool IsEmpty() const; + void Clear(); + uint16_t IncrementTicks(); + News::Item& Current(); + const News::Item& Current() const; + News::Item& Oldest(); + const News::Item& Oldest() const; + bool CurrentShouldBeArchived() const; + void ArchiveCurrent(); + News::Item* FirstOpenOrNewSlot(); + const auto& GetRecent() const + { + return Recent; + } + const auto& GetArchived() const + { + return Archived; + } + + template void ForeachRecentNews(Predicate&& p) + { + for (auto& newsItem : Recent) + { + p(newsItem); + } + } + + template void ForeachArchivedNews(Predicate&& p) + { + for (auto& newsItem : Archived) + { + p(newsItem); + } + } + + private: + int32_t RemoveTime() const; + void AppendToArchive(News::Item& item); + + News::ItemQueue Recent; + News::ItemQueue Archived; + }; + + void InitQueue(); + + void UpdateCurrentItem(); + void CloseCurrentItem(); + + std::optional GetSubjectLocation(News::ItemType type, int32_t subject); + + News::Item* AddItemToQueue(News::ItemType type, rct_string_id string_id, uint32_t assoc); + News::Item* AddItemToQueue(News::ItemType type, const utf8* text, uint32_t assoc); + + void OpenSubject(News::ItemType type, int32_t subject); + + void DisableNewsItems(News::ItemType type, uint32_t assoc); + + News::Item* GetItem(int32_t index); + + bool IsQueueEmpty(); + + bool IsValidIndex(int32_t index); + + void AddItemToQueue(News::Item* newNewsItem); + void RemoveItem(int32_t index); } // namespace News -/** - * A single news item / message. - */ -struct NewsItem -{ - News::ItemType Type; - uint8_t Flags; - uint32_t Assoc; - uint16_t Ticks; - uint16_t MonthYear; - uint8_t Day; - utf8 Text[256]; - - constexpr bool IsEmpty() const noexcept - { - return Type == News::ItemType::Null; - } - - constexpr uint8_t GetTypeProperties() const - { - switch (Type) - { - case News::ItemType::Blank: - return News::ItemTypeProperty::HasLocation; - case News::ItemType::Money: - case News::ItemType::Research: - case News::ItemType::Peeps: - case News::ItemType::Award: - case News::ItemType::Graph: - return News::ItemTypeProperty::HasSubject; - case News::ItemType::Ride: - case News::ItemType::PeepOnRide: - case News::ItemType::Peep: - return News::ItemTypeProperty::HasLocation | News::ItemTypeProperty::HasSubject; - case News::ItemType::Null: - case News::ItemType::Count: - default: - return 0; - } - } - - void SetFlags(uint8_t flag) - { - Flags |= flag; - } - - constexpr bool TypeHasSubject() const - { - return this->GetTypeProperties() & News::ItemTypeProperty::HasSubject; - } - - constexpr bool TypeHasLocation() const - { - return this->GetTypeProperties() & News::ItemTypeProperty::HasLocation; - } - - constexpr bool HasButton() const noexcept - { - return Flags & News::ItemFlags::HasButton; - } -}; - -constexpr int32_t NEWS_ITEM_HISTORY_START = 11; -constexpr int32_t MAX_NEWS_ITEMS_ARCHIVE = 50; -constexpr int32_t MAX_NEWS_ITEMS = NEWS_ITEM_HISTORY_START + MAX_NEWS_ITEMS_ARCHIVE; - -template class NewsItemQueue -{ -public: - static_assert(N > 0, "Cannot instantiate NewsItemQueue with size=0"); - - using value_type = typename std::array::value_type; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using iterator = typename std::array::iterator; - using const_iterator = typename std::array::const_iterator; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - NewsItemQueue() - { - Queue[0].Type = News::ItemType::Null; - } - - constexpr iterator begin() noexcept - { - return std::begin(Queue); - } - constexpr const_iterator begin() const noexcept - { - return cbegin(); - } - constexpr const_iterator cbegin() const noexcept - { - return std::cbegin(Queue); - } - iterator end() noexcept - { - return std::find_if(std::begin(Queue), std::end(Queue), [](const_reference item) { return item.IsEmpty(); }); - } - const_iterator end() const noexcept - { - return cend(); - } - const_iterator cend() const noexcept - { - return std::find_if(std::cbegin(Queue), std::cend(Queue), [](const_reference item) { return item.IsEmpty(); }); - } - - constexpr bool empty() const noexcept - { - return Queue[0].IsEmpty(); - } - - size_type size() const noexcept - { - return std::distance(cbegin(), cend()); - } - - reference front() noexcept - { - return *begin(); - } - const_reference front() const noexcept - { - return *cbegin(); - } - reference back() noexcept - { - return *end(); - } - const_reference back() const noexcept - { - return *cend(); - } - - void pop_front() - { - std::move(std::begin(Queue) + 1, std::end(Queue), std::begin(Queue)); - Queue[N - 1].Type = News::ItemType::Null; - } - - void push_back(const_reference item) - { - auto it = end(); - if (!std::distance(it, std::end(Queue))) - { - // Reached queue max size, need to free some space - pop_front(); - Queue[N - 1] = item; - } - else - { - *it = item; - ++it; - if (std::distance(it, std::end(Queue))) - it->Type = News::ItemType::Null; - } - } - - reference operator[](size_type n) noexcept - { - return Queue[n]; - } - const_reference operator[](size_type n) const noexcept - { - return Queue[n]; - } - - constexpr size_type capacity() const noexcept - { - return N; - } - - void clear() noexcept - { - front().Type = News::ItemType::Null; - } - -private: - std::array Queue; -}; - -struct NewsItemQueues -{ - NewsItem& operator[](size_t index); - const NewsItem& operator[](size_t index) const; - NewsItem* At(int32_t index); - const NewsItem* At(int32_t index) const; - bool IsEmpty() const; - void Clear(); - uint16_t IncrementTicks(); - NewsItem& Current(); - const NewsItem& Current() const; - NewsItem& Oldest(); - const NewsItem& Oldest() const; - bool CurrentShouldBeArchived() const; - void ArchiveCurrent(); - NewsItem* FirstOpenOrNewSlot(); - const auto& GetRecent() const - { - return Recent; - } - const auto& GetArchived() const - { - return Archived; - } - - template void ForeachRecentNews(Predicate&& p) - { - for (auto& newsItem : Recent) - { - p(newsItem); - } - } - - template void ForeachArchivedNews(Predicate&& p) - { - for (auto& newsItem : Archived) - { - p(newsItem); - } - } - -private: - int32_t RemoveTime() const; - void AppendToArchive(NewsItem& item); - - NewsItemQueue Recent; - NewsItemQueue Archived; -}; - -extern NewsItemQueues gNewsItems; - -void news_item_init_queue(); - -void news_item_update_current(); -void news_item_close_current(); - -std::optional news_item_get_subject_location(News::ItemType type, int32_t subject); - -NewsItem* news_item_add_to_queue(News::ItemType type, rct_string_id string_id, uint32_t assoc); -NewsItem* news_item_add_to_queue_raw(News::ItemType type, const utf8* text, uint32_t assoc); - -void news_item_open_subject(News::ItemType type, int32_t subject); - -void news_item_disable_news(News::ItemType type, uint32_t assoc); - -NewsItem* news_item_get(int32_t index); - -bool news_item_is_queue_empty(); - -bool news_item_is_valid_idx(int32_t index); - -void news_item_add_to_queue_custom(NewsItem* newNewsItem); -void news_item_remove(int32_t index); +extern News::ItemQueues gNewsItems; diff --git a/src/openrct2/management/Research.cpp b/src/openrct2/management/Research.cpp index 2406e69d41..9e85c12286 100644 --- a/src/openrct2/management/Research.cpp +++ b/src/openrct2/management/Research.cpp @@ -266,7 +266,7 @@ void research_finish_item(ResearchItem* researchItem) { if (gConfigNotifications.ride_researched) { - news_item_add_to_queue(News::ItemType::Research, availabilityString, researchItem->rawValue); + News::AddItemToQueue(News::ItemType::Research, availabilityString, researchItem->rawValue); } } @@ -288,7 +288,7 @@ void research_finish_item(ResearchItem* researchItem) { if (gConfigNotifications.ride_researched) { - news_item_add_to_queue( + News::AddItemToQueue( News::ItemType::Research, STR_NEWS_ITEM_RESEARCH_NEW_SCENERY_SET_AVAILABLE, researchItem->rawValue); } } diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp index 22cb01c9e2..7fc7d84dd2 100644 --- a/src/openrct2/peep/Guest.cpp +++ b/src/openrct2/peep/Guest.cpp @@ -1702,7 +1702,7 @@ loc_69B221: ft.Add(ShopItems[shopItem].Naming.Indefinite); if (gConfigNotifications.guest_bought_item) { - news_item_add_to_queue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_NOTIFICATION_BOUGHT_X, sprite_index); + News::AddItemToQueue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_NOTIFICATION_BOUGHT_X, sprite_index); } } @@ -3738,7 +3738,7 @@ void Guest::UpdateRideAdvanceThroughEntrance() ride->FormatNameTo(ft); if (gConfigNotifications.ride_warnings) { - news_item_add_to_queue(News::ItemType::Ride, STR_GUESTS_GETTING_STUCK_ON_RIDE, CurrentRide); + News::AddItemToQueue(News::ItemType::Ride, STR_GUESTS_GETTING_STUCK_ON_RIDE, CurrentRide); } } @@ -3908,7 +3908,7 @@ void Guest::UpdateRideFreeVehicleEnterRide(Ride* ride) if (gConfigNotifications.guest_on_ride) { - news_item_add_to_queue(News::ItemType::PeepOnRide, msg_string, sprite_index); + News::AddItemToQueue(News::ItemType::PeepOnRide, msg_string, sprite_index); } } @@ -5022,7 +5022,7 @@ void Guest::UpdateRideLeaveExit() if (gConfigNotifications.guest_left_ride) { - news_item_add_to_queue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_LEFT_RIDE_X, sprite_index); + News::AddItemToQueue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_LEFT_RIDE_X, sprite_index); } } diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index 3afd1aa4e7..0a001a0a6e 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -816,7 +816,7 @@ void peep_sprite_remove(Peep* peep) bool wasGuest = peep->AssignedPeepType == PeepType::Guest; if (peep->AssignedPeepType == PeepType::Guest) { - news_item_disable_news(News::ItemType::PeepOnRide, peep->sprite_index); + News::DisableNewsItems(News::ItemType::PeepOnRide, peep->sprite_index); } else { @@ -825,7 +825,7 @@ void peep_sprite_remove(Peep* peep) staff_update_greyed_patrol_areas(); peep->AssignedPeepType = PeepType::Staff; - news_item_disable_news(News::ItemType::Peep, peep->sprite_index); + News::DisableNewsItems(News::ItemType::Peep, peep->sprite_index); } sprite_remove(peep); @@ -872,7 +872,7 @@ void Peep::UpdateFalling() { auto ft = Formatter::Common(); FormatNameTo(ft); - news_item_add_to_queue(News::ItemType::Blank, STR_NEWS_ITEM_GUEST_DROWNED, x | (y << 16)); + News::AddItemToQueue(News::ItemType::Blank, STR_NEWS_ITEM_GUEST_DROWNED, x | (y << 16)); } gParkRatingCasualtyPenalty = std::min(gParkRatingCasualtyPenalty + 25, 1000); @@ -1238,7 +1238,7 @@ void peep_problem_warnings_update() warning_throttle[0] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_ARE_HUNGRY, 20); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_ARE_HUNGRY, 20); } } @@ -1249,7 +1249,7 @@ void peep_problem_warnings_update() warning_throttle[1] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_ARE_THIRSTY, 21); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_ARE_THIRSTY, 21); } } @@ -1260,7 +1260,7 @@ void peep_problem_warnings_update() warning_throttle[2] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_CANT_FIND_TOILET, 22); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_CANT_FIND_TOILET, 22); } } @@ -1271,7 +1271,7 @@ void peep_problem_warnings_update() warning_throttle[3] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_DISLIKE_LITTER, 26); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_DISLIKE_LITTER, 26); } } @@ -1282,7 +1282,7 @@ void peep_problem_warnings_update() warning_throttle[4] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_DISGUSTED_BY_PATHS, 31); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_DISGUSTED_BY_PATHS, 31); } } @@ -1293,7 +1293,7 @@ void peep_problem_warnings_update() warning_throttle[5] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_DISLIKE_VANDALISM, 33); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_DISLIKE_VANDALISM, 33); } } @@ -1304,7 +1304,7 @@ void peep_problem_warnings_update() warning_throttle[6] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_GETTING_LOST_OR_STUCK, 27); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_GETTING_LOST_OR_STUCK, 27); } } else if (lost_counter >= PEEP_LOST_WARNING_THRESHOLD) @@ -1312,7 +1312,7 @@ void peep_problem_warnings_update() warning_throttle[6] = 4; if (gConfigNotifications.guest_warnings) { - news_item_add_to_queue(News::ItemType::Peeps, STR_PEEPS_GETTING_LOST_OR_STUCK, 16); + News::AddItemToQueue(News::ItemType::Peeps, STR_PEEPS_GETTING_LOST_OR_STUCK, 16); } } } @@ -2401,8 +2401,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin ride->FormatNameTo(ft); if (gConfigNotifications.guest_queuing_for_ride) { - news_item_add_to_queue( - News::ItemType::PeepOnRide, STR_PEEP_TRACKING_PEEP_JOINED_QUEUE_FOR_X, peep->sprite_index); + News::AddItemToQueue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_PEEP_JOINED_QUEUE_FOR_X, peep->sprite_index); } } } @@ -2463,7 +2462,7 @@ static void peep_interact_with_entrance(Peep* peep, const CoordsXYE& coords, uin peep->FormatNameTo(ft); if (gConfigNotifications.guest_left_park) { - news_item_add_to_queue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_LEFT_PARK, peep->sprite_index); + News::AddItemToQueue(News::ItemType::PeepOnRide, STR_PEEP_TRACKING_LEFT_PARK, peep->sprite_index); } } return; @@ -2830,7 +2829,7 @@ static void peep_interact_with_path(Peep* peep, const CoordsXYE& coords) ride->FormatNameTo(ft); if (gConfigNotifications.guest_queuing_for_ride) { - news_item_add_to_queue( + News::AddItemToQueue( News::ItemType::PeepOnRide, STR_PEEP_TRACKING_PEEP_JOINED_QUEUE_FOR_X, peep->sprite_index); } } @@ -2941,7 +2940,7 @@ static bool peep_interact_with_shop(Peep* peep, const CoordsXYE& coords) : STR_PEEP_TRACKING_PEEP_IS_ON_X; if (gConfigNotifications.guest_used_facility) { - news_item_add_to_queue(News::ItemType::PeepOnRide, string_id, peep->sprite_index); + News::AddItemToQueue(News::ItemType::PeepOnRide, string_id, peep->sprite_index); } } } diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index c2686e75f5..c3765ad6b7 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1361,7 +1361,7 @@ private: } } // Fix the news items in advance - for (auto i = 0; i < MAX_NEWS_ITEMS; i++) + for (auto i = 0; i < News::MaxItems; i++) { rct12_news_item* newsItem = &_s4.messages[i]; News::ItemType type = static_cast(newsItem->Type); @@ -2541,7 +2541,7 @@ private: for (size_t i = 0; i < RCT12_MAX_NEWS_ITEMS; i++) { const rct12_news_item* src = &_s4.messages[i]; - NewsItem* dst = &gNewsItems[i]; + News::Item* dst = &gNewsItems[i]; dst->Type = static_cast(src->Type); dst->Flags = src->Flags; diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index afd2617034..38a6be5928 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -397,7 +397,7 @@ void S6Exporter::Export() // News items for (size_t i = 0; i < RCT12_MAX_NEWS_ITEMS; i++) { - const NewsItem* src = &gNewsItems[i]; + const News::Item* src = &gNewsItems[i]; rct12_news_item* dst = &_s6.news_items[i]; dst->Type = static_cast(src->Type); diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 1c9c3e250b..12eaee6400 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -422,11 +422,11 @@ public: gClimateNext.Level = static_cast(_s6.next_rain_level); // News items - news_item_init_queue(); + News::InitQueue(); for (size_t i = 0; i < RCT12_MAX_NEWS_ITEMS; i++) { const rct12_news_item* src = &_s6.news_items[i]; - NewsItem* dst = &gNewsItems[i]; + News::Item* dst = &gNewsItems[i]; if (src->Type < News::ItemTypeCount) { dst->Type = static_cast(src->Type); diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 7685c821d2..d323e3099f 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -2538,7 +2538,7 @@ void ride_breakdown_add_news_item(Ride* ride) ride->FormatNameTo(ft); if (gConfigNotifications.ride_broken_down) { - news_item_add_to_queue(News::ItemType::Ride, STR_RIDE_IS_BROKEN_DOWN, ride->id); + News::AddItemToQueue(News::ItemType::Ride, STR_RIDE_IS_BROKEN_DOWN, ride->id); } } @@ -2565,7 +2565,7 @@ static void ride_breakdown_status_update(Ride* ride) ride->FormatNameTo(ft); if (gConfigNotifications.ride_warnings) { - news_item_add_to_queue(News::ItemType::Ride, STR_RIDE_IS_STILL_NOT_FIXED, ride->id); + News::AddItemToQueue(News::ItemType::Ride, STR_RIDE_IS_STILL_NOT_FIXED, ride->id); } } } @@ -3211,7 +3211,7 @@ static void ride_entrance_exit_connected(Ride* ride) ride->FormatNameTo(ft); if (gConfigNotifications.ride_warnings) { - news_item_add_to_queue(News::ItemType::Ride, STR_ENTRANCE_NOT_CONNECTED, ride->id); + News::AddItemToQueue(News::ItemType::Ride, STR_ENTRANCE_NOT_CONNECTED, ride->id); } ride->connected_message_throttle = 3; } @@ -3223,7 +3223,7 @@ static void ride_entrance_exit_connected(Ride* ride) ride->FormatNameTo(ft); if (gConfigNotifications.ride_warnings) { - news_item_add_to_queue(News::ItemType::Ride, STR_EXIT_NOT_CONNECTED, ride->id); + News::AddItemToQueue(News::ItemType::Ride, STR_EXIT_NOT_CONNECTED, ride->id); } ride->connected_message_throttle = 3; } @@ -3299,7 +3299,7 @@ static void ride_shop_connected(Ride* ride) ride->FormatNameTo(ft); if (gConfigNotifications.ride_warnings) { - news_item_add_to_queue(News::ItemType::Ride, STR_ENTRANCE_NOT_CONNECTED, ride->id); + News::AddItemToQueue(News::ItemType::Ride, STR_ENTRANCE_NOT_CONNECTED, ride->id); } ride->connected_message_throttle = 3; @@ -7077,7 +7077,7 @@ void Ride::Crash(uint8_t vehicleIndex) FormatNameTo(ft); if (gConfigNotifications.ride_crashed) { - news_item_add_to_queue(News::ItemType::Ride, STR_RIDE_HAS_CRASHED, id); + News::AddItemToQueue(News::ItemType::Ride, STR_RIDE_HAS_CRASHED, id); } } diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 65c464bfd6..5643d368cf 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -3479,7 +3479,7 @@ void Vehicle::CheckIfMissing() curRide->FormatNameTo(ft); ft.Add(RideComponentNames[RideTypeDescriptors[curRide->type].NameConvention.station].singular); - news_item_add_to_queue(News::ItemType::Ride, STR_NEWS_VEHICLE_HAS_STALLED, ride); + News::AddItemToQueue(News::ItemType::Ride, STR_NEWS_VEHICLE_HAS_STALLED, ride); } } @@ -5201,7 +5201,7 @@ static void ride_train_crash(Ride* ride, uint16_t numFatalities) if (gConfigNotifications.ride_casualties) { ride->FormatNameTo(ft); - news_item_add_to_queue( + News::AddItemToQueue( News::ItemType::Ride, numFatalities == 1 ? STR_X_PERSON_DIED_ON_X : STR_X_PEOPLE_DIED_ON_X, ride->id); } diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 183677d95d..0bd3b15228 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -99,7 +99,7 @@ void scenario_begin() gParkFlags |= PARK_FLAGS_NO_MONEY; research_reset_current_item(); scenery_set_default_placement_configuration(); - news_item_init_queue(); + News::InitQueue(); if (gScenarioObjectiveType != OBJECTIVE_NONE && !gLoadKeepWindowsOpen) context_open_window_view(WV_PARK_OBJECTIVE); @@ -246,7 +246,7 @@ static void scenario_entrance_fee_too_high_check() uint32_t packed_xy = (y << 16) | x; if (gConfigNotifications.park_warnings) { - news_item_add_to_queue(News::ItemType::Blank, STR_ENTRANCE_FEE_TOO_HI, packed_xy); + News::AddItemToQueue(News::ItemType::Blank, STR_ENTRANCE_FEE_TOO_HI, packed_xy); } } } @@ -793,33 +793,33 @@ static void scenario_objective_check_guests_and_rating() { if (gConfigNotifications.park_rating_warnings) { - news_item_add_to_queue(News::ItemType::Graph, STR_PARK_RATING_WARNING_4_WEEKS_REMAINING, 0); + News::AddItemToQueue(News::ItemType::Graph, STR_PARK_RATING_WARNING_4_WEEKS_REMAINING, 0); } } else if (gScenarioParkRatingWarningDays == 8) { if (gConfigNotifications.park_rating_warnings) { - news_item_add_to_queue(News::ItemType::Graph, STR_PARK_RATING_WARNING_3_WEEKS_REMAINING, 0); + News::AddItemToQueue(News::ItemType::Graph, STR_PARK_RATING_WARNING_3_WEEKS_REMAINING, 0); } } else if (gScenarioParkRatingWarningDays == 15) { if (gConfigNotifications.park_rating_warnings) { - news_item_add_to_queue(News::ItemType::Graph, STR_PARK_RATING_WARNING_2_WEEKS_REMAINING, 0); + News::AddItemToQueue(News::ItemType::Graph, STR_PARK_RATING_WARNING_2_WEEKS_REMAINING, 0); } } else if (gScenarioParkRatingWarningDays == 22) { if (gConfigNotifications.park_rating_warnings) { - news_item_add_to_queue(News::ItemType::Graph, STR_PARK_RATING_WARNING_1_WEEK_REMAINING, 0); + News::AddItemToQueue(News::ItemType::Graph, STR_PARK_RATING_WARNING_1_WEEK_REMAINING, 0); } } else if (gScenarioParkRatingWarningDays == 29) { - news_item_add_to_queue(News::ItemType::Graph, STR_PARK_HAS_BEEN_CLOSED_DOWN, 0); + News::AddItemToQueue(News::ItemType::Graph, STR_PARK_HAS_BEEN_CLOSED_DOWN, 0); gParkFlags &= ~PARK_FLAGS_PARK_OPEN; scenario_failure(); gGuestInitialHappiness = 50; diff --git a/src/openrct2/scripting/ScPark.hpp b/src/openrct2/scripting/ScPark.hpp index a937b7a7b1..8935ecc707 100644 --- a/src/openrct2/scripting/ScPark.hpp +++ b/src/openrct2/scripting/ScPark.hpp @@ -54,9 +54,9 @@ namespace OpenRCT2::Scripting return {}; } - template<> inline NewsItem FromDuk(const DukValue& value) + template<> inline News::Item FromDuk(const DukValue& value) { - NewsItem result{}; + News::Item result{}; result.Type = GetParkMessageType(value["type"].as_string()); result.Assoc = value["subject"].as_int(); result.Ticks = value["tickCount"].as_int(); @@ -92,14 +92,14 @@ namespace OpenRCT2::Scripting } private: - NewsItem* GetMessage() const + News::Item* GetMessage() const { return &gNewsItems[_index]; } bool isArchived_get() const { - return _index >= NEWS_ITEM_HISTORY_START; + return _index >= News::ItemHistoryStart; } uint16_t month_get() const @@ -225,7 +225,7 @@ namespace OpenRCT2::Scripting void remove() { - news_item_remove(static_cast(_index)); + News::RemoveItem(static_cast(_index)); } }; @@ -300,7 +300,7 @@ namespace OpenRCT2::Scripting } for (size_t i = 0, newsSize = gNewsItems.GetArchived().size(); i < newsSize; i++) { - result.push_back(std::make_shared(i + NEWS_ITEM_HISTORY_START)); + result.push_back(std::make_shared(i + News::ItemHistoryStart)); } return result; } @@ -308,14 +308,14 @@ namespace OpenRCT2::Scripting void messages_set(const std::vector& value) { int32_t index = 0; - int32_t archiveIndex = NEWS_ITEM_HISTORY_START; + int32_t archiveIndex = News::ItemHistoryStart; for (const auto& item : value) { auto isArchived = item["isArchived"].as_bool(); - auto newsItem = FromDuk(item); + auto newsItem = FromDuk(item); if (isArchived) { - if (archiveIndex < MAX_NEWS_ITEMS) + if (archiveIndex < News::MaxItems) { gNewsItems[archiveIndex] = newsItem; archiveIndex++; @@ -323,7 +323,7 @@ namespace OpenRCT2::Scripting } else { - if (index < NEWS_ITEM_HISTORY_START) + if (index < News::ItemHistoryStart) { gNewsItems[index] = newsItem; index++; @@ -332,11 +332,11 @@ namespace OpenRCT2::Scripting } // End the lists by setting next item to null - if (index < NEWS_ITEM_HISTORY_START) + if (index < News::ItemHistoryStart) { gNewsItems[index].Type = News::ItemType::Null; } - if (archiveIndex < MAX_NEWS_ITEMS) + if (archiveIndex < News::MaxItems) { gNewsItems[archiveIndex].Type = News::ItemType::Null; } @@ -369,7 +369,7 @@ namespace OpenRCT2::Scripting assoc = static_cast(dukSubject.as_int()); } } - news_item_add_to_queue_raw(type, text.c_str(), assoc); + News::AddItemToQueue(type, text.c_str(), assoc); } catch (const DukException&) {