17 #include "sound.h" |
16 #include "sound.h" |
18 #include "variables.h" |
17 #include "variables.h" |
19 #include "date.h" |
18 #include "date.h" |
20 #include "string.h" |
19 #include "string.h" |
21 |
20 |
22 /* News system |
21 /** @file news_gui.cpp |
|
22 * |
23 * News system is realized as a FIFO queue (in an array) |
23 * News system is realized as a FIFO queue (in an array) |
24 * The positions in the queue can't be rearranged, we only access |
24 * The positions in the queue can't be rearranged, we only access |
25 * the array elements through pointers to the elements. Once the |
25 * the array elements through pointers to the elements. Once the |
26 * array is full, the oldest entry (_oldest_news) is being overwritten |
26 * array is full, the oldest entry (\a _oldest_news) is being overwritten |
27 * by the newest (_latest news). |
27 * by the newest (\a _latest_news). |
28 * |
28 * |
|
29 * \verbatim |
29 * oldest current lastest |
30 * oldest current lastest |
30 * | | | |
31 * | | | |
31 * [O------------F-------------C---------L ] |
32 * [O------------F-------------C---------L ] |
32 * | |
33 * | |
33 * forced |
34 * forced |
|
35 * \endverbatim |
34 * |
36 * |
35 * Of course by using an array we can have situations like |
37 * Of course by using an array we can have situations like |
36 * |
38 * |
|
39 * \verbatim |
37 * [----L O-----F---------C-----------------] |
40 * [----L O-----F---------C-----------------] |
38 * This is where we have wrapped around the array and have |
41 * This is where we have wrapped around the array and have |
39 * (MAX_NEWS - O) + L news items |
42 * (MAX_NEWS - O) + L news items |
|
43 * \endverbatim |
40 */ |
44 */ |
41 |
45 |
|
46 /** Number of news items in the FIFO queue */ |
42 #define MAX_NEWS 30 |
47 #define MAX_NEWS 30 |
43 #define NB_WIDG_PER_SETTING 4 |
48 #define NB_WIDG_PER_SETTING 4 |
44 |
49 |
45 typedef byte NewsID; |
50 typedef byte NewsID; |
46 #define INVALID_NEWS 255 |
51 #define INVALID_NEWS 255 |
47 |
52 |
48 static NewsItem _news_items[MAX_NEWS]; |
53 static NewsItem _news_items[MAX_NEWS]; ///< The news FIFO queue |
49 static NewsID _current_news = INVALID_NEWS; // points to news item that should be shown next |
54 static NewsID _current_news = INVALID_NEWS; ///< points to news item that should be shown next |
50 static NewsID _oldest_news = 0; // points to first item in fifo queue |
55 static NewsID _oldest_news = 0; ///< points to first item in fifo queue |
51 static NewsID _latest_news = INVALID_NEWS; // points to last item in fifo queue |
56 static NewsID _latest_news = INVALID_NEWS; ///< points to last item in fifo queue |
52 /* if the message being shown was forced by the user, its index is stored in |
57 |
53 * _forced_news. forced_news is INVALID_NEWS otherwise. |
58 /** Forced news item. |
54 * (Users can force messages through history or "last message") */ |
59 * Users can force an item by accessing the history or "last message". |
|
60 * If the message being shown was forced by the user, its index is stored in |
|
61 * _forced_news. Otherwise, \a _forced_news variable is INVALID_NEWS. */ |
55 static NewsID _forced_news = INVALID_NEWS; |
62 static NewsID _forced_news = INVALID_NEWS; |
56 |
63 |
57 static byte _total_news = 0; // total news count |
64 static byte _total_news = 0; ///< Number of news items in FIFO queue @see _news_items |
58 |
65 |
59 void DrawNewsNewVehicleAvail(Window *w); |
66 void DrawNewsNewVehicleAvail(Window *w); |
60 void DrawNewsBankrupcy(Window *w); |
67 void DrawNewsBankrupcy(Window *w); |
61 static void MoveToNextItem(); |
68 static void MoveToNextItem(); |
62 |
69 |
63 StringID GetNewsStringNewVehicleAvail(const NewsItem *ni); |
70 StringID GetNewsStringNewVehicleAvail(const NewsItem *ni); |
64 StringID GetNewsStringBankrupcy(const NewsItem *ni); |
71 StringID GetNewsStringBankrupcy(const NewsItem *ni); |
65 |
72 |
66 static DrawNewsCallbackProc * const _draw_news_callback[] = { |
73 static DrawNewsCallbackProc * const _draw_news_callback[] = { |
67 DrawNewsNewVehicleAvail, //< DNC_VEHICLEAVAIL |
74 DrawNewsNewVehicleAvail, ///< DNC_VEHICLEAVAIL |
68 DrawNewsBankrupcy, //< DNC_BANKRUPCY |
75 DrawNewsBankrupcy, ///< DNC_BANKRUPCY |
69 }; |
76 }; |
70 |
77 |
71 extern GetNewsStringCallbackProc * const _get_news_string_callback[]; |
78 extern GetNewsStringCallbackProc * const _get_news_string_callback[]; |
72 GetNewsStringCallbackProc * const _get_news_string_callback[] = { |
79 GetNewsStringCallbackProc * const _get_news_string_callback[] = { |
73 GetNewsStringNewVehicleAvail, ///< DNC_VEHICLEAVAIL |
80 GetNewsStringNewVehicleAvail, ///< DNC_VEHICLEAVAIL |
74 GetNewsStringBankrupcy, ///< DNC_BANKRUPCY |
81 GetNewsStringBankrupcy, ///< DNC_BANKRUPCY |
75 }; |
82 }; |
76 |
83 |
|
84 /** Initialize the news-items data structures */ |
77 void InitNewsItemStructs() |
85 void InitNewsItemStructs() |
78 { |
86 { |
79 memset(_news_items, 0, sizeof(_news_items)); |
87 memset(_news_items, 0, sizeof(_news_items)); |
80 _current_news = INVALID_NEWS; |
88 _current_news = INVALID_NEWS; |
81 _oldest_news = 0; |
89 _oldest_news = 0; |
217 SetDirtyBlocks(w->left, w->top - diff, w->left + w->width, w->top + w->height); |
225 SetDirtyBlocks(w->left, w->top - diff, w->left + w->width, w->top + w->height); |
218 } break; |
226 } break; |
219 } |
227 } |
220 } |
228 } |
221 |
229 |
222 /** Return the correct index in the pseudo-fifo |
230 /** |
223 * queue and deals with overflows when increasing the index */ |
231 * Return the correct index in the pseudo-fifo |
|
232 * queue and deals with overflows when increasing the index |
|
233 */ |
224 static inline NewsID increaseIndex(NewsID i) |
234 static inline NewsID increaseIndex(NewsID i) |
225 { |
235 { |
226 assert(i != INVALID_NEWS); |
236 assert(i != INVALID_NEWS); |
227 return (i + 1) % MAX_NEWS; |
237 return (i + 1) % MAX_NEWS; |
228 } |
238 } |
229 |
239 |
230 /** Return the correct index in the pseudo-fifo |
240 /** |
231 * queue and deals with overflows when decreasing the index */ |
241 * Return the correct index in the pseudo-fifo |
|
242 * queue and deals with overflows when decreasing the index |
|
243 */ |
232 static inline NewsID decreaseIndex(NewsID i) |
244 static inline NewsID decreaseIndex(NewsID i) |
233 { |
245 { |
234 assert(i != INVALID_NEWS); |
246 assert(i != INVALID_NEWS); |
235 return (i + MAX_NEWS - 1) % MAX_NEWS; |
247 return (i + MAX_NEWS - 1) % MAX_NEWS; |
236 } |
248 } |
237 |
249 |
238 /** Add a new newsitem to be shown. |
250 /** |
239 * @param string String to display, can have special values based on parameter 'flags' |
251 * Add a new newsitem to be shown. |
|
252 * @param string String to display, can have special values based on parameter \a flags |
240 * @param flags various control bits that will show various news-types. See macro NEWS_FLAGS() |
253 * @param flags various control bits that will show various news-types. See macro NEWS_FLAGS() |
241 * @param data_a news-specific value based on news type |
254 * @param data_a news-specific value based on news type |
242 * @param data_b news-specific value based on news type |
255 * @param data_b news-specific value based on news type |
243 * @note flags exists of 4 byte-sized extra parameters. |
256 * @note flags exists of 4 byte-sized extra parameters. |
244 * 1. 0 - 7 display_mode, any of the NewsMode enums (NM_) |
257 * -# Bits 0 - 7 display_mode, any of the NewsMode enums (NM_) |
245 * 2. 8 - 15 news flags, any of the NewsFlags enums (NF_) NF_INCOLOR are set automatically if needed |
258 * -# Bits 8 - 15 news flags, any of the NewsFlags enums (NF_) |
246 * 3. 16 - 23 news category, any of the NewsType enums (NT_) |
259 * -# Bits 16 - 23 news category, any of the NewsType enums (NT_) |
247 * 4. 24 - 31 news callback function, any of the NewsCallback enums (DNC_) |
260 * -# Bits 24 - 31 news callback function, any of the NewsCallback enums (DNC_) |
248 * If the display mode is NM_CALLBACK special news is shown and parameter |
261 * |
249 * stringid has a special meaning. |
262 * If the display mode is NM_CALLBACK, special news is shown and parameter |
250 * DNC_TRAINAVAIL, DNC_ROADAVAIL, DNC_SHIPAVAIL, DNC_AIRCRAFTAVAIL: StringID is |
263 * \a string has a special meaning. |
251 * the index of the engine that is shown |
264 * - For DNC_TRAINAVAIL, DNC_ROADAVAIL, DNC_SHIPAVAIL, DNC_AIRCRAFTAVAIL messages: StringID is |
252 * DNC_BANKRUPCY: bytes 0-3 of StringID contains the player that is in trouble, |
265 * the index of the engine that is shown |
253 * and 4-7 contains what kind of bankrupcy message is shown, NewsBankrupcy enum (NB_) |
266 * |
|
267 * - For DNC_BANKRUPCY: bytes 0-3 of StringID contains the player that is in trouble, |
|
268 * and 4-7 contains what kind of bankrupcy message is shown. |
|
269 * @see NewsBankrupcy |
|
270 * |
254 * @see NewsMode |
271 * @see NewsMode |
255 * @see NewsFlags |
272 * @see NewsFlags |
256 * @see NewsType |
273 * @see NewsType |
257 * @see NewsCallback */ |
274 * @see NewsCallback |
|
275 */ |
258 void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b) |
276 void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b) |
259 { |
277 { |
260 NewsID l_news; |
278 NewsID l_news; |
261 |
279 |
262 if (_game_mode == GM_MENU) return; |
280 if (_game_mode == GM_MENU) return; |
308 w->vscroll.count = _total_news; |
326 w->vscroll.count = _total_news; |
309 } |
327 } |
310 } |
328 } |
311 |
329 |
312 |
330 |
313 /* Don't show item if it's older than x days, corresponds with NewsType in news.h */ |
331 /** |
314 static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180}; |
332 * Maximum age of news items. |
|
333 * Don't show item if it's older than x days, corresponds with NewsType in news.h |
|
334 * @see NewsType |
|
335 */ |
|
336 static const byte _news_items_age[NT_END] = { |
|
337 60, ///< NT_ARRIVAL_PLAYER |
|
338 60, ///< NT_ARRIVAL_OTHER |
|
339 90, ///< NT_ACCIDENT |
|
340 60, ///< NT_COMPANY_INFO |
|
341 90, ///< NT_OPENCLOSE |
|
342 30, ///< NT_ECONOMY |
|
343 150, ///< NT_ADVICE |
|
344 30, ///< NT_NEW_VEHICLES |
|
345 90, ///< NT_ACCEPTANCE |
|
346 180, ///< NT_SUBSIDIES |
|
347 60 ///< NT_GENERAL |
|
348 }; |
|
349 |
315 |
350 |
316 static const Widget _news_type13_widgets[] = { |
351 static const Widget _news_type13_widgets[] = { |
317 { WWT_PANEL, RESIZE_NONE, 15, 0, 429, 0, 169, 0x0, STR_NULL}, |
352 { WWT_PANEL, RESIZE_NONE, 15, 0, 429, 0, 169, 0x0, STR_NULL}, |
318 { WWT_PANEL, RESIZE_NONE, 15, 0, 10, 0, 11, 0x0, STR_NULL}, |
353 { WWT_PANEL, RESIZE_NONE, 15, 0, 10, 0, 11, 0x0, STR_NULL}, |
319 { WIDGETS_END}, |
354 { WIDGETS_END}, |
383 "acceptance", |
418 "acceptance", |
384 "subsidies", |
419 "subsidies", |
385 "general", |
420 "general", |
386 }; |
421 }; |
387 |
422 |
388 /** Get the value of an item of the news-display settings. This is |
423 /** |
|
424 * Get the value of an item of the news-display settings. This is |
389 * a little tricky since on/off/summary must use 2 bits to store the value |
425 * a little tricky since on/off/summary must use 2 bits to store the value |
390 * @param item the item whose value is requested |
426 * @param item the item whose value is requested |
391 * @return return the found value which is between 0-2 |
427 * @return return the found value which is between 0-2 |
392 */ |
428 */ |
393 static inline byte GetNewsDisplayValue(byte item) |
429 static inline byte GetNewsDisplayValue(byte item) |
394 { |
430 { |
395 assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2); |
431 assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2); |
396 return GB(_news_display_opt, item * 2, 2); |
432 return GB(_news_display_opt, item * 2, 2); |
397 } |
433 } |
398 |
434 |
399 /** Set the value of an item in the news-display settings. This is |
435 /** |
|
436 * Set the value of an item in the news-display settings. This is |
400 * a little tricky since on/off/summary must use 2 bits to store the value |
437 * a little tricky since on/off/summary must use 2 bits to store the value |
401 * @param item the item whose value is being set |
438 * @param item the item whose value is being set |
402 * @param val new value |
439 * @param val new value |
403 */ |
440 */ |
404 static inline void SetNewsDisplayValue(byte item, byte val) |
441 static inline void SetNewsDisplayValue(byte item, byte val) |
405 { |
442 { |
406 assert(item < NT_END && val <= 2); |
443 assert(item < NT_END && val <= 2); |
407 SB(_news_display_opt, item * 2, 2, val); |
444 SB(_news_display_opt, item * 2, 2, val); |
408 } |
445 } |
409 |
446 |
410 /* open up an own newspaper window for the news item */ |
447 /** Open up an own newspaper window for the news item */ |
411 static void ShowNewspaper(NewsItem *ni) |
448 static void ShowNewspaper(NewsItem *ni) |
412 { |
449 { |
413 Window *w; |
450 Window *w; |
414 SoundFx sound; |
451 SoundFx sound; |
415 int top; |
452 int top; |
507 |
547 |
508 /* check the date, don't show too old items */ |
548 /* check the date, don't show too old items */ |
509 if (_date - _news_items_age[ni->type] > ni->date) return; |
549 if (_date - _news_items_age[ni->type] > ni->date) return; |
510 |
550 |
511 switch (GetNewsDisplayValue(ni->type)) { |
551 switch (GetNewsDisplayValue(ni->type)) { |
512 case 0: { // Off - show nothing only a small reminder in the status bar |
552 default: NOT_REACHED(); |
513 Window *w = FindWindowById(WC_STATUS_BAR, 0); |
553 case 0: { // Off - show nothing only a small reminder in the status bar |
514 |
554 Window *w = FindWindowById(WC_STATUS_BAR, 0); |
515 if (w != NULL) { |
555 |
516 WP(w, def_d).data_2 = 91; |
556 if (w != NULL) { |
517 SetWindowDirty(w); |
557 WP(w, def_d).data_2 = 91; |
518 } |
558 SetWindowDirty(w); |
519 break; |
559 } |
520 } |
|
521 |
|
522 case 1: // Summary - show ticker, but if forced big, cascade to full |
|
523 if (!(ni->flags & NF_FORCE_BIG)) { |
|
524 ShowTicker(ni); |
|
525 break; |
560 break; |
526 } |
561 } |
527 /* Fallthrough */ |
562 |
528 |
563 case 1: // Summary - show ticker, but if forced big, cascade to full |
529 case 2: // Full - show newspaper |
564 if (!(ni->flags & NF_FORCE_BIG)) { |
530 ShowNewspaper(ni); |
565 ShowTicker(ni); |
531 break; |
566 break; |
|
567 } |
|
568 /* Fallthrough */ |
|
569 |
|
570 case 2: // Full - show newspaper |
|
571 ShowNewspaper(ni); |
|
572 break; |
532 } |
573 } |
533 } |
574 } |
534 } |
575 } |
535 |
576 |
536 void NewsLoop() |
577 void NewsLoop() |
731 WIDGET_NEWSOPT_DROP_SUMMARY, ///< Drop down button for same upper button |
775 WIDGET_NEWSOPT_DROP_SUMMARY, ///< Drop down button for same upper button |
732 WIDGET_NEWSOPT_SOUNDTICKER = 7, ///< Button activating sound on events |
776 WIDGET_NEWSOPT_SOUNDTICKER = 7, ///< Button activating sound on events |
733 WIDGET_NEWSOPT_START_OPTION = 9, ///< First widget that is part of a group [<] .. [.] |
777 WIDGET_NEWSOPT_START_OPTION = 9, ///< First widget that is part of a group [<] .. [.] |
734 }; |
778 }; |
735 |
779 |
736 /** Setup the disabled/enabled buttons in the message window |
780 /** |
|
781 * Setup the disabled/enabled buttons in the message window |
737 * If the value is 'off' disable the [<] widget, and enable the [>] one |
782 * If the value is 'off' disable the [<] widget, and enable the [>] one |
738 * Same-wise for all the others. Starting value of 4 is the first widget |
783 * Same-wise for all the others. Starting value of 4 is the first widget |
739 * group. These are grouped as [<][>] .. [<][>], etc. |
784 * group. These are grouped as [<][>] .. [<][>], etc. |
740 * @param w Window been used |
785 * @param w Window been used |
741 * @param value to set in the widget |
786 * @param value to set in the widget |