changed "http" to "https" in URLs
[rocksndiamonds.git] / src / anim.c
index 9ab9f6dcf4356b4d9ec45300daed590a5103fa37..dec9d18ee61d49cf1667e61298111e2c9f9060d0 100644 (file)
@@ -4,7 +4,7 @@
 // (c) 1995-2014 by Artsoft Entertainment
 //                         Holger Schemel
 //                 info@artsoft.org
-//                 http://www.artsoft.org/
+//                 https://www.artsoft.org/
 // ----------------------------------------------------------------------------
 // anim.c
 // ============================================================================
@@ -108,6 +108,7 @@ struct GlobalAnimPartControlInfo
   int step_xoffset, step_yoffset;
 
   unsigned int initial_anim_sync_frame;
+  unsigned int anim_random_frame;
   unsigned int step_delay, step_delay_value;
 
   int init_delay_counter;
@@ -242,6 +243,9 @@ int getAnimationFrame(int num_frames, int delay, int mode, int start_frame,
 {
   int frame = 0;
 
+  if (delay < 1)                       // delay must be at least 1
+    delay = 1;
+
   sync_frame += start_frame * delay;
 
   if (mode & ANIM_LOOP)                        // looping animation
@@ -409,6 +413,7 @@ static void InitToonControls(void)
     part->control_info.y = ARG_UNDEFINED_VALUE;
 
     part->initial_anim_sync_frame = 0;
+    part->anim_random_frame = -1;
 
     part->step_delay = 0;
     part->step_delay_value = graphic_info[control].step_delay;
@@ -513,6 +518,7 @@ static void InitGlobalAnimControls(void)
        part->control_info = graphic_info[control];
 
        part->initial_anim_sync_frame = 0;
+       part->anim_random_frame = -1;
 
        part->step_delay = 0;
        part->step_delay_value = graphic_info[control].step_delay;
@@ -764,6 +770,7 @@ static void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
          (g->draw_masked ? BlitBitmapMasked : BlitBitmap);
        void (*blit_screen)(Bitmap *, int, int, int, int, int, int) =
          (g->draw_masked ? BlitToScreenMasked : BlitToScreen);
+       int last_anim_random_frame = gfx.anim_random_frame;
 
        if (!(part->state & ANIM_STATE_RUNNING))
          continue;
@@ -796,10 +803,21 @@ static void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
        dst_y += part->viewport_y;
 
        sync_frame = anim_sync_frame - part->initial_anim_sync_frame;
+
+       // re-initialize random animation frame after animation delay
+       if (g->anim_mode == ANIM_RANDOM &&
+           sync_frame % g->anim_delay == 0 &&
+           sync_frame > 0)
+         part->anim_random_frame = GetSimpleRandom(g->anim_frames);
+
+       gfx.anim_random_frame = part->anim_random_frame;
+
        frame = getAnimationFrame(g->anim_frames, g->anim_delay,
                                  g->anim_mode, g->anim_start_frame,
                                  sync_frame);
 
+       gfx.anim_random_frame = last_anim_random_frame;
+
        getFixedGraphicSource(part->graphic, frame, &src_bitmap,
                              &src_x, &src_y);
 
@@ -1128,6 +1146,11 @@ static boolean isClickedPart(struct GlobalAnimPartControlInfo *part,
   return TRUE;
 }
 
+static boolean clickBlocked(struct GlobalAnimPartControlInfo *part)
+{
+  return (part->control_info.style & STYLE_BLOCK ? TRUE : FALSE);
+}
+
 static boolean clickConsumed(struct GlobalAnimPartControlInfo *part)
 {
   return (part->control_info.style & STYLE_PASSTHROUGH ? FALSE : TRUE);
@@ -1164,7 +1187,7 @@ static void InitGlobalAnim_Triggered(struct GlobalAnimPartControlInfo *part,
       if (isClickablePart(part2, mask))
       {
        part2->triggered = TRUE;
-       *click_consumed = clickConsumed(part);          // click was on "part"!
+       *click_consumed |= clickConsumed(part);         // click was on "part"!
 
 #if DEBUG_ANIM_EVENTS
        printf("::: => %d.%d TRIGGERED BY %s OF %d.%d\n",
@@ -1260,6 +1283,10 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part,
     part->initial_anim_sync_frame =
       (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
 
+    // do not re-initialize random animation frame after fade-in
+    if (part->anim_random_frame == -1)
+      part->anim_random_frame = GetSimpleRandom(g->anim_frames);
+
     if (c->direction & MV_HORIZONTAL)
     {
       int pos_bottom = part->viewport_height - g->height;
@@ -1760,9 +1787,11 @@ static void InitGlobalAnim_Clickable(void)
 static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
 {
   boolean click_consumed = FALSE;
+  boolean anything_clicked = FALSE;
   boolean any_part_clicked = FALSE;
   boolean any_event_action = FALSE;
   int mode_nr;
+  int i;
 
   // check game modes in reverse draw order (to stop when clicked)
   for (mode_nr = NUM_GAME_MODES - 1; mode_nr >= 0; mode_nr--)
@@ -1803,8 +1832,8 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
                 part->old_anim_nr + 1, part->old_nr + 1);
 #endif
 
-         part->clicked = TRUE;
-         click_consumed = clickConsumed(part);
+         anything_clicked = part->clicked = TRUE;
+         click_consumed |= clickConsumed(part);
        }
 
        // always handle "unclick:any" events (releasing anywhere on screen) ...
@@ -1816,8 +1845,8 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
                 part->old_anim_nr + 1, part->old_nr + 1);
 #endif
 
-         part->clicked = TRUE;
-         click_consumed = clickConsumed(part);
+         anything_clicked = part->clicked = TRUE;
+         click_consumed |= clickConsumed(part);
        }
 
        // ... but only handle the first (topmost) clickable animation
@@ -1837,7 +1866,7 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
            any_event_action = TRUE;
 
          // determine if mouse clicks should be blocked from other animations
-         any_part_clicked = clickConsumed(part);
+         any_part_clicked |= clickConsumed(part);
 
          if (isClickablePart(part, ANIM_EVENT_SELF))
          {
@@ -1846,10 +1875,13 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
                   part->old_anim_nr + 1, part->old_nr + 1);
 #endif
 
-           part->clicked = TRUE;
-           click_consumed = clickConsumed(part);
+           anything_clicked = part->clicked = TRUE;
+           click_consumed |= clickConsumed(part);
          }
 
+         // determine if mouse clicks should be blocked by this animation
+         click_consumed |= clickBlocked(part);
+
          // check if this click is defined to trigger other animations
          InitGlobalAnim_Triggered(part, &click_consumed, &any_event_action,
                                   ANIM_EVENT_CLICK, "CLICK");
@@ -1858,13 +1890,17 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
     }
   }
 
-  if (click_consumed)
+  if (anything_clicked)
   {
     handle_click = TRUE;
 
-    HandleGlobalAnim(ANIM_CONTINUE, game_status);
+    for (i = 0; i < NUM_GAME_MODES; i++)
+      HandleGlobalAnim(ANIM_CONTINUE, i);
 
     handle_click = FALSE;
+
+    // prevent ignoring release event if processed within same game frame
+    StopProcessingEvents();
   }
 
   return (click_consumed || any_event_action);