Refactoring in news_item

Now news_items are fetched only with exposed calls, which add a layer of
simple checks. I also switched few places to access a read-only version
of news_item.
This commit is contained in:
Michał Janiszewski 2015-07-24 23:40:04 +02:00
parent 04dcca5468
commit 6adb384a7e
5 changed files with 132 additions and 68 deletions

View File

@ -28,11 +28,42 @@
#include "../world/sprite.h"
#include "news_item.h"
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
rct_news_item *gNewsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
void window_game_bottom_toolbar_invalidate_news_item();
static int news_item_get_new_history_slot();
#define MAX_NEWS 60
bool news_item_is_valid_idx(const uint8 idx)
{
if (idx > MAX_NEWS)
{
log_error("Tried to get news item past MAX_NEWS.");
return false;
}
return true;
}
rct_news_item *news_item_get(const uint8 idx)
{
if (news_item_is_valid_idx(idx))
{
return &gNewsItems[idx];
} else {
return NULL;
}
}
bool news_item_is_empty(const uint8 idx)
{
return news_item_get(idx)->type == NEWS_ITEM_NULL;
}
bool news_item_is_queue_empty()
{
return news_item_is_empty(0);
}
/**
*
* rct2: 0x0066DF32
@ -40,16 +71,41 @@ static int news_item_get_new_history_slot();
void news_item_init_queue()
{
int i;
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
newsItems[0].type = NEWS_ITEM_NULL;
newsItems[11].type = NEWS_ITEM_NULL;
news_item_get(0)->type = NEWS_ITEM_NULL;
news_item_get(11)->type = NEWS_ITEM_NULL;
// Throttles for warning types (PEEP_*_WARNING)
for (i = 0; i < 16; i++)
RCT2_ADDRESS(0x01358750, uint8)[i] = 0;
window_game_bottom_toolbar_invalidate_news_item();
}
static void news_item_tick_current()
{
int ticks;
ticks = news_item_get(0)->ticks++;
if (ticks == 1 && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) {
// Play sound
sound_play_panned(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0);
}
}
static bool news_item_is_current_old()
{
int remove_time = 320;
if (!news_item_is_empty(5) &&
!news_item_is_empty(4) &&
!news_item_is_empty(3) &&
!news_item_is_empty(2))
remove_time = 256;
if (news_item_get(0)->ticks >= remove_time)
return true;
return false;
}
/**
*
* rct2: 0x0066E252
@ -57,7 +113,6 @@ void news_item_init_queue()
void news_item_update_current()
{
short ax, bx, remove_time;
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
get_system_time();
@ -91,27 +146,16 @@ void news_item_update_current()
RCT2_GLOBAL(0x009DEA6B, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16);
// Check if there is a current news item
if (newsItems[0].type == 0)
if (news_item_is_queue_empty())
return;
window_game_bottom_toolbar_invalidate_news_item();
// Update the current news item
newsItems[0].ticks++;
if (newsItems[0].ticks == 1 && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) {
// Play sound
sound_play_panned(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0);
}
news_item_tick_current();
// Removal of current news item
remove_time = 320;
if (newsItems[2].type != 0 &&
newsItems[3].type != 0 &&
newsItems[4].type != 0 &&
newsItems[5].type != 0)
remove_time = 256;
if (newsItems[0].ticks >= remove_time)
if (news_item_is_current_old())
news_item_close_current();
}
@ -125,7 +169,7 @@ void news_item_close_current()
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
// Check if there is a current message
if (newsItems[0].type == NEWS_ITEM_NULL)
if (news_item_is_queue_empty())
return;
// Find an available history news item slot for current message
@ -135,7 +179,7 @@ void news_item_close_current()
newsItems[i] = newsItems[0];
// Set the end of the end of the history list
if (i < 60)
if (i < MAX_NEWS)
newsItems[i + 1].type = NEWS_ITEM_NULL;
// Invalidate the news window
@ -150,6 +194,15 @@ void news_item_close_current()
window_game_bottom_toolbar_invalidate_news_item();
}
static void news_item_shift_history_up()
{
const int history_idx = 11;
rct_news_item *history_start = news_item_get(history_idx);
const size_t count = sizeof(rct_news_item) * (MAX_NEWS - 1 - history_idx);
memmove(history_start, history_start + 1, count);
}
/**
* Finds a spare history slot or replaces an existing one if there are no spare
* slots available.
@ -157,17 +210,15 @@ void news_item_close_current()
static int news_item_get_new_history_slot()
{
int i;
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
// Find an available history news item slot
for (i = 11; i < 61; i++)
if (newsItems[i].type == NEWS_ITEM_NULL)
for (i = 11; i <= MAX_NEWS; i++)
if (news_item_is_empty(i))
return i;
// Dequeue the first history news item, shift history up
for (i = 11; i < 60; i++)
newsItems[i] = newsItems[i + 1];
return 60;
news_item_shift_history_up();
return MAX_NEWS;
}
/**
@ -264,7 +315,7 @@ void news_item_add_to_queue_raw(uint8 type, const char *text, uint32 assoc)
// find first open slot
while (newsItem->type != NEWS_ITEM_NULL) {
if (newsItem + 1 >= (rct_news_item*)0x13CB1CC)
if (newsItem + 1 >= (rct_news_item*)0x13CB1CC) // &news_list[10]
news_item_close_current();
else
newsItem++;
@ -358,24 +409,36 @@ void news_item_open_subject(int type, int subject)
* rct2: 0x0066E407
*/
void news_item_disable_news(uint8 type, uint32 assoc) {
rct_news_item* newsItem = newsItems;
while (newsItem->type != NEWS_ITEM_NULL) {
// TODO: write test invalidating windows
int i;
for (i = 0; i < 11; i++)
{
if (!news_item_is_empty(i))
{
rct_news_item * const newsItem;
if (type == newsItem->type && assoc == newsItem->assoc) {
newsItem->flags |= 0x1;
if (newsItem == RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)) {
if (i == 0) {
window_game_bottom_toolbar_invalidate_news_item();
}
}
newsItem++;
} else {
break;
}
}
newsItem = &newsItems[11]; //0x13CB2D8
while (newsItem->type != NEWS_ITEM_NULL) {
for (i = 11; i <= MAX_NEWS; i++)
{
if (!news_item_is_empty(i))
{
rct_news_item * const newsItem = news_item_get(i);
if (type == newsItem->type && assoc == newsItem->assoc) {
newsItem->flags |= 0x1;
window_invalidate_by_class(WC_RECENT_NEWS);
}
newsItem++;
} else {
break;
}
}
}

View File

@ -60,5 +60,9 @@ void news_item_add_to_queue(uint8 type, rct_string_id string_id, uint32 assoc);
void news_item_add_to_queue_raw(uint8 type, const char *text, uint32 assoc);
void news_item_open_subject(int type, int subject);
void news_item_disable_news(uint8 type, uint32 assoc);
rct_news_item *news_item_get(const uint8 idx);
bool news_item_is_empty(const uint8 idx);
bool news_item_is_queue_empty();
bool news_item_is_valid_idx(const uint8 idx);
#endif

View File

@ -557,7 +557,7 @@ enum {
#define GET_PEEP(sprite_index) &(g_sprite_list[sprite_index].peep)
/**
* Helper macro loop for enumerating through all the non null rides. To avoid needing a end loop counterpart, statements are
* Helper macro loop for enumerating through all the peeps. To avoid needing a end loop counterpart, statements are
* applied in tautology if statements.
*/
#define FOR_ALL_PEEPS(sprite_index, peep) \

View File

@ -182,15 +182,15 @@ static void window_game_bottom_toolbar_mouseup(rct_window *w, int widgetIndex)
news_item_close_current();
break;
case WIDX_NEWS_SUBJECT:
newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]);
newsItem = news_item_get(0);
news_item_open_subject(newsItem->type, newsItem->assoc);
break;
case WIDX_NEWS_LOCATE:
newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]);
if (newsItem->type == NEWS_ITEM_NULL)
if (news_item_is_queue_empty())
break;
{
newsItem = news_item_get(0);
int x, y, z;
int subject = newsItem->assoc;
@ -268,12 +268,12 @@ 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;
newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]);
if (newsItem->type == 0) {
if (news_item_is_queue_empty()) {
window_game_bottom_toolbar_widgets[WIDX_MIDDLE_INSET].type = WWT_EMPTY;
window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].type = WWT_EMPTY;
window_game_bottom_toolbar_widgets[WIDX_NEWS_LOCATE].type = WWT_EMPTY;
} else {
newsItem = news_item_get(0);
window_game_bottom_toolbar_widgets[WIDX_MIDDLE_INSET].type = WWT_25;
window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].type = WWT_FLATBTN;
window_game_bottom_toolbar_widgets[WIDX_NEWS_LOCATE].type = WWT_FLATBTN;
@ -320,7 +320,7 @@ static void window_game_bottom_toolbar_invalidate(rct_window *w)
void window_game_bottom_toolbar_invalidate_news_item()
{
window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].type =
RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0].type == NEWS_ITEM_NULL ? WWT_EMPTY : WWT_IMGBTN;
news_item_is_queue_empty() ? WWT_EMPTY : WWT_IMGBTN;
widget_invalidate_by_class(WC_BOTTOM_TOOLBAR, WIDX_MIDDLE_OUTSET);
}
@ -353,7 +353,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 (RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0].type != 0)
if (!news_item_is_queue_empty())
window_game_bottom_toolbar_draw_news_item(dpi, w);
else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8))
window_game_bottom_toolbar_draw_tutorial_text(dpi, w);
@ -509,7 +509,7 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc
rct_widget *middleOutsetWidget;
middleOutsetWidget = &window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET];
newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]);
newsItem = news_item_get(0);
// Current news item
gfx_fill_rect_inset(

View File

@ -140,7 +140,6 @@ static void window_news_mouseup(rct_window *w, int widgetIndex)
static void window_news_update(rct_window *w)
{
int i, j, x, y, z;
rct_news_item *newsItems;
if (w->news.var_480 == -1)
return;
@ -150,22 +149,22 @@ static void window_news_update(rct_window *w)
window_invalidate(w);
sound_play_panned(SOUND_CLICK_2, w->x + (w->width / 2), 0, 0, 0);
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
j = w->news.var_480;
w->news.var_480 = -1;
for (i = 11; i < 61; i++) {
if (newsItems[i].type == NEWS_ITEM_NULL)
if (news_item_is_empty(i))
return;
if (j == 0) {
if (newsItems[i].flags & 1)
rct_news_item * const newsItem = news_item_get(i);
if (newsItem->flags & 1)
return;
if (w->news.var_482 == 1) {
news_item_open_subject(newsItems[i].type, newsItems[i].assoc);
news_item_open_subject(newsItem->type, newsItem->assoc);
return;
}
else if (w->news.var_482 > 1) {
news_item_get_subject_location(newsItems[i].type, newsItems[i].assoc, &x, &y, &z);
news_item_get_subject_location(newsItem->type, newsItem->assoc, &x, &y, &z);
if (x != SPRITE_LOCATION_NULL)
if ((w = window_get_main()) != NULL)
window_scroll_to_location(w, x, y, z);
@ -183,11 +182,10 @@ static void window_news_update(rct_window *w)
static void window_news_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
{
int i;
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
*height = 0;
for (i = 11; i < 61; i++) {
if (newsItems[i].type == NEWS_ITEM_NULL)
if (news_item_is_empty(i))
break;
*height += 42;
@ -201,16 +199,15 @@ static void window_news_scrollgetsize(rct_window *w, int scrollIndex, int *width
static void window_news_scrollmousedown(rct_window *w, int scrollIndex, int x, int y)
{
int i, buttonIndex;
rct_news_item *newsItems;
buttonIndex = 0;
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
for (i = 11; i < 61; i++) {
if (newsItems[i].type == NEWS_ITEM_NULL)
if (news_item_is_empty(i))
break;
if (y < 42) {
if (newsItems[i].flags & 1) {
rct_news_item * const newsItem = news_item_get(i);
if (newsItem->flags & 1) {
buttonIndex = 0;
break;
} else if (y < 14) {
@ -223,12 +220,12 @@ static void window_news_scrollmousedown(rct_window *w, int scrollIndex, int x, i
buttonIndex = 0;
break;
} else if (x < 351) {
if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItems[i].type] & 2) {
if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 2) {
buttonIndex = 1;
break;
}
} else if (x < 376) {
if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItems[i].type] & 1) {
if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 1) {
buttonIndex = 2;
break;
}
@ -276,13 +273,11 @@ static void window_news_invalidate(rct_window *w)
static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
int i, x, y, yy, press;
rct_news_item *newsItems, *newsItem, *newsItem2;
y = 0;
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
for (i = 11; i < 61; i++) {
newsItem = &newsItems[i];
if (newsItem->type == NEWS_ITEM_NULL)
rct_news_item * const newsItem = news_item_get(i);
if (news_item_is_empty(i))
break;
if (y >= dpi->y + dpi->height)
break;
@ -313,8 +308,9 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s
press = 0;
if (w->news.var_480 != -1) {
newsItem2 = &newsItems[11 + w->news.var_480];
if (newsItem == newsItem2 && w->news.var_482 == 1)
const uint8 idx = 11 + w->news.var_480;
news_item_is_valid_idx(idx);
if (i == idx && w->news.var_482 == 1)
press = 0x20;
}
gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press);
@ -376,8 +372,9 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s
press = 0;
if (w->news.var_480 != -1) {
newsItem2 = &newsItems[11 + w->news.var_480];
if (newsItem == newsItem2 && w->news.var_482 == 2)
const uint8 idx = 11 + w->news.var_480;
news_item_is_valid_idx(idx);
if (i == idx && w->news.var_482 == 2)
press = 0x20;
}
gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press);
@ -386,4 +383,4 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s
y += 42;
}
}
}