added configurable delay times for some MM style elements (MM engine)
[rocksndiamonds.git] / src / game_mm / mm_game.c
index 543be639102099ba2c1f5bad4e9d52e62e972476..bb579712588767f19b1536b968c009973a61e1b9 100644 (file)
@@ -92,6 +92,7 @@
 static int MovingOrBlocked2Element_MM(int, int);
 static void Bang_MM(int, int);
 static void RaiseScore_MM(int);
+static void RaiseScoreElement_MM(int);
 static void RemoveMovingField_MM(int, int);
 static void InitMovingField_MM(int, int, int);
 static void ContinueMoving_MM(int, int);
@@ -354,6 +355,60 @@ static boolean CheckLaserPixel(int x, int y)
   return (pixel == WHITE_PIXEL);
 }
 
+static void CheckExitMM()
+{
+  int exit_element = EL_EMPTY;
+  int exit_x = 0;
+  int exit_y = 0;
+  int x, y;
+  static int xy[4][2] =
+  {
+    { +1,  0 },
+    {  0, -1 },
+    { -1,  0 },
+    {  0, +1 }
+  };
+
+  for (y = 0; y < lev_fieldy; y++)
+  {
+    for (x = 0; x < lev_fieldx; x++)
+    {
+      if (Feld[x][y] == EL_EXIT_CLOSED)
+      {
+       /* initiate opening animation of exit door */
+       Feld[x][y] = EL_EXIT_OPENING;
+
+       exit_element = EL_EXIT_OPEN;
+       exit_x = x;
+       exit_y = y;
+      }
+      else if (IS_RECEIVER(Feld[x][y]))
+      {
+       /* remove field that blocks receiver */
+       int phase = Feld[x][y] - EL_RECEIVER_START;
+       int blocking_x, blocking_y;
+
+       blocking_x = x + xy[phase][0];
+       blocking_y = y + xy[phase][1];
+
+       if (IN_LEV_FIELD(blocking_x, blocking_y))
+       {
+         Feld[blocking_x][blocking_y] = EL_EMPTY;
+
+         DrawField_MM(blocking_x, blocking_y);
+       }
+
+       exit_element = EL_RECEIVER;
+       exit_x = x;
+       exit_y = y;
+      }
+    }
+  }
+
+  if (exit_element != EL_EMPTY)
+    PlayLevelSound_MM(exit_x, exit_y, exit_element, MM_ACTION_OPENING);
+}
+
 static void InitMovDir_MM(int x, int y)
 {
   int element = Feld[x][y];
@@ -551,6 +606,7 @@ void InitGameEngine_MM()
   game_mm.game_over_cause = 0;
 
   game_mm.laser_overload_value = 0;
+  game_mm.laser_enabled = FALSE;
 
   /* set global laser control values (must be set before "InitLaser()") */
   laser.start_edge.x = 0;
@@ -683,6 +739,9 @@ void InitGameActions_MM()
 #endif
 
   ScanLaser();
+
+  if (game_mm.kettles_still_needed == 0)
+    CheckExitMM();
 }
 
 void AddLaserEdge(int lx, int ly)
@@ -1239,7 +1298,7 @@ void DrawLaser(int start_edge, int mode)
       int num_beamers = laser.num_beamers;
 
       /* delete laser segments backward from the end to the first beamer */
-      for (i = num_beamers-1; i >= 0; i--)
+      for (i = num_beamers - 1; i >= 0; i--)
       {
        int tmp_num_edges = last_num_edges - laser.beamer_edge[i];
 
@@ -1271,6 +1330,13 @@ void DrawLaser(int start_edge, int mode)
   {
     DrawLaserExt(start_edge, laser.num_edges - start_edge, mode);
   }
+
+  game_mm.laser_enabled = mode;
+}
+
+void DrawLaser_MM()
+{
+  DrawLaser(0, game_mm.laser_enabled);
 }
 
 boolean HitElement(int element, int hit_mask)
@@ -1470,48 +1536,9 @@ boolean HitElement(int element, int hit_mask)
       if (game_mm.kettles_still_needed > 0)
        game_mm.kettles_still_needed--;
 
-      RaiseScore_MM(10);
-
       if (game_mm.kettles_still_needed == 0)
       {
-       int exit_element = (element == EL_KETTLE ? EL_EXIT_OPEN : EL_RECEIVER);
-       int x, y;
-       static int xy[4][2] =
-       {
-         { +1,  0 },
-         {  0, -1 },
-         { -1,  0 },
-         {  0, +1 }
-       };
-
-       PlayLevelSound_MM(ELX, ELY, exit_element, MM_ACTION_OPENING);
-
-       for (y = 0; y < lev_fieldy; y++)
-       {
-         for (x = 0; x < lev_fieldx; x++)
-         {
-           /* initiate opening animation of exit door */
-           if (Feld[x][y] == EL_EXIT_CLOSED)
-             Feld[x][y] = EL_EXIT_OPENING;
-
-           /* remove field that blocks receiver */
-           if (IS_RECEIVER(Feld[x][y]))
-           {
-             int phase = Feld[x][y] - EL_RECEIVER_START;
-             int blocking_x, blocking_y;
-
-             blocking_x = x + xy[phase][0];
-             blocking_y = y + xy[phase][1];
-
-             if (IN_LEV_FIELD(blocking_x, blocking_y))
-             {
-               Feld[blocking_x][blocking_y] = EL_EMPTY;
-
-               DrawField_MM(blocking_x, blocking_y);
-             }
-           }
-         }
-       }
+       CheckExitMM();
 
        DrawLaser(0, DL_LASER_ENABLED);
       }
@@ -1520,16 +1547,13 @@ boolean HitElement(int element, int hit_mask)
     {
       game_mm.num_keys++;
     }
-    else if (element == EL_LIGHTBALL)
-    {
-      RaiseScore_MM(10);
-    }
     else if (IS_PACMAN(element))
     {
       DeletePacMan(ELX, ELY);
-      RaiseScore_MM(50);
     }
 
+    RaiseScoreElement_MM(element);
+
     return FALSE;
   }
 
@@ -2801,7 +2825,7 @@ void ClickElement(int x, int y, int button)
   else if (element == EL_LIGHTBALL)
   {
     Bang_MM(x, y);
-    RaiseScore_MM(10);
+    RaiseScoreElement_MM(element);
     DrawLaser(0, DL_LASER_ENABLED);
   }
 
@@ -3279,7 +3303,7 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode)
 
   CT -= Ct;
 
-  if (element == EL_BOMB && CT > 75)
+  if (element == EL_BOMB && CT > native_mm_level.time_bomb)
   {
     if (game_mm.cheat_no_explosion)
       return;
@@ -3317,7 +3341,7 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode)
     return;
   }
 
-  if (element == EL_FUSE_ON && CT > 25)
+  if (element == EL_FUSE_ON && CT > native_mm_level.time_fuse)
   {
     laser.fuse_off = TRUE;
     laser.fuse_x = ELX;
@@ -3327,7 +3351,7 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode)
     DrawGraphic_MM(ELX, ELY, IMG_MM_FUSE);
   }
 
-  if (element == EL_BALL_GRAY && CT > 75)
+  if (element == EL_BALL_GRAY && CT > native_mm_level.time_ball)
   {
     static int new_elements[] =
     {
@@ -3614,7 +3638,7 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode)
   }
 
   if ((element == EL_BLOCK_WOOD || element == EL_BLOCK_STONE) &&
-      laser.stops_inside_element && CT > 75)
+      laser.stops_inside_element && CT > native_mm_level.time_block)
   {
     int x, y;
     int k;
@@ -3873,7 +3897,7 @@ void GameWon_MM()
       if (!setup.sound_loops)
        PlaySoundStereo(SND_SIRR, SOUND_MAX_RIGHT);
       if (TimePlayed < 999 && !(TimePlayed % 10))
-       RaiseScore_MM(native_mm_level.score[SC_ZEITBONUS]);
+       RaiseScore_MM(native_mm_level.score[SC_TIME_BONUS]);
       if (TimePlayed < 900 && !(TimePlayed % 10))
        TimePlayed += 10;
       else
@@ -4142,6 +4166,10 @@ void RaiseScoreElement_MM(int element)
   switch(element)
   {
     case EL_PACMAN:
+    case EL_PACMAN_RIGHT:
+    case EL_PACMAN_UP:
+    case EL_PACMAN_LEFT:
+    case EL_PACMAN_DOWN:
       RaiseScore_MM(native_mm_level.score[SC_PACMAN]);
       break;
 
@@ -4149,6 +4177,15 @@ void RaiseScoreElement_MM(int element)
       RaiseScore_MM(native_mm_level.score[SC_KEY]);
       break;
 
+    case EL_KETTLE:
+    case EL_CELL:
+      RaiseScore_MM(native_mm_level.score[SC_COLLECTIBLE]);
+      break;
+
+    case EL_LIGHTBALL:
+      RaiseScore_MM(native_mm_level.score[SC_LIGHTBALL]);
+      break;
+
     default:
       break;
   }