X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fscreens.c;h=7a6bfe41b9fff219d2430bec383145f9f6d53a38;hb=d0c5c90b881c5764e2da6ca4ff7e5bc66f9a5913;hp=4c361ae4d84b5550c83d82ec1124137f10f7149a;hpb=0e7f11a759f663c364fa0d2c42e77f7d301b25b2;p=rocksndiamonds.git diff --git a/src/screens.c b/src/screens.c index 4c361ae4..7a6bfe41 100644 --- a/src/screens.c +++ b/src/screens.c @@ -184,26 +184,32 @@ // screen gadget identifiers #define SCREEN_CTRL_ID_PREV_LEVEL 0 #define SCREEN_CTRL_ID_NEXT_LEVEL 1 -#define SCREEN_CTRL_ID_FIRST_LEVEL 2 -#define SCREEN_CTRL_ID_LAST_LEVEL 3 -#define SCREEN_CTRL_ID_LEVEL_NUMBER 4 -#define SCREEN_CTRL_ID_PREV_PLAYER 5 -#define SCREEN_CTRL_ID_NEXT_PLAYER 6 -#define SCREEN_CTRL_ID_INSERT_SOLUTION 7 -#define SCREEN_CTRL_ID_PLAY_SOLUTION 8 -#define SCREEN_CTRL_ID_SWITCH_ECS_AGA 9 -#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE 10 -#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE 11 -#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE2 12 -#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE2 13 -#define SCREEN_CTRL_ID_SCROLL_UP 14 -#define SCREEN_CTRL_ID_SCROLL_DOWN 15 -#define SCREEN_CTRL_ID_SCROLL_VERTICAL 16 -#define SCREEN_CTRL_ID_NETWORK_SERVER 17 - -#define NUM_SCREEN_GADGETS 18 - -#define NUM_SCREEN_MENUBUTTONS 14 +#define SCREEN_CTRL_ID_PREV_LEVEL2 2 +#define SCREEN_CTRL_ID_NEXT_LEVEL2 3 +#define SCREEN_CTRL_ID_PREV_SCORE 4 +#define SCREEN_CTRL_ID_NEXT_SCORE 5 +#define SCREEN_CTRL_ID_FIRST_LEVEL 6 +#define SCREEN_CTRL_ID_LAST_LEVEL 7 +#define SCREEN_CTRL_ID_LEVEL_NUMBER 8 +#define SCREEN_CTRL_ID_PREV_PLAYER 9 +#define SCREEN_CTRL_ID_NEXT_PLAYER 10 +#define SCREEN_CTRL_ID_INSERT_SOLUTION 11 +#define SCREEN_CTRL_ID_PLAY_SOLUTION 12 +#define SCREEN_CTRL_ID_SWITCH_ECS_AGA 13 +#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE 14 +#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE 15 +#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE2 16 +#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE2 17 + +#define NUM_SCREEN_MENUBUTTONS 18 + +#define SCREEN_CTRL_ID_SCROLL_UP 18 +#define SCREEN_CTRL_ID_SCROLL_DOWN 19 +#define SCREEN_CTRL_ID_SCROLL_VERTICAL 20 +#define SCREEN_CTRL_ID_NETWORK_SERVER 21 + +#define NUM_SCREEN_GADGETS 22 + #define NUM_SCREEN_SCROLLBUTTONS 2 #define NUM_SCREEN_SCROLLBARS 1 #define NUM_SCREEN_TEXTINPUT 1 @@ -213,6 +219,8 @@ #define SCREEN_MASK_INPUT (1 << 2) #define SCREEN_MASK_TOUCH (1 << 3) #define SCREEN_MASK_TOUCH2 (1 << 4) +#define SCREEN_MASK_SCORES (1 << 5) +#define SCREEN_MASK_SCORES_INFO (1 << 6) // graphic position and size values for buttons and scrollbars #define SC_MENUBUTTON_XSIZE TILEX @@ -259,6 +267,8 @@ static void HandleChooseTree(int, int, int, int, int, TreeInfo **); static void DrawChoosePlayerName(void); static void DrawChooseLevelSet(void); static void DrawChooseLevelNr(void); +static void DrawScoreInfo(int); +static void DrawScoreInfo_Content(int); static void DrawInfoScreen(void); static void DrawSetupScreen(void); static void DrawTypeName(void); @@ -267,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); @@ -286,12 +296,15 @@ static void MapScreenTreeGadgets(TreeInfo *); static void UnmapScreenTreeGadgets(void); static void UpdateScreenMenuGadgets(int, boolean); +static void AdjustScoreInfoButtons(int, int, int); static boolean OfferUploadTapes(void); static void execOfferUploadTapes(void); static void DrawHallOfFame_setScoreEntries(void); -static char *getHallOfFameScoreText(int); +static void HandleHallOfFame_SelectLevel(int, int); +static char *getHallOfFameRankText(int, int); +static char *getHallOfFameScoreText(int, int); static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS]; @@ -615,6 +628,8 @@ static int align_yoffset = 0; #define EXTRA_SPACING_SCORES(i) (EXTRA_SPACING_INFO(i)) +#define EXTRA_SPACING_SCOREINFO(i) (menu.extra_spacing[GAME_MODE_SCOREINFO]) + #define DRAW_XOFFSET(s) ((s) == GAME_MODE_INFO ? \ DRAW_XOFFSET_INFO(info_mode) : \ (s) == GAME_MODE_SETUP ? \ @@ -668,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 @@ -1673,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); @@ -1905,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) { @@ -1918,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]; @@ -3077,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) @@ -3091,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; @@ -3135,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(); @@ -3154,7 +3175,7 @@ void HandleInfoScreen_Elements(int button) return; } - if (page > 0) + if (button != MB_MENU_INITIALIZE) FadeSetNextScreen(); if (button != MB_MENU_INITIALIZE) @@ -3186,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; @@ -3237,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) @@ -3358,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; @@ -3376,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"); @@ -3594,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); @@ -3620,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(); @@ -3639,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 { @@ -4054,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) @@ -4820,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; @@ -4845,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); @@ -4866,12 +4720,17 @@ static void DrawChooseTree(TreeInfo **ti_ptr) OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + // map gadgets for high score screen + if (game_status == GAME_MODE_SCORES) + MapScreenMenuGadgets(SCREEN_MASK_SCORES); + MapScreenTreeGadgets(*ti_ptr); + HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr); DrawMaskedBorder(fade_mask); - if (game_status != game_status_last_screen) + if (restart_music) PlayMenuSoundsAndMusic(); FadeIn(fade_mask); @@ -4918,34 +4777,29 @@ static void drawChooseTreeText(TreeInfo *ti, int y, boolean active) int font_size_1 = getFontWidth(font_nr1); int font_size_3 = getFontWidth(font_nr3); int font_size_4 = getFontWidth(font_nr4); - int text_size_1 = 3 * font_size_1; + int text_size_1 = 4 * font_size_1; int text_size_4 = 5 * font_size_4; int border = amSX - SX + getFontDrawOffsetX(font_nr1); int dx1 = 0; - int dx2 = text_size_1; - int dx3 = dx2 + font_size_1; - int dx4 = screen_width - startdx - 2 * border - text_size_4; + int dx3 = text_size_1; + int dx4 = SXSIZE - 2 * startdx - 2 * border - text_size_4; int num_dots = (dx4 - dx3) / font_size_3; int startx1 = startx + dx1; - int startx2 = startx + dx2; int startx3 = startx + dx3; int startx4 = startx + dx4; int pos = node->pos; - boolean forced = (scores.force_last_added && pos == scores.last_added); - char *pos_text = (forced ? "???" : int2str(pos + 1, 3)); - char *dot_text = "."; + char *pos_text = getHallOfFameRankText(pos, 3); int i; DrawText(startx1, starty, pos_text, font_nr1); - DrawText(startx2, starty, dot_text, font_nr1); for (i = 0; i < num_dots; i++) - DrawText(startx3 + i * font_size_3, starty, dot_text, font_nr3); + DrawText(startx3 + i * font_size_3, starty, ".", font_nr3); if (!strEqual(scores.entry[pos].name, EMPTY_PLAYER_NAME)) DrawText(startx3, starty, scores.entry[pos].name, font_nr2); - DrawText(startx4, starty, getHallOfFameScoreText(pos), font_nr4); + DrawText(startx4, starty, getHallOfFameScoreText(pos, 5), font_nr4); } else { @@ -5099,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) @@ -5133,6 +4992,9 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, int num_entries = numTreeInfoInGroup(ti); int num_page_entries = MIN(num_entries, NUM_MENU_ENTRIES_ON_SCREEN); boolean position_set_by_scrollbar = (dx == 999); + boolean button_action = (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE); + boolean button_is_valid = (mx >= 0 && my >= 0); + boolean button_screen_clicked = (button_action && button_is_valid); if (game_status == GAME_MODE_SCORES) { @@ -5160,7 +5022,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, { drawChooseTreeScreen_Scores_NotAvailable(); } - else if (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE) + else if (button_screen_clicked) { PlaySound(SND_MENU_ITEM_SELECTING); @@ -5322,7 +5184,13 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, y = ti->cl_cursor + dy; } - if (dx == 1) + if (game_status == GAME_MODE_SCORES && ABS(dx) == 1) + { + HandleHallOfFame_SelectLevel(1, dx); + + return; + } + else if (dx == 1) { TreeInfo *node_first, *node_cursor; int entry_pos = ti->cl_first + y; @@ -5546,6 +5414,14 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, level.random_seed); return; } + else + { + SetGameStatus(GAME_MODE_SCOREINFO); + + DrawScoreInfo(node_cursor->pos); + + return; + } } SetGameStatus(GAME_MODE_MAIN); @@ -5678,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; @@ -5690,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); @@ -5754,14 +5634,19 @@ void DrawHallOfFame(int level_nr) DrawChooseTree(&score_entry_current); } -static char *getHallOfFameScoreText(int nr) +static char *getHallOfFameRankText(int nr, int size) { - if (!level.rate_time_over_score) - return int2str(scores.entry[nr].score, 5); // show normal score + static char rank_text[10]; + boolean forced = (scores.force_last_added && nr == scores.last_added); + char *rank_text_raw = (forced ? "???" : int2str(nr + 1, size)); - if (level.use_step_counter) - return int2str(scores.entry[nr].time, 5); // show number of steps + sprintf(rank_text, "%s%s", rank_text_raw, (size > 0 || !forced ? "." : "")); + return rank_text; +} + +static char *getHallOfFameTimeText(int nr) +{ static char score_text[10]; int time_seconds = scores.entry[nr].time / FRAMES_PER_SECOND; int mm = (time_seconds / 60) % 60; @@ -5772,11 +5657,259 @@ static char *getHallOfFameScoreText(int nr) return score_text; } +static char *getHallOfFameScoreText(int nr, int size) +{ + if (!level.rate_time_over_score) + return int2str(scores.entry[nr].score, size); // show normal score + else if (level.use_step_counter) + return int2str(scores.entry[nr].time, size); // show number of steps + else + return getHallOfFameTimeText(nr); // show playing time +} + +static void HandleHallOfFame_SelectLevel(int step, int direction) +{ + int old_level_nr = scores.last_level_nr; + int new_level_nr = old_level_nr + step * direction; + + if (new_level_nr < leveldir_current->first_level) + new_level_nr = leveldir_current->first_level; + if (new_level_nr > leveldir_current->last_level) + new_level_nr = leveldir_current->last_level; + + if (setup.handicap && new_level_nr > leveldir_current->handicap_level) + new_level_nr = leveldir_current->handicap_level; + + if (new_level_nr != old_level_nr) + { + 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); + + DrawHallOfFame_setScoreEntries(); + + if (game_status == GAME_MODE_SCORES) + { + // force remapping optional gadgets (especially scroll bar) + UnmapScreenTreeGadgets(); + + // redraw complete high score screen, as sub-title has changed + ClearField(); + + // redraw level selection buttons (which have just been erased) + RedrawScreenMenuGadgets(SCREEN_MASK_SCORES); + + HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, &score_entry_current); + } + else + { + DrawScoreInfo_Content(scores.last_entry_nr); + } + + SaveLevelSetup_SeriesInfo(); + } +} + void HandleHallOfFame(int mx, int my, int dx, int dy, int button) { HandleChooseTree(mx, my, dx, dy, button, &score_entry_current); } +static void DrawScoreInfo_Content(int entry_nr) +{ + struct ScoreEntry *entry = &scores.entry[entry_nr]; + char *pos_text = getHallOfFameRankText(entry_nr, 0); + 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[GAME_MODE_SCOREINFO]; + int spacing_para = menu.paragraph_spacing[GAME_MODE_SCOREINFO]; + int spacing_line = menu.line_spacing[GAME_MODE_SCOREINFO]; + int xstep = getFontWidth(font_text); + int ystep_title = getMenuTextStep(spacing_title, font_title); + int ystep_para = getMenuTextStep(spacing_para, font_text); + int ystep_line = getMenuTextStep(spacing_line, font_text); + int ystart = mSY - SY + menu.top_spacing[GAME_MODE_SCOREINFO]; + int ybottom = mSY - SY + SYSIZE - menu.bottom_spacing[GAME_MODE_SCOREINFO]; + int xstart1 = mSX - SX + 2 * xstep; + int xstart2 = mSX - SX + 13 * xstep; + int button_x = SX + xstart1; + int button_y1, button_y2; + int font_width = getFontWidth(font_text); + int font_height = getFontHeight(font_text); + int pad_left = xstart2; + int pad_right = MENU_SCREEN_INFO_SPACE_RIGHT; + int max_chars_per_line = (SXSIZE - pad_left - pad_right) / font_width; + int max_lines_per_text = 5; + int lines; + + ClearField(); + + // redraw score selection buttons (which have just been erased) + RedrawScreenMenuGadgets(SCREEN_MASK_SCORES); + + if (score_entries == NULL) + { + drawChooseTreeScreen_Scores_NotAvailable(); + + return; + } + + drawChooseTreeHead(score_entries); + drawChooseTreeInfo(score_entries); + + DrawTextSCentered(ystart, font_title, "Score Information:"); + ystart += ystep_title; + + DrawTextF(xstart1, ystart, font_head, "Level Set"); + lines = DrawTextBufferS(xstart2, ystart, leveldir_current->name, font_text, + max_chars_per_line, -1, max_lines_per_text, 0, -1, + TRUE, FALSE, FALSE); + ystart += ystep_line + (lines > 0 ? lines - 1 : 0) * font_height; + + DrawTextF(xstart1, ystart, font_head, "Level"); + lines = DrawTextBufferS(xstart2, ystart, level.name, font_text, + max_chars_per_line, -1, max_lines_per_text, 0, -1, + TRUE, FALSE, FALSE); + ystart += ystep_para + (lines > 0 ? lines - 1 : 0) * font_height; + + button_y1 = SY + ystart; + ystart += graphic_info[IMG_MENU_BUTTON_PREV_SCORE].height; + + DrawTextF(xstart1, ystart, font_head, "Rank"); + DrawTextF(xstart2, ystart, font_text, pos_text); + ystart += ystep_line; + + DrawTextF(xstart1, ystart, font_head, "Player"); + DrawTextF(xstart2, ystart, font_text, entry->name); + ystart += ystep_line; + + if (level.use_step_counter) + { + DrawTextF(xstart1, ystart, font_head, "Steps"); + DrawTextF(xstart2, ystart, font_text, int2str(entry->time, 5)); + ystart += ystep_line; + } + else + { + DrawTextF(xstart1, ystart, font_head, "Time"); + DrawTextF(xstart2, ystart, font_text, getHallOfFameTimeText(entry_nr)); + ystart += ystep_line; + } + + if (!level.rate_time_over_score || entry->score > 0) + { + DrawTextF(xstart1, ystart, font_head, "Score"); + DrawTextF(xstart2, ystart, font_text, int2str(entry->score, 5)); + ystart += ystep_line; + } + + ystart += ystep_line; + + DrawTextF(xstart1, ystart, font_head, "Tape Date"); + DrawTextF(xstart2, ystart, font_text, entry->tape_date); + ystart += ystep_line; + + DrawTextF(xstart1, ystart, font_head, "Platform"); + DrawTextF(xstart2, ystart, font_text, entry->platform); + ystart += ystep_line; + + DrawTextF(xstart1, ystart, font_head, "Version"); + DrawTextF(xstart2, ystart, font_text, entry->version); + ystart += ystep_line; + + DrawTextF(xstart1, ystart, font_head, "Country"); + lines = DrawTextBufferS(xstart2, ystart, entry->country_name, font_text, + max_chars_per_line, -1, max_lines_per_text, 0, -1, + TRUE, FALSE, FALSE); + ystart += ystep_line; + + button_y2 = SY + ystart; + + DrawTextSCentered(ybottom, font_foot, "Press any key or button to go back"); + + AdjustScoreInfoButtons(button_x, button_y1, button_y2); +} + +static void DrawScoreInfo(int entry_nr) +{ + scores.last_entry_nr = entry_nr; + + SetMainBackgroundImageIfDefined(IMG_BACKGROUND_SCOREINFO); + + UnmapAllGadgets(); + + FadeOut(REDRAW_FIELD); + + DrawScoreInfo_Content(entry_nr); + + // map gadgets for score info screen + MapScreenMenuGadgets(SCREEN_MASK_SCORES_INFO); + + FadeIn(REDRAW_FIELD); +} + +static void HandleScoreInfo_SelectScore(int step, int direction) +{ + int old_entry_nr = scores.last_entry_nr; + int new_entry_nr = old_entry_nr + step * direction; + int num_nodes = numTreeInfoInGroup(score_entry_current); + int num_entries = num_nodes - 1; // score nodes only, without back link + + if (new_entry_nr < 0) + new_entry_nr = 0; + if (new_entry_nr > num_entries - 1) + new_entry_nr = num_entries - 1; + + if (new_entry_nr != old_entry_nr) + { + scores.last_entry_nr = new_entry_nr; + + DrawScoreInfo_Content(new_entry_nr); + } +} + +void HandleScoreInfo(int mx, int my, int dx, int dy, int button) +{ + boolean button_action = (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE); + boolean button_is_valid = (mx >= 0 && my >= 0); + boolean button_screen_clicked = (button_action && button_is_valid); + + if (server_scores.updated) + { + // reload scores, using updated server score cache file + LoadLocalAndServerScore(scores.last_level_nr, FALSE); + + server_scores.updated = FALSE; + + DrawHallOfFame_setScoreEntries(); + + DrawScoreInfo_Content(scores.last_entry_nr); + } + + if (button_screen_clicked) + { + PlaySound(SND_MENU_ITEM_SELECTING); + + SetGameStatus(GAME_MODE_SCORES); + + DrawHallOfFame(level_nr); + } + else if (dx) + { + HandleHallOfFame_SelectLevel(1, SIGN(dx) * (ABS(dx) > 1 ? 10 : 1)); + } + else if (dy) + { + HandleScoreInfo_SelectScore(1, SIGN(dy) * (ABS(dy) > 1 ? 10 : 1)); + } +} + // ============================================================================ // setup screen functions @@ -9608,6 +9741,38 @@ static struct GD_EVENT_PRESSED | GD_EVENT_REPEATED, FALSE, "next level" }, + { + IMG_MENU_BUTTON_PREV_LEVEL2, IMG_MENU_BUTTON_PREV_LEVEL2_ACTIVE, + &menu.scores.button.prev_level, NULL, + SCREEN_CTRL_ID_PREV_LEVEL2, + SCREEN_MASK_SCORES | SCREEN_MASK_SCORES_INFO, + GD_EVENT_PRESSED | GD_EVENT_REPEATED, + FALSE, "previous level" + }, + { + IMG_MENU_BUTTON_NEXT_LEVEL2, IMG_MENU_BUTTON_NEXT_LEVEL2_ACTIVE, + &menu.scores.button.next_level, NULL, + SCREEN_CTRL_ID_NEXT_LEVEL2, + SCREEN_MASK_SCORES | SCREEN_MASK_SCORES_INFO, + GD_EVENT_PRESSED | GD_EVENT_REPEATED, + FALSE, "next level" + }, + { + IMG_MENU_BUTTON_PREV_SCORE, IMG_MENU_BUTTON_PREV_SCORE_ACTIVE, + &menu.scores.button.prev_score, NULL, + SCREEN_CTRL_ID_PREV_SCORE, + SCREEN_MASK_SCORES_INFO, + GD_EVENT_PRESSED | GD_EVENT_REPEATED, + FALSE, "previous score" + }, + { + IMG_MENU_BUTTON_NEXT_SCORE, IMG_MENU_BUTTON_NEXT_SCORE_ACTIVE, + &menu.scores.button.next_score, NULL, + SCREEN_CTRL_ID_NEXT_SCORE, + SCREEN_MASK_SCORES_INFO, + GD_EVENT_PRESSED | GD_EVENT_REPEATED, + FALSE, "next score" + }, { IMG_MENU_BUTTON_FIRST_LEVEL, IMG_MENU_BUTTON_FIRST_LEVEL_ACTIVE, &menu.main.button.first_level, NULL, @@ -9777,8 +9942,10 @@ static void CreateScreenMenubuttons(void) for (i = 0; i < NUM_SCREEN_MENUBUTTONS; i++) { struct MenuPosInfo *pos = menubutton_info[i].pos; + int screen_mask = menubutton_info[i].screen_mask; boolean is_touch_button = menubutton_info[i].is_touch_button; boolean is_check_button = menubutton_info[i].check_value != NULL; + boolean is_score_button = (screen_mask & SCREEN_MASK_SCORES_INFO); Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed; int gfx_unpressed, gfx_pressed; int x, y, width, height; @@ -9826,6 +9993,22 @@ static void CreateScreenMenubuttons(void) checked = *menubutton_info[i].check_value; } + if (is_score_button) + { + // if x/y set to -1, dynamically place buttons next to title text + int title_width = getTextWidth(INFOTEXT_SCORE_ENTRY, FONT_TITLE_1); + + if (pos->x == -1) + x = (id == SCREEN_CTRL_ID_PREV_LEVEL2 ? + SX + (SXSIZE - title_width) / 2 - width * 3 / 2 : + id == SCREEN_CTRL_ID_NEXT_LEVEL2 ? + SX + (SXSIZE + title_width) / 2 + width / 2 : 0); + + if (pos->y == -1) + y = (id == SCREEN_CTRL_ID_PREV_LEVEL2 || + id == SCREEN_CTRL_ID_NEXT_LEVEL2 ? mSY + MENU_TITLE1_YPOS : 0); + } + gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_CUSTOM_TYPE_ID, i, GDI_IMAGE_ID, gfx_unpressed, @@ -10147,6 +10330,20 @@ static void UnmapScreenTreeGadgets(void) UnmapScreenGadgets(); } +static void AdjustScoreInfoButtons(int x, int y1, int y2) +{ + struct GadgetInfo *gi_1 = screen_gadget[SCREEN_CTRL_ID_PREV_SCORE]; + struct GadgetInfo *gi_2 = screen_gadget[SCREEN_CTRL_ID_NEXT_SCORE]; + struct MenuPosInfo *pos_1 = menubutton_info[SCREEN_CTRL_ID_PREV_SCORE].pos; + struct MenuPosInfo *pos_2 = menubutton_info[SCREEN_CTRL_ID_NEXT_SCORE].pos; + + if (pos_1->x == -1 && pos_1->y == -1) + ModifyGadget(gi_1, GDI_X, x, GDI_Y, y1, GDI_END); + + if (pos_2->x == -1 && pos_2->y == -1) + ModifyGadget(gi_2, GDI_X, x, GDI_Y, y2, GDI_END); +} + static void HandleScreenGadgets(struct GadgetInfo *gi) { int id = gi->custom_id; @@ -10165,6 +10362,22 @@ static void HandleScreenGadgets(struct GadgetInfo *gi) HandleMainMenu_SelectLevel(step, +1, NO_DIRECT_LEVEL_SELECT); break; + case SCREEN_CTRL_ID_PREV_LEVEL2: + HandleHallOfFame_SelectLevel(step, -1); + break; + + case SCREEN_CTRL_ID_NEXT_LEVEL2: + HandleHallOfFame_SelectLevel(step, +1); + break; + + case SCREEN_CTRL_ID_PREV_SCORE: + HandleScoreInfo_SelectScore(step, -1); + break; + + case SCREEN_CTRL_ID_NEXT_SCORE: + HandleScoreInfo_SelectScore(step, +1); + break; + case SCREEN_CTRL_ID_FIRST_LEVEL: HandleMainMenu_SelectLevel(MAX_LEVELS, -1, NO_DIRECT_LEVEL_SELECT); break;