added option to not trigger further animations if CE change event consumed
[rocksndiamonds.git] / src / anim.c
index d570be06ae39e8adb013f78a3f3439d3a1595d5f..68147f0bc06ac100e36e0a51135864a93b587e84 100644 (file)
@@ -122,6 +122,9 @@ struct GlobalAnimPartControlInfo
   int x, y;
   int step_xoffset, step_yoffset;
 
+  int tile_x, tile_y;
+  int tile_xoffset, tile_yoffset;
+
   unsigned int initial_anim_sync_frame;
   unsigned int anim_random_frame;
 
@@ -1210,24 +1213,32 @@ static boolean checkGlobalAnimEvent(int anim_event, int mask)
 static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask)
 {
   struct GraphicInfo *c = &part->control_info;
-  int num_init_events = GetGlobalAnimEventValueCount(c->init_event);
-  int num_anim_events = GetGlobalAnimEventValueCount(c->anim_event);
   int i;
 
-  for (i = 0; i < num_init_events; i++)
+  if (part->init_event_state)
   {
-    int init_event = GetGlobalAnimEventValue(c->init_event, i);
+    int num_init_events = GetGlobalAnimEventValueCount(c->init_event);
 
-    if (checkGlobalAnimEvent(init_event, mask))
-      return TRUE;
+    for (i = 0; i < num_init_events; i++)
+    {
+      int init_event = GetGlobalAnimEventValue(c->init_event, i);
+
+      if (checkGlobalAnimEvent(init_event, mask))
+       return TRUE;
+    }
   }
 
-  for (i = 0; i < num_anim_events; i++)
+  if (part->anim_event_state)
   {
-    int anim_event = GetGlobalAnimEventValue(c->anim_event, i);
+    int num_anim_events = GetGlobalAnimEventValueCount(c->anim_event);
+
+    for (i = 0; i < num_anim_events; i++)
+    {
+      int anim_event = GetGlobalAnimEventValue(c->anim_event, i);
 
-    if (checkGlobalAnimEvent(anim_event, mask))
-      return TRUE;
+      if (checkGlobalAnimEvent(anim_event, mask))
+       return TRUE;
+    }
   }
 
   return FALSE;
@@ -1360,7 +1371,8 @@ static void InitGlobalAnim_Triggered(struct GlobalAnimPartControlInfo *part,
   }
 }
 
-static void InitGlobalAnim_Triggered_ByCustomElement(int nr, int page)
+static void InitGlobalAnim_Triggered_ByCustomElement(int nr, int page,
+                                                    int x, int y)
 {
   struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[GAME_MODE_PLAYING];
 
@@ -1383,8 +1395,26 @@ static void InitGlobalAnim_Triggered_ByCustomElement(int nr, int page)
 
       if (isClickablePart(part2, mask))
       {
+       struct GraphicInfo *c = &part2->control_info;
+
+       if (c->position == POS_CE)
+       {
+         // store CE tile and offset position to handle scrolling
+         part2->tile_x = x;
+         part2->tile_y = y;
+         part2->tile_xoffset = c->x;
+         part2->tile_yoffset = c->y;
+
+         // restart animation (by using current sync frame)
+         part2->initial_anim_sync_frame = anim_sync_frame;
+       }
+
        part2->triggered = TRUE;
 
+       // do not trigger any other animation if CE change event was consumed
+       if (c->style == STYLE_CONSUME_CE_EVENT)
+         return;
+
 #if 0
        Debug("anim:InitGlobalAnim_Triggered_ByCustomElement",
              "%d.%d TRIGGERED BY CE %d", anim2_nr, part2_nr, nr + 1);
@@ -1696,8 +1726,27 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part,
   }
 #endif
 
-  part->x += part->step_xoffset;
-  part->y += part->step_yoffset;
+  if (c->position == POS_CE)
+  {
+    // calculate playfield position (with scrolling) for related CE tile
+    int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos);
+    int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos);
+    int sx = FX + SCREENX(part->tile_x) * TILEX_VAR;
+    int sy = FY + SCREENY(part->tile_y) * TILEY_VAR;
+    int x = sx - fx;
+    int y = sy - fy;
+
+    part->tile_xoffset += part->step_xoffset;
+    part->tile_yoffset += part->step_yoffset;
+
+    part->x = x + part->tile_xoffset;
+    part->y = y + part->tile_yoffset;
+  }
+  else
+  {
+    part->x += part->step_xoffset;
+    part->y += part->step_yoffset;
+  }
 
   anim->last_x = part->x;
   anim->last_y = part->y;
@@ -2148,11 +2197,12 @@ int getGlobalAnimSyncFrame(void)
   return anim_sync_frame;
 }
 
-void HandleGlobalAnimEventByElementChange(int element, int page)
+void HandleGlobalAnimEventByElementChange(int element, int page, int x, int y)
 {
   if (!IS_CUSTOM_ELEMENT(element))
     return;
 
   // custom element stored as 0 to 255, change page stored as 1 to 32
-  InitGlobalAnim_Triggered_ByCustomElement(element - EL_CUSTOM_START, page + 1);
+  InitGlobalAnim_Triggered_ByCustomElement(element - EL_CUSTOM_START, page + 1,
+                                          x, y);
 }