// other screen text constants
#define STR_CHOOSE_TREE_EDIT "Edit"
#define MENU_CHOOSE_TREE_FONT(x) (FONT_TEXT_1 + (x))
+#define MENU_CHOOSE_TREE_COLOR(ti, a) TREE_COLOR(ti, a)
// for input setup functions
#define SETUPINPUT_SCREEN_POS_START 0
static void UpdateScreenMenuGadgets(int, boolean);
+static boolean OfferUploadTapes(void);
+static void execOfferUploadTapes(void);
+
static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
static int info_mode = INFO_MODE_MAIN;
return;
}
- // leveldir_current may be invalid (level group, parent link)
- if (!validLevelSeries(leveldir_current))
- leveldir_current = getFirstValidTreeInfoEntry(leveldir_last_valid);
+ // leveldir_current may be invalid (level group, parent link, node copy)
+ leveldir_current = getValidLevelSeries(leveldir_current, leveldir_last_valid);
if (leveldir_current != leveldir_last_valid)
+ {
+ UpdateLastPlayedLevels_TreeInfo();
+
levelset_has_changed = TRUE;
+ }
// store valid level series information
leveldir_last_valid = leveldir_current;
SetMouseCursor(CURSOR_DEFAULT);
OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
+
+ SyncEmscriptenFilesystem();
+
+ // needed once to upload tapes (after program start or after user change)
+ CheckUploadTapes();
}
static void gotoTopLevelDir(void)
}
}
+static void HandleMainMenu_ToggleTeamMode(void)
+{
+ setup.team_mode = !setup.team_mode;
+
+ InitializeMainControls();
+ DrawCursorAndText_Main(MAIN_CONTROL_NAME, TRUE, FALSE);
+
+ DrawPreviewPlayers();
+}
+
static void HandleMainMenu_SelectLevel(int step, int direction,
int selected_level_nr)
{
}
else if (dx != 0)
{
- if (choice != MAIN_CONTROL_INFO &&
- choice != MAIN_CONTROL_SETUP)
+ if (choice == MAIN_CONTROL_NAME)
+ {
+ // special case: cursor left or right pressed -- toggle team mode
+ HandleMainMenu_ToggleTeamMode();
+ }
+ else if (choice != MAIN_CONTROL_INFO &&
+ choice != MAIN_CONTROL_SETUP)
+ {
HandleMainMenu_SelectLevel(1, dx, NO_DIRECT_LEVEL_SELECT);
+ }
}
}
else
insideTextPosRect(main_controls[i].pos_text, mx - mSX, my - mSY))
{
// special case: menu text "name/team" clicked -- toggle team mode
- setup.team_mode = !setup.team_mode;
-
- InitializeMainControls();
- DrawCursorAndText_Main(choice, TRUE, FALSE);
-
- DrawPreviewPlayers();
+ HandleMainMenu_ToggleTeamMode();
}
else
{
SaveLevelSetup_LastSeries();
SaveLevelSetup_SeriesInfo();
+ // restore level set if chosen from "last played level set" menu
+ RestoreLastPlayedLevels(&leveldir_current);
+
if (setup.internal.choose_from_top_leveldir)
gotoTopLevelDir();
SetGameStatus(GAME_MODE_SCORES);
- DrawHallOfFame(level_nr, -1);
+ DrawHallOfFame(level_nr);
}
else if (pos == MAIN_CONTROL_EDITOR)
{
if (leveldir_current->readonly &&
- !strEqual(setup.player_name, "Artsoft"))
- Request("This level is read-only!", REQ_CONFIRM);
+ setup.editor.show_read_only_warning)
+ Request("This level is read-only!", REQ_CONFIRM | REQ_STAY_OPEN);
- CloseDoor(DOOR_CLOSE_2);
+ CloseDoor(DOOR_CLOSE_ALL);
SetGameStatus(GAME_MODE_EDITOR);
SaveLevelSetup_LastSeries();
SaveLevelSetup_SeriesInfo();
- if (Request("Do you really want to quit?", REQ_ASK | REQ_STAY_CLOSED))
+#if defined(PLATFORM_EMSCRIPTEN)
+ Request("Close the browser window to quit!", REQ_CONFIRM);
+#else
+ if (!setup.ask_on_quit_program ||
+ Request("Do you really want to quit?", REQ_ASK | REQ_STAY_CLOSED))
SetGameStatus(GAME_MODE_QUIT);
+#endif
}
}
}
}
+// ============================================================================
+// change name 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));
+
+#if defined(PLATFORM_EMSCRIPTEN)
+ Emscripten_ApiRenamePlayer_HttpRequest(request, data_raw);
+#else
+ ApiRenamePlayer_HttpRequest(request, response, data_raw);
+#endif
+
+ 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");
+}
+
+
// ============================================================================
// type name functions
// ============================================================================
// temporarily change active user to edited user
user.nr = type_name_nr;
- // load setup of edited user (unless creating user with current setup)
- if (!create_user ||
- !Request("Use current setup values for the new player?", REQ_ASK))
+ if (create_user &&
+ Request("Use current setup values for the new player?", REQ_ASK))
+ {
+ // use current setup values for new user, but create new player UUID
+ setup.player_uuid = getStringCopy(getUUID());
+ }
+ else
+ {
+ // load setup for existing user (or start with defaults for new user)
LoadSetup();
+ }
}
char *setup_filename = getSetupFilename();
// save setup of edited user
SaveSetup();
+ // change name of edited user on score server
+ ApiRenamePlayerAsThread();
+
if (game_status == GAME_MODE_PSEUDO_TYPENAMES || reset_setup)
{
if (reset_setup)
if (strEqual((*ti_ptr)->subdir, STRING_TOP_DIRECTORY))
{
- SetGameStatus(GAME_MODE_MAIN);
+ if (game_status == GAME_MODE_SETUP)
+ {
+ execSetupArtwork();
+ }
+ else // GAME_MODE_LEVELS
+ {
+ SetGameStatus(GAME_MODE_MAIN);
- DrawMainMenu();
+ DrawMainMenu();
+ }
return;
}
FadeIn(fade_mask);
}
-static void drawChooseTreeList(int first_entry, int num_page_entries,
- TreeInfo *ti)
+static void drawChooseTreeText(int y, boolean active, TreeInfo *ti)
{
int num_entries = numTreeInfoInGroup(ti);
boolean scrollbar_needed = (num_entries > NUM_MENU_ENTRIES_ON_SCREEN);
int scrollbar_xpos = SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset;
int screen_width = (scrollbar_needed ? scrollbar_xpos : SXSIZE);
+ int first_entry = ti->cl_first;
+ int entry_pos = first_entry + y;
+ TreeInfo *node_first = getTreeInfoFirstGroupEntry(ti);
+ TreeInfo *node = getTreeInfoFromPos(node_first, entry_pos);
+ int font_color = MENU_CHOOSE_TREE_COLOR(node, active);
+ int font_nr = MENU_CHOOSE_TREE_FONT(font_color);
+ int font_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset;
+ int xpos = MENU_SCREEN_START_XPOS;
+ int ypos = MENU_SCREEN_START_YPOS + y;
+ int startx = amSX + xpos * 32;
+ int starty = amSY + ypos * 32;
+ int startx_text = startx + font_xoffset;
+ int endx_text = amSX + screen_width;
+ int max_text_size = endx_text - startx_text;
+ int max_buffer_len = max_text_size / getFontWidth(font_nr);
+ char buffer[max_buffer_len + 1];
+
+ strncpy(buffer, node->name, max_buffer_len);
+ buffer[max_buffer_len] = '\0';
+
+ DrawText(startx, starty, buffer, font_nr);
+}
+
+static void drawChooseTreeList(int first_entry, int num_page_entries,
+ TreeInfo *ti)
+{
int i;
char *title_string = NULL;
int yoffset_sets = MENU_TITLE1_YPOS;
node_first = getTreeInfoFirstGroupEntry(ti);
node = getTreeInfoFromPos(node_first, entry_pos);
- int font_nr = MENU_CHOOSE_TREE_FONT(node->color);
- int font_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset;
- int xpos = MENU_SCREEN_START_XPOS;
- int ypos = MENU_SCREEN_START_YPOS + i;
- int startx = amSX + xpos * 32;
- int starty = amSY + ypos * 32;
- int startx_text = startx + font_xoffset;
- int endx_text = amSX + screen_width;
- int max_text_size = endx_text - startx_text;
- int max_buffer_len = max_text_size / getFontWidth(font_nr);
- char buffer[max_buffer_len + 1];
-
- strncpy(buffer, node->name, max_buffer_len);
- buffer[max_buffer_len] = '\0';
-
- DrawText(startx, starty, buffer, font_nr);
+ drawChooseTreeText(i, FALSE, ti);
if (node->parent_link)
initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
MarkTileDirty(x, 1);
}
+static void drawChooseTreeCursorAndText(int y, boolean active, TreeInfo *ti)
+{
+ drawChooseTreeCursor(y, active);
+ drawChooseTreeText(y, active, ti);
+}
+
static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
TreeInfo **ti_ptr)
{
drawChooseTreeList(ti->cl_first, num_page_entries, ti);
drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
- drawChooseTreeCursor(ti->cl_cursor, TRUE);
+ drawChooseTreeCursorAndText(ti->cl_cursor, TRUE, ti);
return;
}
{
drawChooseTreeList(ti->cl_first, num_page_entries, ti);
drawChooseTreeInfo(ti->cl_first + ti->cl_cursor, ti);
- drawChooseTreeCursor(ti->cl_cursor, TRUE);
+ drawChooseTreeCursorAndText(ti->cl_cursor, TRUE, ti);
AdjustChooseTreeScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
ti->cl_first, ti);
{
PlaySound(SND_MENU_ITEM_ACTIVATING);
- drawChooseTreeCursor(ti->cl_cursor, FALSE);
- drawChooseTreeCursor(y, TRUE);
+ drawChooseTreeCursorAndText(ti->cl_cursor, FALSE, ti);
+ drawChooseTreeCursorAndText(y, TRUE, ti);
drawChooseTreeInfo(ti->cl_first + y, ti);
ti->cl_cursor = y;
HandleMainMenu_SelectLevel(0, 0, new_level_nr);
}
+ else if (game_status == GAME_MODE_LEVELS)
+ {
+ // store level set if chosen from "last played level set" menu
+ StoreLastPlayedLevels(leveldir_current);
+ }
else if (game_status == GAME_MODE_NAMES)
{
if (mx >= sx1_edit_name && mx <= sx2_edit_name)
LoadLevelSetup_LastSeries();
LoadLevelSetup_SeriesInfo();
+ // update list of last played level sets
+ UpdateLastPlayedLevels_TreeInfo();
+
TapeErase();
ToggleFullscreenIfNeeded();
HandleChooseTree(mx, my, dx, dy, button, &level_number_current);
}
-void DrawHallOfFame(int level_nr, int highlight_position)
+void DrawHallOfFame(int level_nr)
{
int fade_mask = REDRAW_FIELD;
SetDrawDeactivationMask(REDRAW_NONE);
SetDrawBackgroundMask(REDRAW_FIELD);
- if (highlight_position < 0)
- LoadScore(level_nr);
- else
+ LoadLocalAndServerScore(level_nr, TRUE);
+
+ if (scores.last_added >= 0)
SetAnimStatus(GAME_MODE_PSEUDO_SCORESNEW);
FadeSetEnterScreen();
OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
- HandleHallOfFame(level_nr, highlight_position, 0, 0, MB_MENU_INITIALIZE);
+ HandleHallOfFame(level_nr, 0, 0, 0, MB_MENU_INITIALIZE);
DrawMaskedBorder(fade_mask);
FadeIn(fade_mask);
}
-static void drawHallOfFameList(int level_nr, int first_entry,
- int highlight_position)
+static int getHallOfFameFirstEntry(int first_entry, int step)
+{
+ if (step == 0)
+ first_entry = scores.last_added - (NUM_MENU_ENTRIES_ON_SCREEN + 1) / 2 + 1;
+ else
+ first_entry += step;
+
+ if (first_entry < 0)
+ first_entry = 0;
+ else if (first_entry > MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN)
+ first_entry = MAX(0, MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN);
+
+ return first_entry;
+}
+
+static char *getHallOfFameScoreText(int nr)
+{
+ if (!level.rate_time_over_score)
+ return int2str(scores.entry[nr].score, 5); // show normal score
+
+ if (level.use_step_counter)
+ return int2str(scores.entry[nr].time, 5); // show number of steps
+
+ static char score_text[10];
+ int time_seconds = scores.entry[nr].time / FRAMES_PER_SECOND;
+ int mm = (time_seconds / 60) % 60;
+ int ss = (time_seconds % 60);
+
+ sprintf(score_text, "%02d:%02d", mm, ss); // show playing time
+
+ return score_text;
+}
+
+static void drawHallOfFameList(int level_nr, int first_entry)
{
int i, j;
for (i = 0; i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
{
int entry = first_entry + i;
- boolean active = (entry == highlight_position);
+ boolean active = (entry == scores.last_added);
+ boolean forced = (scores.force_last_added && active);
int font_nr1 = (active ? FONT_TEXT_1_ACTIVE : FONT_TEXT_1);
int font_nr2 = (active ? FONT_TEXT_2_ACTIVE : FONT_TEXT_2);
int font_nr3 = (active ? FONT_TEXT_3_ACTIVE : FONT_TEXT_3);
int dx3 = SXSIZE - 2 * (mSX - SX + dxoff) - 5 * getFontWidth(font_nr4);
int num_dots = (dx3 - dx2) / getFontWidth(font_nr3);
int sy = mSY + 64 + i * 32;
+ char *pos_text = (forced ? "???" : int2str(entry + 1, 3));
- DrawText(mSX, sy, int2str(entry + 1, 3), font_nr1);
+ DrawText(mSX, sy, pos_text, font_nr1);
DrawText(mSX + dx1, sy, ".", font_nr1);
for (j = 0; j < num_dots; j++)
DrawText(mSX + dx2 + j * getFontWidth(font_nr3), sy, ".", font_nr3);
- if (!strEqual(highscore[entry].Name, EMPTY_PLAYER_NAME))
- DrawText(mSX + dx2, sy, highscore[entry].Name, font_nr2);
+ if (!strEqual(scores.entry[entry].name, EMPTY_PLAYER_NAME))
+ DrawText(mSX + dx2, sy, scores.entry[entry].name, font_nr2);
- DrawText(mSX + dx3, sy, int2str(highscore[entry].Score, 5), font_nr4);
+ DrawText(mSX + dx3, sy, getHallOfFameScoreText(entry), font_nr4);
}
redraw_mask |= REDRAW_FIELD;
{
static int level_nr = 0;
static int first_entry = 0;
- static int highlight_position = 0;
int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
if (button == MB_MENU_INITIALIZE)
{
level_nr = mx;
- first_entry = 0;
- highlight_position = my;
- drawHallOfFameList(level_nr, first_entry, highlight_position);
+ if (server_scores.updated)
+ {
+ // reload scores, using updated server score cache file
+ LoadLocalAndServerScore(level_nr, FALSE);
+
+ server_scores.updated = FALSE;
+ }
+
+ first_entry = getHallOfFameFirstEntry(0, 0);
+
+ drawHallOfFameList(level_nr, first_entry);
return;
}
if (dy < 0)
{
- if (first_entry > 0)
- {
- first_entry -= step;
- if (first_entry < 0)
- first_entry = 0;
+ first_entry = getHallOfFameFirstEntry(first_entry, -step);
- drawHallOfFameList(level_nr, first_entry, highlight_position);
- }
+ drawHallOfFameList(level_nr, first_entry);
}
else if (dy > 0)
{
- if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN < MAX_SCORE_ENTRIES)
- {
- first_entry += step;
- if (first_entry + NUM_MENU_ENTRIES_ON_SCREEN > MAX_SCORE_ENTRIES)
- first_entry = MAX(0, MAX_SCORE_ENTRIES - NUM_MENU_ENTRIES_ON_SCREEN);
+ first_entry = getHallOfFameFirstEntry(first_entry, step);
- drawHallOfFameList(level_nr, first_entry, highlight_position);
- }
+ drawHallOfFameList(level_nr, first_entry);
}
else if (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE)
{
DrawMainMenu();
}
}
+ else if (server_scores.updated)
+ {
+ // reload scores, using updated server score cache file
+ LoadLocalAndServerScore(level_nr, FALSE);
+
+ server_scores.updated = FALSE;
+
+ first_entry = getHallOfFameFirstEntry(0, 0);
+
+ drawHallOfFameList(level_nr, first_entry);
+ }
if (game_status == GAME_MODE_SCORES)
PlayMenuSoundIfLoop();
execSetupGame_setNetworkServerText();
+ if (!setup.provide_uploading_tapes)
+ setHideSetupEntry(execOfferUploadTapes);
+
setup_mode = SETUP_MODE_GAME;
DrawSetupScreen();
static void execSetupArtwork(void)
{
+ static ArtworkDirTree *gfx_last_valid = NULL;
+ static ArtworkDirTree *snd_last_valid = NULL;
+ static ArtworkDirTree *mus_last_valid = NULL;
+
+ // current artwork directory may be invalid (level group, parent link)
+ if (!validLevelSeries(artwork.gfx_current))
+ artwork.gfx_current = getFirstValidTreeInfoEntry(gfx_last_valid);
+ if (!validLevelSeries(artwork.snd_current))
+ artwork.snd_current = getFirstValidTreeInfoEntry(snd_last_valid);
+ if (!validLevelSeries(artwork.mus_current))
+ artwork.mus_current = getFirstValidTreeInfoEntry(mus_last_valid);
+
+ // store valid artwork directory information
+ gfx_last_valid = artwork.gfx_current;
+ snd_last_valid = artwork.snd_current;
+ mus_last_valid = artwork.mus_current;
+
#if 0
Debug("screens:execSetupArtwork", "'%s', '%s', '%s'",
artwork.gfx_current->subdir,
ClickOnGadget(gi, MB_LEFTBUTTON);
}
+static void execOfferUploadTapes(void)
+{
+ OfferUploadTapes();
+}
+
static void ToggleNetworkModeIfNeeded(void)
{
int font_title = FONT_TITLE_1;
{ TYPE_PLAYER, &setup.network_player_nr,"Preferred Network Player:" },
{ TYPE_TEXT_INPUT, execGadgetNetworkServer, "Network Server Hostname:" },
{ TYPE_STRING, &network_server_text, "" },
+ { TYPE_SWITCH, &setup.use_api_server, "Use Highscore Server:" },
+ { TYPE_SWITCH, &setup.only_show_local_scores, "Only Show Local Scores:" },
+ { TYPE_ENTER_LIST, execOfferUploadTapes, "Upload All Tapes to Server" },
{ 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.skip_levels, "Skip Unsolved Levels:" },
{ TYPE_SWITCH, &setup.increment_levels,"Increment Solved Levels:" },
{ TYPE_SWITCH, &setup.auto_play_next_level,"Auto-play Next Level:" },
- { TYPE_SWITCH, &setup.skip_scores_after_game,"Skip Scores After Game:" },
+ { TYPE_SWITCH, &setup.count_score_after_game,"Count Score After Game:" },
+ { TYPE_SWITCH, &setup.show_scores_after_game,"Show Scores After Game:" },
{ TYPE_YES_NO, &setup.ask_on_game_over, "Ask on Game Over:" },
+ { TYPE_YES_NO, &setup.ask_on_quit_game, "Ask on Quit Game:" },
+ { TYPE_YES_NO, &setup.ask_on_quit_program, "Ask on Quit Program:" },
{ TYPE_SWITCH, &setup.autorecord, "Auto-Record Tapes:" },
{ TYPE_ENTER_LIST, execSetupChooseGameSpeed, "Game Speed:" },
{ TYPE_STRING, &game_speed_text, "" },
#endif
{ TYPE_ENTER_LIST, execSetupChooseSnapshotMode,"Game Engine Snapshot Mode:" },
{ TYPE_STRING, &snapshot_mode_text, "" },
- { TYPE_SWITCH, &setup.show_snapshot_buttons,"Show Snapshot Buttons:" },
+ { TYPE_SWITCH, &setup.show_load_save_buttons,"Show Load/Save Buttons:" },
+ { TYPE_SWITCH, &setup.show_undo_redo_buttons,"Show Undo/Redo Buttons:" },
{ TYPE_EMPTY, NULL, "" },
{ TYPE_LEAVE_MENU, execSetupMain, "Back" },
#endif
{ TYPE_SWITCH, &setup.editor.show_element_token, "Show element token:" },
{ TYPE_EMPTY, NULL, "" },
+ { TYPE_SWITCH, &setup.editor.show_read_only_warning, "Show read-only warning:" },
+ { TYPE_EMPTY, NULL, "" },
{ TYPE_LEAVE_MENU, execSetupMain, "Back" },
{ 0, NULL, NULL }
if (si->value == &setup.network_mode)
ToggleNetworkModeIfNeeded();
+ // API server mode may have changed at this point
+ if (si->value == &setup.use_api_server)
+ runtime.use_api_server = setup.use_api_server;
+
// game speed list may have changed at this point
if (si->value == &setup.game_speed_extended)
ToggleGameSpeedsListIfNeeded();
if (game_status != GAME_MODE_PLAYING)
return;
- GameActions(); // main game loop
+ GameActions(); // main game loop
if (tape.auto_play && !tape.playing)
- AutoPlayTapes(); // continue automatically playing next tape
+ AutoPlayTapesContinue(); // continue automatically playing next tape
}
}
}
}
+
+static int UploadTapes(void)
+{
+ SetGameStatus(GAME_MODE_LOADING);
+
+ FadeSetEnterScreen();
+ FadeOut(REDRAW_ALL);
+
+ ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
+
+ FadeIn(REDRAW_ALL);
+
+ DrawInitTextHead("Uploading tapes");
+
+ global.autoplay_mode = AUTOPLAY_MODE_UPLOAD;
+ global.autoplay_leveldir = "ALL";
+ global.autoplay_all = TRUE;
+
+ int num_tapes_uploaded = AutoPlayTapes();
+
+ global.autoplay_mode = AUTOPLAY_MODE_NONE;
+ global.autoplay_leveldir = NULL;
+ global.autoplay_all = FALSE;
+
+ SetGameStatus(GAME_MODE_MAIN);
+
+ DrawMainMenu();
+
+ return num_tapes_uploaded;
+}
+
+static boolean OfferUploadTapes(void)
+{
+ if (!Request("Upload all your tapes to the high score server now?", REQ_ASK))
+ return FALSE;
+
+ int num_tapes_uploaded = UploadTapes();
+ char message[100];
+
+ if (num_tapes_uploaded < 0)
+ {
+ Request("Cannot upload tapes to score server!", REQ_CONFIRM);
+
+ return FALSE;
+ }
+
+ if (num_tapes_uploaded == 0)
+ sprintf(message, "No tapes uploaded!");
+ else if (num_tapes_uploaded == 1)
+ sprintf(message, "1 tape uploaded!");
+ else
+ sprintf(message, "%d tapes uploaded!", num_tapes_uploaded);
+
+ Request(message, REQ_CONFIRM);
+
+ // after all tapes have been uploaded, remove entry from setup menu
+ setup.provide_uploading_tapes = FALSE;
+
+ SaveSetup();
+
+ return TRUE;
+}
+
+void CheckUploadTapes(void)
+{
+ if (!setup.ask_for_uploading_tapes)
+ return;
+
+ // after asking for uploading all tapes once, do not ask again
+ setup.ask_for_uploading_tapes = FALSE;
+
+ if (directoryExists(getTapeDir(NULL)))
+ {
+ boolean tapes_uploaded = OfferUploadTapes();
+
+ if (!tapes_uploaded)
+ Request("You can upload your tapes from the setup menu later!",
+ REQ_CONFIRM);
+ }
+ else
+ {
+ // if tapes directory does not exist yet, never offer uploading all tapes
+ setup.provide_uploading_tapes = FALSE;
+ }
+
+ SaveSetup();
+}