added setting global animation position from CE triggering that animation
[rocksndiamonds.git] / src / game.c
index 56f36518d9576cec0d8752c57ce8944bf373196d..8cabb12de8c3ec028aaf681cc3196b4b00142225 100644 (file)
@@ -3195,6 +3195,17 @@ static void InitGameEngine(void)
     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
   }
 
+  // ---------- initialize if element can trigger global animations -----------
+
+  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+  {
+    struct ElementInfo *ei = &element_info[i];
+
+    ei->has_anim_event = FALSE;
+  }
+
+  InitGlobalAnimEventsForCustomElements();
+
   // ---------- initialize internal run-time variables ------------------------
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -3260,12 +3271,14 @@ static void InitGameEngine(void)
 
     for (j = 0; j < ei->num_change_pages; j++)
     {
-      ei->change_page[j].actual_trigger_element = EL_EMPTY;
-      ei->change_page[j].actual_trigger_player = EL_EMPTY;
-      ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_NONE;
-      ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
-      ei->change_page[j].actual_trigger_ce_value = 0;
-      ei->change_page[j].actual_trigger_ce_score = 0;
+      struct ElementChangeInfo *change = &ei->change_page[j];
+
+      change->actual_trigger_element = EL_EMPTY;
+      change->actual_trigger_player = EL_EMPTY;
+      change->actual_trigger_player_bits = CH_PLAYER_NONE;
+      change->actual_trigger_side = CH_SIDE_NONE;
+      change->actual_trigger_ce_value = 0;
+      change->actual_trigger_ce_score = 0;
     }
   }
 
@@ -3283,16 +3296,18 @@ static void InitGameEngine(void)
 
     for (j = 0; j < ei->num_change_pages; j++)
     {
-      if (!ei->change_page[j].can_change_or_has_action)
+      struct ElementChangeInfo *change = &ei->change_page[j];
+
+      if (!change->can_change_or_has_action)
        continue;
 
-      if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
+      if (change->has_event[CE_BY_OTHER_ACTION])
       {
-       int trigger_element = ei->change_page[j].trigger_element;
+       int trigger_element = change->trigger_element;
 
        for (k = 0; k < NUM_CHANGE_EVENTS; k++)
        {
-         if (ei->change_page[j].has_event[k])
+         if (change->has_event[k])
          {
            if (IS_GROUP_ELEMENT(trigger_element))
            {
@@ -3501,10 +3516,10 @@ static void InitGameEngine(void)
     {
       int element = EL_CUSTOM_START + i;
 
-      if (HAS_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
-         HAS_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE) ||
-         HAS_CHANGE_EVENT(element, CE_MOUSE_CLICKED_ON_X) ||
-         HAS_CHANGE_EVENT(element, CE_MOUSE_PRESSED_ON_X))
+      if (HAS_ANY_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
+         HAS_ANY_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE) ||
+         HAS_ANY_CHANGE_EVENT(element, CE_MOUSE_CLICKED_ON_X) ||
+         HAS_ANY_CHANGE_EVENT(element, CE_MOUSE_PRESSED_ON_X))
        game.use_mouse_actions = TRUE;
     }
   }
@@ -10700,6 +10715,16 @@ static boolean ChangeElement(int x, int y, int element, int page)
 
   ChangeCount[x][y]++;         // count number of changes in the same frame
 
+  if (ei->has_anim_event)
+  {
+    int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos);
+    int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos);
+    int sx = FX + SCREENX(x) * TILEX_VAR;
+    int sy = FY + SCREENY(y) * TILEY_VAR;
+
+    HandleGlobalAnimEventByElementChange(element, page, sx - fx, sy - fy);
+  }
+
   if (change->explode)
   {
     Bang(x, y);
@@ -10934,13 +10959,14 @@ static void HandleElementChange(int x, int y, int page)
 
   if (ChangeDelay[x][y] != 0)          // continue element change
   {
-    if (change->can_change)
-    {
-      int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+    int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
 
-      if (IS_ANIMATED(graphic))
-       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+    // also needed if CE can not change, but has CE delay with CE action
+    if (IS_ANIMATED(graphic))
+      DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
+    if (change->can_change)
+    {
       if (change->change_function)
        change->change_function(x, y);
     }
@@ -11708,6 +11734,49 @@ void AdvanceGfxFrame(void)
   }
 }
 
+static void HandleMouseAction(struct MouseActionInfo *mouse_action,
+                             struct MouseActionInfo *mouse_action_last)
+{
+  if (mouse_action->button)
+  {
+    int new_button = (mouse_action->button && mouse_action_last->button == 0);
+    int ch_button = CH_SIDE_FROM_BUTTON(mouse_action->button);
+    int x = mouse_action->lx;
+    int y = mouse_action->ly;
+    int element = Tile[x][y];
+
+    if (new_button)
+    {
+      CheckElementChangeByMouse(x, y, element, CE_CLICKED_BY_MOUSE, ch_button);
+      CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_CLICKED_ON_X,
+                                        ch_button);
+    }
+
+    CheckElementChangeByMouse(x, y, element, CE_PRESSED_BY_MOUSE, ch_button);
+    CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_PRESSED_ON_X,
+                                      ch_button);
+
+    if (level.use_step_counter)
+    {
+      boolean counted_click = FALSE;
+
+      // element clicked that can change when clicked/pressed
+      if (CAN_CHANGE_OR_HAS_ACTION(element) &&
+         (HAS_ANY_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
+          HAS_ANY_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE)))
+       counted_click = TRUE;
+
+      // element clicked that can trigger change when clicked/pressed
+      if (trigger_events[element][CE_MOUSE_CLICKED_ON_X] ||
+         trigger_events[element][CE_MOUSE_PRESSED_ON_X])
+       counted_click = TRUE;
+
+      if (new_button && counted_click)
+       CheckLevelTime_StepCounter();
+    }
+  }
+}
+
 void StartGameActions(boolean init_network_game, boolean record_tape,
                      int random_seed)
 {
@@ -12274,45 +12343,7 @@ void GameActions_RND(void)
 #endif
   }
 
-  if (mouse_action.button)
-  {
-    int new_button = (mouse_action.button && mouse_action_last.button == 0);
-    int ch_button = CH_SIDE_FROM_BUTTON(mouse_action.button);
-
-    x = mouse_action.lx;
-    y = mouse_action.ly;
-    element = Tile[x][y];
-
-    if (new_button)
-    {
-      CheckElementChangeByMouse(x, y, element, CE_CLICKED_BY_MOUSE, ch_button);
-      CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_CLICKED_ON_X,
-                                        ch_button);
-    }
-
-    CheckElementChangeByMouse(x, y, element, CE_PRESSED_BY_MOUSE, ch_button);
-    CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_PRESSED_ON_X,
-                                      ch_button);
-
-    if (level.use_step_counter)
-    {
-      boolean counted_click = FALSE;
-
-      // element clicked that can change when clicked/pressed
-      if (CAN_CHANGE_OR_HAS_ACTION(element) &&
-         (HAS_ANY_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
-          HAS_ANY_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE)))
-       counted_click = TRUE;
-
-      // element clicked that can trigger change when clicked/pressed
-      if (trigger_events[element][CE_MOUSE_CLICKED_ON_X] ||
-         trigger_events[element][CE_MOUSE_PRESSED_ON_X])
-       counted_click = TRUE;
-
-      if (new_button && counted_click)
-       CheckLevelTime_StepCounter();
-    }
-  }
+  HandleMouseAction(&mouse_action, &mouse_action_last);
 
   SCAN_PLAYFIELD(x, y)
   {