333 w->vscroll.count = _total_news; |
332 w->vscroll.count = _total_news; |
334 } |
333 } |
335 |
334 |
336 |
335 |
337 /** |
336 /** |
338 * Maximum age of news items. |
337 * Per-NewsType data |
339 * Don't show item if it's older than x days, corresponds with NewsType in news_type.h |
|
340 * @see NewsType |
|
341 */ |
338 */ |
342 static const byte _news_items_age[NT_END] = { |
339 NewsTypeData _news_type_data[NT_END] = { |
343 60, ///< NT_ARRIVAL_PLAYER |
340 /* name, age, sound, display */ |
344 60, ///< NT_ARRIVAL_OTHER |
341 { "arrival_player", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_PLAYER |
345 90, ///< NT_ACCIDENT |
342 { "arrival_other", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_OTHER |
346 60, ///< NT_COMPANY_INFO |
343 { "accident", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCIDENT |
347 90, ///< NT_OPENCLOSE |
344 { "company_info", 60, SND_BEGIN, ND_FULL }, ///< NT_COMPANY_INFO |
348 30, ///< NT_ECONOMY |
345 { "openclose", 90, SND_BEGIN, ND_FULL }, ///< NT_OPENCLOSE |
349 30, ///< NT_INDUSTRY_PLAYER |
346 { "economy", 30, SND_BEGIN, ND_FULL }, ///< NT_ECONOMY |
350 30, ///< NT_INDUSTRY_OTHER |
347 { "production_player", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_PLAYER |
351 30, ///< NT_INDUSTRY_NOBODY |
348 { "production_other", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_OTHER |
352 150, ///< NT_ADVICE |
349 { "production_nobody", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_NOBODY |
353 30, ///< NT_NEW_VEHICLES |
350 { "advice", 150, SND_BEGIN, ND_FULL }, ///< NT_ADVICE |
354 90, ///< NT_ACCEPTANCE |
351 { "new_vehicles", 30, SND_1E_OOOOH, ND_FULL }, ///< NT_NEW_VEHICLES |
355 180, ///< NT_SUBSIDIES |
352 { "acceptance", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCEPTANCE |
356 60 ///< NT_GENERAL |
353 { "subsidies", 180, SND_BEGIN, ND_FULL }, ///< NT_SUBSIDIES |
|
354 { "general", 60, SND_BEGIN, ND_FULL }, ///< NT_GENERAL |
357 }; |
355 }; |
358 |
356 |
359 |
357 |
360 static const Widget _news_type13_widgets[] = { |
358 static const Widget _news_type13_widgets[] = { |
361 { WWT_PANEL, RESIZE_NONE, 15, 0, 429, 0, 169, 0x0, STR_NULL}, |
359 { WWT_PANEL, RESIZE_NONE, 15, 0, 429, 0, 169, 0x0, STR_NULL}, |
399 WDF_DEF_WIDGET, |
397 WDF_DEF_WIDGET, |
400 _news_type0_widgets, |
398 _news_type0_widgets, |
401 NewsWindowProc |
399 NewsWindowProc |
402 }; |
400 }; |
403 |
401 |
404 static const SoundFx _news_sounds[NT_END] = { |
|
405 SND_1D_APPLAUSE, ///< NT_ARRIVAL_PLAYER |
|
406 SND_1D_APPLAUSE, ///< NT_ARRIVAL_OTHER |
|
407 SND_BEGIN, ///< NT_ACCIDENT |
|
408 SND_BEGIN, ///< NT_COMPANY_INFO |
|
409 SND_BEGIN, ///< NT_OPENCLOSE |
|
410 SND_BEGIN, ///< NT_ECONOMY |
|
411 SND_BEGIN, ///< NT_INDUSTRY_PLAYER |
|
412 SND_BEGIN, ///< NT_INDUSTRY_OTHER |
|
413 SND_BEGIN, ///< NT_INDUSTRY_NOBODY |
|
414 SND_BEGIN, ///< NT_ADVICE |
|
415 SND_1E_OOOOH, ///< NT_NEW_VEHICLES |
|
416 SND_BEGIN, ///< NT_ACCEPTANCE |
|
417 SND_BEGIN, ///< NT_SUBSIDIES |
|
418 SND_BEGIN, ///< NT_GENERAL |
|
419 }; |
|
420 |
|
421 const char *_news_display_name[NT_END] = { |
|
422 "arrival_player", |
|
423 "arrival_other", |
|
424 "accident", |
|
425 "company_info", |
|
426 "openclose", |
|
427 "economy", |
|
428 "production_player", |
|
429 "production_other", |
|
430 "production_nobody", |
|
431 "advice", |
|
432 "new_vehicles", |
|
433 "acceptance", |
|
434 "subsidies", |
|
435 "general", |
|
436 }; |
|
437 |
|
438 /** |
|
439 * Get the value of an item of the news-display settings. This is |
|
440 * a little tricky since on/off/summary must use 2 bits to store the value |
|
441 * @param item the item whose value is requested |
|
442 * @return return the found value which is between 0-2 |
|
443 */ |
|
444 static inline byte GetNewsDisplayValue(byte item) |
|
445 { |
|
446 assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2); |
|
447 return GB(_news_display_opt, item * 2, 2); |
|
448 } |
|
449 |
|
450 /** |
|
451 * Set the value of an item in the news-display settings. This is |
|
452 * a little tricky since on/off/summary must use 2 bits to store the value |
|
453 * @param item the item whose value is being set |
|
454 * @param val new value |
|
455 */ |
|
456 static inline void SetNewsDisplayValue(byte item, byte val) |
|
457 { |
|
458 assert(item < NT_END && val <= 2); |
|
459 SB(_news_display_opt, item * 2, 2, val); |
|
460 } |
|
461 |
402 |
462 /** Open up an own newspaper window for the news item */ |
403 /** Open up an own newspaper window for the news item */ |
463 static void ShowNewspaper(NewsItem *ni) |
404 static void ShowNewspaper(NewsItem *ni) |
464 { |
405 { |
465 ni->flags &= ~NF_FORCE_BIG; |
406 ni->flags &= ~NF_FORCE_BIG; |
466 ni->duration = 555; |
407 ni->duration = 555; |
467 |
408 |
468 SoundFx sound = _news_sounds[ni->type]; |
409 SoundFx sound = _news_type_data[ni->type].sound; |
469 if (sound != 0) SndPlayFx(sound); |
410 if (sound != 0) SndPlayFx(sound); |
470 |
411 |
471 int top = _screen.height; |
412 int top = _screen.height; |
472 Window *w; |
413 Window *w; |
473 switch (ni->display_mode) { |
414 switch (ni->display_mode) { |
474 case NM_NORMAL: |
415 case NM_NORMAL: |
475 case NM_CALLBACK: |
416 case NM_CALLBACK: |
476 _news_type13_desc.top = top; |
417 _news_type13_desc.top = top; |
477 w = AllocateWindowDesc(&_news_type13_desc); |
418 w = AllocateWindowDesc(&_news_type13_desc); |
478 if (ni->flags & NF_VIEWPORT) { |
419 if (ni->flags & NF_VIEWPORT) { |
479 AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E, |
420 InitializeWindowViewport(w, 2, 58, 426, 110, |
480 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); |
421 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); |
481 } |
422 } |
482 break; |
423 break; |
483 |
424 |
484 case NM_THIN: |
425 case NM_THIN: |
485 _news_type2_desc.top = top; |
426 _news_type2_desc.top = top; |
486 w = AllocateWindowDesc(&_news_type2_desc); |
427 w = AllocateWindowDesc(&_news_type2_desc); |
487 if (ni->flags & NF_VIEWPORT) { |
428 if (ni->flags & NF_VIEWPORT) { |
488 AssignWindowViewport(w, 2, 58, 0x1AA, 0x46, |
429 InitializeWindowViewport(w, 2, 58, 426, 70, |
489 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); |
430 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); |
490 } |
431 } |
491 break; |
432 break; |
492 |
433 |
493 default: |
434 default: |
494 _news_type0_desc.top = top; |
435 _news_type0_desc.top = top; |
495 w = AllocateWindowDesc(&_news_type0_desc); |
436 w = AllocateWindowDesc(&_news_type0_desc); |
496 if (ni->flags & NF_VIEWPORT) { |
437 if (ni->flags & NF_VIEWPORT) { |
497 AssignWindowViewport(w, 3, 17, 0x112, 0x2F, |
438 InitializeWindowViewport(w, 3, 17, 274, 47, |
498 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); |
439 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); |
499 } |
440 } |
500 break; |
441 break; |
501 } |
442 } |
502 |
443 |
551 if (_current_news != _latest_news) { |
492 if (_current_news != _latest_news) { |
552 _current_news = (_current_news == INVALID_NEWS) ? _oldest_news : IncreaseIndex(_current_news); |
493 _current_news = (_current_news == INVALID_NEWS) ? _oldest_news : IncreaseIndex(_current_news); |
553 NewsItem *ni = &_news_items[_current_news]; |
494 NewsItem *ni = &_news_items[_current_news]; |
554 |
495 |
555 /* check the date, don't show too old items */ |
496 /* check the date, don't show too old items */ |
556 if (_date - _news_items_age[ni->type] > ni->date) return; |
497 if (_date - _news_type_data[ni->type].age > ni->date) return; |
557 |
498 |
558 switch (GetNewsDisplayValue(ni->type)) { |
499 switch (_news_type_data[ni->type].display) { |
559 default: NOT_REACHED(); |
500 default: NOT_REACHED(); |
560 case 0: { // Off - show nothing only a small reminder in the status bar |
501 case ND_OFF: { // Off - show nothing only a small reminder in the status bar |
561 Window *w = FindWindowById(WC_STATUS_BAR, 0); |
502 Window *w = FindWindowById(WC_STATUS_BAR, 0); |
562 |
503 |
563 if (w != NULL) { |
504 if (w != NULL) { |
564 WP(w, def_d).data_2 = 91; |
505 WP(w, def_d).data_2 = 91; |
565 SetWindowDirty(w); |
506 SetWindowDirty(w); |
566 } |
507 } |
567 break; |
508 break; |
568 } |
509 } |
569 |
510 |
570 case 1: // Summary - show ticker, but if forced big, cascade to full |
511 case ND_SUMMARY: // Summary - show ticker, but if forced big, cascade to full |
571 if (!(ni->flags & NF_FORCE_BIG)) { |
512 if (!(ni->flags & NF_FORCE_BIG)) { |
572 ShowTicker(ni); |
513 ShowTicker(ni); |
573 break; |
514 break; |
574 } |
515 } |
575 /* Fallthrough */ |
516 /* Fallthrough */ |
576 |
517 |
577 case 2: // Full - show newspaper |
518 case ND_FULL: // Full - show newspaper |
578 ShowNewspaper(ni); |
519 ShowNewspaper(ni); |
579 break; |
520 break; |
580 } |
521 } |
581 } |
522 } |
582 } |
523 } |
801 static const StringID message_opt[] = {STR_OFF, STR_SUMMARY, STR_FULL, INVALID_STRING_ID}; |
742 static const StringID message_opt[] = {STR_OFF, STR_SUMMARY, STR_FULL, INVALID_STRING_ID}; |
802 |
743 |
803 /* WP(w, def_d).data_1 stores state of the ALL on/off/summary button */ |
744 /* WP(w, def_d).data_1 stores state of the ALL on/off/summary button */ |
804 switch (e->event) { |
745 switch (e->event) { |
805 case WE_CREATE: { |
746 case WE_CREATE: { |
806 uint32 val = _news_display_opt; |
747 NewsDisplay all_val; |
807 uint32 all_val; |
|
808 |
748 |
809 /* Set up the initial disabled buttons in the case of 'off' or 'full' */ |
749 /* Set up the initial disabled buttons in the case of 'off' or 'full' */ |
810 all_val = val & 0x3; |
750 all_val = _news_type_data[0].display; |
811 for (int i = 0; i < NT_END; i++, val >>= 2) { |
751 for (int i = 0; i < NT_END; i++) { |
812 SetMessageButtonStates(w, val & 0x3, i); |
752 SetMessageButtonStates(w, _news_type_data[i].display, i); |
813 /* If the value doesn't match the ALL-button value, set the ALL-button value to 'off' */ |
753 /* If the value doesn't match the ALL-button value, set the ALL-button value to 'off' */ |
814 if ((val & 0x3) != all_val) all_val = 0; |
754 if (_news_type_data[i].display != all_val) all_val = ND_OFF; |
815 } |
755 } |
816 /* If all values are the same value, the ALL-button will take over this value */ |
756 /* If all values are the same value, the ALL-button will take over this value */ |
817 WP(w, def_d).data_1 = all_val; |
757 WP(w, def_d).data_1 = all_val; |
818 } break; |
758 } break; |
819 |
759 |
820 case WE_PAINT: { |
760 case WE_PAINT: { |
821 uint32 val = _news_display_opt; |
|
822 |
|
823 if (_news_ticker_sound) w->LowerWidget(WIDGET_NEWSOPT_SOUNDTICKER); |
761 if (_news_ticker_sound) w->LowerWidget(WIDGET_NEWSOPT_SOUNDTICKER); |
824 |
762 |
825 w->widget[WIDGET_NEWSOPT_DROP_SUMMARY].data = message_opt[WP(w, def_d).data_1]; |
763 w->widget[WIDGET_NEWSOPT_DROP_SUMMARY].data = message_opt[WP(w, def_d).data_1]; |
826 DrawWindowWidgets(w); |
764 DrawWindowWidgets(w); |
827 |
765 |
828 /* Draw the string of each setting on each button. */ |
766 /* Draw the string of each setting on each button. */ |
829 for (int i = 0, y = 26; i < NT_END; i++, y += 12, val >>= 2) { |
767 for (int i = 0, y = 26; i < NT_END; i++, y += 12) { |
830 /* 51 comes from 13 + 89 (left and right of the button)+1, shiefted by one as to get division, |
768 /* 51 comes from 13 + 89 (left and right of the button)+1, shiefted by one as to get division, |
831 * which will give centered position */ |
769 * which will give centered position */ |
832 DrawStringCentered(51, y + 1, message_opt[val & 0x3], TC_BLACK); |
770 DrawStringCentered(51, y + 1, message_opt[_news_type_data[i].display], TC_BLACK); |
833 } |
771 } |
834 } break; |
772 } break; |
835 |
773 |
836 case WE_CLICK: |
774 case WE_CLICK: |
837 switch (e->we.click.widget) { |
775 switch (e->we.click.widget) { |