fixed bug with gray ball creating wrong game elements in MM engine
[rocksndiamonds.git] / src / game_mm / mm_game.c
index 8583a9a7d7d056e43e13b3e2bcc80ffefe35af3a..e822706ff9a00902ee49de8dc9fd5115aef8d05a 100644 (file)
@@ -644,8 +644,6 @@ void InitGameEngine_MM(void)
   game_mm.laser_green = FALSE;
   game_mm.laser_blue = TRUE;
 
-  game_mm.lightball_rnd = TRUE;
-
   game_mm.level_solved = FALSE;
   game_mm.game_over = FALSE;
   game_mm.game_over_cause = 0;
@@ -716,8 +714,6 @@ void InitGameActions_MM(void)
 
   InitLaser();
 
-  game_mm.lightball_rnd = FALSE;
-
   for (i = 0; i <= num_init_game_frames; i++)
   {
     if (i == num_init_game_frames)
@@ -753,8 +749,6 @@ void InitGameActions_MM(void)
 #endif
   }
 
-  game_mm.lightball_rnd = TRUE;
-
   ScanLaser();
 
   if (game_mm.kettles_still_needed == 0)
@@ -763,7 +757,11 @@ void InitGameActions_MM(void)
   SetTileCursorXY(laser.start_edge.x, laser.start_edge.y);
   SetTileCursorActive(TRUE);
 
+  // restart all delay counters after initially cycling game elements
+  ResetFrameCounter(&rotate_delay);
+  ResetFrameCounter(&pacman_delay);
   ResetFrameCounter(&energy_delay);
+  ResetFrameCounter(&overload_delay);
 }
 
 static void FadeOutLaser(void)
@@ -827,6 +825,13 @@ void AddLaserEdge(int lx, int ly)
 
 void AddDamagedField(int ex, int ey)
 {
+  // prevent adding the same field position again
+  if (laser.num_damages > 0 &&
+      laser.damage[laser.num_damages - 1].x == ex &&
+      laser.damage[laser.num_damages - 1].y == ey &&
+      laser.damage[laser.num_damages - 1].edge == laser.num_edges)
+    return;
+
   laser.damage[laser.num_damages].is_mirror = FALSE;
   laser.damage[laser.num_damages].angle = laser.current_angle;
   laser.damage[laser.num_damages].edge = laser.num_edges;
@@ -1658,9 +1663,11 @@ boolean HitElement(int element, int hit_mask)
       element == EL_KEY ||
       element == EL_LIGHTBALL ||
       element == EL_PACMAN ||
-      IS_PACMAN(element))
+      IS_PACMAN(element) ||
+      IS_ENVELOPE(element))
   {
-    if (!IS_PACMAN(element))
+    if (!IS_PACMAN(element) &&
+       !IS_ENVELOPE(element))
       Bang_MM(ELX, ELY);
 
     if (element == EL_PACMAN)
@@ -1688,6 +1695,10 @@ boolean HitElement(int element, int hit_mask)
     {
       DeletePacMan(ELX, ELY);
     }
+    else if (IS_ENVELOPE(element))
+    {
+      Tile[ELX][ELY] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(Tile[ELX][ELY]);
+    }
 
     RaiseScoreElement_MM(element);
 
@@ -2477,6 +2488,42 @@ static void OpenSurpriseBall(int x, int y)
   }
 }
 
+static void OpenEnvelope(int x, int y)
+{
+  int num_frames = 8;          // seven frames plus final empty space
+
+  if (!MovDelay[x][y])         // next animation frame
+    MovDelay[x][y] = num_frames;
+
+  if (MovDelay[x][y])          // wait some time before next frame
+  {
+    int nr = ENVELOPE_OPENING_NR(Tile[x][y]);
+
+    MovDelay[x][y]--;
+
+    if (MovDelay[x][y] > 0 && IN_SCR_FIELD(x, y))
+    {
+      int graphic = el_act2gfx(EL_ENVELOPE_1 + nr, MM_ACTION_COLLECTING);
+      int frame = num_frames - MovDelay[x][y] - 1;
+
+      DrawGraphicAnimation_MM(x, y, graphic, frame);
+
+      laser.redraw = TRUE;
+    }
+
+    if (MovDelay[x][y] == 0)
+    {
+      Tile[x][y] = EL_EMPTY;
+
+      DrawField_MM(x, y);
+
+      ScanLaser();
+
+      ShowEnvelope_MM(nr);
+    }
+  }
+}
+
 static void MeltIce(int x, int y)
 {
   int frames = 5;
@@ -2978,6 +3025,12 @@ boolean ClickElement(int x, int y, int button)
 
     element_clicked = TRUE;
   }
+  else if (IS_ENVELOPE(element))
+  {
+    Tile[x][y] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(element);
+
+    element_clicked = TRUE;
+  }
 
   click_delay.value = (new_button ? CLICK_DELAY_FIRST : CLICK_DELAY);
   new_button = FALSE;
@@ -3060,8 +3113,6 @@ void RotateMirror(int x, int y, int button)
         IS_POLAR(Tile[x][y]) ||
         IS_POLAR_CROSS(Tile[x][y])) && x == ELX && y == ELY)
     {
-      check = 0;
-
       if (IS_BEAMER(Tile[x][y]))
       {
 #if 0
@@ -3069,12 +3120,13 @@ void RotateMirror(int x, int y, int button)
              LX, LY, laser.beamer_edge, laser.beamer[1].num);
 #endif
 
-#if 0
-       laser.num_edges--;
-#endif
+       if (check == 1)
+         laser.num_edges--;
       }
 
       ScanLaser();
+
+      check = 0;
     }
 
     if (check == 2)
@@ -3235,6 +3287,8 @@ static void GameActions_MM_Ext(void)
       OpenExit(x, y);
     else if (element == EL_GRAY_BALL_OPENING)
       OpenSurpriseBall(x, y);
+    else if (IS_ENVELOPE_OPENING(element))
+      OpenEnvelope(x, y);
     else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_ICE)
       MeltIce(x, y);
     else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA)
@@ -3437,7 +3491,7 @@ static void GameActions_MM_Ext(void)
 
       int new_element = native_mm_level.ball_content[element_pos];
 
-      Store[ELX][ELY] = new_element + RND(get_num_elements(new_element));
+      Store[ELX][ELY] = get_rotated_element(new_element, RND(16));
       Store2[ELX][ELY] = TRUE;
     }