added reading credits info (global or level set specific) from files
[rocksndiamonds.git] / src / screens.c
index c036c5a2531b2c7db1cef126d03da8685488710f..7a6bfe41b9fff219d2430bec383145f9f6d53a38 100644 (file)
@@ -277,10 +277,10 @@ static void DrawInfoScreen_NotAvailable(char *, char *);
 static void DrawInfoScreen_HelpAnim(int, int, boolean);
 static void DrawInfoScreen_HelpText(int, int, int, int);
 static void HandleInfoScreen_Main(int, int, int, int, int);
-static void HandleInfoScreen_TitleScreen(int);
-static void HandleInfoScreen_Elements(int);
-static void HandleInfoScreen_Music(int);
-static void HandleInfoScreen_Credits(int);
+static void HandleInfoScreen_TitleScreen(int, int, int);
+static void HandleInfoScreen_Elements(int, int, int);
+static void HandleInfoScreen_Music(int, int, int);
+static void HandleInfoScreen_Credits(int, int, int);
 static void HandleInfoScreen_Program(int);
 static void HandleInfoScreen_Version(int);
 
@@ -683,6 +683,13 @@ struct TitleControlInfo
 
 struct TitleControlInfo title_controls[MAX_NUM_TITLE_SCREENS];
 
+
+// credits screens definitions
+
+static int num_credits_screens = 0;
+static boolean use_global_credits_screens = FALSE;
+
+
 // main menu display and control definitions
 
 #define MAIN_CONTROL_NAME                      0
@@ -1688,8 +1695,6 @@ void DrawMainMenu(void)
   // store valid level series information
   leveldir_last_valid = leveldir_current;
 
-  init_last = init;                    // switch to new busy animation
-
   // needed if last screen (level choice) changed graphics, sounds or music
   ReloadCustomArtwork(0);
 
@@ -1920,7 +1925,7 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
   {
     return_to_main_menu = TRUE;
   }
-  else if (button == MB_MENU_CHOICE)
+  else if (button == MB_MENU_CHOICE || dx)
   {
     if (game_status_last_screen == GAME_MODE_INFO && num_title_screens == 0)
     {
@@ -1933,9 +1938,10 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
       return;
     }
 
-    title_screen_nr++;
+    title_screen_nr +=
+      (game_status_last_screen == GAME_MODE_INFO && dx < 0 ? -1 : +1);
 
-    if (title_screen_nr < num_title_screens)
+    if (title_screen_nr >= 0 && title_screen_nr < num_title_screens)
     {
       tci = &title_controls[title_screen_nr];
 
@@ -3092,9 +3098,9 @@ static void DrawInfoScreen_TitleScreen(void)
   DrawTitleScreen();
 }
 
-void HandleInfoScreen_TitleScreen(int button)
+void HandleInfoScreen_TitleScreen(int dx, int dy, int button)
 {
-  HandleTitleScreen(0, 0, 0, 0, button);
+  HandleTitleScreen(0, 0, dx, dy, button);
 }
 
 static void DrawInfoScreen_Elements(void)
@@ -3106,12 +3112,12 @@ static void DrawInfoScreen_Elements(void)
   LoadHelpAnimInfo();
   LoadHelpTextInfo();
 
-  HandleInfoScreen_Elements(MB_MENU_INITIALIZE);
+  HandleInfoScreen_Elements(0, 0, MB_MENU_INITIALIZE);
 
   FadeIn(REDRAW_FIELD);
 }
 
-void HandleInfoScreen_Elements(int button)
+void HandleInfoScreen_Elements(int dx, int dy, int button)
 {
   static unsigned int info_delay = 0;
   static int num_anims;
@@ -3150,16 +3156,16 @@ void HandleInfoScreen_Elements(int button)
 
     return;
   }
-  else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE)
+  else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE || dx)
   {
     if (button != MB_MENU_INITIALIZE)
     {
       PlaySound(SND_MENU_ITEM_SELECTING);
 
-      page++;
+      page += (dx < 0 ? -1 : +1);
     }
 
-    if (page >= num_pages)
+    if (page < 0 || page >= num_pages)
     {
       FadeMenuSoundsAndMusic();
 
@@ -3169,7 +3175,7 @@ void HandleInfoScreen_Elements(int button)
       return;
     }
 
-    if (page > 0)
+    if (button != MB_MENU_INITIALIZE)
       FadeSetNextScreen();
 
     if (button != MB_MENU_INITIALIZE)
@@ -3201,12 +3207,12 @@ static void DrawInfoScreen_Music(void)
 
   LoadMusicInfo();
 
-  HandleInfoScreen_Music(MB_MENU_INITIALIZE);
+  HandleInfoScreen_Music(0, 0, MB_MENU_INITIALIZE);
 
   FadeIn(REDRAW_FIELD);
 }
 
-void HandleInfoScreen_Music(int button)
+void HandleInfoScreen_Music(int dx, int dy, int button)
 {
   static struct MusicFileInfo *list = NULL;
   int font_title = MENU_INFO_FONT_TITLE;
@@ -3252,14 +3258,14 @@ void HandleInfoScreen_Music(int button)
 
     return;
   }
-  else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE)
+  else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE || dx)
   {
     if (button != MB_MENU_INITIALIZE)
     {
       PlaySound(SND_MENU_ITEM_SELECTING);
 
       if (list != NULL)
-       list = list->next;
+       list = (dx < 0 ? list->prev : list->next);
     }
 
     if (list == NULL)
@@ -3373,17 +3379,11 @@ void HandleInfoScreen_Music(int button)
 static void DrawInfoScreen_CreditsScreen(int screen_nr)
 {
   int font_title = MENU_INFO_FONT_TITLE;
-  int font_head  = MENU_INFO_FONT_HEAD;
   int font_text  = MENU_INFO_FONT_TEXT;
   int font_foot  = MENU_INFO_FONT_FOOT;
   int spacing_title = menu.headline1_spacing_info[info_mode];
-  int spacing_head  = menu.headline2_spacing_info[info_mode];
-  int spacing_para  = menu.paragraph_spacing_info[info_mode];
   int spacing_line  = menu.line_spacing_info[info_mode];
   int ystep_title = getMenuTextStep(spacing_title, font_title);
-  int ystep_head  = getMenuTextStep(spacing_head,  font_head);
-  int ystep_para  = getMenuTextStep(spacing_para,  font_text);
-  int ystep_line  = getMenuTextStep(spacing_line,  font_text);
   int ystart  = mSY - SY + MENU_SCREEN_INFO_YSTART1;
   int ybottom = mSY - SY + MENU_SCREEN_INFO_YBOTTOM;
 
@@ -3391,211 +3391,21 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr)
   DrawHeadline();
 
   DrawTextSCentered(ystart, font_title, "Credits:");
-  ystart += ystep_title;
 
-  if (screen_nr == 0)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Special thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Peter Liepa");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for creating");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "\"Boulder Dash\"");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "in the year");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "1984");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "published by");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "First Star Software");
-  }
-  else if (screen_nr == 1)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Special thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Klaus Heinz & Volker Wertich");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for creating");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "\"Emerald Mine\"");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "in the year");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "1987");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "published by");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Kingsoft");
-  }
-  else if (screen_nr == 2)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Special thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Michael Stopp & Philip Jespersen");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for creating");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "\"Supaplex\"");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "in the year");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "1991");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "published by");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Digital Integration");
-  }
-  else if (screen_nr == 3)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Special thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Hiroyuki Imabayashi");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for creating");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "\"Sokoban\"");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "in the year");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "1982");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "published by");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Thinking Rabbit");
-  }
-  else if (screen_nr == 4)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Special thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Alan Bond");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "and");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "J\xfcrgen Bonhagen");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for the continuous creation");
-    ystart += ystep_line;
-    DrawTextSCentered(ystart, font_head,
-                     "of outstanding level sets");
-  }
-  else if (screen_nr == 5)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Peter Elzner");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for ideas and inspiration by");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Diamond Caves");
-    ystart += ystep_para;
-
-    DrawTextSCentered(ystart, font_head,
-                     "Thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Steffest");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for ideas and inspiration by");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "DX-Boulderdash");
-  }
-  else if (screen_nr == 6)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "David Tritscher");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for the code base used for the");
-    ystart += ystep_line;
-    DrawTextSCentered(ystart, font_head,
-                     "native Emerald Mine engine");
-  }
-  else if (screen_nr == 7)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "Thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Guido Schulz");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for the initial DOS port");
-    ystart += ystep_para;
-
-    DrawTextSCentered(ystart, font_head,
-                     "Thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "Karl H\xf6rnell");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "for some additional toons");
-  }
-  else if (screen_nr == 8)
-  {
-    DrawTextSCentered(ystart, font_head,
-                     "And not to forget:");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_head,
-                     "Many thanks to");
-    ystart += ystep_head;
-    DrawTextSCentered(ystart, font_text,
-                     "All those who contributed");
-    ystart += ystep_line;
-    DrawTextSCentered(ystart, font_text,
-                     "levels to this game");
-    ystart += ystep_line;
-    DrawTextSCentered(ystart, font_text,
-                     "since 1995");
-  }
+  char *filename = getCreditsFilename(screen_nr, use_global_credits_screens);
+  int width = SXSIZE;
+  int height = MENU_SCREEN_INFO_YBOTTOM - MENU_SCREEN_INFO_YSTART1;
+  int chars = width / getFontWidth(font_text);
+  int lines = height / getFontHeight(font_text);
+  int padx = (width - chars * getFontWidth(font_text)) / 2;
+  int line_spacing = getMenuTextSpacing(spacing_line, font_text);
+  boolean autowrap = FALSE;
+  boolean centered = TRUE;
+  boolean parse_comments = TRUE;
+
+  DrawTextFile(mSX + padx, mSY + MENU_SCREEN_INFO_YSTART1 + ystep_title,
+              filename, font_text, chars, -1, lines, line_spacing, -1,
+              autowrap, centered, parse_comments);
 
   DrawTextSCentered(ybottom, font_foot,
                    "Press any key or button for next page");
@@ -3609,24 +3419,57 @@ static void DrawInfoScreen_Credits(void)
 
   FadeOut(REDRAW_FIELD);
 
-  HandleInfoScreen_Credits(MB_MENU_INITIALIZE);
+  HandleInfoScreen_Credits(0, 0, MB_MENU_INITIALIZE);
 
   FadeIn(REDRAW_FIELD);
 }
 
-void HandleInfoScreen_Credits(int button)
+void HandleInfoScreen_Credits(int dx, int dy, int button)
 {
   static int screen_nr = 0;
-  int num_screens = 9;
 
   if (button == MB_MENU_INITIALIZE)
   {
+    int i;
+
+    // determine number of (global or level set specific) credits screens
+    for (i = 0; i < 2; i++)
+    {
+      num_credits_screens = 0;
+      use_global_credits_screens = i;
+
+      while (getCreditsFilename(num_credits_screens,
+                               use_global_credits_screens) != NULL)
+       num_credits_screens++;
+
+      if (num_credits_screens > 0)
+       break;
+    }
+
+    if (num_credits_screens == 0)
+    {
+      int font_title = MENU_INFO_FONT_TITLE;
+      int font_foot  = MENU_INFO_FONT_FOOT;
+      int ystart  = mSY - SY + MENU_SCREEN_INFO_YSTART1;
+      int ybottom = mSY - SY + MENU_SCREEN_INFO_YBOTTOM;
+
+      ClearField();
+      DrawHeadline();
+
+      DrawTextSCentered(ystart, font_title,
+                       "No credits for this level set.");
+
+      DrawTextSCentered(ybottom, font_foot,
+                       "Press any key or button for info menu");
+
+      return;
+    }
+
     screen_nr = 0;
 
-    // DrawInfoScreen_CreditsScreen(screen_nr);
+    DrawInfoScreen_CreditsScreen(screen_nr);
   }
-
-  if (button == MB_MENU_LEAVE)
+  else if (button == MB_MENU_LEAVE)
   {
     PlaySound(SND_MENU_ITEM_SELECTING);
 
@@ -3635,16 +3478,13 @@ void HandleInfoScreen_Credits(int button)
 
     return;
   }
-  else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE)
+  else if (button == MB_MENU_CHOICE || dx)
   {
-    if (button != MB_MENU_INITIALIZE)
-    {
-      PlaySound(SND_MENU_ITEM_SELECTING);
+    PlaySound(SND_MENU_ITEM_SELECTING);
 
-      screen_nr++;
-    }
+    screen_nr += (dx < 0 ? -1 : +1);
 
-    if (screen_nr >= num_screens)
+    if (screen_nr < 0 || screen_nr >= num_credits_screens)
     {
       FadeMenuSoundsAndMusic();
 
@@ -3654,16 +3494,13 @@ void HandleInfoScreen_Credits(int button)
       return;
     }
 
-    if (screen_nr > 0)
-      FadeSetNextScreen();
+    FadeSetNextScreen();
 
-    if (button != MB_MENU_INITIALIZE)
-      FadeOut(REDRAW_FIELD);
+    FadeOut(REDRAW_FIELD);
 
     DrawInfoScreen_CreditsScreen(screen_nr);
 
-    if (button != MB_MENU_INITIALIZE)
-      FadeIn(REDRAW_FIELD);
+    FadeIn(REDRAW_FIELD);
   }
   else
   {
@@ -4069,13 +3906,13 @@ static void DrawInfoScreen(void)
 void HandleInfoScreen(int mx, int my, int dx, int dy, int button)
 {
   if (info_mode == INFO_MODE_TITLE)
-    HandleInfoScreen_TitleScreen(button);
+    HandleInfoScreen_TitleScreen(dx, dy, button);
   else if (info_mode == INFO_MODE_ELEMENTS)
-    HandleInfoScreen_Elements(button);
+    HandleInfoScreen_Elements(dx, dy, button);
   else if (info_mode == INFO_MODE_MUSIC)
-    HandleInfoScreen_Music(button);
+    HandleInfoScreen_Music(dx, dy, button);
   else if (info_mode == INFO_MODE_CREDITS)
-    HandleInfoScreen_Credits(button);
+    HandleInfoScreen_Credits(dx, dy, button);
   else if (info_mode == INFO_MODE_PROGRAM)
     HandleInfoScreen_Program(button);
   else if (info_mode == INFO_MODE_VERSION)
@@ -4835,6 +4672,8 @@ static int getAlignYOffsetFromTreeInfo(TreeInfo *ti)
 static void DrawChooseTree(TreeInfo **ti_ptr)
 {
   int fade_mask = REDRAW_FIELD;
+  boolean restart_music = (game_status != game_status_last_screen &&
+                          game_status_last_screen != GAME_MODE_SCOREINFO);
 
   if (CheckFadeAll())
     fade_mask = REDRAW_ALL;
@@ -4860,7 +4699,7 @@ static void DrawChooseTree(TreeInfo **ti_ptr)
   FreeScreenGadgets();
   CreateScreenGadgets();
 
-  if (game_status != game_status_last_screen)
+  if (restart_music)
     FadeMenuSoundsAndMusic();
 
   FadeOut(fade_mask);
@@ -4891,7 +4730,7 @@ static void DrawChooseTree(TreeInfo **ti_ptr)
 
   DrawMaskedBorder(fade_mask);
 
-  if (game_status != game_status_last_screen)
+  if (restart_music)
     PlayMenuSoundsAndMusic();
 
   FadeIn(fade_mask);
@@ -4943,7 +4782,7 @@ static void drawChooseTreeText(TreeInfo *ti, int y, boolean active)
     int border = amSX - SX + getFontDrawOffsetX(font_nr1);
     int dx1 = 0;
     int dx3 = text_size_1;
-    int dx4 = screen_width - startdx - 2 * border - text_size_4;
+    int dx4 = SXSIZE - 2 * startdx - 2 * border - text_size_4;
     int num_dots = (dx4 - dx3) / font_size_3;
     int startx1 = startx + dx1;
     int startx3 = startx + dx3;
@@ -5114,8 +4953,13 @@ static void drawChooseTreeScreen_Scores_NotAvailable(void)
 
 static TreeInfo *setHallOfFameActiveEntry(TreeInfo **ti_ptr)
 {
+  int score_pos = scores.last_added;
+
+  if (game_status_last_screen == GAME_MODE_SCOREINFO)
+    score_pos = scores.last_entry_nr;
+
   // set current tree entry to last added score entry
-  *ti_ptr = getTreeInfoFromIdentifier(score_entries, i_to_a(scores.last_added));
+  *ti_ptr = getTreeInfoFromIdentifier(score_entries, i_to_a(score_pos));
 
   // if that fails, set current tree entry to first entry (back link)
   if (*ti_ptr == NULL)
@@ -5710,6 +5554,9 @@ void HandleChooseLevelNr(int mx, int my, int dx, int dy, int button)
 
 static void DrawHallOfFame_setScoreEntries(void)
 {
+  int max_empty_entries = 10;  // at least show "top ten" list, if empty
+  int max_visible_entries = NUM_MENU_ENTRIES_ON_SCREEN - 1;   // w/o back link
+  int min_score_entries = MIN(max_empty_entries, max_visible_entries);
   int score_pos = (scores.last_added >= 0 ? scores.last_added : 0);
   int i;
 
@@ -5722,9 +5569,10 @@ static void DrawHallOfFame_setScoreEntries(void)
 
   for (i = 0; i < MAX_SCORE_ENTRIES; i++)
   {
-    // do not add empty score entries
+    // do not add empty score entries if off-screen
     if (scores.entry[i].score == 0 &&
-       scores.entry[i].time == 0)
+       scores.entry[i].time == 0 &&
+       i >= min_score_entries)
       break;
 
     TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_SCORE_ENTRY);
@@ -5837,6 +5685,7 @@ static void HandleHallOfFame_SelectLevel(int step, int direction)
     PlaySound(SND_MENU_ITEM_SELECTING);
 
     scores.last_level_nr = level_nr = new_level_nr;
+    scores.last_entry_nr = 0;
 
     LoadLevel(level_nr);
     LoadLocalAndServerScore(level_nr, TRUE);
@@ -5858,8 +5707,6 @@ static void HandleHallOfFame_SelectLevel(int step, int direction)
     }
     else
     {
-      scores.last_entry_nr = 0;
-
       DrawScoreInfo_Content(scores.last_entry_nr);
     }