renamed function for game element in MM engine
[rocksndiamonds.git] / src / game_mm / mm_game.c
index 2805fb77d3af6f33e4bebc4ce3967b61de5bf956..39807089220c07c13f880f356ee1445aa7f5c137 100644 (file)
@@ -951,6 +951,7 @@ static void DeactivateLaserTargetElement(void)
 {
   if (laser.dest_element_last == EL_BOMB_ACTIVE ||
       laser.dest_element_last == EL_MINE_ACTIVE ||
+      laser.dest_element_last == EL_GRAY_BALL_ACTIVE ||
       laser.dest_element_last == EL_GRAY_BALL_OPENING)
   {
     int x = laser.dest_element_last_x;
@@ -959,9 +960,9 @@ static void DeactivateLaserTargetElement(void)
 
     if (Tile[x][y] == element)
       Tile[x][y] = (element == EL_BOMB_ACTIVE ? EL_BOMB :
-                   element == EL_MINE_ACTIVE ? EL_MINE : EL_BALL_GRAY);
+                   element == EL_MINE_ACTIVE ? EL_MINE : EL_GRAY_BALL);
 
-    if (Tile[x][y] == EL_BALL_GRAY)
+    if (Tile[x][y] == EL_GRAY_BALL)
       MovDelay[x][y] = 0;
 
     laser.dest_element_last = EL_EMPTY;
@@ -1185,6 +1186,22 @@ void ScanLaser(void)
 #endif
 }
 
+static void ScanLaser_FromLastMirror(void)
+{
+  int start_pos = (laser.num_damages > 0 ? laser.num_damages - 1 : 0);
+  int i;
+
+  for (i = start_pos; i >= 0; i--)
+    if (laser.damage[i].is_mirror)
+      break;
+
+  int start_edge = (i > 0 ? laser.damage[i].edge - 1 : 0);
+
+  DrawLaser(start_edge, DL_LASER_DISABLED);
+
+  ScanLaser();
+}
+
 static void DrawLaserExt(int start_edge, int num_edges, int mode)
 {
   int element;
@@ -1652,11 +1669,13 @@ boolean HitElement(int element, int hit_mask)
     return TRUE;
   }
 
-  if (element == EL_BOMB || element == EL_MINE)
+  if (element == EL_BOMB || element == EL_MINE || element == EL_GRAY_BALL)
   {
     PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_HITTING);
 
-    Tile[ELX][ELY] = (element == EL_BOMB ? EL_BOMB_ACTIVE : EL_MINE_ACTIVE);
+    Tile[ELX][ELY] = (element == EL_BOMB ? EL_BOMB_ACTIVE :
+                     element == EL_MINE ? EL_MINE_ACTIVE :
+                     EL_GRAY_BALL_ACTIVE);
 
     laser.dest_element_last = Tile[ELX][ELY];
     laser.dest_element_last_x = ELX;
@@ -2458,12 +2477,25 @@ static void OpenExit(int x, int y)
   }
 }
 
-static void OpenSurpriseBall(int x, int y)
+static void OpenGrayBall(int x, int y)
 {
   int delay = 2;
 
   if (!MovDelay[x][y])         // next animation frame
+  {
+    if (IS_WALL(Store[x][y]))
+    {
+      DrawWalls_MM(x, y, Store[x][y]);
+
+      // copy wall tile to spare bitmap for "melting" animation
+      BlitBitmap(drawto, bitmap_db_field, cSX + x * TILEX, cSY + y * TILEY,
+                TILEX, TILEY, x * TILEX, y * TILEY);
+
+      DrawElement_MM(x, y, EL_GRAY_BALL);
+    }
+
     MovDelay[x][y] = 50 * delay;
+  }
 
   if (MovDelay[x][y])          // wait some time before next frame
   {
@@ -2472,11 +2504,22 @@ static void OpenSurpriseBall(int x, int y)
     if (!(MovDelay[x][y] % delay) && IN_SCR_FIELD(x, y))
     {
       Bitmap *bitmap;
-      int graphic = el2gfx(Store[x][y]);
       int gx, gy;
       int dx = RND(26), dy = RND(26);
 
-      getGraphicSource(graphic, 0, &bitmap, &gx, &gy);
+      if (IS_WALL(Store[x][y]))
+      {
+       // copy wall tile from spare bitmap for "melting" animation
+       bitmap = bitmap_db_field;
+       gx = x * TILEX;
+       gy = y * TILEY;
+      }
+      else
+      {
+       int graphic = el2gfx(Store[x][y]);
+
+       getGraphicSource(graphic, 0, &bitmap, &gx, &gy);
+      }
 
       BlitBitmap(bitmap, drawto, gx + dx, gy + dy, 6, 6,
                 cSX + x * TILEX + dx, cSY + y * TILEY + dy);
@@ -2495,7 +2538,7 @@ static void OpenSurpriseBall(int x, int y)
       InitField(x, y, FALSE);
       DrawField_MM(x, y);
 
-      ScanLaser();
+      ScanLaser_FromLastMirror();
     }
   }
 }
@@ -2555,8 +2598,6 @@ static void MeltIce(int x, int y)
 
     if (!MovDelay[x][y])
     {
-      int i;
-
       Tile[x][y] = real_element & (wall_mask ^ 0xFF);
       Store[x][y] = Store2[x][y] = 0;
 
@@ -2565,16 +2606,7 @@ static void MeltIce(int x, int y)
       if (Tile[x][y] == EL_WALL_ICE)
        Tile[x][y] = EL_EMPTY;
 
-      for (i = (laser.num_damages > 0 ? laser.num_damages - 1 : 0); i >= 0; i--)
-       if (laser.damage[i].is_mirror)
-         break;
-
-      if (i > 0)
-       DrawLaser(laser.damage[i].edge - 1, DL_LASER_DISABLED);
-      else
-       DrawLaser(0, DL_LASER_DISABLED);
-
-      ScanLaser();
+      ScanLaser_FromLastMirror();
     }
     else if (!(MovDelay[x][y] % delay) && IN_SCR_FIELD(x, y))
     {
@@ -3295,7 +3327,7 @@ static void GameActions_MM_Ext(void)
     else if (element == EL_EXIT_OPENING)
       OpenExit(x, y);
     else if (element == EL_GRAY_BALL_OPENING)
-      OpenSurpriseBall(x, y);
+      OpenGrayBall(x, y);
     else if (IS_ENVELOPE_OPENING(element))
       OpenEnvelope(x, y);
     else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_ICE)
@@ -3306,7 +3338,7 @@ static void GameActions_MM_Ext(void)
             IS_MIRROR_FIXED(element) ||
             element == EL_PRISM)
       DrawFieldTwinkle(x, y);
-    else if (element == EL_GRAY_BALL_OPENING ||
+    else if (element == EL_GRAY_BALL_ACTIVE ||
             element == EL_BOMB_ACTIVE ||
             element == EL_MINE_ACTIVE)
       DrawFieldAnimated_MM(x, y);
@@ -3374,7 +3406,8 @@ static void GameActions_MM_Ext(void)
       element != EL_BOMB_ACTIVE &&
       element != EL_MINE &&
       element != EL_MINE_ACTIVE &&
-      element != EL_BALL_GRAY &&
+      element != EL_GRAY_BALL &&
+      element != EL_GRAY_BALL_ACTIVE &&
       element != EL_BLOCK_STONE &&
       element != EL_BLOCK_WOOD &&
       element != EL_FUSE_ON &&
@@ -3479,7 +3512,7 @@ static void GameActions_MM_Ext(void)
     DrawGraphic_MM(ELX, ELY, IMG_MM_FUSE);
   }
 
-  if (element == EL_BALL_GRAY && CT > native_mm_level.time_ball)
+  if (element == EL_GRAY_BALL && CT > native_mm_level.time_ball)
   {
     if (!Store2[ELX][ELY])     // check if content element not yet determined
     {
@@ -3499,10 +3532,19 @@ static void GameActions_MM_Ext(void)
       game_mm.ball_choice_pos++;
 
       int new_element = native_mm_level.ball_content[element_pos];
+      int new_element_unmapped = unmap_element(new_element);
 
-      // randomly rotate newly created game element, if needed
-      if (native_mm_level.rotate_ball_content)
+      if (IS_WALL(new_element_unmapped))
+      {
+       // always use completely filled wall element
+       new_element = new_element_unmapped | 0x000f;
+      }
+      else if (native_mm_level.rotate_ball_content &&
+              get_num_elements(new_element) > 1)
+      {
+       // randomly rotate newly created game element
        new_element = get_rotated_element(new_element, RND(16));
+      }
 
       Store[ELX][ELY] = new_element;
       Store2[ELX][ELY] = TRUE;
@@ -3510,12 +3552,7 @@ static void GameActions_MM_Ext(void)
 
     Tile[ELX][ELY] = EL_GRAY_BALL_OPENING;
 
-    // !!! CHECK AGAIN: Laser on Polarizer !!!
-    ScanLaser();
-
     laser.dest_element_last = Tile[ELX][ELY];
-    laser.dest_element_last_x = ELX;
-    laser.dest_element_last_y = ELY;
 
     return;
 
@@ -3648,16 +3685,7 @@ static void GameActions_MM_Ext(void)
     LY = laser.edge[laser.num_edges].y - cSY2;
 */
 
-    for (i = (laser.num_damages > 0 ? laser.num_damages - 1 : 0); i >= 0; i--)
-      if (laser.damage[i].is_mirror)
-       break;
-
-    if (i > 0)
-      DrawLaser(laser.damage[i].edge - 1, DL_LASER_DISABLED);
-    else
-      DrawLaser(0, DL_LASER_DISABLED);
-
-    ScanLaser();
+    ScanLaser_FromLastMirror();
 
     return;
   }