added support for text envelope elements to the MM engine
authorHolger Schemel <info@artsoft.org>
Sun, 29 Jan 2023 13:55:18 +0000 (14:55 +0100)
committerHolger Schemel <info@artsoft.org>
Sun, 29 Jan 2023 13:55:18 +0000 (14:55 +0100)
src/conf_gfx.c
src/editor.c
src/engines.h
src/game_mm/export.h
src/game_mm/mm_game.c
src/game_mm/mm_init.c
src/game_mm/mm_main.h
src/main.c
src/main.h
src/tools.c

index b4789635243a7cb622ecc6ae8344291c72165c76..3616c73b7662f854fc962f041c16db0cc4f58c7f 100644 (file)
@@ -5223,6 +5223,23 @@ struct ConfigInfo image_config[] =
   { "mm_pacman.eating.down.ypos",              "4"                     },
   { "mm_pacman.eating.down.frames",            "1"                     },
 
+  { "mm_envelope_1",                           UNDEFINED_FILENAME      },
+  { "mm_envelope_1.clone_from",                        "envelope_1"            },
+  { "mm_envelope_1.collecting",                        UNDEFINED_FILENAME      },
+  { "mm_envelope_1.collecting.clone_from",     "envelope_1.collecting" },
+  { "mm_envelope_2",                           UNDEFINED_FILENAME      },
+  { "mm_envelope_2.clone_from",                        "envelope_2"            },
+  { "mm_envelope_2.collecting",                        UNDEFINED_FILENAME      },
+  { "mm_envelope_2.collecting.clone_from",     "envelope_2.collecting" },
+  { "mm_envelope_3",                           UNDEFINED_FILENAME      },
+  { "mm_envelope_3.clone_from",                        "envelope_3"            },
+  { "mm_envelope_3.collecting",                        UNDEFINED_FILENAME      },
+  { "mm_envelope_3.collecting.clone_from",     "envelope_3.collecting" },
+  { "mm_envelope_4",                           UNDEFINED_FILENAME      },
+  { "mm_envelope_4.clone_from",                        "envelope_4"            },
+  { "mm_envelope_4.collecting",                        UNDEFINED_FILENAME      },
+  { "mm_envelope_4.collecting.clone_from",     "envelope_4.collecting" },
+
   { "[mm_default].exploding",                  "RocksMM.png"           },
   { "[mm_default].exploding.xpos",             "0"                     },
   { "[mm_default].exploding.ypos",             "8"                     },
index 6df9c2eda5286351891676cf6881bf850fe95376..ab9b1c0082978f836972c77b2eed54763fd85f78 100644 (file)
@@ -4644,7 +4644,12 @@ static int editor_el_mirror_magic[] =
   EL_MM_WOODEN_GRID_FIXED_1,
   EL_MM_WOODEN_GRID_FIXED_2,
   EL_MM_WOODEN_GRID_FIXED_3,
-  EL_MM_WOODEN_GRID_FIXED_4
+  EL_MM_WOODEN_GRID_FIXED_4,
+
+  EL_MM_ENVELOPE_1,
+  EL_MM_ENVELOPE_2,
+  EL_MM_ENVELOPE_3,
+  EL_MM_ENVELOPE_4
 };
 static int *editor_hl_mirror_magic_ptr = editor_hl_mirror_magic;
 static int *editor_el_mirror_magic_ptr = editor_el_mirror_magic;
@@ -9962,6 +9967,7 @@ static boolean checkPropertiesConfig(int element)
       IS_EMPTY_ELEMENT(element) ||
       IS_BALLOON_ELEMENT(element) ||
       IS_ENVELOPE(element) ||
+      IS_MM_ENVELOPE(element) ||
       IS_MM_MCDUFFIN(element) ||
       IS_DF_LASER(element) ||
       IS_PLAYER_ELEMENT(element) ||
@@ -10266,13 +10272,14 @@ static void DrawPropertiesConfig(void)
   if (IS_BALLOON_ELEMENT(properties_element))
     MapSelectboxGadget(ED_SELECTBOX_ID_WIND_DIRECTION);
 
-  if (IS_ENVELOPE(properties_element))
+  if (IS_ENVELOPE(properties_element) ||
+      IS_MM_ENVELOPE(properties_element))
   {
     int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE;
     int counter2_id = ED_COUNTER_ID_ENVELOPE_YSIZE;
     int button1_id = ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP;
     int button2_id = ED_CHECKBUTTON_ID_ENVELOPE_CENTERED;
-    int envelope_nr = properties_element - EL_ENVELOPE_1;
+    int envelope_nr = ENVELOPE_NR(properties_element);
 
     counterbutton_info[counter1_id].value = &level.envelope[envelope_nr].xsize;
     counterbutton_info[counter2_id].value = &level.envelope[envelope_nr].ysize;
index 254f82d4a636fb1e06401188122a7295524075b3..142c064f7040b42e17ceee386eb9c28d72176375 100644 (file)
@@ -64,6 +64,7 @@ int el2img_mm(int);
 int el_act2img_mm(int, int);
 
 void CheckSingleStepMode_MM(boolean, boolean);
+void ShowEnvelope_MM(int);
 
 int getGraphicAnimationFrame(int, int);
 int getGraphicAnimationFrameXY(int, int, int);
index b628a8d04c3b16ae3cee8b7479bd175abacaf173..8b92ab0a0a135cff67ae86e80328b6708bc458a7 100644 (file)
@@ -34,7 +34,7 @@
 
 
 #define EL_MM_START_1_NATIVE           0
-#define EL_MM_END_1_NATIVE             155
+#define EL_MM_END_1_NATIVE             159
 
 #define EL_MM_CHAR_START_NATIVE                160
 #define EL_MM_CHAR_END_NATIVE          239
index 641aa4fde5c8fdf0759e408bb686fdf80fddc4d6..27aada30a7c2d95fd5f320996e1163b06c391df5 100644 (file)
@@ -1663,9 +1663,11 @@ boolean HitElement(int element, int hit_mask)
       element == EL_KEY ||
       element == EL_LIGHTBALL ||
       element == EL_PACMAN ||
-      IS_PACMAN(element))
+      IS_PACMAN(element) ||
+      IS_ENVELOPE(element))
   {
-    if (!IS_PACMAN(element))
+    if (!IS_PACMAN(element) &&
+       !IS_ENVELOPE(element))
       Bang_MM(ELX, ELY);
 
     if (element == EL_PACMAN)
@@ -1693,6 +1695,10 @@ boolean HitElement(int element, int hit_mask)
     {
       DeletePacMan(ELX, ELY);
     }
+    else if (IS_ENVELOPE(element))
+    {
+      Tile[ELX][ELY] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(Tile[ELX][ELY]);
+    }
 
     RaiseScoreElement_MM(element);
 
@@ -2482,6 +2488,42 @@ static void OpenSurpriseBall(int x, int y)
   }
 }
 
+static void OpenEnvelope(int x, int y)
+{
+  int num_frames = 8;          // seven frames plus final empty space
+
+  if (!MovDelay[x][y])         // next animation frame
+    MovDelay[x][y] = num_frames;
+
+  if (MovDelay[x][y])          // wait some time before next frame
+  {
+    int nr = ENVELOPE_OPENING_NR(Tile[x][y]);
+
+    MovDelay[x][y]--;
+
+    if (MovDelay[x][y] > 0 && IN_SCR_FIELD(x, y))
+    {
+      int graphic = el_act2gfx(EL_ENVELOPE_1 + nr, MM_ACTION_COLLECTING);
+      int frame = num_frames - MovDelay[x][y] - 1;
+
+      DrawGraphicAnimation_MM(x, y, graphic, frame);
+
+      laser.redraw = TRUE;
+    }
+
+    if (MovDelay[x][y] == 0)
+    {
+      Tile[x][y] = EL_EMPTY;
+
+      DrawField_MM(x, y);
+
+      ScanLaser();
+
+      ShowEnvelope_MM(nr);
+    }
+  }
+}
+
 static void MeltIce(int x, int y)
 {
   int frames = 5;
@@ -2983,6 +3025,12 @@ boolean ClickElement(int x, int y, int button)
 
     element_clicked = TRUE;
   }
+  else if (IS_ENVELOPE(element))
+  {
+    Tile[x][y] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(element);
+
+    element_clicked = TRUE;
+  }
 
   click_delay.value = (new_button ? CLICK_DELAY_FIRST : CLICK_DELAY);
   new_button = FALSE;
@@ -3239,6 +3287,8 @@ static void GameActions_MM_Ext(void)
       OpenExit(x, y);
     else if (element == EL_GRAY_BALL_OPENING)
       OpenSurpriseBall(x, y);
+    else if (IS_ENVELOPE_OPENING(element))
+      OpenEnvelope(x, y);
     else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_ICE)
       MeltIce(x, y);
     else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA)
index 6ed89c955eac8caf4c04de683371e720baae1b35..a82b61df28d21917bb3a6258b2bda0e7e62c1f5d 100644 (file)
@@ -171,6 +171,15 @@ void InitElementProperties_MM(void)
   };
   static int ep_pacman_num = sizeof(ep_pacman) / sizeof(int);
 
+  static int ep_envelope[] =
+  {
+    EL_ENVELOPE_1,
+    EL_ENVELOPE_2,
+    EL_ENVELOPE_3,
+    EL_ENVELOPE_4,
+  };
+  static int ep_envelope_num = sizeof(ep_envelope) / sizeof(int);
+
   static long ep_bit[] =
   {
     EP_BIT_GRID,
@@ -186,6 +195,7 @@ void InitElementProperties_MM(void)
     EP_BIT_INACTIVE,
     EP_BIT_WALL,
     EP_BIT_PACMAN,
+    EP_BIT_ENVELOPE,
   };
   static int *ep_array[] =
   {
@@ -202,6 +212,7 @@ void InitElementProperties_MM(void)
     ep_inactive,
     ep_wall,
     ep_pacman,
+    ep_envelope,
   };
   static int *ep_num[] =
   {
@@ -218,6 +229,7 @@ void InitElementProperties_MM(void)
     &ep_inactive_num,
     &ep_wall_num,
     &ep_pacman_num,
+    &ep_envelope_num,
   };
   static int num_properties = sizeof(ep_num) / sizeof(int *);
 
index 0fb74d9e215efac28658873ccd73d46ee89f8ec6..dafaa5d60d043a20df3846b876f41f14bfa087f4 100644 (file)
@@ -48,6 +48,7 @@
 #define EP_BIT_INACTIVE                (1 << 11)
 #define EP_BIT_WALL            (1 << 12)
 #define EP_BIT_PACMAN          (1 << 13)
+#define EP_BIT_ENVELOPE                (1 << 14)
 
 #define IS_GRID(e)             (Elementeigenschaften[e] & EP_BIT_GRID)
 #define IS_MCDUFFIN(e)         (Elementeigenschaften[e] & EP_BIT_MCDUFFIN)
@@ -63,6 +64,7 @@
 #define IS_INACTIVE(e)         (Elementeigenschaften[e] & EP_BIT_INACTIVE)
 #define IS_MM_WALL(e)          (Elementeigenschaften[e] & EP_BIT_WALL)
 #define IS_PACMAN(e)           (Elementeigenschaften[e] & EP_BIT_PACMAN)
+#define IS_ENVELOPE(e)         (Elementeigenschaften[e] & EP_BIT_ENVELOPE)
 
 #define IS_WALL_STEEL(e)       ((e) >= EL_WALL_STEEL_START &&          \
                                 (e) <= EL_WALL_STEEL_END)
                                 (e) == EL_BOMB ||                      \
                                 IS_WALL_AMOEBA(e))
 
+#define IS_ENVELOPE_OPENING(e) ((e) >= EL_ENVELOPE_OPENING_START &&    \
+                                (e) <= EL_ENVELOPE_OPENING_END)
+
+#define ENVELOPE_NR(e)         ((e) - EL_ENVELOPE_1)
+#define ENVELOPE_OPENING_NR(e) ((e) - EL_ENVELOPE_1_OPENING)
+
 #define CAN_MOVE(e)            ((e) == EL_PACMAN)
 #define IS_FREE(x,y)            (Tile[x][y] == EL_EMPTY)
 
@@ -451,8 +459,12 @@ extern int         num_element_info;
 #define EL_GRID_WOOD_03                (EL_GRID_WOOD_START + 3)
 #define EL_GRID_WOOD_END       EL_GRID_WOOD_03
 #define EL_FUEL_EMPTY          155
+#define EL_ENVELOPE_1          156
+#define EL_ENVELOPE_2          157
+#define EL_ENVELOPE_3          158
+#define EL_ENVELOPE_4          159
 
-#define EL_MM_END_1            155
+#define EL_MM_END_1            159
 
 #define EL_CHAR_START          160
 #define EL_CHAR_ASCII0         (EL_CHAR_START - 32)
@@ -655,6 +667,13 @@ extern int         num_element_info;
 #define EL_AMOEBA_WALL_GROWING 504
 #define EL_BOMB_ACTIVE         505
 #define EL_MINE_ACTIVE         506
+#define EL_ENVELOPE_1_OPENING  507
+#define EL_ENVELOPE_2_OPENING  508
+#define EL_ENVELOPE_3_OPENING  509
+#define EL_ENVELOPE_4_OPENING  510
+
+#define EL_ENVELOPE_OPENING_START      EL_ENVELOPE_1_OPENING
+#define EL_ENVELOPE_OPENING_END                EL_ENVELOPE_4_OPENING
 
 #define EL_WALL_CHANGING       512
 #define EL_WALL_CHANGING_START (EL_WALL_CHANGING + 0)
index 13cab898ed95bf930dccaa0c2d8e8b1949b29bfa..cf51e039414079e374806a48a7334e770507fcb0 100644 (file)
@@ -5297,24 +5297,24 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
     "extra energy ball (empty)"
   },
   {
-    "mm_unused_156",
-    "unused",
-    "(not used)"
+    "mm_envelope_1",
+    "mm_envelope",
+    "mail envelope 1 (MM style)"
   },
   {
-    "mm_unused_157",
-    "unused",
-    "(not used)"
+    "mm_envelope_2",
+    "mm_envelope",
+    "mail envelope 2 (MM style)"
   },
   {
-    "mm_unused_158",
-    "unused",
-    "(not used)"
+    "mm_envelope_3",
+    "mm_envelope",
+    "mail envelope 3 (MM style)"
   },
   {
-    "mm_unused_159",
-    "unused",
-    "(not used)"
+    "mm_envelope_4",
+    "mm_envelope",
+    "mail envelope 4 (MM style)"
   },
   {
     "df_mirror_1",
index a943547a875a67819374a679b030e06ac8c38cd3..e111f027262d11f89b4864c911a132f254ca468e 100644 (file)
 #define IS_ENVELOPE(e)         ((e) >= EL_ENVELOPE_1 &&                \
                                 (e) <= EL_ENVELOPE_4)
 
+#define IS_MM_ENVELOPE(e)      ((e) >= EL_MM_ENVELOPE_1 &&             \
+                                (e) <= EL_MM_ENVELOPE_4)
+
 #define IS_BALLOON_ELEMENT(e)  ((e) == EL_BALLOON ||                   \
                                 (e) == EL_BALLOON_SWITCH_LEFT ||       \
                                 (e) == EL_BALLOON_SWITCH_RIGHT ||      \
                                 IS_EM_GATE_GRAY(e) ?  EM_GATE_GRAY_NR(e) :   \
                                 IS_EMC_GATE_GRAY(e) ? EMC_GATE_GRAY_NR(e) : 0)
 
+#define RND_ENVELOPE_NR(e)     ((e) - EL_ENVELOPE_1)
+#define MM_ENVELOPE_NR(e)      ((e) - EL_MM_ENVELOPE_1)
+#define ENVELOPE_NR(e)         (IS_ENVELOPE(e) ? RND_ENVELOPE_NR(e) :  \
+                                MM_ENVELOPE_NR(e))
+
 #define IS_ACID_POOL_OR_ACID(e)        (IS_ACID_POOL(e) || (e) == EL_ACID)
 
 #define IS_EMC_PILLAR(e)       ((e) >= EL_EMC_WALL_1 &&                \
 #define EL_MM_WOODEN_GRID_FIXED_4      (EL_MM_WOODEN_GRID_FIXED_START + 3)
 #define EL_MM_WOODEN_GRID_FIXED_END    EL_MM_WOODEN_GRID_FIXED_03
 #define EL_MM_FUEL_EMPTY               (EL_MM_START + 155)
-
-#define EL_MM_UNUSED_156               (EL_MM_START + 156)
-#define EL_MM_UNUSED_157               (EL_MM_START + 157)
-#define EL_MM_UNUSED_158               (EL_MM_START + 158)
-#define EL_MM_UNUSED_159               (EL_MM_START + 159)
+#define EL_MM_ENVELOPE_1               (EL_MM_START + 156)
+#define EL_MM_ENVELOPE_2               (EL_MM_START + 157)
+#define EL_MM_ENVELOPE_3               (EL_MM_START + 158)
+#define EL_MM_ENVELOPE_4               (EL_MM_START + 159)
 
 #define EL_MM_END_1                    (EL_MM_START + 159)
 #define EL_MM_START_2                  (EL_MM_START + 160)
index 5e5a2e1d01708640a63511faab85a617e596d843..d9e3652c2500d1598391fbbe4f09e0f69fe4e467 100644 (file)
@@ -2989,6 +2989,16 @@ void ShowEnvelope(int envelope_nr)
   BackToFront();
 }
 
+void ShowEnvelope_MM(int envelope_nr)
+{
+  BlitBitmap(backbuffer, bitmap_db_field, REAL_SX, REAL_SY,
+            FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
+
+  ShowEnvelope(envelope_nr);
+
+  SetDrawtoField(DRAW_TO_BACKBUFFER);
+}
+
 static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy,
                                           int xsize, int ysize)
 {