fixed bugs when re-charging laser with fuel element in MM engine
[rocksndiamonds.git] / src / game_mm / mm_game.c
index 9d32be5e813033793684fdcf3a1940cb3f43ed93..7ab1c98a3b8be997de2b995266bf14a0bf4df134 100644 (file)
@@ -411,6 +411,20 @@ static void CheckExitMM(void)
     PlayLevelSound_MM(exit_x, exit_y, exit_element, MM_ACTION_OPENING);
 }
 
+static void SetLaserColor(int brightness)
+{
+  int color_min = 0x00;
+  int color_max = brightness;          // (0x00 <= brightness <= 0xFF)
+  int color_up   = color_max * laser.overload_value / MAX_LASER_OVERLOAD;
+  int color_down = color_max - color_up;
+
+  pen_ray =
+    GetPixelFromRGB(window,
+                   (native_mm_level.laser_red   ? color_max  : color_up),
+                   (native_mm_level.laser_green ? color_down : color_min),
+                   (native_mm_level.laser_blue  ? color_down : color_min));
+}
+
 static void InitMovDir_MM(int x, int y)
 {
   int element = Tile[x][y];
@@ -573,10 +587,7 @@ static void InitLaser(void)
 
   AddLaserEdge(LX, LY);                // set laser starting edge
 
-  pen_ray = GetPixelFromRGB(window,
-                           native_mm_level.laser_red   * 0xFF,
-                           native_mm_level.laser_green * 0xFF,
-                           native_mm_level.laser_blue  * 0xFF);
+  SetLaserColor(0xFF);
 }
 
 void InitGameEngine_MM(void)
@@ -712,21 +723,17 @@ void InitGameActions_MM(void)
 
   SetTileCursorXY(laser.start_edge.x, laser.start_edge.y);
   SetTileCursorActive(TRUE);
+
+  ResetFrameCounter(&energy_delay);
 }
 
-static void FadeOutLaser(boolean overloaded)
+static void FadeOutLaser(void)
 {
   int i;
 
   for (i = 15; i >= 0; i--)
   {
-    if (overloaded)
-      pen_ray = GetPixelFromRGB(window, 0x11 * i, 0x00, 0x00);
-    else
-      pen_ray = GetPixelFromRGB(window,
-                               native_mm_level.laser_red   * 0x11 * i,
-                               native_mm_level.laser_green * 0x11 * i,
-                               native_mm_level.laser_blue  * 0x11 * i);
+    SetLaserColor(0x11 * i);
 
     DrawLaser(0, DL_LASER_ENABLED);
 
@@ -736,8 +743,7 @@ static void FadeOutLaser(boolean overloaded)
 
   DrawLaser(0, DL_LASER_DISABLED);
 
-  if (!overloaded)
-    StopSound_MM(SND_MM_GAME_HEALTH_CHARGING);
+  StopSound_MM(SND_MM_GAME_HEALTH_CHARGING);
 }
 
 static void GameOver_MM(int game_over_cause)
@@ -3196,22 +3202,21 @@ static void GameActions_MM_Ext(void)
   if (game_mm.game_over)
     return;
 
+  if (game_mm.energy_left == 0 && !game.no_level_time_limit && game.time_limit)
+  {
+    FadeOutLaser();
+
+    GameOver_MM(GAME_OVER_NO_ENERGY);
+
+    return;
+  }
+
   if (FrameReached(&energy_delay))
   {
     if (game_mm.energy_left > 0)
-    {
       game_mm.energy_left--;
 
-      redraw_mask |= REDRAW_DOOR_1;
-    }
-    else if (game.time_limit && !game_mm.game_over)
-    {
-      FadeOutLaser(FALSE);
-
-      GameOver_MM(GAME_OVER_NO_ENERGY);
-
-      return;
-    }
+    // when out of energy, wait another frame to play "out of time" sound
   }
 
   element = laser.dest_element;
@@ -3257,18 +3262,7 @@ static void GameActions_MM_Ext(void)
 
     if (laser.overload_value < MAX_LASER_OVERLOAD - 8)
     {
-      int color_up = 0xFF * laser.overload_value / MAX_LASER_OVERLOAD;
-      int color_down = 0xFF - color_up;
-
-#if 0
-      SetRGB(pen_ray, (laser.overload_value / 6) * color_scale, 0x0000,
-            (15 - (laser.overload_value / 6)) * color_scale);
-#endif
-      pen_ray =
-       GetPixelFromRGB(window,
-                       (native_mm_level.laser_red  ? 0xFF : color_up),
-                       (native_mm_level.laser_green ? color_down : 0x00),
-                       (native_mm_level.laser_blue  ? color_down : 0x00));
+      SetLaserColor(0xFF);
 
       DrawLaser(0, DL_LASER_ENABLED);
     }
@@ -3308,7 +3302,7 @@ static void GameActions_MM_Ext(void)
     {
       UpdateAndDisplayGameControlValues();
 
-      FadeOutLaser(TRUE);
+      FadeOutLaser();
 
       GameOver_MM(GAME_OVER_OVERLOADED);
 
@@ -3685,24 +3679,27 @@ static void GameActions_MM_Ext(void)
 
   if (element == EL_FUEL_FULL && CT > 10)
   {
-    for (i = game_mm.energy_left; i <= MAX_LASER_ENERGY; i+=2)
+    int num_init_game_frames = INIT_GAME_ACTIONS_DELAY;
+    int start = num_init_game_frames * game_mm.energy_left / native_mm_level.time;
+
+    for (i = start; i <= num_init_game_frames; i++)
     {
-#if 0
-      BlitBitmap(pix[PIX_DOOR], drawto,
-                DOOR_GFX_PAGEX4 + XX_ENERGY,
-                DOOR_GFX_PAGEY1 + YY_ENERGY + ENERGY_YSIZE - i,
-                ENERGY_XSIZE, i, DX_ENERGY,
-                DY_ENERGY + ENERGY_YSIZE - i);
-#endif
+      if (i == num_init_game_frames)
+       StopSound_MM(SND_MM_GAME_LEVELTIME_CHARGING);
+      else if (setup.sound_loops)
+       PlaySoundLoop_MM(SND_MM_GAME_LEVELTIME_CHARGING);
+      else
+       PlaySound_MM(SND_MM_GAME_LEVELTIME_CHARGING);
 
-      redraw_mask |= REDRAW_DOOR_1;
-      BackToFront();
+      game_mm.energy_left = native_mm_level.time * i / num_init_game_frames;
 
-      Delay_WithScreenUpdates(20);
+      UpdateAndDisplayGameControlValues();
+
+      BackToFront();
     }
 
-    game_mm.energy_left = MAX_LASER_ENERGY;
-    Tile[ELX][ELY] = EL_FUEL_EMPTY;
+    Tile[ELX][ELY] = laser.dest_element = EL_FUEL_EMPTY;
+
     DrawField_MM(ELX, ELY);
 
     DrawLaser(0, DL_LASER_ENABLED);