added saving tape basename for each high score entry
[rocksndiamonds.git] / src / files.c
index 133a2d2609b2515de8b5eeb3edf82d34ae65a798..a4f7f10a786f31803e77ae160a858778a96e86c9 100644 (file)
@@ -3938,12 +3938,11 @@ static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
   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++)
@@ -6611,6 +6610,27 @@ static void LoadLevel_InitCustomElements(struct LevelInfo *level)
       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)
@@ -8275,13 +8295,10 @@ void SaveTapeToFilename(char *filename)
   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;
 
@@ -8297,6 +8314,25 @@ void SaveTape(int nr)
   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)
 {
@@ -8394,6 +8430,7 @@ static void setScoreInfoToDefaults(void)
 
   for (i = 0; i < MAX_SCORE_ENTRIES; i++)
   {
+    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;
@@ -8452,6 +8489,25 @@ static void LoadScore_OLD(int nr)
   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);
@@ -8527,6 +8583,23 @@ static int LoadScore_TIME(File *file, int chunk_size, struct ScoreInfo *scores)
   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);
@@ -8581,6 +8654,9 @@ void LoadScore(int 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
   {
@@ -8597,6 +8673,7 @@ void LoadScore(int nr)
       { "NAME", -1,                    LoadScore_NAME },
       { "SCOR", -1,                    LoadScore_SCOR },
       { "TIME", -1,                    LoadScore_TIME },
+      { "TAPE", -1,                    LoadScore_TAPE },
 
       {  NULL,  0,                     NULL }
     };
@@ -8723,6 +8800,19 @@ static void SaveScore_TIME(FILE *file, struct ScoreInfo *scores)
     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)
 {
   FILE *file;
@@ -8731,6 +8821,7 @@ static void SaveScoreToFilename(char *filename)
   int name_chunk_size;
   int scor_chunk_size;
   int time_chunk_size;
+  int tape_chunk_size;
 
   if (!(file = fopen(filename, MODE_WRITE)))
   {
@@ -8743,6 +8834,7 @@ static void SaveScoreToFilename(char *filename)
   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);
@@ -8762,6 +8854,9 @@ static void SaveScoreToFilename(char *filename)
   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);