#include "network.h"
#include "init.h"
#include "config.h"
+#include "api.h"
#define DEBUG_JOYSTICKS 0
#define MENU_CHOOSE_TREE_FONT(x) (FONT_TEXT_1 + (x))
#define MENU_CHOOSE_TREE_COLOR(ti, a) TREE_COLOR(ti, a)
+#define TEXT_NEXT_PAGE "Press any key or button for next page"
+#define TEXT_INFO_MENU "Press any key or button for info menu"
+
// for input setup functions
#define SETUPINPUT_SCREEN_POS_START 0
#define SETUPINPUT_SCREEN_POS_EMPTY1 3
#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 SCREEN_CTRL_ID_PLAY_TAPE 6
+#define SCREEN_CTRL_ID_FIRST_LEVEL 7
+#define SCREEN_CTRL_ID_LAST_LEVEL 8
+#define SCREEN_CTRL_ID_LEVEL_NUMBER 9
+#define SCREEN_CTRL_ID_PREV_PLAYER 10
+#define SCREEN_CTRL_ID_NEXT_PLAYER 11
+#define SCREEN_CTRL_ID_INSERT_SOLUTION 12
+#define SCREEN_CTRL_ID_PLAY_SOLUTION 13
+#define SCREEN_CTRL_ID_SWITCH_ECS_AGA 14
+#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE 15
+#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE 16
+#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE2 17
+#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE2 18
+
+#define NUM_SCREEN_MENUBUTTONS 19
+
+#define SCREEN_CTRL_ID_SCROLL_UP 19
+#define SCREEN_CTRL_ID_SCROLL_DOWN 20
+#define SCREEN_CTRL_ID_SCROLL_VERTICAL 21
+#define SCREEN_CTRL_ID_NETWORK_SERVER 22
+
+#define NUM_SCREEN_GADGETS 23
#define NUM_SCREEN_SCROLLBUTTONS 2
#define NUM_SCREEN_SCROLLBARS 1
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_Program(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, int, int);
static void HandleInfoScreen_Version(int);
static void ModifyGameSpeedIfNeeded(void);
static void UnmapScreenTreeGadgets(void);
static void UpdateScreenMenuGadgets(int, boolean);
-static void AdjustScoreInfoButtons(int, int, int);
+static void AdjustScoreInfoButtons_SelectScore(int, int, int);
+static void AdjustScoreInfoButtons_PlayTape(int, int, boolean);
static boolean OfferUploadTapes(void);
static void execOfferUploadTapes(void);
static char *getHallOfFameRankText(int, int);
static char *getHallOfFameScoreText(int, int);
+static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *);
+
static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
static int info_mode = INFO_MODE_MAIN;
struct TitleControlInfo title_controls[MAX_NUM_TITLE_SCREENS];
+
+// credits screens definitions
+
+static int num_credits_screens = 0;
+static boolean use_global_credits_screens = FALSE;
+
+
+// program info screens definitions
+
+static int num_program_info_screens = 0;
+
+
// main menu display and control definitions
#define MAIN_CONTROL_NAME 0
// clear menu list area, but not title or scrollbar
DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
+
+ // special compatibility handling for "Snake Bite" graphics set
+ if (strPrefix(leveldir_current->identifier, "snake_bite"))
+ ClearRectangle(drawto, mSX, mSY + MENU_SCREEN_START_YPOS * 32,
+ scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
}
static void drawCursorExt(int xpos, int ypos, boolean active, int graphic)
return sy;
}
+static int getChooseTreeEditXPosReal(int pos)
+{
+ int xpos = getChooseTreeEditXPos(pos);
+ int font_nr = getChooseTreeEditFont(FALSE);
+ int font_xoffset = getFontDrawOffsetX(font_nr);
+
+ return xpos + font_xoffset;
+}
+
static void drawChooseTreeEdit(int ypos_raw, boolean active)
{
int sx = getChooseTreeEditXPos(POS_LEFT);
return;
}
+ // needed if last screen was the playing screen, invoked from hall of fame
+ if (score_info_tape_play)
+ {
+ CloseDoor(DOOR_CLOSE_ALL);
+
+ SetGameStatus(GAME_MODE_SCOREINFO);
+
+ DrawScoreInfo(scores.last_entry_nr);
+
+ return;
+ }
+
+ // reset flag to continue playing next level from hall of fame
+ scores.continue_playing = FALSE;
+
// leveldir_current may be invalid (level group, parent link, node copy)
leveldir_current = getValidLevelSeries(leveldir_current, leveldir_last_valid);
// 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);
{
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)
{
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];
{
// skipping levels is only allowed when trying to skip single level
if (setup.skip_levels && new_level_nr == old_level_nr + 1 &&
- Request("Level still unsolved! Skip despite handicap?", REQ_ASK))
+ Request("Level still unsolved! Skip it anyway?", REQ_ASK))
{
leveldir_current->handicap_level++;
SaveLevelSetup_SeriesInfo();
info_info = info_info_main;
+ // use modified info screen info without info screen entries marked as hidden
+ info_info = getSetupInfoFinal(info_info);
+
// determine maximal number of info entries that can be displayed on screen
num_info_info = 0;
for (i = 0; info_info[i].type != 0 && i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
DrawTextSCentered(ystart1, font_title, text_title);
DrawTextSCentered(ystart2, font_error, text_error);
- DrawTextSCentered(ybottom, font_foot,
- "Press any key or button for info menu");
+ DrawTextSCentered(ybottom, font_foot, TEXT_INFO_MENU);
FadeIn(REDRAW_FIELD);
}
DrawHeadline();
DrawTextSCentered(ystart1, font_title, "The Game Elements:");
-
- DrawTextSCentered(ybottom, font_foot,
- "Press any key or button for next page");
+ DrawTextSCentered(ybottom, font_foot, TEXT_NEXT_PAGE);
FrameCounter = 0;
}
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)
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;
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();
return;
}
- if (page > 0)
+ if (button != MB_MENU_INITIALIZE)
FadeSetNextScreen();
if (button != MB_MENU_INITIALIZE)
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;
ClearField();
DrawHeadline();
- DrawTextSCentered(ystart, font_title,
- "No music info for this level set.");
-
- DrawTextSCentered(ybottom, font_foot,
- "Press any key or button for info menu");
+ DrawTextSCentered(ystart, font_title, "No music info for this level set.");
+ DrawTextSCentered(ybottom, font_foot, TEXT_INFO_MENU);
return;
}
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)
ystart += ystep_head;
}
- DrawTextSCentered(ybottom, FONT_TEXT_4,
- "Press any key or button for next page");
+ DrawTextSCentered(ybottom, font_foot, TEXT_NEXT_PAGE);
if (button != MB_MENU_INITIALIZE)
FadeIn(REDRAW_FIELD);
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;
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;
- DrawTextSCentered(ybottom, font_foot,
- "Press any key or button for next page");
+ DrawTextFile(mSX + padx, mSY + MENU_SCREEN_INFO_YSTART1 + ystep_title,
+ filename, font_text, chars, -1, lines, line_spacing, -1,
+ autowrap, centered, parse_comments);
+
+ boolean last_screen = (screen_nr == num_credits_screens - 1);
+ char *text_foot = (last_screen ? TEXT_INFO_MENU : TEXT_NEXT_PAGE);
+
+ DrawTextSCentered(ybottom, font_foot, text_foot);
}
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, TEXT_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);
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();
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
{
}
}
-static void DrawInfoScreen_Program(void)
+static void DrawInfoScreen_ProgramScreen(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;
- SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_PROGRAM);
-
- FadeOut(REDRAW_FIELD);
-
ClearField();
DrawHeadline();
DrawTextSCentered(ystart, font_title, "Program Information:");
- ystart += ystep_title;
- DrawTextSCentered(ystart, font_head,
- "This game is Freeware!");
- ystart += ystep_head;
- DrawTextSCentered(ystart, font_head,
- "If you like it, send e-mail to:");
- ystart += ystep_head;
- DrawTextSCentered(ystart, font_text,
- setup.internal.program_email);
- ystart += ystep_para;
+ char *filename = getProgramInfoFilename(screen_nr);
+ 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;
- DrawTextSCentered(ystart, font_head,
- "More information and levels:");
- ystart += ystep_head;
- DrawTextSCentered(ystart, font_text,
- setup.internal.program_website);
- ystart += ystep_para;
+ DrawTextFile(mSX + padx, mSY + MENU_SCREEN_INFO_YSTART1 + ystep_title,
+ filename, font_text, chars, -1, lines, line_spacing, -1,
+ autowrap, centered, parse_comments);
- DrawTextSCentered(ystart, font_head,
- "If you have created new levels,");
- ystart += ystep_line;
- DrawTextSCentered(ystart, font_head,
- "send them to me to include them!");
- ystart += ystep_head;
- DrawTextSCentered(ystart, font_head,
- ":-)");
+ boolean last_screen = (screen_nr == num_program_info_screens - 1);
+ char *text_foot = (last_screen ? TEXT_INFO_MENU : TEXT_NEXT_PAGE);
- DrawTextSCentered(ybottom, font_foot,
- "Press any key or button for info menu");
+ DrawTextSCentered(ybottom, font_foot, text_foot);
+}
+
+static void DrawInfoScreen_Program(void)
+{
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_PROGRAM);
+
+ FadeMenuSoundsAndMusic();
+
+ FadeOut(REDRAW_FIELD);
+
+ HandleInfoScreen_Program(0, 0, MB_MENU_INITIALIZE);
FadeIn(REDRAW_FIELD);
}
-void HandleInfoScreen_Program(int button)
+void HandleInfoScreen_Program(int dx, int dy, int button)
{
- if (button == MB_MENU_LEAVE)
+ static int screen_nr = 0;
+
+ if (button == MB_MENU_INITIALIZE)
+ {
+ // determine number of program info screens
+ num_program_info_screens = 0;
+
+ while (getProgramInfoFilename(num_program_info_screens) != NULL)
+ num_program_info_screens++;
+
+ if (num_program_info_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 program info available.");
+ DrawTextSCentered(ybottom, font_foot, TEXT_INFO_MENU);
+
+ return;
+ }
+
+ screen_nr = 0;
+
+ DrawInfoScreen_ProgramScreen(screen_nr);
+ }
+ else if (button == MB_MENU_LEAVE)
{
PlaySound(SND_MENU_ITEM_SELECTING);
return;
}
- else if (button == MB_MENU_CHOICE)
+ else if (button == MB_MENU_CHOICE || dx)
{
PlaySound(SND_MENU_ITEM_SELECTING);
- FadeMenuSoundsAndMusic();
+ screen_nr += (dx < 0 ? -1 : +1);
- info_mode = INFO_MODE_MAIN;
- DrawInfoScreen();
+ if (screen_nr < 0 || screen_nr >= num_program_info_screens)
+ {
+ FadeMenuSoundsAndMusic();
+
+ info_mode = INFO_MODE_MAIN;
+ DrawInfoScreen();
+
+ return;
+ }
+
+ FadeSetNextScreen();
+
+ FadeOut(REDRAW_FIELD);
+
+ DrawInfoScreen_ProgramScreen(screen_nr);
+
+ FadeIn(REDRAW_FIELD);
}
else
{
DrawTextF(xstart2, ystart, font_text, "%s", setup.system.sdl_audiodriver);
DrawTextF(xstart3, ystart, font_text, "%s", driver_name);
- DrawTextSCentered(ybottom, font_foot,
- "Press any key or button for info menu");
+ DrawTextSCentered(ybottom, font_foot, TEXT_INFO_MENU);
FadeIn(REDRAW_FIELD);
}
struct TitleMessageInfo *tmi = &readme;
char *filename = getLevelSetInfoFilename();
char *title = "Level Set Information:";
+ int font_foot = MENU_INFO_FONT_FOOT;
int ystart = mSY - SY + MENU_SCREEN_INFO_YSTART1;
int ybottom = mSY - SY + MENU_SCREEN_INFO_YBOTTOM;
filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1,
tmi->autowrap, tmi->centered, tmi->parse_comments);
- DrawTextSCentered(ybottom, FONT_TEXT_4,
- "Press any key or button for info menu");
+ DrawTextSCentered(ybottom, font_foot, TEXT_INFO_MENU);
FadeIn(REDRAW_FIELD);
}
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);
+ HandleInfoScreen_Program(dx, dy, button);
else if (info_mode == INFO_MODE_VERSION)
HandleInfoScreen_Version(button);
else if (info_mode == INFO_MODE_LEVELSET)
}
-// ============================================================================
-// rename player API functions
-// ============================================================================
-
-struct ApiRenamePlayerThreadData
-{
- char *player_name;
- char *player_uuid;
-};
-
-static void *CreateThreadData_ApiRenamePlayer(void)
-{
- struct ApiRenamePlayerThreadData *data =
- checked_malloc(sizeof(struct ApiRenamePlayerThreadData));
-
- data->player_name = getStringCopy(setup.player_name);
- data->player_uuid = getStringCopy(setup.player_uuid);
-
- return data;
-}
-
-static void FreeThreadData_ApiRenamePlayer(void *data_raw)
-{
- struct ApiRenamePlayerThreadData *data = data_raw;
-
- checked_free(data->player_name);
- checked_free(data->player_uuid);
- checked_free(data);
-}
-
-static boolean SetRequest_ApiRenamePlayer(struct HttpRequest *request,
- void *data_raw)
-{
- struct ApiRenamePlayerThreadData *data = data_raw;
- char *player_name_raw = data->player_name;
- char *player_uuid_raw = data->player_uuid;
-
- request->hostname = setup.api_server_hostname;
- request->port = API_SERVER_PORT;
- request->method = API_SERVER_METHOD;
- request->uri = API_SERVER_URI_RENAME;
-
- char *player_name = getEscapedJSON(player_name_raw);
- char *player_uuid = getEscapedJSON(player_uuid_raw);
-
- snprintf(request->body, MAX_HTTP_BODY_SIZE,
- "{\n"
- "%s"
- " \"game_version\": \"%s\",\n"
- " \"game_platform\": \"%s\",\n"
- " \"name\": \"%s\",\n"
- " \"uuid\": \"%s\"\n"
- "}\n",
- getPasswordJSON(setup.api_server_password),
- getProgramRealVersionString(),
- getProgramPlatformString(),
- player_name,
- player_uuid);
-
- checked_free(player_name);
- checked_free(player_uuid);
-
- ConvertHttpRequestBodyToServerEncoding(request);
-
- return TRUE;
-}
-
-static void HandleResponse_ApiRenamePlayer(struct HttpResponse *response,
- void *data_raw)
-{
- // nothing to do here
-}
-
-#if defined(PLATFORM_EMSCRIPTEN)
-static void Emscripten_ApiRenamePlayer_Loaded(unsigned handle, void *data_raw,
- void *buffer, unsigned int size)
-{
- struct HttpResponse *response = GetHttpResponseFromBuffer(buffer, size);
-
- if (response != NULL)
- {
- HandleResponse_ApiRenamePlayer(response, data_raw);
-
- checked_free(response);
- }
- else
- {
- Error("server response too large to handle (%d bytes)", size);
- }
-
- FreeThreadData_ApiRenamePlayer(data_raw);
-}
-
-static void Emscripten_ApiRenamePlayer_Failed(unsigned handle, void *data_raw,
- int code, const char *status)
-{
- Error("server failed to handle request: %d %s", code, status);
-
- FreeThreadData_ApiRenamePlayer(data_raw);
-}
-
-static void Emscripten_ApiRenamePlayer_Progress(unsigned handle, void *data_raw,
- int bytes, int size)
-{
- // nothing to do here
-}
-
-static void Emscripten_ApiRenamePlayer_HttpRequest(struct HttpRequest *request,
- void *data_raw)
-{
- if (!SetRequest_ApiRenamePlayer(request, data_raw))
- {
- FreeThreadData_ApiRenamePlayer(data_raw);
-
- return;
- }
-
- emscripten_async_wget2_data(request->uri,
- request->method,
- request->body,
- data_raw,
- TRUE,
- Emscripten_ApiRenamePlayer_Loaded,
- Emscripten_ApiRenamePlayer_Failed,
- Emscripten_ApiRenamePlayer_Progress);
-}
-
-#else
-
-static void ApiRenamePlayer_HttpRequestExt(struct HttpRequest *request,
- struct HttpResponse *response,
- void *data_raw)
-{
- if (!SetRequest_ApiRenamePlayer(request, data_raw))
- return;
-
- if (!DoHttpRequest(request, response))
- {
- Error("HTTP request failed: %s", GetHttpError());
-
- return;
- }
-
- if (!HTTP_SUCCESS(response->status_code))
- {
- Error("server failed to handle request: %d %s",
- response->status_code,
- response->status_text);
-
- return;
- }
-
- HandleResponse_ApiRenamePlayer(response, data_raw);
-}
-
-static void ApiRenamePlayer_HttpRequest(struct HttpRequest *request,
- struct HttpResponse *response,
- void *data_raw)
-{
- ApiRenamePlayer_HttpRequestExt(request, response, data_raw);
-
- FreeThreadData_ApiRenamePlayer(data_raw);
-}
-#endif
-
-static int ApiRenamePlayerThread(void *data_raw)
-{
- struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
- struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
-
- program.api_thread_count++;
-
-#if defined(PLATFORM_EMSCRIPTEN)
- Emscripten_ApiRenamePlayer_HttpRequest(request, data_raw);
-#else
- ApiRenamePlayer_HttpRequest(request, response, data_raw);
-#endif
-
- program.api_thread_count--;
-
- checked_free(request);
- checked_free(response);
-
- return 0;
-}
-
-static void ApiRenamePlayerAsThread(void)
-{
- struct ApiRenamePlayerThreadData *data = CreateThreadData_ApiRenamePlayer();
-
- ExecuteAsThread(ApiRenamePlayerThread,
- "ApiRenamePlayer", data,
- "rename player on server");
-}
-
-
-// ============================================================================
-// reset player UUID API functions
-// ============================================================================
-
-struct ApiResetUUIDThreadData
-{
- char *player_name;
- char *player_uuid_old;
- char *player_uuid_new;
-};
-
-static void *CreateThreadData_ApiResetUUID(char *uuid_new)
-{
- struct ApiResetUUIDThreadData *data =
- checked_malloc(sizeof(struct ApiResetUUIDThreadData));
-
- data->player_name = getStringCopy(setup.player_name);
- data->player_uuid_old = getStringCopy(setup.player_uuid);
- data->player_uuid_new = getStringCopy(uuid_new);
-
- return data;
-}
-
-static void FreeThreadData_ApiResetUUID(void *data_raw)
-{
- struct ApiResetUUIDThreadData *data = data_raw;
-
- checked_free(data->player_name);
- checked_free(data->player_uuid_old);
- checked_free(data->player_uuid_new);
- checked_free(data);
-}
-
-static boolean SetRequest_ApiResetUUID(struct HttpRequest *request,
- void *data_raw)
-{
- struct ApiResetUUIDThreadData *data = data_raw;
- char *player_name_raw = data->player_name;
- char *player_uuid_old_raw = data->player_uuid_old;
- char *player_uuid_new_raw = data->player_uuid_new;
-
- request->hostname = setup.api_server_hostname;
- request->port = API_SERVER_PORT;
- request->method = API_SERVER_METHOD;
- request->uri = API_SERVER_URI_RESETUUID;
-
- char *player_name = getEscapedJSON(player_name_raw);
- char *player_uuid_old = getEscapedJSON(player_uuid_old_raw);
- char *player_uuid_new = getEscapedJSON(player_uuid_new_raw);
-
- snprintf(request->body, MAX_HTTP_BODY_SIZE,
- "{\n"
- "%s"
- " \"game_version\": \"%s\",\n"
- " \"game_platform\": \"%s\",\n"
- " \"name\": \"%s\",\n"
- " \"uuid_old\": \"%s\",\n"
- " \"uuid_new\": \"%s\"\n"
- "}\n",
- getPasswordJSON(setup.api_server_password),
- getProgramRealVersionString(),
- getProgramPlatformString(),
- player_name,
- player_uuid_old,
- player_uuid_new);
-
- checked_free(player_name);
- checked_free(player_uuid_old);
- checked_free(player_uuid_new);
-
- ConvertHttpRequestBodyToServerEncoding(request);
-
- return TRUE;
-}
-
-static void HandleResponse_ApiResetUUID(struct HttpResponse *response,
- void *data_raw)
-{
- struct ApiResetUUIDThreadData *data = data_raw;
-
- // upgrade player UUID in server setup file
- setup.player_uuid = getStringCopy(data->player_uuid_new);
- setup.player_version = 2;
-
- SaveSetup_ServerSetup();
-}
-
-#if defined(PLATFORM_EMSCRIPTEN)
-static void Emscripten_ApiResetUUID_Loaded(unsigned handle, void *data_raw,
- void *buffer, unsigned int size)
-{
- struct HttpResponse *response = GetHttpResponseFromBuffer(buffer, size);
-
- if (response != NULL)
- {
- HandleResponse_ApiResetUUID(response, data_raw);
-
- checked_free(response);
- }
- else
- {
- Error("server response too large to handle (%d bytes)", size);
- }
-
- FreeThreadData_ApiResetUUID(data_raw);
-}
-
-static void Emscripten_ApiResetUUID_Failed(unsigned handle, void *data_raw,
- int code, const char *status)
-{
- Error("server failed to handle request: %d %s", code, status);
-
- FreeThreadData_ApiResetUUID(data_raw);
-}
-
-static void Emscripten_ApiResetUUID_Progress(unsigned handle, void *data_raw,
- int bytes, int size)
-{
- // nothing to do here
-}
-
-static void Emscripten_ApiResetUUID_HttpRequest(struct HttpRequest *request,
- void *data_raw)
-{
- if (!SetRequest_ApiResetUUID(request, data_raw))
- {
- FreeThreadData_ApiResetUUID(data_raw);
-
- return;
- }
-
- emscripten_async_wget2_data(request->uri,
- request->method,
- request->body,
- data_raw,
- TRUE,
- Emscripten_ApiResetUUID_Loaded,
- Emscripten_ApiResetUUID_Failed,
- Emscripten_ApiResetUUID_Progress);
-}
-
-#else
-
-static void ApiResetUUID_HttpRequestExt(struct HttpRequest *request,
- struct HttpResponse *response,
- void *data_raw)
-{
- if (!SetRequest_ApiResetUUID(request, data_raw))
- return;
-
- if (!DoHttpRequest(request, response))
- {
- Error("HTTP request failed: %s", GetHttpError());
-
- return;
- }
-
- if (!HTTP_SUCCESS(response->status_code))
- {
- Error("server failed to handle request: %d %s",
- response->status_code,
- response->status_text);
-
- return;
- }
-
- HandleResponse_ApiResetUUID(response, data_raw);
-}
-
-static void ApiResetUUID_HttpRequest(struct HttpRequest *request,
- struct HttpResponse *response,
- void *data_raw)
-{
- ApiResetUUID_HttpRequestExt(request, response, data_raw);
-
- FreeThreadData_ApiResetUUID(data_raw);
-}
-#endif
-
-static int ApiResetUUIDThread(void *data_raw)
-{
- struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
- struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
-
- program.api_thread_count++;
-
-#if defined(PLATFORM_EMSCRIPTEN)
- Emscripten_ApiResetUUID_HttpRequest(request, data_raw);
-#else
- ApiResetUUID_HttpRequest(request, response, data_raw);
-#endif
-
- program.api_thread_count--;
-
- checked_free(request);
- checked_free(response);
-
- return 0;
-}
-
-static void ApiResetUUIDAsThread(char *uuid_new)
-{
- struct ApiResetUUIDThreadData *data = CreateThreadData_ApiResetUUID(uuid_new);
-
- ExecuteAsThread(ApiResetUUIDThread,
- "ApiResetUUID", data,
- "reset UUID on server");
-}
-
-
// ============================================================================
// type name functions
// ============================================================================
}
static void drawTypeNameText(char *name, struct TextPosInfo *pos,
- boolean active)
+ boolean active)
{
char text[MAX_PLAYER_NAME_LEN + 2] = { 0 };
boolean multiple_users = (game_status == GAME_MODE_PSEUDO_TYPENAMES);
int sy = (multiple_users ? amSY + pos->y : mSY + ALIGNED_TEXT_YPOS(pos));
int font_nr = (active ? FONT_ACTIVE(pos->font) : pos->font);
int font_width = getFontWidth(font_nr);
+ int font_xoffset = getFontDrawOffsetX(font_nr);
+ int font_yoffset = getFontDrawOffsetY(font_nr);
+ int font_sx = sx + font_xoffset;
+ int font_sy = sy + font_yoffset;
- DrawBackgroundForFont(sx, sy, pos->width, pos->height, font_nr);
+ DrawBackgroundForFont(font_sx, font_sy, pos->width, pos->height, font_nr);
sprintf(text, "%s%c", name, (active ? '_' : '\0'));
return align_yoffset;
}
+static void StartPlayingFromHallOfFame(void)
+{
+ level_nr = scores.next_level_nr;
+ LoadLevel(level_nr);
+
+ StartGameActions(network.enabled, setup.autorecord, level.random_seed);
+}
+
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);
+
+ scores.continue_on_return = (game_status == GAME_MODE_SCORES &&
+ game_status_last_screen == GAME_MODE_PLAYING);
if (CheckFadeAll())
fade_mask = REDRAW_ALL;
{
execSetupArtwork();
}
- else // GAME_MODE_LEVELS
+ else if (game_status == GAME_MODE_SCORES && scores.continue_playing)
+ {
+ StartPlayingFromHallOfFame();
+ }
+ else
{
SetGameStatus(GAME_MODE_MAIN);
FreeScreenGadgets();
CreateScreenGadgets();
- if (game_status != game_status_last_screen)
+ if (restart_music)
FadeMenuSoundsAndMusic();
FadeOut(fade_mask);
DrawMaskedBorder(fade_mask);
- if (game_status != game_status_last_screen)
+ if (restart_music)
PlayMenuSoundsAndMusic();
FadeIn(fade_mask);
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;
boolean has_scrollbar = screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->mapped;
int mx_scrollbar = screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x;
int mx_right_border = (has_scrollbar ? mx_scrollbar : SX + SXSIZE);
- int sx1_edit_name = getChooseTreeEditXPos(POS_LEFT);
- int sx2_edit_name = getChooseTreeEditXPos(POS_RIGHT);
+ int sx1_edit_name = getChooseTreeEditXPosReal(POS_LEFT);
+ int sx2_edit_name = getChooseTreeEditXPosReal(POS_RIGHT);
int x = 0;
int y = (ti != NULL ? ti->cl_cursor : 0);
int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
return;
}
+#if defined(PLATFORM_ANDROID)
+ // directly continue when touching the screen after playing
+ if ((mx || my) && scores.continue_on_return)
+ {
+ // ignore touch events until released
+ mx = my = 0;
+ }
+#endif
+
+ // any mouse click or cursor key stops leaving scores by "Return" key
+ if ((mx || my || dx || dy) && scores.continue_on_return)
+ {
+ scores.continue_on_return = FALSE;
+ level_nr = scores.last_level_nr;
+ LoadLevel(level_nr);
+ }
+
if (mx || my) // mouse input
{
x = (mx - amSX) / 32;
node_cursor->cl_first = ti->cl_first;
node_cursor->cl_cursor = ti->cl_cursor;
+
*ti_ptr = node_cursor->node_group;
DrawChooseTree(ti_ptr);
return;
}
}
- else if (dx == -1 && ti->node_parent)
+ else if ((dx == -1 || button == MB_MENU_CONTINUE) && ti->node_parent)
{
- FadeSetLeaveMenu();
+ if (game_status != GAME_MODE_SCORES)
+ FadeSetLeaveMenu();
PlaySound(SND_MENU_ITEM_SELECTING);
node_cursor->cl_first = ti->cl_first;
node_cursor->cl_cursor = ti->cl_cursor;
+
*ti_ptr = node_cursor->node_group;
DrawChooseTree(ti_ptr);
}
node_cursor->cl_first = ti->cl_first;
node_cursor->cl_cursor = ti->cl_cursor;
+
*ti_ptr = node_cursor;
if (ti->type == TREE_TYPE_LEVEL_DIR)
}
else if (game_status == GAME_MODE_SCORES)
{
- if (game_status_last_screen == GAME_MODE_PLAYING &&
- setup.auto_play_next_level && setup.increment_levels &&
- scores.last_level_nr < leveldir_current->last_level &&
- !network_playing)
+ if (scores.continue_playing && scores.continue_on_return)
{
- StartGameActions(network.enabled, setup.autorecord,
- level.random_seed);
+ StartPlayingFromHallOfFame();
+
return;
}
- else
+ else if (!scores.continue_on_return)
{
SetGameStatus(GAME_MODE_SCOREINFO);
if (player_name_current == NULL)
player_name_current = player_name;
+ // set text size for main name input (also used on name selection screen)
+ InitializeMainControls();
+
DrawChooseTree(&player_name_current);
}
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;
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);
if (score_entry_current == NULL)
score_entry_current = getFirstValidTreeInfoEntry(score_entries);
+ if (score_entries != NULL && scores.continue_playing)
+ setString(&score_entries->node_group->name, BACKLINK_TEXT_NEXT);
+
// ("score_entries" and "score_entry_current" may be NULL here)
}
-void DrawHallOfFame(int level_nr)
+void DrawHallOfFame(int nr)
{
- scores.last_level_nr = level_nr;
+ scores.last_level_nr = nr;
// (this is needed when called from GameEnd() after winning a game)
KeyboardAutoRepeatOn();
SetDrawDeactivationMask(REDRAW_NONE);
SetDrawBackgroundMask(REDRAW_FIELD);
- LoadLocalAndServerScore(level_nr, TRUE);
+ LoadLocalAndServerScore(scores.last_level_nr, TRUE);
DrawHallOfFame_setScoreEntries();
return getHallOfFameTimeText(nr); // show playing time
}
+static char *getHallOfFameTapeDateText(struct ScoreEntry *entry)
+{
+ static char tape_date[MAX_ISO_DATE_LEN + 1];
+ int i, j;
+
+ if (!strEqual(entry->tape_date, UNKNOWN_NAME) ||
+ strEqual(entry->tape_basename, UNDEFINED_FILENAME))
+ return entry->tape_date;
+
+ for (i = 0, j = 0; i < 8; i++, j++)
+ {
+ tape_date[j] = entry->tape_basename[i];
+
+ if (i == 3 || i == 5)
+ tape_date[++j] = '-';
+ }
+
+ tape_date[MAX_ISO_DATE_LEN] = '\0';
+
+ return tape_date;
+}
+
static void HandleHallOfFame_SelectLevel(int step, int direction)
{
int old_level_nr = scores.last_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);
}
else
{
- scores.last_entry_nr = 0;
-
DrawScoreInfo_Content(scores.last_entry_nr);
}
{
struct ScoreEntry *entry = &scores.entry[entry_nr];
char *pos_text = getHallOfFameRankText(entry_nr, 0);
+ char *tape_date = getHallOfFameTapeDateText(entry);
int font_title = MENU_INFO_FONT_TITLE;
int font_head = MENU_INFO_FONT_HEAD;
int font_text = MENU_INFO_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 xstart = mSX - SX + menu.left_spacing[GAME_MODE_SCOREINFO];
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 xstart1 = xstart + xstep;
+ int xstart2 = xstart + xstep * 12;
+ int select_x = SX + xstart1;
+ int select_y1, select_y2;
+ int play_x, play_y;
+ int play_height = screen_gadget[SCREEN_CTRL_ID_PLAY_TAPE]->height;
+ boolean play_visible = !strEqual(tape_date, UNKNOWN_NAME);
int font_width = getFontWidth(font_text);
int font_height = getFontHeight(font_text);
+ int tape_date_width = getTextWidth(tape_date, font_text);
int pad_left = xstart2;
- int pad_right = MENU_SCREEN_INFO_SPACE_RIGHT;
+ int pad_right = menu.right_spacing[GAME_MODE_SCOREINFO];
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)
+ // redraw level selection buttons (which have just been erased)
RedrawScreenMenuGadgets(SCREEN_MASK_SCORES);
if (score_entries == NULL)
TRUE, FALSE, FALSE);
ystart += ystep_para + (lines > 0 ? lines - 1 : 0) * font_height;
- button_y1 = SY + ystart;
+ select_y1 = SY + ystart;
ystart += graphic_info[IMG_MENU_BUTTON_PREV_SCORE].height;
DrawTextF(xstart1, ystart, font_head, "Rank");
ystart += ystep_line;
+ play_x = SX + xstart2 + tape_date_width + font_width;
+ play_y = SY + ystart + (font_height - play_height) / 2;
+
DrawTextF(xstart1, ystart, font_head, "Tape Date");
- DrawTextF(xstart2, ystart, font_text, entry->tape_date);
+ DrawTextF(xstart2, ystart, font_text, tape_date);
ystart += ystep_line;
DrawTextF(xstart1, ystart, font_head, "Platform");
TRUE, FALSE, FALSE);
ystart += ystep_line;
- button_y2 = SY + ystart;
+ select_y2 = SY + ystart;
DrawTextSCentered(ybottom, font_foot, "Press any key or button to go back");
- AdjustScoreInfoButtons(button_x, button_y1, button_y2);
+ AdjustScoreInfoButtons_SelectScore(select_x, select_y1, select_y2);
+ AdjustScoreInfoButtons_PlayTape(play_x, play_y, play_visible);
}
static void DrawScoreInfo(int entry_nr)
{
scores.last_entry_nr = entry_nr;
-
- SetMainBackgroundImageIfDefined(IMG_BACKGROUND_SCOREINFO);
+ score_info_tape_play = FALSE;
UnmapAllGadgets();
+ FreeScreenGadgets();
+ CreateScreenGadgets();
+
FadeOut(REDRAW_FIELD);
+ // needed if different viewport properties defined after playing score tape
+ ChangeViewportPropertiesIfNeeded();
+
+ // set this after "ChangeViewportPropertiesIfNeeded()" (which may reset it)
+ SetDrawDeactivationMask(REDRAW_NONE);
+ SetDrawBackgroundMask(REDRAW_FIELD);
+
+ // needed if different background image defined after playing score tape
+ SetMainBackgroundImage(IMG_BACKGROUND_SCORES);
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_SCOREINFO);
+
+ // special compatibility handling for "Snake Bite" graphics set
+ if (strPrefix(leveldir_current->identifier, "snake_bite"))
+ ClearRectangle(gfx.background_bitmap, gfx.real_sx, gfx.real_sy + 64,
+ gfx.full_sxsize, gfx.full_sysize - 64);
+
DrawScoreInfo_Content(entry_nr);
// map gadgets for score info screen
}
}
+static void HandleScoreInfo_PlayTape(void)
+{
+ if (!PlayScoreTape(scores.last_entry_nr))
+ {
+ DrawScoreInfo_Content(scores.last_entry_nr);
+
+ FadeIn(REDRAW_FIELD);
+ }
+}
+
void HandleScoreInfo(int mx, int my, int dx, int dy, int button)
{
boolean button_action = (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE);
SetGameStatus(GAME_MODE_SCORES);
- DrawHallOfFame(level_nr);
+ DrawHallOfFame(scores.last_level_nr);
}
else if (dx)
{
{ &setup.internal.menu_exit, execExitSetup },
{ &setup.internal.menu_save_and_exit, execSaveAndExitSetup },
+ { &setup.internal.info_title, execInfoTitleScreen },
+ { &setup.internal.info_elements, execInfoElements },
+ { &setup.internal.info_music, execInfoMusic },
+ { &setup.internal.info_credits, execInfoCredits },
+ { &setup.internal.info_program, execInfoProgram },
+ { &setup.internal.info_version, execInfoVersion },
+ { &setup.internal.info_levelset, execInfoLevelSet },
+ { &setup.internal.info_exit, execExitInfo },
+
{ NULL, NULL }
};
{ TYPE_SWITCH, &setup.multiple_users, "Multiple Users/Teams:" },
{ TYPE_YES_NO, &setup.input_on_focus, "Only Move Focussed Player:" },
{ TYPE_SWITCH, &setup.time_limit, "Time Limit:" },
- { TYPE_SWITCH, &setup.handicap, "Handicap:" },
- { TYPE_SWITCH, &setup.skip_levels, "Skip Unsolved Levels:" },
+ { TYPE_SWITCH, &setup.handicap, "Force Solving Levels:" },
+ { TYPE_SWITCH, &setup.skip_levels, "Allow Skipping Levels:" },
{ TYPE_SWITCH, &setup.increment_levels,"Increment Solved Levels:" },
{ TYPE_SWITCH, &setup.auto_play_next_level,"Auto-play Next Level:" },
{ TYPE_SWITCH, &setup.count_score_after_game,"Count Score After Game:" },
static struct TokenInfo setup_info_graphics[] =
{
-#if !defined(PLATFORM_ANDROID)
+#if !defined(PLATFORM_ANDROID) && !defined(PLATFORM_EMSCRIPTEN)
{ TYPE_SWITCH, &setup.fullscreen, "Fullscreen:" },
{ TYPE_ENTER_LIST, execSetupChooseWindowSize, "Window Scaling:" },
{ TYPE_STRING, &window_size_text, "" },
{ TYPE_ENTER_LIST, execSetupChooseScrollDelay, "Scroll Delay:" },
{ TYPE_STRING, &scroll_delay_text, "" },
#endif
+#if !defined(PLATFORM_EMSCRIPTEN)
{ TYPE_ENTER_LIST, execSetupChooseVsyncMode, "Vertical Sync (VSync):" },
{ TYPE_STRING, &vsync_mode_text, "" },
+#endif
{ TYPE_SWITCH, &setup.fade_screens, "Fade Screens:" },
{ TYPE_SWITCH, &setup.quick_switch, "Quick Player Focus Switch:" },
{ TYPE_SWITCH, &setup.quick_doors, "Quick Menu Doors:" },
GD_EVENT_PRESSED | GD_EVENT_REPEATED,
FALSE, "next score"
},
+ {
+ IMG_MENU_BUTTON_PLAY_TAPE, IMG_MENU_BUTTON_PLAY_TAPE,
+ &menu.scores.button.play_tape, NULL,
+ SCREEN_CTRL_ID_PLAY_TAPE,
+ SCREEN_MASK_SCORES_INFO,
+ GD_EVENT_RELEASED,
+ FALSE, "play tape"
+ },
{
IMG_MENU_BUTTON_FIRST_LEVEL, IMG_MENU_BUTTON_FIRST_LEVEL_ACTIVE,
&menu.main.button.first_level, NULL,
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);
+ boolean has_gfx_pressed = (menubutton_info[i].gfx_pressed ==
+ menubutton_info[i].gfx_unpressed);
Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed;
int gfx_unpressed, gfx_pressed;
int x, y, width, height;
gd_x2a = gd_x2;
gd_y2a = gd_y2;
- if (is_touch_button)
+ if (has_gfx_pressed)
{
gd_x2 += graphic_info[gfx_pressed].pressed_xoffset;
gd_y2 += graphic_info[gfx_pressed].pressed_yoffset;
// if x/y set to -1, dynamically place buttons next to title text
int title_width = getTextWidth(INFOTEXT_SCORE_ENTRY, FONT_TITLE_1);
+ // special compatibility handling for "Snake Bite" graphics set
+ if (strPrefix(leveldir_current->identifier, "snake_bite"))
+ title_width = strlen(INFOTEXT_SCORE_ENTRY) * 32;
+
+ // use "SX" here to center buttons (ignore horizontal draw offset)
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);
+ // use "mSY" here to place buttons (respect vertical draw offset)
if (pos->y == -1)
y = (id == SCREEN_CTRL_ID_PREV_LEVEL2 ||
id == SCREEN_CTRL_ID_NEXT_LEVEL2 ? mSY + MENU_TITLE1_YPOS : 0);
UnmapScreenGadgets();
}
-static void AdjustScoreInfoButtons(int x, int y1, int y2)
+static void AdjustScoreInfoButtons_SelectScore(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];
ModifyGadget(gi_2, GDI_X, x, GDI_Y, y2, GDI_END);
}
+static void AdjustScoreInfoButtons_PlayTape(int x, int y, boolean visible)
+{
+ struct GadgetInfo *gi = screen_gadget[SCREEN_CTRL_ID_PLAY_TAPE];
+ struct MenuPosInfo *pos = menubutton_info[SCREEN_CTRL_ID_PLAY_TAPE].pos;
+
+ // set gadget position dynamically, pre-defined or off-screen
+ int xx = (visible ? (pos->x == -1 ? x : pos->x) : POS_OFFSCREEN);
+ int yy = (visible ? (pos->y == -1 ? y : pos->y) : POS_OFFSCREEN);
+
+ ModifyGadget(gi, GDI_X, xx, GDI_Y, yy, GDI_END);
+ MapGadget(gi); // (needed if deactivated on last score page)
+}
+
static void HandleScreenGadgets(struct GadgetInfo *gi)
{
int id = gi->custom_id;
HandleScoreInfo_SelectScore(step, +1);
break;
+ case SCREEN_CTRL_ID_PLAY_TAPE:
+ HandleScoreInfo_PlayTape();
+ break;
+
case SCREEN_CTRL_ID_FIRST_LEVEL:
HandleMainMenu_SelectLevel(MAX_LEVELS, -1, NO_DIRECT_LEVEL_SELECT);
break;
}
}
+void HandleScreenGadgetKeys(Key key)
+{
+ if (key == setup.shortcut.tape_play)
+ HandleScreenGadgets(screen_gadget[SCREEN_CTRL_ID_PLAY_TAPE]);
+}
+
void DumpScreenIdentifiers(void)
{
int i;