added support for scheduling type in BD engine to level editor
[rocksndiamonds.git] / src / files.c
index 1cb235ced68f5daa059138da80c795251f411423..62069398a849b7b5aa877e95ead9b6a120ee4db1 100644 (file)
@@ -273,6 +273,24 @@ static struct LevelFileConfigInfo chunk_config_INFO[] =
     &li.rate_time_over_score,          FALSE
   },
 
+  {
+    -1,                                        -1,
+    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(14),
+    &li.bd_intermission,               FALSE
+  },
+
+  {
+    -1,                                        -1,
+    TYPE_INTEGER,                      CONF_VALUE_8_BIT(15),
+    &li.bd_scheduling_type,            GD_SCHEDULING_MILLISECONDS
+  },
+
+  {
+    -1,                                        -1,
+    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(16),
+    &li.bd_pal_timing,                 FALSE
+  },
+
   {
     -1,                                        -1,
     -1,                                        -1,
@@ -563,6 +581,21 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] =
     &li.initial_inventory_size[3],     1, MAX_INITIAL_INVENTORY_SIZE
   },
 
+  // (these values are only valid for BD style levels)
+  {
+    EL_BD_PLAYER,                      -1,
+    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(1),
+    &li.bd_diagonal_movements,         FALSE
+  },
+
+  {
+    EL_BD_DIAMOND,                     -1,
+    TYPE_INTEGER,                      CONF_VALUE_16_BIT(1),
+    &li.score[SC_DIAMOND_EXTRA],       20
+  },
+
+  // (the following values are related to various game elements)
+
   {
     EL_EMERALD,                                -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(1),
@@ -943,14 +976,6 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] =
     &li.score[SC_ELEM_BONUS],          10
   },
 
-  // ---------- unused values -------------------------------------------------
-
-  {
-    EL_UNKNOWN,                                SAVE_CONF_NEVER,
-    TYPE_INTEGER,                      CONF_VALUE_16_BIT(1),
-    &li.score[SC_UNKNOWN_15],          10
-  },
-
   {
     -1,                                        -1,
     -1,                                        -1,
@@ -2067,6 +2092,27 @@ static void ActivateLevelTemplate(void)
   }
 }
 
+static boolean checkForPackageFromBasename_BD(char *basename)
+{
+  // check for native BD level file extensions
+  if (!strSuffixLower(basename, ".bd") &&
+      !strSuffixLower(basename, ".bdr") &&
+      !strSuffixLower(basename, ".brc") &&
+      !strSuffixLower(basename, ".gds"))
+    return FALSE;
+
+  // check for standard single-level BD files (like "001.bd")
+  if (strSuffixLower(basename, ".bd") &&
+      strlen(basename) == 6 &&
+      basename[0] >= '0' && basename[0] <= '9' &&
+      basename[1] >= '0' && basename[1] <= '9' &&
+      basename[2] >= '0' && basename[2] <= '9')
+    return FALSE;
+
+  // this is a level package in native BD file format
+  return TRUE;
+}
+
 static char *getLevelFilenameFromBasename(char *basename)
 {
   static char *filename = NULL;
@@ -2102,10 +2148,7 @@ static int getFileTypeFromBasename(char *basename)
     return LEVEL_FILE_TYPE_SB;
 
   // check for typical filename of a Boulder Dash (GDash) level package file
-  if (strSuffixLower(basename, ".bd") ||
-      strSuffixLower(basename, ".bdr") ||
-      strSuffixLower(basename, ".brc") ||
-      strSuffixLower(basename, ".gds"))
+  if (checkForPackageFromBasename_BD(basename))
     return LEVEL_FILE_TYPE_BD;
 
   // ---------- try to determine file type from filesize ----------
@@ -2367,6 +2410,11 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
   if (fileExists(lfi->filename))
     return;
 
+  // check for native Boulder Dash level file
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_BD, "%03d.bd", nr);
+  if (fileExists(lfi->filename))
+    return;
+
   // check for Emerald Mine level file (V1)
   setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "a%c%c",
                                       'a' + (nr / 10) % 26, '0' + nr % 10);
@@ -3682,11 +3730,16 @@ static void CopyNativeLevel_RND_to_BD(struct LevelInfo *level)
     cave->level_timevalue[i]           = level->score[SC_TIME_BONUS];
   }
 
-  cave->diamond_value                  = level->score[SC_DIAMOND];
-  cave->extra_diamond_value            = level->score[SC_DIAMOND];
+  cave->diamond_value                  = level->score[SC_EMERALD];
+  cave->extra_diamond_value            = level->score[SC_DIAMOND_EXTRA];
 
   cave->level_speed[0]                 = 160;  // set cave speed
 
+  cave->scheduling                     = level->bd_scheduling_type;
+  cave->pal_timing                     = level->bd_pal_timing;
+  cave->intermission                   = level->bd_intermission;
+  cave->diagonal_movements             = level->bd_diagonal_movements;
+
   strncpy(cave->name, level->name, sizeof(GdString));
   cave->name[sizeof(GdString) - 1] = '\0';
 
@@ -3705,12 +3758,18 @@ static void CopyNativeLevel_BD_to_RND(struct LevelInfo *level)
   level->fieldx = MIN(cave->w, MAX_LEV_FIELDX);
   level->fieldy = MIN(cave->h, MAX_LEV_FIELDY);
 
-  level->time                  = cave->level_time[bd_level_nr];
-  level->gems_needed           = cave->level_diamonds[bd_level_nr];
-  level->time_magic_wall       = cave->level_magic_wall_time[bd_level_nr];
+  level->time                          = cave->level_time[bd_level_nr];
+  level->gems_needed                   = cave->level_diamonds[bd_level_nr];
+  level->time_magic_wall               = cave->level_magic_wall_time[bd_level_nr];
+
+  level->score[SC_TIME_BONUS]          = cave->level_timevalue[bd_level_nr];
+  level->score[SC_EMERALD]             = cave->diamond_value;
+  level->score[SC_DIAMOND_EXTRA]       = cave->extra_diamond_value;
 
-  level->score[SC_TIME_BONUS]  = cave->level_timevalue[bd_level_nr];
-  level->score[SC_DIAMOND]     = cave->diamond_value;
+  level->bd_scheduling_type            = cave->scheduling;
+  level->bd_pal_timing                 = cave->pal_timing;
+  level->bd_intermission               = cave->intermission;
+  level->bd_diagonal_movements         = cave->diagonal_movements;
 
   strncpy(level->name, cave->name, MAX_LEVEL_NAME_LEN);
   level->name[MAX_LEVEL_NAME_LEN] = '\0';
@@ -6491,16 +6550,40 @@ void CopyNativeLevel_Native_to_RND(struct LevelInfo *level)
 
 void SaveNativeLevel(struct LevelInfo *level)
 {
-  if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
+  // saving native level files only supported for some game engines
+  if (level->game_engine_type != GAME_ENGINE_TYPE_BD &&
+      level->game_engine_type != GAME_ENGINE_TYPE_SP)
+    return;
+
+  char *file_ext = (level->game_engine_type == GAME_ENGINE_TYPE_BD ? "bd" :
+                   level->game_engine_type == GAME_ENGINE_TYPE_SP ? "sp" : "");
+  char *basename = getSingleLevelBasenameExt(level->file_info.nr, file_ext);
+  char *filename = getLevelFilenameFromBasename(basename);
+
+  if (fileExists(filename) && !Request("Native level file already exists! Overwrite it?", REQ_ASK))
+    return;
+
+  boolean success = FALSE;
+
+  if (level->game_engine_type == GAME_ENGINE_TYPE_BD)
   {
-    char *basename = getSingleLevelBasenameExt(level->file_info.nr, "sp");
-    char *filename = getLevelFilenameFromBasename(basename);
+    CopyNativeLevel_RND_to_BD(level);
+    // CopyNativeTape_RND_to_BD(level);
 
+    success = SaveNativeLevel_BD(filename);
+  }
+  else if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
+  {
     CopyNativeLevel_RND_to_SP(level);
     CopyNativeTape_RND_to_SP(level);
 
-    SaveNativeLevel_SP(filename);
+    success = SaveNativeLevel_SP(filename);
   }
+
+  if (success)
+    Request("Native level file saved!", REQ_CONFIRM);
+  else
+    Request("Failed to save native level file!", REQ_CONFIRM);
 }