&li.time_score_base, 1
},
+ {
+ -1, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(13),
+ &li.rate_time_over_score, FALSE
+ },
+
{
-1, -1,
-1, -1,
level->time_wheel = 0;
level->amoeba_content = EL_EMPTY;
-#if 1
- // original Supaplex does not use score values -- use default values
-#else
+ // original Supaplex does not use score values -- rate by playing time
for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
level->score[i] = 0;
-#endif
+
+ level->rate_time_over_score = TRUE;
// there are no yamyams in supaplex levels
for (i = 0; i < level->num_yamyam_contents; i++)
element_info[element].ignition_delay = 8;
}
}
+
+ // set mouse click change events to work for left/middle/right mouse button
+ if (level->game_version < VERSION_IDENT(4,2,3,0))
+ {
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ struct ElementChangeInfo *change = &ei->change_page[j];
+
+ if (change->has_event[CE_CLICKED_BY_MOUSE] ||
+ change->has_event[CE_PRESSED_BY_MOUSE] ||
+ change->has_event[CE_MOUSE_CLICKED_ON_X] ||
+ change->has_event[CE_MOUSE_PRESSED_ON_X])
+ change->trigger_side = CH_SIDE_ANY;
+ }
+ }
+ }
}
static void LoadLevel_InitElements(struct LevelInfo *level)
SetFilePermissions(filename, PERMS_PRIVATE);
}
-void SaveTape(int nr)
+static void SaveTapeExt(char *filename)
{
- char *filename = getTapeFilename(nr);
int i;
- InitTapeDirectory(leveldir_current->subdir);
-
tape.file_version = FILE_VERSION_ACTUAL;
tape.game_version = GAME_VERSION_ACTUAL;
tape.changed = FALSE;
}
+void SaveTape(int nr)
+{
+ char *filename = getTapeFilename(nr);
+
+ InitTapeDirectory(leveldir_current->subdir);
+
+ SaveTapeExt(filename);
+}
+
+void SaveScoreTape(int nr)
+{
+ char *filename = getScoreTapeFilename(tape.score_tape_basename, nr);
+
+ // used instead of "leveldir_current->subdir" (for network games)
+ InitScoreTapeDirectory(levelset.identifier, nr);
+
+ SaveTapeExt(filename);
+}
+
static boolean SaveTapeCheckedExt(int nr, char *msg_replace, char *msg_saved,
unsigned int req_state_added)
{
for (i = 0; i < MAX_SCORE_ENTRIES; i++)
{
- strcpy(highscore[i].Name, EMPTY_PLAYER_NAME);
- highscore[i].Score = 0;
+ strcpy(scores.entry[i].tape_basename, UNDEFINED_FILENAME);
+ strcpy(scores.entry[i].name, EMPTY_PLAYER_NAME);
+ scores.entry[i].score = 0;
+ scores.entry[i].time = 0;
}
}
for (i = 0; i < MAX_SCORE_ENTRIES; i++)
{
- if (fscanf(file, "%d", &highscore[i].Score) == EOF)
+ if (fscanf(file, "%d", &scores.entry[i].score) == EOF)
Warn("fscanf() failed; %s", strerror(errno));
if (fgets(line, MAX_LINE_LEN, file) == NULL)
{
if (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != '\0')
{
- strncpy(highscore[i].Name, line_ptr, MAX_PLAYER_NAME_LEN);
- highscore[i].Name[MAX_PLAYER_NAME_LEN] = '\0';
+ strncpy(scores.entry[i].name, line_ptr, MAX_PLAYER_NAME_LEN);
+ scores.entry[i].name[MAX_PLAYER_NAME_LEN] = '\0';
break;
}
}
fclose(file);
}
+static void ConvertScore_OLD(void)
+{
+ // only convert score to time for levels that rate playing time over score
+ if (!level.rate_time_over_score)
+ return;
+
+ // convert old score to playing time for score-less levels (like Supaplex)
+ int time_final_max = 999;
+ int i;
+
+ for (i = 0; i < MAX_SCORE_ENTRIES; i++)
+ {
+ int score = scores.entry[i].score;
+
+ if (score > 0 && score < time_final_max)
+ scores.entry[i].time = (time_final_max - score - 1) * FRAMES_PER_SECOND;
+ }
+}
+
static int LoadScore_VERS(File *file, int chunk_size, struct ScoreInfo *scores)
{
scores->file_version = getFileVersion(file);
for (i = 0; i < scores->num_entries; i++)
{
for (j = 0; j < MAX_PLAYER_NAME_LEN; j++)
- highscore[i].Name[j] = getFile8Bit(file);
+ scores->entry[i].name[j] = getFile8Bit(file);
- highscore[i].Name[MAX_PLAYER_NAME_LEN] = '\0';
+ scores->entry[i].name[MAX_PLAYER_NAME_LEN] = '\0';
}
chunk_size = scores->num_entries * MAX_PLAYER_NAME_LEN;
int i;
for (i = 0; i < scores->num_entries; i++)
- highscore[i].Score = getFile16BitBE(file);
+ scores->entry[i].score = getFile16BitBE(file);
chunk_size = scores->num_entries * 2;
return chunk_size;
}
+static int LoadScore_TIME(File *file, int chunk_size, struct ScoreInfo *scores)
+{
+ int i;
+
+ for (i = 0; i < scores->num_entries; i++)
+ scores->entry[i].time = getFile32BitBE(file);
+
+ chunk_size = scores->num_entries * 4;
+
+ return chunk_size;
+}
+
+static int LoadScore_TAPE(File *file, int chunk_size, struct ScoreInfo *scores)
+{
+ int i, j;
+
+ for (i = 0; i < scores->num_entries; i++)
+ {
+ for (j = 0; j < MAX_SCORE_TAPE_BASENAME_LEN; j++)
+ scores->entry[i].tape_basename[j] = getFile8Bit(file);
+
+ scores->entry[i].tape_basename[MAX_SCORE_TAPE_BASENAME_LEN] = '\0';
+ }
+
+ chunk_size = scores->num_entries * MAX_SCORE_TAPE_BASENAME_LEN;
+
+ return chunk_size;
+}
+
void LoadScore(int nr)
{
char *filename = getScoreFilename(nr);
{
// score files from versions before 4.2.4.0 without chunk structure
LoadScore_OLD(nr);
+
+ // convert score to time, if possible (mainly for Supaplex levels)
+ ConvertScore_OLD();
}
else
{
{ "INFO", -1, LoadScore_INFO },
{ "NAME", -1, LoadScore_NAME },
{ "SCOR", -1, LoadScore_SCOR },
+ { "TIME", -1, LoadScore_TIME },
+ { "TAPE", -1, LoadScore_TAPE },
{ NULL, 0, NULL }
};
fprintf(file, "%s\n\n", SCORE_COOKIE);
for (i = 0; i < MAX_SCORE_ENTRIES; i++)
- fprintf(file, "%d %s\n", highscore[i].Score, highscore[i].Name);
+ fprintf(file, "%d %s\n", scores.entry[i].score, scores.entry[i].name);
fclose(file);
for (i = 0; i < scores->num_entries; i++)
{
- int name_size = strlen(highscore[i].Name);
+ int name_size = strlen(scores->entry[i].name);
for (j = 0; j < MAX_PLAYER_NAME_LEN; j++)
- putFile8Bit(file, (j < name_size ? highscore[i].Name[j] : 0));
+ putFile8Bit(file, (j < name_size ? scores->entry[i].name[j] : 0));
}
}
int i;
for (i = 0; i < scores->num_entries; i++)
- putFile16BitBE(file, highscore[i].Score);
+ putFile16BitBE(file, scores->entry[i].score);
+}
+
+static void SaveScore_TIME(FILE *file, struct ScoreInfo *scores)
+{
+ int i;
+
+ for (i = 0; i < scores->num_entries; i++)
+ putFile32BitBE(file, scores->entry[i].time);
+}
+
+static void SaveScore_TAPE(FILE *file, struct ScoreInfo *scores)
+{
+ int i, j;
+
+ for (i = 0; i < scores->num_entries; i++)
+ {
+ int size = strlen(scores->entry[i].tape_basename);
+
+ for (j = 0; j < MAX_SCORE_TAPE_BASENAME_LEN; j++)
+ putFile8Bit(file, (j < size ? scores->entry[i].tape_basename[j] : 0));
+ }
}
static void SaveScoreToFilename(char *filename)
int info_chunk_size;
int name_chunk_size;
int scor_chunk_size;
+ int time_chunk_size;
+ int tape_chunk_size;
if (!(file = fopen(filename, MODE_WRITE)))
{
info_chunk_size = 2 + (strlen(scores.level_identifier) + 1) + 2 + 2;
name_chunk_size = scores.num_entries * MAX_PLAYER_NAME_LEN;
scor_chunk_size = scores.num_entries * 2;
+ time_chunk_size = scores.num_entries * 4;
+ tape_chunk_size = scores.num_entries * MAX_SCORE_TAPE_BASENAME_LEN;
putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
putFileChunkBE(file, "SCOR", CHUNK_SIZE_NONE);
putFileChunkBE(file, "SCOR", scor_chunk_size);
SaveScore_SCOR(file, &scores);
+ putFileChunkBE(file, "TIME", time_chunk_size);
+ SaveScore_TIME(file, &scores);
+
+ putFileChunkBE(file, "TAPE", tape_chunk_size);
+ SaveScore_TAPE(file, &scores);
+
fclose(file);
SetFilePermissions(filename, permissions);
scores.level_nr = level_nr;
for (i = 0; i < MAX_SCORE_ENTRIES; i++)
- if (highscore[i].Score == 0 &&
- strEqual(highscore[i].Name, EMPTY_PLAYER_NAME))
+ if (scores.entry[i].score == 0 &&
+ scores.entry[i].time == 0 &&
+ strEqual(scores.entry[i].name, EMPTY_PLAYER_NAME))
break;
scores.num_entries = i;