rnd-20031127-1-src
[rocksndiamonds.git] / src / tools.c
index 932df515bd7080d4cd4c671a4e204930d5eb2210..c9d3e4baf4203d124152a7b8ae9eb2733c0e0efc 100644 (file)
@@ -486,7 +486,7 @@ void DrawLevelGraphicAnimation(int x, int y, int graphic)
 void DrawLevelElementAnimation(int x, int y, int element)
 {
 #if 1
-  int graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
+  int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
 
   DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
 #else
@@ -518,7 +518,7 @@ void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
   if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
     return;
 
-  graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
+  graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
 
   if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
     return;
@@ -529,6 +529,127 @@ void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
     DrawLevelFieldCrumbledSand(x, y);
 }
 
+static int getPlayerAction(struct PlayerInfo *player, int move_dir)
+{
+  int action = (player->is_pushing    ? ACTION_PUSHING    :
+               player->is_digging    ? ACTION_DIGGING    :
+               player->is_collecting ? ACTION_COLLECTING :
+               player->is_moving     ? ACTION_MOVING     :
+               player->is_snapping   ? ACTION_SNAPPING   :
+               player->is_sleeping   ? ACTION_SLEEPING   :
+               player->is_bored      ? ACTION_BORING     :
+               player->is_waiting    ? ACTION_WAITING    : ACTION_DEFAULT);
+
+  if (player->is_sleeping)
+  {
+    if (player->num_special_action_sleeping > 0)
+    {
+      if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
+      {
+       int last_special_action = player->special_action_sleeping;
+       int num_special_action = player->num_special_action_sleeping;
+       int special_action =
+         (last_special_action == ACTION_DEFAULT ? ACTION_SLEEPING_1 :
+          last_special_action == ACTION_SLEEPING ? ACTION_SLEEPING :
+          last_special_action < ACTION_SLEEPING_1 + num_special_action - 1 ?
+          last_special_action + 1 : ACTION_SLEEPING);
+       int special_graphic =
+         el_act_dir2img(player->element_nr, special_action, move_dir);
+
+       player->anim_delay_counter =
+         graphic_info[special_graphic].anim_delay_fixed +
+         SimpleRND(graphic_info[special_graphic].anim_delay_random);
+       player->post_delay_counter =
+         graphic_info[special_graphic].post_delay_fixed +
+         SimpleRND(graphic_info[special_graphic].post_delay_random);
+
+       player->special_action_sleeping = special_action;
+      }
+
+      if (player->anim_delay_counter > 0)
+      {
+       action = player->special_action_sleeping;
+       player->anim_delay_counter--;
+      }
+      else if (player->post_delay_counter > 0)
+      {
+       player->post_delay_counter--;
+      }
+    }
+  }
+  else if (player->is_bored)
+  {
+    if (player->num_special_action_bored > 0)
+    {
+      if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
+      {
+       int special_action =
+         ACTION_BORING_1 + SimpleRND(player->num_special_action_bored);
+       int special_graphic =
+         el_act_dir2img(player->element_nr, special_action, move_dir);
+
+       player->anim_delay_counter =
+         graphic_info[special_graphic].anim_delay_fixed +
+         SimpleRND(graphic_info[special_graphic].anim_delay_random);
+       player->post_delay_counter =
+         graphic_info[special_graphic].post_delay_fixed +
+         SimpleRND(graphic_info[special_graphic].post_delay_random);
+
+       player->special_action_bored = special_action;
+      }
+
+      if (player->anim_delay_counter > 0)
+      {
+       action = player->special_action_bored;
+       player->anim_delay_counter--;
+      }
+      else if (player->post_delay_counter > 0)
+      {
+       player->post_delay_counter--;
+      }
+    }
+  }
+
+  return action;
+}
+
+static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
+{
+  if (player->use_murphy_graphic)
+  {
+    /* this works only because currently only one player can be "murphy" ... */
+    static int last_horizontal_dir = MV_LEFT;
+    int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
+
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      last_horizontal_dir = move_dir;
+
+    if (graphic == IMG_SP_MURPHY)      /* undefined => use special graphic */
+    {
+      int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
+
+      graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
+    }
+
+    return graphic;
+  }
+  else
+    return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
+}
+
+static boolean equalGraphics(int graphic1, int graphic2)
+{
+  struct GraphicInfo *g1 = &graphic_info[graphic1];
+  struct GraphicInfo *g2 = &graphic_info[graphic2];
+
+  return (g1->bitmap      == g2->bitmap &&
+         g1->src_x       == g2->src_x &&
+         g1->src_y       == g2->src_y &&
+         g1->anim_frames == g2->anim_frames &&
+         g1->anim_delay  == g2->anim_delay &&
+         g1->anim_mode   == g2->anim_mode);
+}
+
 void DrawAllPlayers()
 {
   int i;
@@ -571,6 +692,8 @@ void DrawPlayer(struct PlayerInfo *player)
   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
   int graphic;
   int action = ACTION_DEFAULT;
+  int last_player_graphic = getPlayerGraphic(player, move_dir);
+  int last_player_frame = player->Frame;
   int frame = 0;
 
   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
@@ -589,11 +712,51 @@ void DrawPlayer(struct PlayerInfo *player)
   if (element == EL_EXPLOSION)
     return;
 
-  action = (player->is_pushing    ? ACTION_PUSHING    :
+#if 1
+
+  action = getPlayerAction(player, move_dir);
+
+#else
+
+  action = (player->is_pushing   ? ACTION_PUSHING    :
            player->is_digging    ? ACTION_DIGGING    :
            player->is_collecting ? ACTION_COLLECTING :
            player->is_moving     ? ACTION_MOVING     :
-           player->is_snapping   ? ACTION_SNAPPING   : ACTION_DEFAULT);
+           player->is_snapping   ? ACTION_SNAPPING   :
+           player->is_sleeping   ? ACTION_SLEEPING   :
+           player->is_bored      ? ACTION_BORING     :
+           player->is_waiting    ? ACTION_WAITING    : ACTION_DEFAULT);
+
+  if (player->is_bored && player->num_special_action_bored > 0)
+  {
+    if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
+    {
+      int graphic_waiting;
+
+      action = ACTION_BORING_1 + SimpleRND(player->num_special_action_bored);
+      special_graphic = el_act_dir2img(EL_SP_MURPHY, action, move_dir);
+
+      player->anim_delay_counter =
+       graphic_info[special_graphic].anim_delay_fixed +
+       SimpleRND(graphic_info[special_graphic].anim_delay_random);
+      player->post_delay_counter =
+       graphic_info[special_graphic].post_delay_fixed +
+       SimpleRND(graphic_info[special_graphic].post_delay_random);
+      player->special_action_bored = action;
+    }
+
+    if (player->anim_delay_counter > 0)
+    {
+      action = player->special_action_bored;
+      player->anim_delay_counter--;
+    }
+
+    if (player->post_delay_counter > 0)
+    {
+      player->post_delay_counter--;
+    }
+  }
+#endif
 
 #if 0
   printf("::: '%s'\n", element_action_info[action].suffix);
@@ -672,6 +835,17 @@ void DrawPlayer(struct PlayerInfo *player)
   /* draw player himself                                                     */
   /* ----------------------------------------------------------------------- */
 
+#if 1
+
+  graphic = getPlayerGraphic(player, move_dir);
+
+  /* in the case of changed player action or direction, prevent the current
+     animation frame from being restarted for identical animations */
+  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+    player->Frame = last_player_frame;
+
+#else
+
   if (player->use_murphy_graphic)
   {
     static int last_horizontal_dir = MV_LEFT;
@@ -691,6 +865,8 @@ void DrawPlayer(struct PlayerInfo *player)
   else
     graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
 
+#endif
+
   frame = getGraphicAnimationFrame(graphic, player->Frame);
 
   if (player->GfxPos)
@@ -743,7 +919,11 @@ void DrawPlayer(struct PlayerInfo *player)
     {
       int element = MovingOrBlocked2Element(next_jx, next_jy);
       int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+#if 1
+      int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
+#else
       int frame = getGraphicAnimationFrame(graphic, player->Frame);
+#endif
 
       DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
                         NO_CUTTING, NO_MASKING);
@@ -1068,7 +1248,7 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
   {
     SetRandomAnimationValue(lx, ly);
 
-    graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
+    graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
     frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
   }
   else /* border element */