rnd-20040316-1-src
[rocksndiamonds.git] / src / editor.c
index 5a567832af99981e765126f20de38453970183b6..2627994b80409a409999385f5578ba3d71cca085 100644 (file)
@@ -47,6 +47,8 @@
 #define ED_CTRL1_BUTTONS_GFX_YPOS      236
 #define ED_CTRL2_BUTTONS_GFX_YPOS      236
 #define ED_CTRL3_BUTTONS_GFX_YPOS      324
+#define ED_CTRL4_BUTTONS_GFX_XPOS      44
+#define ED_CTRL4_BUTTONS_GFX_YPOS      214
 #define ED_CTRL1_BUTTONS_ALT_GFX_YPOS  142
 #define ED_CTRL3_BUTTONS_ALT_GFX_YPOS  302
 
 #define ED_CTRL3_BUTTON_YSIZE          22
 #define ED_CTRL3_BUTTONS_XPOS          6
 #define ED_CTRL3_BUTTONS_YPOS          6
+#define ED_CTRL4_BUTTON_XSIZE          22
+#define ED_CTRL4_BUTTON_YSIZE          22
+#define ED_CTRL4_BUTTONS_XPOS          6
+#define ED_CTRL4_BUTTONS_YPOS          6
 
 #define ED_CTRL1_BUTTONS_HORIZ         4
 #define ED_CTRL1_BUTTONS_VERT          4
 #define ED_CTRL2_BUTTONS_VERT          2
 #define ED_CTRL3_BUTTONS_HORIZ         3
 #define ED_CTRL3_BUTTONS_VERT          1
+#define ED_CTRL4_BUTTONS_HORIZ         2
+#define ED_CTRL4_BUTTONS_VERT          1
 
 #define ED_NUM_CTRL1_BUTTONS   (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
 #define ED_NUM_CTRL2_BUTTONS   (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
 #define ED_NUM_CTRL3_BUTTONS   (ED_CTRL3_BUTTONS_HORIZ * ED_CTRL3_BUTTONS_VERT)
-#define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
+#define ED_NUM_CTRL4_BUTTONS   (ED_CTRL4_BUTTONS_HORIZ * ED_CTRL4_BUTTONS_VERT)
+#define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS   + ED_NUM_CTRL2_BUTTONS)
+#define ED_NUM_CTRL1_3_BUTTONS (ED_NUM_CTRL1_2_BUTTONS + ED_NUM_CTRL3_BUTTONS)
 #define ED_NUM_CTRL_BUTTONS    (ED_NUM_CTRL1_BUTTONS + \
                                ED_NUM_CTRL2_BUTTONS + \
-                               ED_NUM_CTRL3_BUTTONS)
+                               ED_NUM_CTRL3_BUTTONS + \
+                               ED_NUM_CTRL4_BUTTONS)
 
 /* values for the element list */
 #define ED_ELEMENTLIST_XPOS            5
 #define GADGET_ID_CUSTOM_COPY_FROM     (GADGET_ID_TOOLBOX_FIRST + 22)
 #define GADGET_ID_CUSTOM_COPY_TO       (GADGET_ID_TOOLBOX_FIRST + 23)
 #define GADGET_ID_CUSTOM_EXCHANGE      (GADGET_ID_TOOLBOX_FIRST + 24)
+#define GADGET_ID_CUSTOM_COPY          (GADGET_ID_TOOLBOX_FIRST + 25)
+#define GADGET_ID_CUSTOM_PASTE         (GADGET_ID_TOOLBOX_FIRST + 26)
 
 /* counter button identifiers */
-#define GADGET_ID_COUNTER_FIRST                (GADGET_ID_TOOLBOX_FIRST + 25)
+#define GADGET_ID_COUNTER_FIRST                (GADGET_ID_TOOLBOX_FIRST + 27)
 
 #define GADGET_ID_SELECT_LEVEL_DOWN    (GADGET_ID_COUNTER_FIRST + 0)
 #define GADGET_ID_SELECT_LEVEL_TEXT    (GADGET_ID_COUNTER_FIRST + 1)
 #define GADGET_ID_CHANGE_SIDE          (GADGET_ID_SELECTBOX_FIRST + 17)
 #define GADGET_ID_CHANGE_PLAYER                (GADGET_ID_SELECTBOX_FIRST + 18)
 #define GADGET_ID_CHANGE_PAGE          (GADGET_ID_SELECTBOX_FIRST + 19)
-#define GADGET_ID_CHANGE_POWER         (GADGET_ID_SELECTBOX_FIRST + 20)
+#define GADGET_ID_CHANGE_REPLACE_WHEN  (GADGET_ID_SELECTBOX_FIRST + 20)
 #define GADGET_ID_SELECT_CHANGE_PAGE   (GADGET_ID_SELECTBOX_FIRST + 21)
 #define GADGET_ID_GROUP_CHOICE_MODE    (GADGET_ID_SELECTBOX_FIRST + 22)
 
 #define GADGET_ID_USE_SPRING_BUG       (GADGET_ID_CHECKBUTTON_FIRST + 7)
 #define GADGET_ID_BLOCK_LAST_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 8)
 #define GADGET_ID_SP_BLOCK_LAST_FIELD  (GADGET_ID_CHECKBUTTON_FIRST + 9)
-#define GADGET_ID_CAN_MOVE_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 10)
-#define GADGET_ID_CUSTOM_EXPLODE_RESULT        (GADGET_ID_CHECKBUTTON_FIRST + 11)
-#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 12)
-#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 13)
-#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 14)
-#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 15)
-#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 16)
-#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 17)
-#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 18)
-#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 19)
-#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 27)
-#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 28)
-#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 29)
-#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 30)
-#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 31)
+#define GADGET_ID_CAN_FALL_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 10)
+#define GADGET_ID_CAN_MOVE_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 11)
+#define GADGET_ID_DONT_COLLIDE_WITH    (GADGET_ID_CHECKBUTTON_FIRST + 12)
+#define GADGET_ID_CUSTOM_EXPLODE_RESULT        (GADGET_ID_CHECKBUTTON_FIRST + 13)
+#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 14)
+#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 15)
+#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 16)
+#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 17)
+#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 18)
+#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 19)
+#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 20)
+#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 21)
+#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 22)
+#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 23)
+#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 29)
+#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 30)
+#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 31)
+#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 33)
 
 /* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 34)
 #define GADGET_ID_ELEMENTLIST_LAST     (GADGET_ID_ELEMENTLIST_FIRST +  \
                                        ED_NUM_ELEMENTLIST_BUTTONS - 1)
 
 #define ED_SELECTBOX_ID_CHANGE_SIDE            17
 #define ED_SELECTBOX_ID_CHANGE_PLAYER          18
 #define ED_SELECTBOX_ID_CHANGE_PAGE            19
-#define ED_SELECTBOX_ID_CHANGE_POWER           20
+#define ED_SELECTBOX_ID_CHANGE_REPLACE_WHEN    20
 #define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE     21
 #define ED_SELECTBOX_ID_GROUP_CHOICE_MODE      22
 
 #define ED_CHECKBUTTON_ID_USE_SPRING_BUG       5
 #define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD     6
 #define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD  7
-#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID   8
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   9
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  10
-#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    11
-#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        12
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      13
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      14
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     15
-#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      16
-#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                17
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT        18
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  19
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 20
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        21
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    22
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY         23
-#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 24
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  25
-#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 26
-#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   27
-#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 28
-#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    29
-
-#define ED_NUM_CHECKBUTTONS                    30
+#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID   8
+#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID   9
+#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH    10
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   11
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  12
+#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    13
+#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        14
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      15
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      16
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     17
+#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      18
+#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                19
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT        20
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  21
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 22
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        23
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    24
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY         25
+#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 26
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  27
+#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 28
+#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   29
+#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 30
+#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    31
+
+#define ED_NUM_CHECKBUTTONS                    32
 
 #define ED_CHECKBUTTON_ID_LEVEL_FIRST  ED_CHECKBUTTON_ID_DOUBLE_SPEED
 #define ED_CHECKBUTTON_ID_LEVEL_LAST   ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
@@ -862,6 +879,9 @@ static struct
   { '\0',      "copy settings from other element"      },
   { '\0',      "copy settings to other element"        },
   { '\0',      "exchange settings with other element"  },
+
+  { '\0',      "copy settings from this element"       },
+  { '\0',      "paste settings to this element"        },
 };
 
 static int random_placement_value = 10;
@@ -1084,7 +1104,7 @@ static struct
     0,                                 100,
     GADGET_ID_CHANGE_CONT_RND_DOWN,    GADGET_ID_CHANGE_CONT_RND_UP,
     GADGET_ID_CHANGE_CONT_RND_TEXT,    GADGET_ID_NONE,
-    &custom_element_change.random,
+    &custom_element_change.random_percentage,
     NULL,                              "use random replace:", "%"
   },
 };
@@ -1416,11 +1436,11 @@ static struct ValueTextInfo options_change_trigger_page[] =
   { -1,                                NULL                            }
 };
 
-static struct ValueTextInfo options_change_power[] =
+static struct ValueTextInfo options_change_replace_when[] =
 {
-  { CP_NON_DESTRUCTIVE,                "empty"                         },
-  { CP_HALF_DESTRUCTIVE,       "diggable"                      },
-  { CP_FULL_DESTRUCTIVE,       "destructible"                  },
+  { CP_WHEN_EMPTY,             "empty"                         },
+  { CP_WHEN_DIGGABLE,          "diggable"                      },
+  { CP_WHEN_DESTRUCTIBLE,      "destructible"                  },
 
   { -1,                                NULL                            }
 };
@@ -1626,10 +1646,10 @@ static struct
   },
   {
     ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(10),
-    GADGET_ID_CHANGE_POWER,            GADGET_ID_NONE,
+    GADGET_ID_CHANGE_REPLACE_WHEN,     GADGET_ID_NONE,
     -1,
-    options_change_power,
-    &custom_element_change.power,
+    options_change_replace_when,
+    &custom_element_change.replace_when,
     "replace when", NULL,              "which elements can be replaced"
   },
   {
@@ -1924,19 +1944,26 @@ static struct
     "use spring pushing bug",          "use odd spring pushing behaviour"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
     GADGET_ID_BLOCK_LAST_FIELD,                GADGET_ID_NONE,
     &level.block_last_field,
     NULL,
     "block last field when moving",    "player blocks last field when moving"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
     GADGET_ID_SP_BLOCK_LAST_FIELD,     GADGET_ID_NONE,
     &level.sp_block_last_field,
     NULL,
     "block last field when moving",    "player blocks last field when moving"
   },
+  {
+    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    GADGET_ID_CAN_FALL_INTO_ACID,      GADGET_ID_NONE,
+    &custom_element_properties[EP_CAN_MOVE_INTO_ACID],
+    NULL,
+    "can fall into acid (with gravity)","player can fall into acid pool"
+  },
   {
     ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
     GADGET_ID_CAN_MOVE_INTO_ACID,      GADGET_ID_NONE,
@@ -1944,6 +1971,13 @@ static struct
     NULL,
     "can move into acid",              "element can move into acid pool"
   },
+  {
+    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    GADGET_ID_DONT_COLLIDE_WITH,       GADGET_ID_NONE,
+    &custom_element_properties[EP_DONT_COLLIDE_WITH],
+    NULL,
+    "deadly when colliding with",      "element is deadly when hitting player"
+  },
 
   /* ---------- element settings: configure 1 (custom elements) ----------- */
 
@@ -2064,19 +2098,19 @@ static struct
   {
     ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(9),
     GADGET_ID_CHANGE_USE_CONTENT,      GADGET_ID_NONE,
-    &custom_element_change.use_content,
+    &custom_element_change.use_target_content,
     NULL, "use extended change target:","element changes to more elements"
   },
   {
     ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(11),
     GADGET_ID_CHANGE_ONLY_COMPLETE,    GADGET_ID_NONE,
-    &custom_element_change.only_complete,
+    &custom_element_change.only_if_complete,
     NULL, "replace all or nothing",    "only replace when all can be changed"
   },
   {
     ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(12),
     GADGET_ID_CHANGE_USE_RANDOM,       GADGET_ID_NONE,
-    &custom_element_change.use_random_change,
+    &custom_element_change.use_random_replace,
     NULL, NULL,                                "use percentage for random replace"
   },
 };
@@ -3276,7 +3310,12 @@ static int editor_el_custom_more[] =
   EL_CUSTOM_START + 252,
   EL_CUSTOM_START + 253,
   EL_CUSTOM_START + 254,
-  EL_CUSTOM_START + 255
+  EL_CUSTOM_START + 255,
+
+  EL_TRIGGER_ELEMENT,
+  EL_TRIGGER_PLAYER,
+  EL_EMPTY,
+  EL_EMPTY
 };
 static int *editor_hl_custom_more_ptr = editor_hl_custom_more;
 static int *editor_el_custom_more_ptr = editor_el_custom_more;
@@ -3946,7 +3985,7 @@ static void DrawDrawingArea(int id)
       for (x = 0; x < 3; x++)
        DrawMiniGraphicExt(drawto,
                           gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
-                          el2edimg(custom_element_change.content[x][y]));
+                          el2edimg(custom_element_change.target_content[x][y]));
   else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER)
     DrawMiniGraphicExt(drawto, gi->x, gi->y,
                       el2edimg(custom_element_change.trigger_element));
@@ -4056,7 +4095,7 @@ static void CreateControlButtons()
 
       gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
       gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
-      width = ED_CTRL1_BUTTON_XSIZE;
+      width  = ED_CTRL1_BUTTON_XSIZE;
       height = ED_CTRL1_BUTTON_YSIZE;
 
       gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
@@ -4071,7 +4110,7 @@ static void CreateControlButtons()
 
       gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
       gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
-      width = ED_CTRL2_BUTTON_XSIZE;
+      width  = ED_CTRL2_BUTTON_XSIZE;
       height = ED_CTRL2_BUTTON_YSIZE;
 
       gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
@@ -4079,14 +4118,14 @@ static void CreateControlButtons()
       gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL2_BUTTONS_GFX_YPOS + gd_yoffset;
       gd_y2 = 0;       /* no alternative graphic for these buttons */
     }
-    else
+    else if (id < ED_NUM_CTRL1_3_BUTTONS)
     {
       int x = (i - ED_NUM_CTRL1_2_BUTTONS) % ED_CTRL3_BUTTONS_HORIZ + 1;
       int y = (i - ED_NUM_CTRL1_2_BUTTONS) / ED_CTRL3_BUTTONS_HORIZ;
 
       gd_xoffset = ED_CTRL3_BUTTONS_XPOS + x * ED_CTRL3_BUTTON_XSIZE;
       gd_yoffset = ED_CTRL3_BUTTONS_YPOS + y * ED_CTRL3_BUTTON_YSIZE;
-      width = ED_CTRL3_BUTTON_XSIZE;
+      width  = ED_CTRL3_BUTTON_XSIZE;
       height = ED_CTRL3_BUTTON_YSIZE;
 
       gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
@@ -4094,6 +4133,21 @@ static void CreateControlButtons()
       gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_GFX_YPOS     + gd_yoffset;
       gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
     }
+    else
+    {
+      int x = (i - ED_NUM_CTRL1_3_BUTTONS) % ED_CTRL4_BUTTONS_HORIZ;
+      int y = (i - ED_NUM_CTRL1_3_BUTTONS) / ED_CTRL4_BUTTONS_HORIZ + 3;
+
+      gd_xoffset = ED_CTRL4_BUTTONS_XPOS + x * ED_CTRL4_BUTTON_XSIZE;
+      gd_yoffset = ED_CTRL4_BUTTONS_YPOS + y * ED_CTRL4_BUTTON_YSIZE;
+      width  = ED_CTRL4_BUTTON_XSIZE;
+      height = ED_CTRL4_BUTTON_YSIZE;
+
+      gd_x1 = DOOR_GFX_PAGEX6 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
+      gd_x2 = DOOR_GFX_PAGEX5 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
+      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL4_BUTTONS_GFX_YPOS + gd_yoffset;
+      gd_y2 = 0;       /* no alternative graphic for these buttons */
+    }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_CUSTOM_TYPE_ID, i,
@@ -5208,8 +5262,7 @@ static void MapCheckbuttonGadget(int id)
   int y;       /* set after gadget position was modified */
 
   /* set position for "stickybutton" and "can move into acid" gadgets */
-  if (id == ED_CHECKBUTTON_ID_STICK_ELEMENT ||
-      id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID)
+  if (id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID)
     ModifyGadget(gi, GDI_Y, SY + checkbutton_info[id].y, GDI_END);
 
   y = gi->y + yoffset;
@@ -5264,7 +5317,9 @@ static void MapOrUnmapLevelEditorToolboxCustomGadgets(boolean map)
   {
     if (i == GADGET_ID_CUSTOM_COPY_FROM ||
         i == GADGET_ID_CUSTOM_COPY_TO ||
-        i == GADGET_ID_CUSTOM_EXCHANGE)
+        i == GADGET_ID_CUSTOM_EXCHANGE ||
+        i == GADGET_ID_CUSTOM_COPY ||
+        i == GADGET_ID_CUSTOM_PASTE)
     {
       if (map)
        MapGadget(level_editor_gadget[i]);
@@ -5512,15 +5567,15 @@ static void copy_custom_element_settings(int element_from, int element_to)
 
     change_to->explode = change_from->explode;
     change_to->use_content = change_from->use_content;
-    change_to->only_complete = change_from->only_complete;
+    change_to->only_if_complete = change_from->only_if_complete;
     change_to->use_random_change = change_from->use_random_change;
 
-    change_to->random = change_from->random;
-    change_to->power = change_from->power;
+    change_to->random_percentage = change_from->random_percentage;
+    change_to->replace_when = change_from->replace_when;
 
     for (y = 0; y < 3; y++)
       for (x = 0; x < 3; x++)
-       change_to->content[x][y] = change_from->content[x][y];
+       change_to->target_content[x][y] = change_from->target_content[x][y];
 
     change_to->can_change = change_from->can_change;
 
@@ -5558,8 +5613,8 @@ static void replace_custom_element_in_settings(int element_from,
 
       for (y = 0; y < 3; y++)
        for (x = 0; x < 3; x++)
-         if (change->content[x][y] == element_from)
-           change->content[x][y] = element_to;
+         if (change->target_content[x][y] == element_from)
+           change->target_content[x][y] = element_to;
     }
 
     if (ei->group != NULL)                             /* group or internal */
@@ -5583,7 +5638,19 @@ static void replace_custom_element_in_playfield(int element_from,
 static boolean CopyCustomElement(int element_old, int element_new,
                                 int copy_mode)
 {
-  if (IS_CUSTOM_ELEMENT(element_old) && !IS_CUSTOM_ELEMENT(element_new))
+  if (copy_mode == GADGET_ID_CUSTOM_COPY)
+  {
+    element_new = (IS_CUSTOM_ELEMENT(element_old) ?
+                  EL_INTERNAL_CLIPBOARD_CUSTOM : EL_INTERNAL_CLIPBOARD_GROUP);
+    copy_mode = GADGET_ID_CUSTOM_COPY_TO;
+  }
+  else if (copy_mode == GADGET_ID_CUSTOM_PASTE)
+  {
+    element_old = (IS_CUSTOM_ELEMENT(element_new) ?
+                  EL_INTERNAL_CLIPBOARD_CUSTOM : EL_INTERNAL_CLIPBOARD_GROUP);
+    copy_mode = GADGET_ID_CUSTOM_COPY_TO;
+  }
+  else if (IS_CUSTOM_ELEMENT(element_old) && !IS_CUSTOM_ELEMENT(element_new))
   {
     Request("Please choose custom element !", REQ_CONFIRM);
 
@@ -5606,17 +5673,17 @@ static boolean CopyCustomElement(int element_old, int element_new,
   }
   else if (copy_mode == GADGET_ID_CUSTOM_EXCHANGE)
   {
-    copy_custom_element_settings(element_old, EL_INTERNAL_EDITOR);
+    copy_custom_element_settings(element_old, EL_INTERNAL_DUMMY);
     copy_custom_element_settings(element_new, element_old);
-    copy_custom_element_settings(EL_INTERNAL_EDITOR, element_new);
+    copy_custom_element_settings(EL_INTERNAL_DUMMY, element_new);
 
-    replace_custom_element_in_settings(element_old, EL_INTERNAL_EDITOR);
+    replace_custom_element_in_settings(element_old, EL_INTERNAL_DUMMY);
     replace_custom_element_in_settings(element_new, element_old);
-    replace_custom_element_in_settings(EL_INTERNAL_EDITOR, element_new);
+    replace_custom_element_in_settings(EL_INTERNAL_DUMMY, element_new);
 
-    replace_custom_element_in_playfield(element_old, EL_INTERNAL_EDITOR);
+    replace_custom_element_in_playfield(element_old, EL_INTERNAL_DUMMY);
     replace_custom_element_in_playfield(element_new, element_old);
-    replace_custom_element_in_playfield(EL_INTERNAL_EDITOR, element_new);
+    replace_custom_element_in_playfield(EL_INTERNAL_DUMMY, element_new);
   }
 
   UpdateCustomElementGraphicGadgets();
@@ -5781,10 +5848,13 @@ static void CopyGroupElementPropertiesToEditor(int element)
 static void CopyClassicElementPropertiesToEditor(int element)
 {
 #if 1
-  if (COULD_MOVE_INTO_ACID(element))
+  if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
     custom_element_properties[EP_CAN_MOVE_INTO_ACID] =
       getMoveIntoAcidProperty(&level, element);
 
+  if (MAYBE_DONT_COLLIDE_WITH(element))
+    custom_element_properties[EP_DONT_COLLIDE_WITH] =
+      getDontCollideWithProperty(&level, element);
 #else
 
   if (COULD_MOVE_INTO_ACID(element))
@@ -5957,10 +6027,13 @@ static void CopyGroupElementPropertiesToGame(int element)
 static void CopyClassicElementPropertiesToGame(int element)
 {
 #if 1
-  if (COULD_MOVE_INTO_ACID(element))
+  if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
     setMoveIntoAcidProperty(&level, element,
                            custom_element_properties[EP_CAN_MOVE_INTO_ACID]);
 
+  if (MAYBE_DONT_COLLIDE_WITH(element))
+    setDontCollideWithProperty(&level, element,
+                             custom_element_properties[EP_DONT_COLLIDE_WITH]);
 #else
 
   if (COULD_MOVE_INTO_ACID(element))
@@ -6324,7 +6397,7 @@ static void DrawCustomChangeContentArea()
   int id = ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT;
   struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
   int x1 = right_gadget_border[GADGET_ID_CHANGE_USE_CONTENT];
-  int x2 = right_gadget_border[GADGET_ID_CHANGE_POWER];
+  int x2 = right_gadget_border[GADGET_ID_CHANGE_REPLACE_WHEN];
   int x3 = right_gadget_border[GADGET_ID_CHANGE_ONLY_COMPLETE];
   int xoffset = ED_DRAWINGAREA_TEXT_DISTANCE;
 
@@ -6827,7 +6900,7 @@ static boolean checkPropertiesConfig(int element)
       ELEM_IS_PLAYER(element) ||
       HAS_CONTENT(element) ||
       COULD_MOVE_INTO_ACID(element) ||
-      element == EL_SPRING)
+      MAYBE_DONT_COLLIDE_WITH(element))
     return TRUE;
   else
     for (i = 0; elements_with_counter[i].element != -1; i++)
@@ -6857,6 +6930,7 @@ static void DrawPropertiesConfig()
 
       counterbutton_info[counter_id].y =
        ED_SETTINGS_YPOS((HAS_CONTENT(properties_element) ? 1 : 0) +
+                        (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 : 0)+
                         (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0));
 
       counterbutton_info[counter_id].value = elements_with_counter[i].value;
@@ -6880,9 +6954,12 @@ static void DrawPropertiesConfig()
   }
 
   if (ELEM_IS_PLAYER(properties_element))
+  {
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID);
     MapCheckbuttonGadget(properties_element == EL_SP_MURPHY ?
                         ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD :
                         ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD);
+  }
 
   if (IS_GEM(properties_element))
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS);
@@ -6891,6 +6968,7 @@ static void DrawPropertiesConfig()
       (!IS_CUSTOM_ELEMENT(properties_element) ||
        edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2))
   {
+    /* set position for special checkbutton for "can move into acid" */
     checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].y =
       ED_SETTINGS_YPOS(IS_CUSTOM_ELEMENT(properties_element) ? 6 :
                       HAS_CONTENT(properties_element) ? 1 : 0);
@@ -6898,6 +6976,9 @@ static void DrawPropertiesConfig()
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID);
   }
 
+  if (MAYBE_DONT_COLLIDE_WITH(properties_element))
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH);
+
   if (properties_element == EL_SPRING)
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_SPRING_BUG);
 
@@ -6952,8 +7033,6 @@ static void DrawPropertiesConfig()
     }
     else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
     {
-      /* set position for special checkbutton for "can move into acid" */
-
       /* draw checkbutton gadgets */
       for (i =  ED_CHECKBUTTON_ID_CUSTOM2_FIRST;
           i <= ED_CHECKBUTTON_ID_CUSTOM2_LAST; i++)
@@ -8004,7 +8083,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        }
        else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
        {
-         custom_element_change.content[sx][sy] = new_element;
+         custom_element_change.target_content[sx][sy] = new_element;
 
          CopyCustomElementPropertiesToGame(properties_element);
        }
@@ -8137,7 +8216,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
       else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
        PickDrawingElement(button, custom_element_change.target_element);
       else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
-       PickDrawingElement(button, custom_element_change.content[sx][sy]);
+       PickDrawingElement(button, custom_element_change.target_content[sx][sy]);
       else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
        PickDrawingElement(button, custom_element_change.trigger_element);
       else if (id == GADGET_ID_GROUP_CONTENT)
@@ -8361,7 +8440,9 @@ static void HandleCheckbuttons(struct GadgetInfo *gi)
 
   *checkbutton_info[type_id].value ^= TRUE;
 
-  if (type_id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID ||
+  if (type_id == ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID ||
+      type_id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID ||
+      type_id == ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH ||
       (((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
         type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) ||
        (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST &&
@@ -8601,6 +8682,14 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       last_drawing_function = drawing_function;
       break;
 
+    case GADGET_ID_CUSTOM_COPY:
+      CopyCustomElement(properties_element, -1, id);
+      break;
+
+    case GADGET_ID_CUSTOM_PASTE:
+      CopyCustomElement(-1, properties_element, id);
+      break;
+
     case GADGET_ID_UNDO:
       if (undo_buffer_steps == 0)
       {
@@ -9071,7 +9160,7 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
     else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
       element = custom_element_change.target_element;
     else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
-      element = custom_element_change.content[sx][sy];
+      element = custom_element_change.target_content[sx][sy];
     else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
       element = custom_element_change.trigger_element;
     else if (id == GADGET_ID_GROUP_CONTENT)