rnd-19990214-1
[rocksndiamonds.git] / src / tools.c
index 2a8b6f17b3d901eec7188a60715bd69d7f9c140c..4c74046cedcab26e3fd0cf3f886343b73fb99db3 100644 (file)
@@ -43,6 +43,7 @@ extern boolean wait_for_vsync;
 #define NUM_TOOL_BUTTONS       7
 
 /* forward declaration for internal use */
+static int getGraphicAnimationPhase(int, int, int);
 static void UnmapToolButtons();
 static void HandleToolButtons(struct GadgetInfo *);
 
@@ -455,8 +456,9 @@ void DrawPlayer(struct PlayerInfo *player)
   int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
   int sx = SCREENX(jx), sy = SCREENY(jy);
   int sxx = 0, syy = 0;
-  int element = Feld[jx][jy];
+  int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
   int graphic, phase;
+  boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
 
   if (!player->active || player->gone ||
       !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
@@ -477,14 +479,18 @@ void DrawPlayer(struct PlayerInfo *player)
 
   /* draw things in the field the player is leaving, if needed */
 
+  /*
   if (last_jx != jx || last_jy != jy)
+  */
+
+  if (player_is_moving)
   {
-    if (Store[last_jx][last_jy])
+    if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
     {
       DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
       DrawLevelFieldThruMask(last_jx, last_jy);
     }
-    else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
+    else if (last_element == EL_DYNAMIT)
       DrawDynamite(last_jx, last_jy);
     else
       DrawLevelField(last_jx, last_jy);
@@ -520,30 +526,13 @@ void DrawPlayer(struct PlayerInfo *player)
 
   if (game_emulation == EMU_SUPAPLEX)
   {
-#if 0
-    if (player->MovDir == MV_LEFT)
-      graphic =
-       (player->Pushing ? GFX_MURPHY_PUSH_LEFT : GFX_MURPHY_LEFT);
-    else if (player->MovDir == MV_RIGHT)
-      graphic =
-       (player->Pushing ? GFX_MURPHY_PUSH_RIGHT : GFX_MURPHY_RIGHT);
-    else if (player->MovDir == MV_UP)
-      graphic = GFX_MURPHY_UP;
-    else if (player->MovDir == MV_DOWN)
-      graphic = GFX_MURPHY_DOWN;
-    else       /* MV_NO_MOVING */
-      graphic = GFX_SP_MURPHY;
-
+    static int last_dir = MV_LEFT;
+    boolean action_moving =
+      (player_is_moving ||
+       ((player->action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
+       !(player->action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
 
-    /*
-    if (player->snapped)
-      graphic = GFX_SPIELER1_PUSH_LEFT;
-    else
-      graphic = GFX_SPIELER1_PUSH_RIGHT;
-    */
-#endif
-
-    static last_dir = MV_LEFT;
+    graphic = GFX_SP_MURPHY;
 
     if (player->Pushing)
     {
@@ -551,12 +540,10 @@ void DrawPlayer(struct PlayerInfo *player)
        graphic = GFX_MURPHY_PUSH_LEFT;
       else if (player->MovDir == MV_RIGHT)
        graphic = GFX_MURPHY_PUSH_RIGHT;
-      else if (last_dir == MV_LEFT)
-       graphic = GFX_MURPHY_ANY_LEFT;
-      else if (last_dir == MV_RIGHT)
-       graphic = GFX_MURPHY_ANY_RIGHT;
-      else
-       graphic = GFX_SP_MURPHY;
+      else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
+       graphic = GFX_MURPHY_PUSH_LEFT;
+      else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
+       graphic = GFX_MURPHY_PUSH_RIGHT;
     }
     else if (player->snapped)
     {
@@ -568,28 +555,23 @@ void DrawPlayer(struct PlayerInfo *player)
        graphic = GFX_MURPHY_SNAP_UP;
       else if (player->MovDir == MV_DOWN)
        graphic = GFX_MURPHY_SNAP_DOWN;
-      else
-       graphic = GFX_SP_MURPHY;
     }
-    else
+    else if (action_moving)
     {
       if (player->MovDir == MV_LEFT)
-       graphic = GFX_MURPHY_ANY_LEFT;
+       graphic = GFX_MURPHY_GO_LEFT;
       else if (player->MovDir == MV_RIGHT)
-       graphic = GFX_MURPHY_ANY_RIGHT;
-      else if (last_dir == MV_LEFT)
-       graphic = GFX_MURPHY_ANY_LEFT;
-      else if (last_dir == MV_RIGHT)
-       graphic = GFX_MURPHY_ANY_RIGHT;
-      else
-       graphic = GFX_SP_MURPHY;
+       graphic = GFX_MURPHY_GO_RIGHT;
+      else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
+       graphic = GFX_MURPHY_GO_LEFT;
+      else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
+       graphic = GFX_MURPHY_GO_RIGHT;
+
+      graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
     }
 
     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
       last_dir = player->MovDir;
-
-    if (!player->Pushing && !player->snapped && player->MovDir != MV_NO_MOVING)
-      graphic -= player->Frame % 2;
   }
   else
   {
@@ -625,7 +607,7 @@ void DrawPlayer(struct PlayerInfo *player)
   {
     int px = SCREENX(next_jx), py = SCREENY(next_jy);
 
-    if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
+    if (element == EL_SOKOBAN_FELD_LEER ||
        Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
       DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
                                 NO_CUTTING);
@@ -634,21 +616,21 @@ void DrawPlayer(struct PlayerInfo *player)
       int element = Feld[next_jx][next_jy];
       int graphic = el2gfx(element);
 
-      if (element == EL_FELSBROCKEN && sxx)
+      if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
       {
-       int phase = (player->GfxPos / (TILEX/4));
+       int phase = (player->GfxPos / (TILEX / 4));
 
        if (player->MovDir == MV_LEFT)
          graphic += phase;
        else
-         graphic += (phase+4)%4;
+         graphic += (phase + 4) % 4;
       }
 
       DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
     }
   }
 
-  /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
+  /* draw things in front of player (EL_DYNAMIT or EL_DYNABOMB) */
 
   if (element == EL_DYNAMIT || element == EL_DYNABOMB)
   {
@@ -671,8 +653,11 @@ void DrawPlayer(struct PlayerInfo *player)
       DrawGraphicThruMask(sx, sy, graphic + phase);
   }
 
-  if ((last_jx != jx || last_jy != jy) &&
-      Feld[last_jx][last_jy] == EL_EXPLODING)
+  /*
+  if ((last_jx != jx || last_jy != jy) && last_element == EL_EXPLODING)
+  */
+
+  if (player_is_moving && last_element == EL_EXPLODING)
   {
     int phase = Frame[last_jx][last_jy];
     int delay = 2;
@@ -682,6 +667,14 @@ void DrawPlayer(struct PlayerInfo *player)
                          GFX_EXPLOSION + ((phase - 1) / delay - 1));
   }
 
+  /* draw elements that stay over the player */
+  /* handle the field the player is leaving ... */
+  if (player_is_moving && IS_OVER_PLAYER(last_element))
+    DrawLevelField(last_jx, last_jy);
+  /* ... and the field the player is entering */
+  if (IS_OVER_PLAYER(element))
+    DrawLevelField(jx, jy);
+
   if (setup.direct_draw)
   {
     int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
@@ -876,6 +869,9 @@ void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
   Pixmap src_pixmap;
   GC drawing_gc;
 
+  if (graphic == GFX_LEERRAUM)
+    return;
+
   getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
   src_pixmap = pix[pixmap_nr];
   drawing_gc = clip_gc[pixmap_nr];
@@ -957,6 +953,7 @@ void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
+    graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
     *pixmap = pix[PIX_MORE];
     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
@@ -1247,10 +1244,35 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
   {
     graphic += !phase2;
   }
-  else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
+  else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
+           IS_GEM(element)) && !cut_mode)
   {
-    if (element != EL_SP_INFOTRON)
+    if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
+    {
+      if (dir == MV_LEFT)
+       graphic += (4 - phase4) % 4;
+      else if (dir == MV_RIGHT)
+       graphic += phase4;
+      else
+       graphic += phase2 * 2;
+    }
+    else if (element != EL_SP_INFOTRON)
+      graphic += phase2;
+
+    /*
+    if (element == EL_SP_ZONK)
+    {
+      if (dir == MV_LEFT)
+       graphic += (4 - phase4) % 4;
+      else if (dir == MV_RIGHT)
+       graphic += phase4;
+      else
+       graphic += phase2 * 2;
+    }
+    else if (element != EL_SP_INFOTRON)
       graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
+    */
+
   }
   else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
           element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
@@ -1618,6 +1640,7 @@ void DrawMicroElement(int xpos, int ypos, int element)
   if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
   {
     graphic -= GFX_START_ROCKSMORE;
+    graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
     XCopyArea(display, pix[PIX_MORE], drawto, gc,
              MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
              MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
@@ -2430,8 +2453,8 @@ void CreateToolButtons()
   for (i=0; i<NUM_TOOL_BUTTONS; i++)
   {
     Pixmap gd_pixmap = pix[PIX_DOOR];
-    Pixmap deco_pixmap = 0;
-    int deco_x, deco_y, deco_xpos, deco_ypos;
+    Pixmap deco_pixmap = None;
+    int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
     struct GadgetInfo *gi;
     unsigned long event_mask;
     int gd_xoffset, gd_yoffset;
@@ -2722,7 +2745,26 @@ int el2gfx(int element)
     case EL_SPEED_PILL:                return GFX_SPEED_PILL;
     case EL_SP_TERMINAL_ACTIVE:        return GFX_SP_TERMINAL;
     case EL_SP_BUG_ACTIVE:     return GFX_SP_BUG_ACTIVE;
+    case EL_SP_ZONK:           return GFX_SP_ZONK;
+      /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
     case EL_INVISIBLE_STEEL:   return GFX_INVISIBLE_STEEL;
+    case EL_BLACK_ORB:         return GFX_BLACK_ORB;
+    case EL_EM_GATE_1:         return GFX_EM_GATE_1;
+    case EL_EM_GATE_2:         return GFX_EM_GATE_2;
+    case EL_EM_GATE_3:         return GFX_EM_GATE_3;
+    case EL_EM_GATE_4:         return GFX_EM_GATE_4;
+    case EL_EM_GATE_1X:                return GFX_EM_GATE_1X;
+    case EL_EM_GATE_2X:                return GFX_EM_GATE_2X;
+    case EL_EM_GATE_3X:                return GFX_EM_GATE_3X;
+    case EL_EM_GATE_4X:                return GFX_EM_GATE_4X;
+    case EL_EM_KEY_1_FILE:     return GFX_EM_KEY_1;
+    case EL_EM_KEY_2_FILE:     return GFX_EM_KEY_2;
+    case EL_EM_KEY_3_FILE:     return GFX_EM_KEY_3;
+    case EL_EM_KEY_4_FILE:     return GFX_EM_KEY_4;
+    case EL_EM_KEY_1:          return GFX_EM_KEY_1;
+    case EL_EM_KEY_2:          return GFX_EM_KEY_2;
+    case EL_EM_KEY_3:          return GFX_EM_KEY_3;
+    case EL_EM_KEY_4:          return GFX_EM_KEY_4;
 
     default:
     {