X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=0ed7c8ca792851de30b7927ff2c064efe247420c;hb=c64be0354d88b9776537a907f524993e29e074aa;hp=c9f44597a5d3bbe3bea0c3c00905e812cd9ef224;hpb=e803a798c70f90963b68085ef6ebe22eb30a57b5;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index c9f44597..0ed7c8ca 100644 --- a/src/editor.c +++ b/src/editor.c @@ -24,6 +24,9 @@ #include "tape.h" +#define INFOTEXT_UNKNOWN_ELEMENT "unknown" + + /* ----------------------------------------------------------------------------- screen and artwork graphic pixel position definitions @@ -39,24 +42,41 @@ #define ED_WIN_MB_RIGHT_YPOS ED_WIN_MB_LEFT_YPOS /* values for the control window */ -#define ED_CTRL_BUTTONS_GFX_YPOS 236 -#define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142 +#define ED_CTRL_NO_BUTTONS_GFX_XPOS 6 +#define ED_CTRL_NO_BUTTONS_GFX_YPOS 286 +#define ED_CTRL1_BUTTONS_GFX_YPOS 236 +#define ED_CTRL2_BUTTONS_GFX_YPOS 236 +#define ED_CTRL3_BUTTONS_GFX_YPOS 324 +#define ED_CTRL1_BUTTONS_ALT_GFX_YPOS 142 +#define ED_CTRL3_BUTTONS_ALT_GFX_YPOS 302 -#define ED_CTRL1_BUTTONS_HORIZ 4 -#define ED_CTRL1_BUTTONS_VERT 4 #define ED_CTRL1_BUTTON_XSIZE 22 #define ED_CTRL1_BUTTON_YSIZE 22 #define ED_CTRL1_BUTTONS_XPOS 6 #define ED_CTRL1_BUTTONS_YPOS 6 -#define ED_CTRL2_BUTTONS_HORIZ 3 -#define ED_CTRL2_BUTTONS_VERT 2 #define ED_CTRL2_BUTTON_XSIZE 30 #define ED_CTRL2_BUTTON_YSIZE 20 #define ED_CTRL2_BUTTONS_XPOS 5 #define ED_CTRL2_BUTTONS_YPOS 99 +#define ED_CTRL3_BUTTON_XSIZE 22 +#define ED_CTRL3_BUTTON_YSIZE 22 +#define ED_CTRL3_BUTTONS_XPOS 6 +#define ED_CTRL3_BUTTONS_YPOS 6 + +#define ED_CTRL1_BUTTONS_HORIZ 4 +#define ED_CTRL1_BUTTONS_VERT 4 +#define ED_CTRL2_BUTTONS_HORIZ 3 +#define ED_CTRL2_BUTTONS_VERT 2 +#define ED_CTRL3_BUTTONS_HORIZ 3 +#define ED_CTRL3_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_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS) +#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_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + \ + ED_NUM_CTRL2_BUTTONS + \ + ED_NUM_CTRL3_BUTTONS) /* values for the element list */ #define ED_ELEMENTLIST_XPOS 5 @@ -124,15 +144,25 @@ ED_GADGET_DISTANCE) /* custom element content */ #define ED_AREA_ELEM_CONTENT4_XPOS (29 * MINI_TILEX) -#define ED_AREA_ELEM_CONTENT4_YPOS (ED_SETTINGS_YPOS(12) + \ +#define ED_AREA_ELEM_CONTENT4_YPOS (ED_SETTINGS_YPOS(13) + \ ED_GADGET_DISTANCE - MINI_TILEY) +/* movement enter/leave element */ +#define ED_AREA_ELEM_CONTENT4a_XPOS (29 * MINI_TILEX) +#define ED_AREA_ELEM_CONTENT4a_YPOS (ED_SETTINGS_YPOS(7) + \ + ED_GADGET_DISTANCE) +#define ED_AREA_ELEM_CONTENT4b_XPOS (29 * MINI_TILEX) +#define ED_AREA_ELEM_CONTENT4b_YPOS (ED_SETTINGS_YPOS(7) + \ + ED_GADGET_DISTANCE) /* custom change trigger element */ #define ED_AREA_ELEM_CONTENT5_YPOS (ED_SETTINGS_YPOS(6) + \ ED_GADGET_DISTANCE) /* extended custom change target */ #define ED_AREA_ELEM_CONTENT6_XPOS (29 * MINI_TILEX) -#define ED_AREA_ELEM_CONTENT6_YPOS (ED_SETTINGS_YPOS(9) + \ +#define ED_AREA_ELEM_CONTENT6_YPOS (ED_SETTINGS_YPOS(10) + \ ED_GADGET_DISTANCE - MINI_TILEY) +/* group element content */ +#define ED_AREA_GROUP_CONTENT_XPOS ED_SETTINGS_XPOS(0) +#define ED_AREA_GROUP_CONTENT_YPOS (22 * MINI_TILEY) /* values for random placement background drawing area */ #define ED_AREA_RANDOM_BACKGROUND_YPOS (31 * MINI_TILEY) @@ -280,6 +310,7 @@ #define GADGET_ID_GRAB_BRUSH (GADGET_ID_TOOLBOX_FIRST + 13) #define GADGET_ID_WRAP_DOWN (GADGET_ID_TOOLBOX_FIRST + 14) #define GADGET_ID_PICK_ELEMENT (GADGET_ID_TOOLBOX_FIRST + 15) + #define GADGET_ID_UNDO (GADGET_ID_TOOLBOX_FIRST + 16) #define GADGET_ID_INFO (GADGET_ID_TOOLBOX_FIRST + 17) #define GADGET_ID_SAVE (GADGET_ID_TOOLBOX_FIRST + 18) @@ -287,8 +318,12 @@ #define GADGET_ID_TEST (GADGET_ID_TOOLBOX_FIRST + 20) #define GADGET_ID_EXIT (GADGET_ID_TOOLBOX_FIRST + 21) +#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) + /* counter button identifiers */ -#define GADGET_ID_COUNTER_FIRST (GADGET_ID_TOOLBOX_FIRST + 22) +#define GADGET_ID_COUNTER_FIRST (GADGET_ID_TOOLBOX_FIRST + 25) #define GADGET_ID_SELECT_LEVEL_DOWN (GADGET_ID_COUNTER_FIRST + 0) #define GADGET_ID_SELECT_LEVEL_TEXT (GADGET_ID_COUNTER_FIRST + 1) @@ -350,9 +385,12 @@ #define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 57) #define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 58) #define GADGET_ID_CHANGE_CONT_RND_UP (GADGET_ID_COUNTER_FIRST + 59) +#define GADGET_ID_GROUP_CONTENT_DOWN (GADGET_ID_COUNTER_FIRST + 60) +#define GADGET_ID_GROUP_CONTENT_TEXT (GADGET_ID_COUNTER_FIRST + 61) +#define GADGET_ID_GROUP_CONTENT_UP (GADGET_ID_COUNTER_FIRST + 62) /* drawing area identifiers */ -#define GADGET_ID_DRAWING_AREA_FIRST (GADGET_ID_COUNTER_FIRST + 60) +#define GADGET_ID_DRAWING_AREA_FIRST (GADGET_ID_COUNTER_FIRST + 63) #define GADGET_ID_DRAWING_LEVEL (GADGET_ID_DRAWING_AREA_FIRST + 0) #define GADGET_ID_ELEMENT_CONTENT_0 (GADGET_ID_DRAWING_AREA_FIRST + 1) @@ -366,13 +404,16 @@ #define GADGET_ID_AMOEBA_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 9) #define GADGET_ID_CUSTOM_GRAPHIC (GADGET_ID_DRAWING_AREA_FIRST + 10) #define GADGET_ID_CUSTOM_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 11) -#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 12) -#define GADGET_ID_CUSTOM_CHANGE_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 13) -#define GADGET_ID_CUSTOM_CHANGE_TRIGGER (GADGET_ID_DRAWING_AREA_FIRST + 14) -#define GADGET_ID_RANDOM_BACKGROUND (GADGET_ID_DRAWING_AREA_FIRST + 15) +#define GADGET_ID_CUSTOM_MOVE_ENTER (GADGET_ID_DRAWING_AREA_FIRST + 12) +#define GADGET_ID_CUSTOM_MOVE_LEAVE (GADGET_ID_DRAWING_AREA_FIRST + 13) +#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 14) +#define GADGET_ID_CUSTOM_CHANGE_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 15) +#define GADGET_ID_CUSTOM_CHANGE_TRIGGER (GADGET_ID_DRAWING_AREA_FIRST + 16) +#define GADGET_ID_GROUP_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 17) +#define GADGET_ID_RANDOM_BACKGROUND (GADGET_ID_DRAWING_AREA_FIRST + 18) /* text input identifiers */ -#define GADGET_ID_TEXT_INPUT_FIRST (GADGET_ID_DRAWING_AREA_FIRST + 16) +#define GADGET_ID_TEXT_INPUT_FIRST (GADGET_ID_DRAWING_AREA_FIRST + 19) #define GADGET_ID_LEVEL_NAME (GADGET_ID_TEXT_INPUT_FIRST + 0) #define GADGET_ID_LEVEL_AUTHOR (GADGET_ID_TEXT_INPUT_FIRST + 1) @@ -392,18 +433,21 @@ #define GADGET_ID_CUSTOM_MOVE_PATTERN (GADGET_ID_SELECTBOX_FIRST + 3) #define GADGET_ID_CUSTOM_MOVE_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 4) #define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 5) -#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 6) -#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 7) -#define GADGET_ID_CUSTOM_ACCESS_TYPE (GADGET_ID_SELECTBOX_FIRST + 8) -#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 9) -#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 10) -#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 11) -#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 12) -#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 13) -#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 14) +#define GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE (GADGET_ID_SELECTBOX_FIRST + 6) +#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 7) +#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 8) +#define GADGET_ID_CUSTOM_ACCESS_TYPE (GADGET_ID_SELECTBOX_FIRST + 9) +#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 10) +#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 11) +#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 12) +#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 13) +#define GADGET_ID_CHANGE_SIDES (GADGET_ID_SELECTBOX_FIRST + 14) +#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 15) +#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 16) +#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 17) /* textbutton identifiers */ -#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 15) +#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 18) #define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0) #define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1) @@ -435,7 +479,7 @@ #define GADGET_ID_SCROLL_LIST_DOWN (GADGET_ID_SCROLLING_LIST_FIRST + 1) #define GADGET_ID_SCROLL_LIST_VERTICAL (GADGET_ID_SCROLLING_LIST_FIRST + 2) -/* checkbuttons for level/element properties */ +/* checkbuttons/radiobuttons for level/element properties */ #define GADGET_ID_CHECKBUTTON_FIRST (GADGET_ID_SCROLLING_LIST_FIRST + 3) #define GADGET_ID_RANDOM_PERCENTAGE (GADGET_ID_CHECKBUTTON_FIRST + 0) @@ -445,30 +489,32 @@ #define GADGET_ID_GRAVITY (GADGET_ID_CHECKBUTTON_FIRST + 4) #define GADGET_ID_STICK_ELEMENT (GADGET_ID_CHECKBUTTON_FIRST + 5) #define GADGET_ID_EM_SLIPPERY_GEMS (GADGET_ID_CHECKBUTTON_FIRST + 6) -#define GADGET_ID_CUSTOM_EXPLODE_RESULT (GADGET_ID_CHECKBUTTON_FIRST + 7) -#define GADGET_ID_CUSTOM_EXPLODE_FIRE (GADGET_ID_CHECKBUTTON_FIRST + 8) -#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 9) -#define GADGET_ID_CUSTOM_EXPLODE_IMPACT (GADGET_ID_CHECKBUTTON_FIRST + 10) -#define GADGET_ID_CUSTOM_WALK_TO_OBJECT (GADGET_ID_CHECKBUTTON_FIRST + 11) -#define GADGET_ID_CUSTOM_DEADLY (GADGET_ID_CHECKBUTTON_FIRST + 12) -#define GADGET_ID_CUSTOM_CAN_MOVE (GADGET_ID_CHECKBUTTON_FIRST + 13) -#define GADGET_ID_CUSTOM_CAN_FALL (GADGET_ID_CHECKBUTTON_FIRST + 14) -#define GADGET_ID_CUSTOM_CAN_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 15) -#define GADGET_ID_CUSTOM_SLIPPERY (GADGET_ID_CHECKBUTTON_FIRST + 16) -#define GADGET_ID_CUSTOM_ACCESSIBLE (GADGET_ID_CHECKBUTTON_FIRST + 17) -#define GADGET_ID_CUSTOM_USE_GRAPHIC (GADGET_ID_CHECKBUTTON_FIRST + 18) -#define GADGET_ID_CUSTOM_USE_TEMPLATE (GADGET_ID_CHECKBUTTON_FIRST + 19) -#define GADGET_ID_CUSTOM_CAN_CHANGE (GADGET_ID_CHECKBUTTON_FIRST + 20) -#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 21) -#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 22) -#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 23) -#define GADGET_ID_CHANGE_USE_RANDOM (GADGET_ID_CHECKBUTTON_FIRST + 24) -#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 25) -#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 26) -#define GADGET_ID_CHANGE_BY_OTHER_ACT (GADGET_ID_CHECKBUTTON_FIRST + 27) +#define GADGET_ID_BLOCK_LAST_FIELD (GADGET_ID_CHECKBUTTON_FIRST + 7) +#define GADGET_ID_SP_BLOCK_LAST_FIELD (GADGET_ID_CHECKBUTTON_FIRST + 8) +#define GADGET_ID_CUSTOM_EXPLODE_RESULT (GADGET_ID_CHECKBUTTON_FIRST + 9) +#define GADGET_ID_CUSTOM_EXPLODE_FIRE (GADGET_ID_CHECKBUTTON_FIRST + 10) +#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 11) +#define GADGET_ID_CUSTOM_EXPLODE_IMPACT (GADGET_ID_CHECKBUTTON_FIRST + 12) +#define GADGET_ID_CUSTOM_WALK_TO_OBJECT (GADGET_ID_CHECKBUTTON_FIRST + 13) +#define GADGET_ID_CUSTOM_DEADLY (GADGET_ID_CHECKBUTTON_FIRST + 14) +#define GADGET_ID_CUSTOM_CAN_MOVE (GADGET_ID_CHECKBUTTON_FIRST + 15) +#define GADGET_ID_CUSTOM_CAN_FALL (GADGET_ID_CHECKBUTTON_FIRST + 16) +#define GADGET_ID_CUSTOM_CAN_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 17) +#define GADGET_ID_CUSTOM_SLIPPERY (GADGET_ID_CHECKBUTTON_FIRST + 18) +#define GADGET_ID_CUSTOM_ACCESSIBLE (GADGET_ID_CHECKBUTTON_FIRST + 19) +#define GADGET_ID_CUSTOM_USE_GRAPHIC (GADGET_ID_CHECKBUTTON_FIRST + 20) +#define GADGET_ID_CUSTOM_USE_TEMPLATE (GADGET_ID_CHECKBUTTON_FIRST + 21) +#define GADGET_ID_CUSTOM_CAN_CHANGE (GADGET_ID_CHECKBUTTON_FIRST + 22) +#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 23) +#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 24) +#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 25) +#define GADGET_ID_CHANGE_USE_RANDOM (GADGET_ID_CHECKBUTTON_FIRST + 26) +#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 27) +#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 28) +#define GADGET_ID_CHANGE_BY_OTHER_ACT (GADGET_ID_CHECKBUTTON_FIRST + 29) /* gadgets for buttons in element list */ -#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 28) +#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 30) #define GADGET_ID_ELEMENTLIST_LAST (GADGET_ID_ELEMENTLIST_FIRST + \ ED_NUM_ELEMENTLIST_BUTTONS - 1) @@ -497,11 +543,12 @@ #define ED_COUNTER_ID_PUSH_DELAY_RND 14 #define ED_COUNTER_ID_MOVE_DELAY_FIX 15 #define ED_COUNTER_ID_MOVE_DELAY_RND 16 -#define ED_COUNTER_ID_CHANGE_DELAY_FIX 17 -#define ED_COUNTER_ID_CHANGE_DELAY_RND 18 -#define ED_COUNTER_ID_CHANGE_CONT_RND 19 +#define ED_COUNTER_ID_GROUP_CONTENT 17 +#define ED_COUNTER_ID_CHANGE_DELAY_FIX 18 +#define ED_COUNTER_ID_CHANGE_DELAY_RND 19 +#define ED_COUNTER_ID_CHANGE_CONT_RND 20 -#define ED_NUM_COUNTERBUTTONS 20 +#define ED_NUM_COUNTERBUTTONS 21 #define ED_COUNTER_ID_LEVEL_FIRST ED_COUNTER_ID_LEVEL_XSIZE #define ED_COUNTER_ID_LEVEL_LAST ED_COUNTER_ID_LEVEL_RANDOM @@ -560,17 +607,20 @@ #define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 3 #define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 4 #define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 5 -#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 6 -#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 7 -#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 8 -#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 9 -#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 10 -#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 11 -#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 12 -#define ED_SELECTBOX_ID_CHANGE_POWER 13 -#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 14 - -#define ED_NUM_SELECTBOX 15 +#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 6 +#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 7 +#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 8 +#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 9 +#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 10 +#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 11 +#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 12 +#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 13 +#define ED_SELECTBOX_ID_CHANGE_SIDES 14 +#define ED_SELECTBOX_ID_CHANGE_POWER 15 +#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 16 +#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 17 + +#define ED_NUM_SELECTBOX 18 #define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE #define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM_CONSISTENCY @@ -609,29 +659,31 @@ #define ED_CHECKBUTTON_ID_RANDOM_RESTRICTED 2 #define ED_CHECKBUTTON_ID_STICK_ELEMENT 3 #define ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS 4 -#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 5 -#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 6 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 7 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 8 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 9 -#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 10 -#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 11 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT 12 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 13 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 14 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 15 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 16 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 17 -#define ED_CHECKBUTTON_ID_CHANGE_DELAY 18 -#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 19 -#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 20 -#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 21 -#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 22 -#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 23 -#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 24 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 25 - -#define ED_NUM_CHECKBUTTONS 26 +#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD 5 +#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD 6 +#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 7 +#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 8 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 9 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 10 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 11 +#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 12 +#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 13 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT 14 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 15 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 16 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 17 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 18 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 19 +#define ED_CHECKBUTTON_ID_CHANGE_DELAY 20 +#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 21 +#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 22 +#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 23 +#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 24 +#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 25 +#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 26 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 27 + +#define ED_NUM_CHECKBUTTONS 28 #define ED_CHECKBUTTON_ID_LEVEL_FIRST ED_CHECKBUTTON_ID_DOUBLE_SPEED #define ED_CHECKBUTTON_ID_LEVEL_LAST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED @@ -664,12 +716,15 @@ #define ED_DRAWING_ID_AMOEBA_CONTENT 9 #define ED_DRAWING_ID_CUSTOM_GRAPHIC 10 #define ED_DRAWING_ID_CUSTOM_CONTENT 11 -#define ED_DRAWING_ID_CUSTOM_CHANGE_TARGET 12 -#define ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT 13 -#define ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER 14 -#define ED_DRAWING_ID_RANDOM_BACKGROUND 15 +#define ED_DRAWING_ID_CUSTOM_MOVE_ENTER 12 +#define ED_DRAWING_ID_CUSTOM_MOVE_LEAVE 13 +#define ED_DRAWING_ID_CUSTOM_CHANGE_TARGET 14 +#define ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT 15 +#define ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER 16 +#define ED_DRAWING_ID_GROUP_CONTENT 17 +#define ED_DRAWING_ID_RANDOM_BACKGROUND 18 -#define ED_NUM_DRAWING_AREAS 16 +#define ED_NUM_DRAWING_AREAS 19 /* @@ -731,28 +786,33 @@ static struct char *text; } control_info[ED_NUM_CTRL_BUTTONS] = { - { 's', "draw single items" }, - { 'd', "draw connected items" }, - { 'l', "draw lines" }, - { 'a', "draw arcs" }, - { 'r', "draw outline rectangles" }, - { 'R', "draw filled rectangles" }, - { '\0', "wrap (rotate) level up" }, - { 't', "enter text elements" }, - { 'f', "flood fill" }, - { '\0', "wrap (rotate) level left" }, - { '?', "properties of drawing element" }, - { '\0', "wrap (rotate) level right" }, - { '\0', "random element placement" }, - { 'b', "grab brush" }, - { '\0', "wrap (rotate) level down" }, - { ',', "pick drawing element" }, - { 'U', "undo last operation" }, - { 'I', "level properties" }, - { 'S', "save level" }, - { 'C', "clear level" }, - { 'T', "test level" }, - { 'E', "exit level editor" } + { 's', "draw single items" }, + { 'd', "draw connected items" }, + { 'l', "draw lines" }, + { 'a', "draw arcs" }, + { 'r', "draw outline rectangles" }, + { 'R', "draw filled rectangles" }, + { '\0', "wrap (rotate) level up" }, + { 't', "enter text elements" }, + { 'f', "flood fill" }, + { '\0', "wrap (rotate) level left" }, + { '?', "properties of drawing element" }, + { '\0', "wrap (rotate) level right" }, + { '\0', "random element placement" }, + { 'b', "grab brush" }, + { '\0', "wrap (rotate) level down" }, + { ',', "pick drawing element" }, + + { 'U', "undo last operation" }, + { 'I', "level properties" }, + { 'S', "save level" }, + { 'C', "clear level" }, + { 'T', "test level" }, + { 'E', "exit level editor" }, + + { '\0', "copy settings from other element" }, + { '\0', "copy settings to other element" }, + { '\0', "exchange settings with other element" }, }; static int random_placement_value = 10; @@ -763,6 +823,7 @@ static boolean stick_element_properties_window = FALSE; static boolean custom_element_properties[NUM_ELEMENT_PROPERTIES]; static boolean custom_element_change_events[NUM_CHANGE_EVENTS]; static struct ElementChangeInfo custom_element_change; +static struct ElementGroupInfo group_element_info; static struct ElementInfo custom_element; static struct @@ -858,7 +919,7 @@ static struct MIN_ENVELOPE_XSIZE, MAX_ENVELOPE_XSIZE, GADGET_ID_ENVELOPE_XSIZE_DOWN, GADGET_ID_ENVELOPE_XSIZE_UP, GADGET_ID_ENVELOPE_XSIZE_TEXT, GADGET_ID_NONE, - &level.envelope_xsize, + NULL, NULL, NULL, "width", }, { @@ -866,11 +927,11 @@ static struct MIN_ENVELOPE_YSIZE, MAX_ENVELOPE_YSIZE, GADGET_ID_ENVELOPE_YSIZE_DOWN, GADGET_ID_ENVELOPE_YSIZE_UP, GADGET_ID_ENVELOPE_YSIZE_TEXT, GADGET_ID_ENVELOPE_XSIZE_UP, - &level.envelope_ysize, + NULL, NULL, " ", "height", }, - /* ---------- element settings: configure (custom elements) ------------- */ + /* ---------- element settings: configure (custom elements) -------------- */ { ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(3), @@ -905,7 +966,7 @@ static struct NULL, "+random", NULL }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9), 0, 999, GADGET_ID_MOVE_DELAY_FIX_DOWN, GADGET_ID_MOVE_DELAY_FIX_UP, GADGET_ID_MOVE_DELAY_FIX_TEXT, GADGET_ID_NONE, @@ -913,7 +974,7 @@ static struct NULL, "move delay", NULL }, { - -1, ED_SETTINGS_YPOS(7), + -1, ED_SETTINGS_YPOS(9), 0, 999, GADGET_ID_MOVE_DELAY_RND_DOWN, GADGET_ID_MOVE_DELAY_RND_UP, GADGET_ID_MOVE_DELAY_RND_TEXT, GADGET_ID_MOVE_DELAY_FIX_UP, @@ -921,6 +982,17 @@ static struct NULL, "+random", NULL }, + /* ---------- element settings: configure (group elements) --------------- */ + + { + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(6), + MIN_ELEMENTS_IN_GROUP, MAX_ELEMENTS_IN_GROUP, + GADGET_ID_GROUP_CONTENT_DOWN, GADGET_ID_GROUP_CONTENT_UP, + GADGET_ID_GROUP_CONTENT_TEXT, GADGET_ID_NONE, + &group_element_info.num_elements, + NULL, NULL, "number of elements in group" + }, + /* ---------- element settings: advanced (custom elements) --------------- */ { @@ -940,12 +1012,12 @@ static struct NULL, "+random", NULL }, { - ED_SETTINGS_XPOS(3), ED_SETTINGS_YPOS(11), + ED_SETTINGS_XPOS(3), ED_SETTINGS_YPOS(12), 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, - NULL, "use random change:", "(%)" + NULL, "use random replace:", "%" }, }; @@ -994,7 +1066,7 @@ static struct ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(2), GADGET_ID_ENVELOPE_INFO, MAX_ENVELOPE_XSIZE, MAX_ENVELOPE_YSIZE, - level.envelope, + NULL, "Envelope Info:", "Envelope Info" } }; @@ -1038,16 +1110,27 @@ static struct ValueTextInfo options_move_pattern[] = { MV_ALONG_RIGHT_SIDE, "along right side" }, { MV_TURNING_LEFT, "turning left" }, { MV_TURNING_RIGHT, "turning right" }, + { MV_TURNING_LEFT_RIGHT, "turning left, right" }, + { MV_TURNING_RIGHT_LEFT, "turning right, left" }, + { MV_TURNING_RANDOM, "turning random" }, + { MV_WHEN_PUSHED, "when pushed" }, + { MV_WHEN_DROPPED, "when dropped" }, +#if 1 + { MV_MAZE_RUNNER, "maze runner style" }, + { MV_MAZE_HUNTER, "maze hunter style" }, +#endif { -1, NULL } }; static struct ValueTextInfo options_move_direction[] = { - { MV_NO_MOVING, "automatic" }, + { MV_AUTOMATIC, "automatic" }, { MV_LEFT, "left" }, { MV_RIGHT, "right" }, { MV_UP, "up" }, { MV_DOWN, "down" }, + { MV_RANDOM, "random" }, + { MV_PREVIOUS, "previous" }, { -1, NULL } }; @@ -1061,6 +1144,13 @@ static struct ValueTextInfo options_move_stepsize[] = { -1, NULL } }; +static struct ValueTextInfo options_move_leave_type[] = +{ + { LEAVE_TYPE_UNLIMITED, "leave behind" }, + { LEAVE_TYPE_LIMITED, "change it to" }, + { -1, NULL } +}; + static struct ValueTextInfo options_smash_targets[] = { { EP_CAN_SMASH_PLAYER, "player" }, @@ -1092,6 +1182,7 @@ static struct ValueTextInfo options_deadliness[] = static struct ValueTextInfo options_consistency[] = { { EP_CAN_EXPLODE_3X3, "can explode 3x3" }, + { EP_CAN_EXPLODE_DYNA, "can explode 3+3" }, { EP_CAN_EXPLODE_1X1, "can explode 1x1" }, { EP_INDESTRUCTIBLE, "indestructible" }, { -1, NULL } @@ -1099,37 +1190,64 @@ static struct ValueTextInfo options_consistency[] = static struct ValueTextInfo options_time_units[] = { - { FRAMES_PER_SECOND, "seconds" }, { 1, "frames" }, + { FRAMES_PER_SECOND, "seconds" }, { -1, NULL } }; static struct ValueTextInfo options_change_direct_action[] = { - { CE_TOUCHED_BY_PLAYER, "touched by player" }, - { CE_PRESSED_BY_PLAYER, "pressed by player" }, - { CE_PUSHED_BY_PLAYER, "pushed by player" }, + { CE_TOUCHED_BY_PLAYER, "touched by player ..." }, + { CE_PRESSED_BY_PLAYER, "pressed by player ..." }, + { CE_PUSHED_BY_PLAYER, "pushed by player ..." }, + { CE_ENTERED_BY_PLAYER, "entered by player ..." }, + { CE_LEFT_BY_PLAYER, "left by player ..." }, { CE_DROPPED_BY_PLAYER, "dropped by player" }, - { CE_COLLISION, "collision" }, - { CE_IMPACT, "impact" }, - { CE_SMASHED, "smashed" }, + { CE_SWITCHED, "switched ..." }, +#if 1 + { CE_HITTING_SOMETHING, "hitting something ..." }, + { CE_HIT_BY_SOMETHING, "hit by something ..." }, +#else + { CE_HITTING_SOMETHING, "collision ..." }, +#endif + { CE_IMPACT, "impact (on something)" }, + { CE_SMASHED, "smashed (from above)" }, { -1, NULL } }; static struct ValueTextInfo options_change_other_action[] = { - { CE_OTHER_GETS_TOUCHED, "player touches" }, - { CE_OTHER_GETS_PRESSED, "player presses" }, - { CE_OTHER_GETS_PUSHED, "player pushes" }, + { CE_OTHER_GETS_TOUCHED, "player touches ..." }, + { CE_OTHER_GETS_PRESSED, "player presses ..." }, + { CE_OTHER_GETS_PUSHED, "player pushes ..." }, + { CE_OTHER_GETS_ENTERED, "player enters ..." }, + { CE_OTHER_GETS_LEFT, "player leaves ..." }, { CE_OTHER_GETS_DIGGED, "player digs" }, { CE_OTHER_GETS_COLLECTED, "player collects" }, { CE_OTHER_GETS_DROPPED, "player drops" }, - { CE_OTHER_IS_TOUCHING, "touching" }, + { CE_OTHER_IS_TOUCHING, "touching ..." }, +#if 1 + { CE_OTHER_IS_HITTING, "hitting ..." }, + { CE_OTHER_GETS_HIT, "hit by ..." }, +#endif + { CE_OTHER_IS_SWITCHING, "switch of ..." }, { CE_OTHER_IS_CHANGING, "change of" }, { CE_OTHER_IS_EXPLODING, "explosion of" }, { -1, NULL } }; +static struct ValueTextInfo options_change_sides[] = +{ + { CH_SIDE_LEFT, "left side" }, + { CH_SIDE_RIGHT, "right side" }, + { CH_SIDE_TOP, "top side" }, + { CH_SIDE_BOTTOM, "bottom side" }, + { CH_SIDE_LEFT_RIGHT, "left/right side" }, + { CH_SIDE_TOP_BOTTOM, "top/bottom side" }, + { CH_SIDE_ANY, "any side" }, + { -1, NULL } +}; + static struct ValueTextInfo options_change_power[] = { { CP_NON_DESTRUCTIVE, "empty" }, @@ -1144,6 +1262,16 @@ static struct ValueTextInfo options_change_page[MAX_CHANGE_PAGES + 1] = { -1, NULL } }; +static struct ValueTextInfo options_group_choice_mode[] = +{ + { ANIM_RANDOM, "random" }, + { ANIM_LOOP, "loop" }, + { ANIM_LINEAR, "linear" }, + { ANIM_PINGPONG, "pingpong" }, + { ANIM_PINGPONG2, "pingpong 2" }, + { -1, NULL } +}; + static struct { int x, y; @@ -1206,7 +1334,15 @@ static struct "move/fall speed", NULL, "speed of element movement" }, { - -1, ED_SETTINGS_YPOS(9), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7), + GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE, GADGET_ID_NONE, + -1, + options_move_leave_type, + &custom_element.move_leave_type, + "can dig: can", ":", "leave behind or change element" + }, + { + -1, ED_SETTINGS_YPOS(10), GADGET_ID_CUSTOM_SMASH_TARGETS, GADGET_ID_CUSTOM_CAN_SMASH, -1, options_smash_targets, @@ -1214,7 +1350,7 @@ static struct "can smash", NULL, "elements that can be smashed" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(10), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(11), GADGET_ID_CUSTOM_SLIPPERY_TYPE, GADGET_ID_NONE, -1, options_slippery_type, @@ -1222,7 +1358,7 @@ static struct "slippery", NULL, "where other elements fall down" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(11), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(12), GADGET_ID_CUSTOM_DEADLINESS, GADGET_ID_NONE, -1, options_deadliness, @@ -1230,7 +1366,7 @@ static struct "deadly when", NULL, "deadliness of element" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(12), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13), GADGET_ID_CUSTOM_CONSISTENCY, GADGET_ID_NONE, -1, options_consistency, @@ -1265,7 +1401,15 @@ static struct NULL, "element:", "type of other element action" }, { - ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(9), + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(7), + GADGET_ID_CHANGE_SIDES, GADGET_ID_NONE, + -1, + options_change_sides, + &custom_element_change.sides, + "... at", NULL, "element side that causes change" + }, + { + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(10), GADGET_ID_CHANGE_POWER, GADGET_ID_NONE, -1, options_change_power, @@ -1273,13 +1417,24 @@ static struct "replace when", NULL, "which elements can be replaced" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(14), GADGET_ID_SELECT_CHANGE_PAGE, GADGET_ID_NONE, 3, options_change_page, &custom_element.current_change_page, NULL, NULL, "element config page" }, + + /* ---------- element settings: configure (group elements) --------------- */ + + { + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10), + GADGET_ID_GROUP_CHOICE_MODE, GADGET_ID_NONE, + -1, + options_group_choice_mode, + &group_element_info.choice_mode, + "choice type:", NULL, "type of group element choice" + }, }; static struct @@ -1311,19 +1466,19 @@ static struct NULL, NULL, "Advanced element configuration" }, { - -1, ED_SETTINGS_YPOS(12), + -1, ED_SETTINGS_YPOS(13), GADGET_ID_SAVE_AS_TEMPLATE, GADGET_ID_CUSTOM_USE_TEMPLATE, -1, "Save as template", " ", NULL, "Save current settings as new template" }, { - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), GADGET_ID_ADD_CHANGE_PAGE, GADGET_ID_NEXT_CHANGE_PAGE, -1, "New", " ", NULL, "Add new config page" }, { - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), GADGET_ID_DEL_CHANGE_PAGE, GADGET_ID_ADD_CHANGE_PAGE, -1, "Delete", NULL, NULL, "Delete current config page" @@ -1342,14 +1497,14 @@ static struct { { ED_BUTTON_MINUS_XPOS, ED_BUTTON_COUNT_YPOS, - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(14), ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE, GADGET_ID_PREV_CHANGE_PAGE, GADGET_ID_NONE, NULL, NULL, "select previous config page" }, { ED_BUTTON_PLUS_XPOS, ED_BUTTON_COUNT_YPOS, - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE, GADGET_ID_NEXT_CHANGE_PAGE, GADGET_ID_SELECT_CHANGE_PAGE, NULL, "config page", "select next config page" @@ -1485,7 +1640,7 @@ static struct { -1, ED_COUNTER_YPOS(6) - MINI_TILEY, GADGET_ID_GRAVITY, GADGET_ID_DOUBLE_SPEED, - &level.gravity, + &level.initial_gravity, " ", "gravity", "set level gravity" }, { @@ -1512,6 +1667,20 @@ static struct NULL, "slip down from certain flat walls","use EM style slipping behaviour" }, + { + ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(4), + 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_COUNTER_YPOS(4), + 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" + }, /* ---------- element settings: configure (custom elements) ------------- */ @@ -1534,49 +1703,49 @@ static struct NULL, NULL, "element can move in some direction" }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(9), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10), GADGET_ID_CUSTOM_CAN_FALL, GADGET_ID_NONE, &custom_element_properties[EP_CAN_FALL], NULL, "can fall", "element can fall down" }, { - -1, ED_SETTINGS_YPOS(9), + -1, ED_SETTINGS_YPOS(10), GADGET_ID_CUSTOM_CAN_SMASH, GADGET_ID_CUSTOM_CAN_FALL, &custom_element_properties[EP_CAN_SMASH], " ", NULL, "element can smash other elements" }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(11), GADGET_ID_CUSTOM_SLIPPERY, GADGET_ID_NONE, &custom_element_properties[EP_SLIPPERY], NULL, NULL, "other elements can fall down from it" }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(11), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12), GADGET_ID_CUSTOM_DEADLY, GADGET_ID_NONE, &custom_element_properties[EP_DEADLY], NULL, NULL, "element can kill the player" }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13), GADGET_ID_CUSTOM_EXPLODE_RESULT, GADGET_ID_NONE, &custom_element_properties[EP_EXPLODE_RESULT], NULL, NULL, "set consistency/destructibility" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(14), GADGET_ID_CUSTOM_EXPLODE_FIRE, GADGET_ID_NONE, &custom_element.can_explode_by_fire, NULL, "by fire", "element can explode by fire/explosion" }, { - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), GADGET_ID_CUSTOM_EXPLODE_SMASH, GADGET_ID_CUSTOM_EXPLODE_FIRE, &custom_element.can_explode_smashed, " ", "smashed", "element can explode when smashed" }, { - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), GADGET_ID_CUSTOM_EXPLODE_IMPACT, GADGET_ID_CUSTOM_EXPLODE_SMASH, &custom_element.can_explode_impact, " ", "impact", "element can explode on impact" @@ -1615,31 +1784,31 @@ static struct NULL, NULL, "element changes by other element" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8), GADGET_ID_CHANGE_USE_EXPLOSION, GADGET_ID_NONE, &custom_element_change.explode, NULL, "explode instead of change", "element explodes instead of change" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9), GADGET_ID_CHANGE_USE_CONTENT, GADGET_ID_NONE, &custom_element_change.use_content, NULL, "use extended change target:","element changes to more elements" }, { - ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(10), + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(11), GADGET_ID_CHANGE_ONLY_COMPLETE, GADGET_ID_NONE, &custom_element_change.only_complete, - NULL, "only use complete change", "only use complete extended content" + NULL, "replace all or nothing", "only replace when all can be changed" }, { - ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(11), + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(12), GADGET_ID_CHANGE_USE_RANDOM, GADGET_ID_NONE, &custom_element_change.use_random_change, - NULL, NULL, "use random value for new content" + NULL, NULL, "use percentage for random replace" }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13), GADGET_ID_CUSTOM_USE_TEMPLATE, GADGET_ID_NONE, &level.use_custom_template, NULL, "use template", "use template for custom properties" @@ -1742,6 +1911,21 @@ static struct "content:", NULL, NULL }, + /* ---------- custom enter and leave element (when moving) --------------- */ + + { + ED_SETTINGS_XPOS(1), ED_AREA_ELEM_CONTENT4a_YPOS, + 1, 1, + GADGET_ID_CUSTOM_MOVE_ENTER, GADGET_ID_NONE, + "can dig:", " ", NULL + }, + { + -1, ED_AREA_ELEM_CONTENT4b_YPOS, + 1, 1, + GADGET_ID_CUSTOM_MOVE_LEAVE, GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE, + NULL, NULL, NULL + }, + /* ---------- custom change target --------------------------------------- */ { @@ -1769,6 +1953,15 @@ static struct NULL, NULL, NULL }, + /* ---------- group element content -------------------------------------- */ + + { + ED_AREA_GROUP_CONTENT_XPOS, ED_AREA_GROUP_CONTENT_YPOS, + MAX_ELEMENTS_IN_GROUP, 1, + GADGET_ID_GROUP_CONTENT, GADGET_ID_NONE, + "content:", NULL, NULL + }, + /* ---------- random background (for random painting) -------------------- */ { @@ -1808,11 +2001,13 @@ static int new_element3 = EL_SAND; static void ModifyEditorCounter(int, int); static void ModifyEditorCounterLimits(int, int, int); static void ModifyEditorSelectbox(int, int); +static void ModifyEditorDrawingArea(int, int, int); static void ModifyEditorElementList(); static void RedrawDrawingElements(); static void DrawDrawingWindow(); static void DrawLevelInfoWindow(); static void DrawPropertiesWindow(); +static void UpdateCustomElementGraphicGadgets(); static boolean checkPropertiesConfig(); static void CopyLevelToUndoBuffer(int); static void HandleDrawingAreas(struct GadgetInfo *); @@ -1890,6 +2085,8 @@ static int editor_el_boulderdash[] = EL_BD_FIREFLY_DOWN, EL_EMPTY, }; +static int *editor_hl_boulderdash_ptr = editor_hl_boulderdash; +static int *editor_el_boulderdash_ptr = editor_el_boulderdash; static int num_editor_hl_boulderdash = SIZEOF_ARRAY_INT(editor_hl_boulderdash); static int num_editor_el_boulderdash = SIZEOF_ARRAY_INT(editor_el_boulderdash); @@ -1973,10 +2170,17 @@ static int editor_el_emerald_mine[] = EL_AMOEBA_WET, EL_AMOEBA_DRY, +#if 1 + EL_EM_KEY_1, + EL_EM_KEY_2, + EL_EM_KEY_3, + EL_EM_KEY_4, +#else EL_EM_KEY_1_FILE, EL_EM_KEY_2_FILE, EL_EM_KEY_3_FILE, EL_EM_KEY_4_FILE, +#endif EL_EM_GATE_1, EL_EM_GATE_2, @@ -1988,6 +2192,8 @@ static int editor_el_emerald_mine[] = EL_EM_GATE_3_GRAY, EL_EM_GATE_4_GRAY, }; +static int *editor_hl_emerald_mine_ptr = editor_hl_emerald_mine; +static int *editor_el_emerald_mine_ptr = editor_el_emerald_mine; static int num_editor_hl_emerald_mine=SIZEOF_ARRAY_INT(editor_hl_emerald_mine); static int num_editor_el_emerald_mine=SIZEOF_ARRAY_INT(editor_el_emerald_mine); @@ -2056,17 +2262,17 @@ static int editor_el_more[] = EL_PIG, EL_DRAGON, - EL_EMPTY, + EL_BUG, EL_MOLE_UP, - EL_EMPTY, - EL_EMPTY, + EL_BD_BUTTERFLY, + EL_BD_FIREFLY, EL_MOLE_LEFT, EL_EMPTY, EL_MOLE_RIGHT, - EL_EMPTY, + EL_PACMAN, - EL_EMPTY, + EL_SPACESHIP, EL_MOLE_DOWN, EL_BALLOON, EL_BALLOON_SWITCH_ANY, @@ -2096,6 +2302,8 @@ static int editor_el_more[] = EL_EMC_WALL_6, EL_EMC_WALL_7, }; +static int *editor_hl_more_ptr = editor_hl_more; +static int *editor_el_more_ptr = editor_el_more; static int num_editor_hl_more = SIZEOF_ARRAY_INT(editor_hl_more); static int num_editor_el_more = SIZEOF_ARRAY_INT(editor_el_more); @@ -2117,8 +2325,10 @@ static int editor_el_sokoban[] = EL_SOKOBAN_OBJECT, EL_SOKOBAN_FIELD_EMPTY, EL_SOKOBAN_FIELD_FULL, - EL_STEELWALL, + EL_SOKOBAN_FIELD_PLAYER, }; +static int *editor_hl_sokoban_ptr = editor_hl_sokoban; +static int *editor_el_sokoban_ptr = editor_el_sokoban; static int num_editor_hl_sokoban = SIZEOF_ARRAY_INT(editor_hl_sokoban); static int num_editor_el_sokoban = SIZEOF_ARRAY_INT(editor_el_sokoban); @@ -2137,7 +2347,11 @@ static int editor_hl_supaplex[] = static int editor_el_supaplex[] = { +#if 1 + EL_EMPTY, +#else EL_SP_EMPTY, +#endif EL_SP_ZONK, EL_SP_BASE, EL_SP_MURPHY, @@ -2187,6 +2401,8 @@ static int editor_el_supaplex[] = EL_SP_CHIP_TOP, EL_SP_CHIP_BOTTOM, }; +static int *editor_hl_supaplex_ptr = editor_hl_supaplex; +static int *editor_el_supaplex_ptr = editor_el_supaplex; static int num_editor_hl_supaplex = SIZEOF_ARRAY_INT(editor_hl_supaplex); static int num_editor_el_supaplex = SIZEOF_ARRAY_INT(editor_el_supaplex); @@ -2253,7 +2469,12 @@ static int editor_el_diamond_caves[] = EL_SWITCHGATE_OPEN, EL_SWITCHGATE_CLOSED, EL_SWITCHGATE_SWITCH_UP, - EL_ENVELOPE, + EL_EMPTY, + + EL_ENVELOPE_1, + EL_ENVELOPE_2, + EL_ENVELOPE_3, + EL_ENVELOPE_4, EL_TIMEGATE_CLOSED, EL_TIMEGATE_OPEN, @@ -2275,6 +2496,8 @@ static int editor_el_diamond_caves[] = EL_EXTRA_TIME, EL_EMPTY, }; +static int *editor_hl_diamond_caves_ptr = editor_hl_diamond_caves; +static int *editor_el_diamond_caves_ptr = editor_el_diamond_caves; static int num_editor_hl_diamond_caves = SIZEOF_ARRAY_INT(editor_hl_diamond_caves); static int num_editor_el_diamond_caves = SIZEOF_ARRAY_INT(editor_el_diamond_caves); @@ -2323,6 +2546,8 @@ static int editor_el_dx_boulderdash[] = EL_EMPTY, EL_EMPTY }; +static int *editor_hl_dx_boulderdash_ptr = editor_hl_dx_boulderdash; +static int *editor_el_dx_boulderdash_ptr = editor_el_dx_boulderdash; static int num_editor_hl_dx_boulderdash = SIZEOF_ARRAY_INT(editor_hl_dx_boulderdash); static int num_editor_el_dx_boulderdash = SIZEOF_ARRAY_INT(editor_el_dx_boulderdash); @@ -2426,6 +2651,8 @@ static int editor_el_chars[] = EL_CHAR(FONT_ASCII_CURSOR), EL_CHAR(' ') }; +static int *editor_hl_chars_ptr = editor_hl_chars; +static int *editor_el_chars_ptr = editor_el_chars; static int num_editor_hl_chars = SIZEOF_ARRAY_INT(editor_hl_chars); static int num_editor_el_chars = SIZEOF_ARRAY_INT(editor_el_chars); @@ -2614,6 +2841,8 @@ static int editor_el_custom[] = EL_CUSTOM_START + 126, EL_CUSTOM_START + 127 }; +static int *editor_hl_custom_ptr = editor_hl_custom; +static int *editor_el_custom_ptr = editor_el_custom; static int num_editor_hl_custom = SIZEOF_ARRAY_INT(editor_hl_custom); static int num_editor_el_custom = SIZEOF_ARRAY_INT(editor_el_custom); @@ -2783,9 +3012,125 @@ static int editor_el_custom_more[] = EL_CUSTOM_START + 254, EL_CUSTOM_START + 255 }; +static int *editor_hl_custom_more_ptr = editor_hl_custom_more; +static int *editor_el_custom_more_ptr = editor_el_custom_more; static int num_editor_hl_custom_more = SIZEOF_ARRAY_INT(editor_hl_custom_more); static int num_editor_el_custom_more = SIZEOF_ARRAY_INT(editor_el_custom_more); +static int editor_hl_group[] = +{ + EL_CHAR('G'), + EL_CHAR('R'), + EL_CHAR('O'), + EL_CHAR('U'), + + EL_CHAR('P'), + EL_CHAR(' '), + EL_CHAR(' '), + EL_CHAR(' '), + + EL_CHAR('E'), + EL_CHAR('L'), + EL_CHAR('E'), + EL_CHAR('M'), + + EL_CHAR('E'), + EL_CHAR('N'), + EL_CHAR('T'), + EL_CHAR('S'), +}; + +static int editor_el_group[] = +{ + EL_GROUP_START + 0, + EL_GROUP_START + 1, + EL_GROUP_START + 2, + EL_GROUP_START + 3, + + EL_GROUP_START + 4, + EL_GROUP_START + 5, + EL_GROUP_START + 6, + EL_GROUP_START + 7, + + EL_GROUP_START + 8, + EL_GROUP_START + 9, + EL_GROUP_START + 10, + EL_GROUP_START + 11, + + EL_GROUP_START + 12, + EL_GROUP_START + 13, + EL_GROUP_START + 14, + EL_GROUP_START + 15 +}; +static int *editor_hl_group_ptr = editor_hl_group; +static int *editor_el_group_ptr = editor_el_group; +static int num_editor_hl_group = SIZEOF_ARRAY_INT(editor_hl_group); +static int num_editor_el_group = SIZEOF_ARRAY_INT(editor_el_group); + +static int editor_hl_group_more[] = +{ +}; + +static int editor_el_group_more[] = +{ + EL_GROUP_START + 16, + EL_GROUP_START + 17, + EL_GROUP_START + 18, + EL_GROUP_START + 19, + + EL_GROUP_START + 20, + EL_GROUP_START + 21, + EL_GROUP_START + 22, + EL_GROUP_START + 23, + + EL_GROUP_START + 24, + EL_GROUP_START + 25, + EL_GROUP_START + 26, + EL_GROUP_START + 27, + + EL_GROUP_START + 28, + EL_GROUP_START + 29, + EL_GROUP_START + 30, + EL_GROUP_START + 31 +}; +static int *editor_hl_group_more_ptr = editor_hl_group_more; +static int *editor_el_group_more_ptr = editor_el_group_more; +static int num_editor_hl_group_more = SIZEOF_ARRAY_INT(editor_hl_group_more); +static int num_editor_el_group_more = SIZEOF_ARRAY_INT(editor_el_group_more); + +static int editor_hl_user_defined[] = +{ + EL_CHAR('U'), + EL_CHAR('S'), + EL_CHAR('E'), + EL_CHAR('R'), + + EL_CHAR('D'), + EL_CHAR('E'), + EL_CHAR('F'), + EL_CHAR('I'), + + EL_CHAR('-'), + EL_CHAR('N'), + EL_CHAR('E'), + EL_CHAR('D'), +}; + +static int *editor_hl_user_defined_ptr = editor_hl_user_defined; +static int *editor_el_user_defined_ptr = NULL; +static int num_editor_hl_user_defined=SIZEOF_ARRAY_INT(editor_hl_user_defined); +static int num_editor_el_user_defined = 0; + +static int editor_hl_empty[] = { }; +static int editor_el_empty[ED_NUM_ELEMENTLIST_BUTTONS]; + +static int *editor_hl_empty_ptr = editor_hl_empty; +static int *editor_el_empty_ptr = editor_el_empty; +static int num_editor_hl_empty = 0; +static int num_editor_el_empty = 0; /* dynamically determined, if needed */ + +static boolean use_el_empty = FALSE; + static int *editor_elements = NULL; /* dynamically allocated */ static int num_editor_elements = 0; /* dynamically determined */ @@ -2793,10 +3138,10 @@ static struct { boolean *setup_value; - int *headline_list; + int **headline_list; int *headline_list_size; - int *element_list; + int **element_list; int *element_list_size; boolean last_setup_value; @@ -2805,53 +3150,73 @@ editor_elements_info[] = { { &setup.editor.el_boulderdash, - editor_hl_boulderdash, &num_editor_hl_boulderdash, - editor_el_boulderdash, &num_editor_el_boulderdash + &editor_hl_boulderdash_ptr, &num_editor_hl_boulderdash, + &editor_el_boulderdash_ptr, &num_editor_el_boulderdash }, { &setup.editor.el_emerald_mine, - editor_hl_emerald_mine, &num_editor_hl_emerald_mine, - editor_el_emerald_mine, &num_editor_el_emerald_mine + &editor_hl_emerald_mine_ptr, &num_editor_hl_emerald_mine, + &editor_el_emerald_mine_ptr, &num_editor_el_emerald_mine }, { &setup.editor.el_more, - editor_hl_more, &num_editor_hl_more, - editor_el_more, &num_editor_el_more + &editor_hl_more_ptr, &num_editor_hl_more, + &editor_el_more_ptr, &num_editor_el_more }, { &setup.editor.el_sokoban, - editor_hl_sokoban, &num_editor_hl_sokoban, - editor_el_sokoban, &num_editor_el_sokoban + &editor_hl_sokoban_ptr, &num_editor_hl_sokoban, + &editor_el_sokoban_ptr, &num_editor_el_sokoban }, { &setup.editor.el_supaplex, - editor_hl_supaplex, &num_editor_hl_supaplex, - editor_el_supaplex, &num_editor_el_supaplex + &editor_hl_supaplex_ptr, &num_editor_hl_supaplex, + &editor_el_supaplex_ptr, &num_editor_el_supaplex }, { &setup.editor.el_diamond_caves, - editor_hl_diamond_caves, &num_editor_hl_diamond_caves, - editor_el_diamond_caves, &num_editor_el_diamond_caves + &editor_hl_diamond_caves_ptr, &num_editor_hl_diamond_caves, + &editor_el_diamond_caves_ptr, &num_editor_el_diamond_caves }, { &setup.editor.el_dx_boulderdash, - editor_hl_dx_boulderdash, &num_editor_hl_dx_boulderdash, - editor_el_dx_boulderdash, &num_editor_el_dx_boulderdash + &editor_hl_dx_boulderdash_ptr, &num_editor_hl_dx_boulderdash, + &editor_el_dx_boulderdash_ptr, &num_editor_el_dx_boulderdash }, { &setup.editor.el_chars, - editor_hl_chars, &num_editor_hl_chars, - editor_el_chars, &num_editor_el_chars + &editor_hl_chars_ptr, &num_editor_hl_chars, + &editor_el_chars_ptr, &num_editor_el_chars + }, + { + &setup.editor.el_custom, + &editor_hl_custom_ptr, &num_editor_hl_custom, + &editor_el_custom_ptr, &num_editor_el_custom + }, + { + &setup.editor.el_custom_more, + &editor_hl_custom_more_ptr, &num_editor_hl_custom_more, + &editor_el_custom_more_ptr, &num_editor_el_custom_more }, { &setup.editor.el_custom, - editor_hl_custom, &num_editor_hl_custom, - editor_el_custom, &num_editor_el_custom + &editor_hl_group_ptr, &num_editor_hl_group, + &editor_el_group_ptr, &num_editor_el_group }, { &setup.editor.el_custom_more, - editor_hl_custom_more, &num_editor_hl_custom_more, - editor_el_custom_more, &num_editor_el_custom_more + &editor_hl_group_more_ptr, &num_editor_hl_group_more, + &editor_el_group_more_ptr, &num_editor_el_group_more + }, + { + &setup.editor.el_user_defined, + &editor_hl_user_defined_ptr, &num_editor_hl_user_defined, + &editor_el_user_defined_ptr, &num_editor_el_user_defined + }, + { + &use_el_empty, + &editor_hl_empty_ptr, &num_editor_hl_empty, + &editor_el_empty_ptr, &num_editor_el_empty, }, { NULL, @@ -2860,6 +3225,205 @@ editor_elements_info[] = } }; +static struct +{ + short element; + short element_mapped; +} +forum_sketch_element_mapping[] = +{ + { EL_WALL_SLIPPERY, EL_WALL }, + { EL_EXPANDABLE_WALL, EL_WALL }, + { EL_EXPANDABLE_WALL_HORIZONTAL, EL_WALL }, + { EL_EXPANDABLE_WALL_VERTICAL, EL_WALL }, + { EL_EXPANDABLE_WALL_ANY, EL_WALL }, + { EL_WALL_EMERALD, EL_WALL }, + { EL_WALL_DIAMOND, EL_WALL }, + { EL_WALL_BD_DIAMOND, EL_WALL }, + { EL_WALL_EMERALD_YELLOW, EL_WALL }, + { EL_WALL_EMERALD_RED, EL_WALL }, + { EL_WALL_EMERALD_PURPLE, EL_WALL }, + { EL_ACID_POOL_TOPLEFT, EL_WALL }, + { EL_ACID_POOL_TOPRIGHT, EL_WALL }, + { EL_ACID_POOL_BOTTOMLEFT, EL_WALL }, + { EL_ACID_POOL_BOTTOM, EL_WALL }, + { EL_ACID_POOL_BOTTOMRIGHT, EL_WALL }, + { EL_BD_WALL, EL_WALL }, + + { EL_BD_ROCK, EL_ROCK }, + + { EL_SP_ZONK, EL_ROCK }, + { EL_SP_BASE, EL_SAND }, + { EL_SP_MURPHY, EL_PLAYER_1 }, + { EL_SP_INFOTRON, EL_EMERALD }, + { EL_SP_HARDWARE_GRAY, EL_STEELWALL }, + { EL_SP_EXIT_CLOSED, EL_EXIT_OPEN }, + { EL_SP_DISK_ORANGE, EL_BOMB }, + { EL_SP_DISK_RED, EL_BOMB }, + { EL_SP_DISK_YELLOW, EL_BOMB }, + { EL_SP_PORT_RIGHT, EL_GATE_1_GRAY }, + { EL_SP_PORT_DOWN, EL_GATE_1_GRAY }, + { EL_SP_PORT_LEFT, EL_GATE_1_GRAY }, + { EL_SP_PORT_UP, EL_GATE_1_GRAY }, + { EL_SP_GRAVITY_PORT_RIGHT, EL_GATE_1_GRAY }, + { EL_SP_GRAVITY_PORT_DOWN, EL_GATE_1_GRAY }, + { EL_SP_GRAVITY_PORT_LEFT, EL_GATE_1_GRAY }, + { EL_SP_GRAVITY_PORT_UP, EL_GATE_1_GRAY }, + { EL_SP_PORT_VERTICAL, EL_GATE_1_GRAY }, + { EL_SP_PORT_HORIZONTAL, EL_GATE_1_GRAY }, + { EL_SP_PORT_ANY, EL_GATE_1_GRAY }, + { EL_SP_SNIKSNAK, EL_BUG }, + { EL_SP_ELECTRON, EL_SPACESHIP }, + { EL_SP_CHIP_SINGLE, EL_WALL }, + { EL_SP_CHIP_LEFT, EL_WALL }, + { EL_SP_CHIP_RIGHT, EL_WALL }, + { EL_SP_CHIP_TOP, EL_WALL }, + { EL_SP_CHIP_BOTTOM, EL_WALL }, + { EL_SP_HARDWARE_BASE_1, EL_STEELWALL }, + { EL_SP_HARDWARE_GREEN, EL_STEELWALL }, + { EL_SP_HARDWARE_BLUE, EL_STEELWALL }, + { EL_SP_HARDWARE_RED, EL_STEELWALL }, + { EL_SP_HARDWARE_YELLOW, EL_STEELWALL }, + { EL_SP_HARDWARE_BASE_2, EL_STEELWALL }, + { EL_SP_HARDWARE_BASE_3, EL_STEELWALL }, + { EL_SP_HARDWARE_BASE_3, EL_STEELWALL }, + { EL_SP_HARDWARE_BASE_4, EL_STEELWALL }, + { EL_SP_HARDWARE_BASE_5, EL_STEELWALL }, + { EL_SP_HARDWARE_BASE_6, EL_STEELWALL }, + + { EL_STEELWALL_SLIPPERY, EL_STEELWALL }, + + { EL_EXIT_CLOSED, EL_EXIT_OPEN }, + + { EL_DIAMOND, EL_EMERALD }, + { EL_BD_DIAMOND, EL_EMERALD }, + { EL_EMERALD_YELLOW, EL_EMERALD }, + { EL_EMERALD_RED, EL_EMERALD }, + { EL_EMERALD_PURPLE, EL_EMERALD }, + + { EL_AMOEBA_DEAD, EL_AMOEBA }, + { EL_AMOEBA_DROP, EL_AMOEBA }, + { EL_AMOEBA_WET, EL_AMOEBA }, + { EL_AMOEBA_DRY, EL_AMOEBA }, + { EL_AMOEBA_FULL, EL_AMOEBA }, + { EL_BD_AMOEBA, EL_AMOEBA }, + { EL_AMOEBA_TO_DIAMOND, EL_AMOEBA }, + + { EL_DYNAMITE_ACTIVE, EL_DYNAMITE }, + + { EL_GATE_2_GRAY, EL_GATE_1_GRAY }, + { EL_GATE_3_GRAY, EL_GATE_1_GRAY }, + { EL_GATE_4_GRAY, EL_GATE_1_GRAY }, + + { EL_EM_KEY_1, EL_KEY_1 }, + { EL_EM_KEY_2, EL_KEY_2 }, + { EL_EM_KEY_3, EL_KEY_3 }, + { EL_EM_KEY_4, EL_KEY_4 }, + + { EL_EM_GATE_1, EL_GATE_1 }, + { EL_EM_GATE_2, EL_GATE_2 }, + { EL_EM_GATE_3, EL_GATE_3 }, + { EL_EM_GATE_4, EL_GATE_4 }, + + { EL_EM_GATE_1_GRAY, EL_GATE_1_GRAY }, + { EL_EM_GATE_2_GRAY, EL_GATE_1_GRAY }, + { EL_EM_GATE_3_GRAY, EL_GATE_1_GRAY }, + { EL_EM_GATE_4_GRAY, EL_GATE_1_GRAY }, + + { EL_INVISIBLE_SAND, EL_EMPTY }, + { EL_INVISIBLE_WALL, EL_EMPTY }, + { EL_INVISIBLE_STEELWALL, EL_EMPTY }, + + { EL_PACMAN, EL_YAMYAM }, + { EL_DARK_YAMYAM, EL_YAMYAM }, + + { EL_BD_MAGIC_WALL, EL_MAGIC_WALL }, + + { EL_DYNABOMB_INCREASE_NUMBER, EL_BOMB }, + { EL_DYNABOMB_INCREASE_SIZE, EL_BOMB }, + { EL_DYNABOMB_INCREASE_POWER, EL_BOMB }, + { EL_BLACK_ORB, EL_BOMB }, + { EL_DX_SUPABOMB, EL_BOMB }, + + { EL_SOKOBAN_OBJECT, EL_KEY_1 }, + { EL_SOKOBAN_FIELD_EMPTY, EL_GATE_1_GRAY }, + { EL_SOKOBAN_FIELD_FULL, EL_GATE_1 }, + { EL_SOKOBAN_FIELD_PLAYER, EL_PLAYER_1 }, + + { EL_BD_BUTTERFLY_RIGHT, EL_BD_BUTTERFLY }, + { EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY }, + { EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY }, + { EL_BD_BUTTERFLY_DOWN, EL_BD_BUTTERFLY }, + + { EL_BD_FIREFLY_RIGHT, EL_BD_FIREFLY }, + { EL_BD_FIREFLY_UP, EL_BD_FIREFLY }, + { EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY }, + { EL_BD_FIREFLY_DOWN, EL_BD_FIREFLY }, + + { EL_PLAYER_2, EL_PLAYER_1 }, + { EL_PLAYER_3, EL_PLAYER_1 }, + { EL_PLAYER_4, EL_PLAYER_1 }, + + { EL_BUG_RIGHT, EL_BUG }, + { EL_BUG_UP, EL_BUG }, + { EL_BUG_LEFT, EL_BUG }, + { EL_BUG_DOWN, EL_BUG }, + + { EL_SPACESHIP_RIGHT, EL_SPACESHIP }, + { EL_SPACESHIP_UP, EL_SPACESHIP }, + { EL_SPACESHIP_LEFT, EL_SPACESHIP }, + { EL_SPACESHIP_DOWN, EL_SPACESHIP }, + + { EL_PACMAN_RIGHT, EL_YAMYAM }, + { EL_PACMAN_UP, EL_YAMYAM }, + { EL_PACMAN_LEFT, EL_YAMYAM }, + { EL_PACMAN_DOWN, EL_YAMYAM }, + + { -1, -1 } +}; + +static struct +{ + short element; + char *element_string; +} +forum_sketch_element_strings[] = +{ + { EL_PLAYER_1, "p" }, + { EL_EMPTY, "_" }, + { EL_SAND, "s" }, + { EL_ROCK, "b" }, + { EL_EMERALD, "e" }, + { EL_BUG, "u" }, + { EL_SPACESHIP, "h" }, + { EL_BD_FIREFLY, "f" }, + { EL_BD_BUTTERFLY, "b" }, + { EL_AMOEBA, "a" }, + { EL_YAMYAM, "y" }, + { EL_WALL, "w" }, + { EL_STEELWALL, "t" }, + { EL_MAGIC_WALL, "m" }, + { EL_EXIT_OPEN, "x" }, + { EL_DYNAMITE, "d" }, + { EL_KEY_1, "1" }, + { EL_KEY_2, "2" }, + { EL_KEY_3, "3" }, + { EL_KEY_4, "4" }, + { EL_GATE_1, "5" }, + { EL_GATE_2, "6" }, + { EL_GATE_3, "7" }, + { EL_GATE_4, "8" }, + { EL_GATE_1_GRAY, "9" }, + { EL_BOMB, "@" }, + { EL_ROBOT, "r" }, + { EL_ROBOT_WHEEL, "0" }, + { EL_NUT, "n" }, + { EL_CUSTOM_1, "c" }, + { EL_CHAR_QUESTION, "?" }, + + { -1, NULL } +}; + /* ----------------------------------------------------------------------------- @@ -2867,18 +3431,93 @@ editor_elements_info[] = ----------------------------------------------------------------------------- */ +static int getMaxInfoTextLength() +{ + return (SXSIZE / getFontWidth(FONT_TEXT_2)); +} + +static int getTextWidthForGadget(char *text) +{ + if (text == NULL) + return 0; + + return (getTextWidth(text, FONT_TEXT_1) + ED_GADGET_TEXT_DISTANCE); +} + +static int getTextWidthForDrawingArea(char *text) +{ + if (text == NULL) + return 0; + + return (getTextWidth(text, FONT_TEXT_1) + ED_DRAWINGAREA_TEXT_DISTANCE); +} + +static int getRightGadgetBorder(struct GadgetInfo *gi, char *text) +{ + return (gi->x + gi->width + getTextWidthForGadget(text)); +} + +static char *getElementInfoText(int element) +{ + char *info_text = NULL; + + if (element < NUM_FILE_ELEMENTS) + { + if (strlen(element_info[element].description) > 0) + info_text = element_info[element].description; + else if (element_info[element].custom_description != NULL) + info_text = element_info[element].custom_description; + else if (element_info[element].editor_description != NULL) + info_text = element_info[element].editor_description; + } + + if (info_text == NULL) + info_text = INFOTEXT_UNKNOWN_ELEMENT; + + return info_text; +} + static void ReinitializeElementList() { + static boolean initialized = FALSE; int pos = 0; int i, j; - if (editor_elements != NULL) - free(editor_elements); + checked_free(editor_elements); + + if (!initialized) + { + /* initialize optional user defined element list */ + LoadUserDefinedEditorElementList(&editor_el_user_defined_ptr, + &num_editor_el_user_defined); + + /* initialize list of empty elements (used for padding, if needed) */ + for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++) + editor_el_empty[i] = EL_EMPTY; + + /* do some sanity checks for each element from element list */ + for (i = 0; editor_elements_info[i].setup_value != NULL; i++) + { + for (j = 0; j < *editor_elements_info[i].element_list_size; j++) + { + int element = (*editor_elements_info[i].element_list)[j]; + + if (element >= NUM_FILE_ELEMENTS) + Error(ERR_WARN, "editor element %d is runtime element", element); + + if (strcmp(getElementInfoText(element), INFOTEXT_UNKNOWN_ELEMENT) == 0) + Error(ERR_WARN, "no element description for element %d", element); + } + } + + initialized = TRUE; + } num_editor_elements = 0; + use_el_empty = FALSE; /* determine size of element list */ - for (i=0; editor_elements_info[i].setup_value != NULL; i++) + for (i = 0; editor_elements_info[i].setup_value != NULL; i++) { if (*editor_elements_info[i].setup_value) { @@ -2891,26 +3530,26 @@ static void ReinitializeElementList() if (num_editor_elements < ED_NUM_ELEMENTLIST_BUTTONS) { - /* workaround: offer at least as many elements as element buttons exist */ - int list_nr = 1; /* see above: editor_elements_info for Emerald Mine */ + /* offer at least as many elements as element buttons exist */ + use_el_empty = TRUE; + num_editor_el_empty = ED_NUM_ELEMENTLIST_BUTTONS - num_editor_elements; - *editor_elements_info[list_nr].setup_value = TRUE; - num_editor_elements += *editor_elements_info[list_nr].element_list_size; + num_editor_elements += num_editor_el_empty; } editor_elements = checked_malloc(num_editor_elements * sizeof(int)); /* fill element list */ - for (i=0; editor_elements_info[i].setup_value != NULL; i++) + for (i = 0; editor_elements_info[i].setup_value != NULL; i++) { if (*editor_elements_info[i].setup_value) { if (setup.editor.el_headlines) - for (j=0; j < *editor_elements_info[i].headline_list_size; j++) - editor_elements[pos++] = editor_elements_info[i].headline_list[j]; + for (j = 0; j < *editor_elements_info[i].headline_list_size; j++) + editor_elements[pos++] = (*editor_elements_info[i].headline_list)[j]; - for (j=0; j < *editor_elements_info[i].element_list_size; j++) - editor_elements[pos++] = editor_elements_info[i].element_list[j]; + for (j = 0; j < *editor_elements_info[i].element_list_size; j++) + editor_elements[pos++] = (*editor_elements_info[i].element_list)[j]; } } @@ -2921,6 +3560,35 @@ static void ReinitializeElementList() element_shift = num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS; } +void PrintEditorElementList() +{ + boolean *stop = &setup.editor.el_user_defined; + int i, j; + + for (i = 0; editor_elements_info[i].setup_value != stop; i++) + { + for (j = 0; j < *editor_elements_info[i].headline_list_size; j++) + { + int element = (*editor_elements_info[i].headline_list)[j]; + + printf("# %s\n", element_info[element].token_name); + } + + if (j > 0) + printf("#\n"); + + for (j = 0; j < *editor_elements_info[i].element_list_size; j++) + { + int element = (*editor_elements_info[i].element_list)[j]; + + printf("# %s\n", element_info[element].token_name); + } + + if (j > 0) + printf("#\n"); + } +} + static void ReinitializeElementListButtons() { static boolean last_setup_value_headlines = FALSE; @@ -2932,7 +3600,7 @@ static void ReinitializeElementListButtons() if (last_setup_value_headlines != setup.editor.el_headlines) initialization_needed = TRUE; - for (i=0; editor_elements_info[i].setup_value != NULL; i++) + for (i = 0; editor_elements_info[i].setup_value != NULL; i++) if (editor_elements_info[i].last_setup_value != *editor_elements_info[i].setup_value) initialization_needed = TRUE; @@ -2946,63 +3614,13 @@ static void ReinitializeElementListButtons() /* store current setup values for next invocation of this function */ last_setup_value_headlines = setup.editor.el_headlines; - for (i=0; editor_elements_info[i].setup_value != NULL; i++) + for (i = 0; editor_elements_info[i].setup_value != NULL; i++) editor_elements_info[i].last_setup_value = *editor_elements_info[i].setup_value; initialization_needed = FALSE; } -static int getMaxInfoTextLength() -{ - return (SXSIZE / getFontWidth(FONT_TEXT_2)); -} - -static int getTextWidthForGadget(char *text) -{ - if (text == NULL) - return 0; - - return (getTextWidth(text, FONT_TEXT_1) + ED_GADGET_TEXT_DISTANCE); -} - -static int getTextWidthForDrawingArea(char *text) -{ - if (text == NULL) - return 0; - - return (getTextWidth(text, FONT_TEXT_1) + ED_DRAWINGAREA_TEXT_DISTANCE); -} - -static int getRightGadgetBorder(struct GadgetInfo *gi, char *text) -{ - return (gi->x + gi->width + getTextWidthForGadget(text)); -} - -static char *getElementInfoText(int element) -{ - char *info_text = NULL; - - if (element < NUM_FILE_ELEMENTS) - { - if (strlen(element_info[element].description) > 0) - info_text = element_info[element].description; - else if (element_info[element].custom_description != NULL) - info_text = element_info[element].custom_description; - else if (element_info[element].editor_description != NULL) - info_text = element_info[element].editor_description; - } - - if (info_text == NULL) - { - info_text = "unknown"; - - Error(ERR_WARN, "no element description for element %d", element); - } - - return info_text; -} - static void DrawElementBorder(int dest_x, int dest_y, int width, int height, boolean input) { @@ -3010,14 +3628,14 @@ static void DrawElementBorder(int dest_x, int dest_y, int width, int height, (input ? IMG_EDITOR_ELEMENT_BORDER_INPUT : IMG_EDITOR_ELEMENT_BORDER); Bitmap *src_bitmap; int src_x, src_y; - int num_mini_tilex = width / MINI_TILEX + 1; - int num_mini_tiley = width / MINI_TILEY + 1; + int num_mini_tilex = width / MINI_TILEX + 1; + int num_mini_tiley = height / MINI_TILEY + 1; int x, y; getMiniGraphicSource(border_graphic, &src_bitmap, &src_x, &src_y); - for (y=0; y < num_mini_tiley; y++) - for (x=0; x < num_mini_tilex; x++) + for (y = 0; y < num_mini_tiley; y++) + for (x = 0; x < num_mini_tilex; x++) BlitBitmap(src_bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY, dest_x - MINI_TILEX / 2 + x * MINI_TILEX, dest_y - MINI_TILEY / 2 + y * MINI_TILEY); @@ -3039,30 +3657,40 @@ static void DrawDrawingArea(int id) DrawMiniGraphicExt(drawto, gi->x, gi->y, el2edimg(custom_element.gfx_element)); else if (id == ED_DRAWING_ID_CUSTOM_CONTENT) - for (y=0; y<3; y++) - for (x=0; x<3; x++) + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY, el2edimg(custom_element.content[x][y])); + else if (id == ED_DRAWING_ID_CUSTOM_MOVE_ENTER) + DrawMiniGraphicExt(drawto, gi->x, gi->y, + el2edimg(custom_element.move_enter_element)); + else if (id == ED_DRAWING_ID_CUSTOM_MOVE_LEAVE) + DrawMiniGraphicExt(drawto, gi->x, gi->y, + el2edimg(custom_element.move_leave_element)); else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TARGET) DrawMiniGraphicExt(drawto, gi->x, gi->y, el2edimg(custom_element_change.target_element)); else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT) - for (y=0; y < 3; y++) - for (x=0; x < 3; x++) + for (y = 0; y < 3; y++) + 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])); else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER) DrawMiniGraphicExt(drawto, gi->x, gi->y, el2edimg(custom_element_change.trigger_element)); + else if (id == ED_DRAWING_ID_GROUP_CONTENT) + for (x = 0; x < group_element_info.num_elements; x++) + DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y, + el2edimg(group_element_info.element[x])); else if (id >= ED_DRAWING_ID_ELEMENT_CONTENT_0 && id <= ED_DRAWING_ID_ELEMENT_CONTENT_7) { int nr = id - ED_DRAWING_ID_ELEMENT_CONTENT_0; - for (y=0; y < 3; y++) - for (x=0; x < 3; x++) + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY, el2edimg(level.yamyam_content[nr][x][y])); @@ -3085,13 +3713,13 @@ static void ScrollMiniLevel(int from_x, int from_y, int scroll) if (dx) { x = (dx == 1 ? 0 : ed_fieldx - 1); - for(y=0; y selectbox_info[i].size) selectbox_info[i].size = strlen(selectbox_info[i].options[j].text); @@ -3689,7 +4340,7 @@ static void CreateTextbuttonGadgets() int max_infotext_len = getMaxInfoTextLength(); int i; - for (i=0; iwidth, gi->height, gi->x, gi->y); + + redraw_mask |= REDRAW_DOOR_3; + } + } + } +} + +static void MapLevelEditorToolboxDrawingGadgets() +{ + MapOrUnmapLevelEditorToolboxDrawingGadgets(TRUE); +} + +static void UnmapLevelEditorToolboxDrawingGadgets() +{ + MapOrUnmapLevelEditorToolboxDrawingGadgets(FALSE); +} + static void UnmapDrawingArea(int id) { - UnmapGadget(level_editor_gadget[id]); + UnmapGadget(level_editor_gadget[drawingarea_info[id].gadget_id]); } -void UnmapLevelEditorWindowGadgets() +static void UnmapLevelEditorWindowGadgets() { int i; - for (i=0; ix < SX + SXSIZE) UnmapGadget(level_editor_gadget[i]); } @@ -4337,7 +5056,7 @@ void UnmapLevelEditorGadgets() { int i; - for (i=0; itoken_name = ei_to_old.token_name; + ei_to->class_name = ei_to_old.class_name; + ei_to->editor_description = ei_to_old.editor_description; + ei_to->custom_description = ei_to_old.custom_description; + ei_to->change_page = ei_to_old.change_page; + ei_to->change = ei_to_old.change; + ei_to->group = ei_to_old.group; + + /* ---------- copy element base properties ---------- */ + Properties[element_to][EP_BITFIELD_BASE] = + Properties[element_from][EP_BITFIELD_BASE]; + + /* ---------- reinitialize and copy change pages ---------- */ + setElementChangePages(ei_to, ei_to->num_change_pages); + + for (i=0; i < ei_to->num_change_pages; i++) + ei_to->change_page[i] = ei_from->change_page[i]; + + /* ---------- copy group element info ---------- */ + if (ei_from->group != NULL && ei_to->group != NULL) /* group or internal */ + *ei_to->group = *ei_from->group; + +#else + + struct ElementInfo *ei_from = &element_info[element_from]; + struct ElementInfo *ei_to = &element_info[element_to]; + int i, x, y; + + /* ---------- copy element description ---------- */ + for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++) + ei_to->description[i] = ei_from->description[i]; + + /* ---------- copy element properties ---------- */ + Properties[element_to][EP_BITFIELD_BASE] = + Properties[element_from][EP_BITFIELD_BASE]; + + /* ---------- copy custom property values ---------- */ + + ei_to->use_gfx_element = ei_from->use_gfx_element; + ei_to->gfx_element = ei_from->gfx_element; + + ei_to->collect_score = ei_from->collect_score; + ei_to->collect_count = ei_from->collect_count; + + ei_to->push_delay_fixed = ei_from->push_delay_fixed; + ei_to->push_delay_random = ei_from->push_delay_random; + ei_to->move_delay_fixed = ei_from->move_delay_fixed; + ei_to->move_delay_random = ei_from->move_delay_random; + + ei_to->move_pattern = ei_from->move_pattern; + ei_to->move_direction_initial = ei_from->move_direction_initial; + ei_to->move_stepsize = ei_from->move_stepsize; + + ei_to->slippery_type = ei_from->slippery_type; + + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) + ei_to->content[x][y] = ei_from->content[x][y]; + + ei_to->num_change_pages = ei_from->num_change_pages; + setElementChangePages(ei_to, ei_to->num_change_pages); + + for (i=0; i < ei_to->num_change_pages; i++) + { + struct ElementChangeInfo *change_to = &ei_to->change_page[i]; + struct ElementChangeInfo *change_from = &ei_from->change_page[i]; + + /* always start with reliable default values */ + setElementChangeInfoToDefaults(change_to); + + change_to->events = change_from->events; + + change_to->target_element = change_from->target_element; + + change_to->delay_fixed = change_from->delay_fixed; + change_to->delay_random = change_from->delay_random; + change_to->delay_frames = change_from->delay_frames; + + change_to->trigger_element = change_from->trigger_element; + + change_to->explode = change_from->explode; + change_to->use_content = change_from->use_content; + change_to->only_complete = change_from->only_complete; + change_to->use_random_change = change_from->use_random_change; + + change_to->random = change_from->random; + change_to->power = change_from->power; + + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) + change_to->content[x][y] = change_from->content[x][y]; + + change_to->can_change = change_from->can_change; + + change_to->sides = change_from->sides; + } +#endif + + /* mark this custom element as modified */ + ei_to->modified_settings = TRUE; +} + +static void replace_custom_element_in_settings(int element_from, + int element_to) +{ + int i, j, x, y; + + for (i = 0; i < NUM_FILE_ELEMENTS; i++) + { + struct ElementInfo *ei = &element_info[i]; + + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) + if (ei->content[x][y] == element_from) + ei->content[x][y] = element_to; + + for (j = 0; j < ei->num_change_pages; j++) + { + struct ElementChangeInfo *change = &ei->change_page[j]; + + if (change->target_element == element_from) + change->target_element = element_to; + + if (change->trigger_element == element_from) + change->trigger_element = element_to; + + 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 (ei->group != NULL) /* group or internal */ + for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++) + if (ei->group->element[j] == element_from) + ei->group->element[j] = element_to; + } +} + +static void replace_custom_element_in_playfield(int element_from, + int element_to) +{ + int x, y; + + for (x = 0; x < lev_fieldx; x++) + for (y = 0; y < lev_fieldy; y++) + if (Feld[x][y] == element_from) + Feld[x][y] = element_to; } -static int setSelectboxValue(int selectbox_id, int new_value) +static boolean CopyCustomElement(int element_old, int element_new, + int copy_mode) { - int new_index_value = 0; - int i; + if (IS_CUSTOM_ELEMENT(element_old) && !IS_CUSTOM_ELEMENT(element_new)) + { + Request("Please choose custom element !", REQ_CONFIRM); - for(i=0; selectbox_info[selectbox_id].options[i].text != NULL; i++) - if (selectbox_info[selectbox_id].options[i].value == new_value) - new_index_value = i; + return FALSE; + } + else if (IS_GROUP_ELEMENT(element_old) && !IS_GROUP_ELEMENT(element_new)) + { + Request("Please choose group element !", REQ_CONFIRM); - *selectbox_info[selectbox_id].value = - selectbox_info[selectbox_id].options[new_index_value].value; + return FALSE; + } - return new_index_value; + if (copy_mode == GADGET_ID_CUSTOM_COPY_FROM) + { + copy_custom_element_settings(element_new, element_old); + } + else if (copy_mode == GADGET_ID_CUSTOM_COPY_TO) + { + copy_custom_element_settings(element_old, element_new); + } + else if (copy_mode == GADGET_ID_CUSTOM_EXCHANGE) + { + copy_custom_element_settings(element_old, EL_INTERNAL_EDITOR); + copy_custom_element_settings(element_new, element_old); + copy_custom_element_settings(EL_INTERNAL_EDITOR, element_new); + + replace_custom_element_in_settings(element_old, EL_INTERNAL_EDITOR); + replace_custom_element_in_settings(element_new, element_old); + replace_custom_element_in_settings(EL_INTERNAL_EDITOR, element_new); + + replace_custom_element_in_playfield(element_old, EL_INTERNAL_EDITOR); + replace_custom_element_in_playfield(element_new, element_old); + replace_custom_element_in_playfield(EL_INTERNAL_EDITOR, element_new); + } + + UpdateCustomElementGraphicGadgets(); + DrawPropertiesWindow(); + + return TRUE; } static void CopyCustomElementPropertiesToEditor(int element) @@ -4419,7 +5345,7 @@ static void CopyCustomElementPropertiesToEditor(int element) int current_change_page = element_info[element].current_change_page; /* dynamically (re)build selectbox for selecting change page */ - for (i=0; i < element_info[element].num_change_pages; i++) + for (i = 0; i < element_info[element].num_change_pages; i++) { sprintf(options_change_page_strings[i], "%d", i + 1); @@ -4440,13 +5366,13 @@ static void CopyCustomElementPropertiesToEditor(int element) custom_element_change = *element_info[element].change; /* needed to initially set selectbox value variables to reliable defaults */ - for (i=0; i < ED_NUM_SELECTBOX; i++) + for (i = 0; i < ED_NUM_SELECTBOX; i++) setSelectboxValue(i, *selectbox_info[i].value); - for (i=0; i < NUM_ELEMENT_PROPERTIES; i++) + for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++) custom_element_properties[i] = HAS_PROPERTY(element, i); - for (i=0; i < NUM_CHANGE_EVENTS; i++) + for (i = 0; i < NUM_CHANGE_EVENTS; i++) custom_element_change_events[i] = HAS_CHANGE_EVENT(element, i); /* ---------- element settings: configure (custom elements) ------------- */ @@ -4506,11 +5432,13 @@ static void CopyCustomElementPropertiesToEditor(int element) (IS_INDESTRUCTIBLE(element) ? EP_INDESTRUCTIBLE : CAN_EXPLODE_1X1(element) ? EP_CAN_EXPLODE_1X1 : CAN_EXPLODE_3X3(element) ? EP_CAN_EXPLODE_3X3 : + CAN_EXPLODE_DYNA(element) ? EP_CAN_EXPLODE_DYNA : custom_element.consistency); custom_element_properties[EP_EXPLODE_RESULT] = (IS_INDESTRUCTIBLE(element) || CAN_EXPLODE_1X1(element) || - CAN_EXPLODE_3X3(element)); + CAN_EXPLODE_3X3(element) || + CAN_EXPLODE_DYNA(element)); /* special case: sub-settings dependent from main setting */ if (CAN_EXPLODE_BY_FIRE(element)) @@ -4527,27 +5455,49 @@ static void CopyCustomElementPropertiesToEditor(int element) (HAS_CHANGE_EVENT(element, CE_TOUCHED_BY_PLAYER) ? CE_TOUCHED_BY_PLAYER : HAS_CHANGE_EVENT(element, CE_PRESSED_BY_PLAYER) ? CE_PRESSED_BY_PLAYER : HAS_CHANGE_EVENT(element, CE_PUSHED_BY_PLAYER) ? CE_PUSHED_BY_PLAYER : + HAS_CHANGE_EVENT(element, CE_ENTERED_BY_PLAYER) ? CE_ENTERED_BY_PLAYER : + HAS_CHANGE_EVENT(element, CE_LEFT_BY_PLAYER) ? CE_LEFT_BY_PLAYER : HAS_CHANGE_EVENT(element, CE_DROPPED_BY_PLAYER) ? CE_DROPPED_BY_PLAYER : - HAS_CHANGE_EVENT(element, CE_COLLISION) ? CE_COLLISION : + HAS_CHANGE_EVENT(element, CE_SWITCHED) ? CE_SWITCHED : + HAS_CHANGE_EVENT(element, CE_HITTING_SOMETHING) ? CE_HITTING_SOMETHING : + HAS_CHANGE_EVENT(element, CE_HIT_BY_SOMETHING) ? CE_HIT_BY_SOMETHING : HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT : HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED : custom_element_change.direct_action); /* set "change by other element action" selectbox help value */ custom_element_change.other_action = - ( - HAS_CHANGE_EVENT(element, CE_OTHER_GETS_TOUCHED) ? CE_OTHER_GETS_TOUCHED : + (HAS_CHANGE_EVENT(element, CE_OTHER_GETS_TOUCHED) ? CE_OTHER_GETS_TOUCHED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PRESSED) ? CE_OTHER_GETS_PRESSED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PUSHED) ? CE_OTHER_GETS_PUSHED : + HAS_CHANGE_EVENT(element, CE_OTHER_GETS_ENTERED) ? CE_OTHER_GETS_ENTERED : + HAS_CHANGE_EVENT(element, CE_OTHER_GETS_LEFT) ? CE_OTHER_GETS_LEFT : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DIGGED) ? CE_OTHER_GETS_DIGGED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_COLLECTED) ? CE_OTHER_GETS_COLLECTED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DROPPED) ? CE_OTHER_GETS_DROPPED : HAS_CHANGE_EVENT(element, CE_OTHER_IS_TOUCHING) ? CE_OTHER_IS_TOUCHING : + HAS_CHANGE_EVENT(element, CE_OTHER_IS_HITTING) ? CE_OTHER_IS_HITTING : + HAS_CHANGE_EVENT(element, CE_OTHER_GETS_HIT) ? CE_OTHER_GETS_HIT : + HAS_CHANGE_EVENT(element, CE_OTHER_IS_SWITCHING) ? CE_OTHER_IS_SWITCHING : HAS_CHANGE_EVENT(element, CE_OTHER_IS_CHANGING) ? CE_OTHER_IS_CHANGING : HAS_CHANGE_EVENT(element, CE_OTHER_IS_EXPLODING) ? CE_OTHER_IS_EXPLODING : custom_element_change.other_action); } +static void CopyGroupElementPropertiesToEditor(int element) +{ + group_element_info = *element_info[element].group; + custom_element = element_info[element]; /* needed for description */ +} + +static void CopyElementPropertiesToEditor(int element) +{ + if (IS_CUSTOM_ELEMENT(element)) + CopyCustomElementPropertiesToEditor(element); + else if (IS_GROUP_ELEMENT(element)) + CopyGroupElementPropertiesToEditor(element); +} + static void CopyCustomElementPropertiesToGame(int element) { int i; @@ -4558,7 +5508,7 @@ static void CopyCustomElementPropertiesToGame(int element) if (level.use_custom_template) { - if (Request("Copy and modify level tem- plate ?", REQ_ASK)) + if (Request("Copy and modify level template ?", REQ_ASK)) { level.use_custom_template = FALSE; ModifyGadget(level_editor_gadget[GADGET_ID_CUSTOM_USE_TEMPLATE], @@ -4616,6 +5566,7 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_properties[EP_INDESTRUCTIBLE] = FALSE; custom_element_properties[EP_CAN_EXPLODE_1X1] = FALSE; custom_element_properties[EP_CAN_EXPLODE_3X3] = FALSE; + custom_element_properties[EP_CAN_EXPLODE_DYNA] = FALSE; custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] = FALSE; custom_element_properties[EP_CAN_EXPLODE_SMASHED] = FALSE; custom_element_properties[EP_CAN_EXPLODE_IMPACT] = FALSE; @@ -4623,8 +5574,9 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_properties[EP_EXPLODE_RESULT]; /* special case: sub-settings dependent from main setting */ - if (custom_element_properties[EP_CAN_EXPLODE_3X3] || - custom_element_properties[EP_CAN_EXPLODE_1X1]) + if (custom_element_properties[EP_CAN_EXPLODE_1X1] || + custom_element_properties[EP_CAN_EXPLODE_3X3] || + custom_element_properties[EP_CAN_EXPLODE_DYNA]) { custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] = custom_element.can_explode_by_fire; @@ -4640,30 +5592,39 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_change_events[CE_TOUCHED_BY_PLAYER] = FALSE; custom_element_change_events[CE_PRESSED_BY_PLAYER] = FALSE; custom_element_change_events[CE_PUSHED_BY_PLAYER] = FALSE; + custom_element_change_events[CE_ENTERED_BY_PLAYER] = FALSE; + custom_element_change_events[CE_LEFT_BY_PLAYER] = FALSE; custom_element_change_events[CE_DROPPED_BY_PLAYER] = FALSE; - custom_element_change_events[CE_COLLISION] = FALSE; + custom_element_change_events[CE_SWITCHED] = FALSE; + custom_element_change_events[CE_HITTING_SOMETHING] = FALSE; + custom_element_change_events[CE_HIT_BY_SOMETHING] = FALSE; custom_element_change_events[CE_IMPACT] = FALSE; custom_element_change_events[CE_SMASHED] = FALSE; custom_element_change_events[custom_element_change.direct_action] = custom_element_change_events[CE_BY_DIRECT_ACTION]; /* set other element action change event from checkbox and selectbox */ - custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE; - custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE; - custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE; custom_element_change_events[CE_OTHER_GETS_TOUCHED] = FALSE; custom_element_change_events[CE_OTHER_GETS_PRESSED] = FALSE; custom_element_change_events[CE_OTHER_GETS_PUSHED] = FALSE; + custom_element_change_events[CE_OTHER_GETS_ENTERED] = FALSE; + custom_element_change_events[CE_OTHER_GETS_LEFT] = FALSE; custom_element_change_events[CE_OTHER_GETS_DIGGED] = FALSE; custom_element_change_events[CE_OTHER_GETS_COLLECTED] = FALSE; custom_element_change_events[CE_OTHER_GETS_DROPPED] = FALSE; + custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE; + custom_element_change_events[CE_OTHER_IS_HITTING] = FALSE; + custom_element_change_events[CE_OTHER_GETS_HIT] = FALSE; + custom_element_change_events[CE_OTHER_IS_SWITCHING] = FALSE; + custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE; + custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE; custom_element_change_events[custom_element_change.other_action] = custom_element_change_events[CE_BY_OTHER_ACTION]; - for (i=0; i < NUM_ELEMENT_PROPERTIES; i++) + for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++) SET_PROPERTY(element, i, custom_element_properties[i]); - for (i=0; i < NUM_CHANGE_EVENTS; i++) + for (i = 0; i < NUM_CHANGE_EVENTS; i++) SET_CHANGE_EVENT(element, i, custom_element_change_events[i]); /* copy change events also to special level editor variable */ @@ -4671,6 +5632,23 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_change = *element_info[element].change; } +static void CopyGroupElementPropertiesToGame(int element) +{ + element_info[element] = custom_element; + *element_info[element].group = group_element_info; + + /* mark that this group element has been modified */ + element_info[element].modified_settings = TRUE; +} + +static void CopyElementPropertiesToGame(int element) +{ + if (IS_CUSTOM_ELEMENT(element)) + CopyCustomElementPropertiesToGame(element); + else if (IS_GROUP_ELEMENT(element)) + CopyGroupElementPropertiesToGame(element); +} + void DrawLevelEd() { CloseDoor(DOOR_CLOSE_ALL); @@ -4862,11 +5840,19 @@ static void ModifyEditorSelectbox(int selectbox_id, int new_value) ModifyGadget(gi, GDI_SELECTBOX_INDEX, new_index_value, GDI_END); } +static void ModifyEditorDrawingArea(int drawingarea_id, int xsize, int ysize) +{ + int gadget_id = drawingarea_info[drawingarea_id].gadget_id; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + + ModifyGadget(gi, GDI_AREA_SIZE, xsize, ysize, GDI_END); +} + static void ModifyEditorElementList() { int i; - for (i=0; ix, gi->y, gi->width, gi->height); - ModifyGadget(gi, GDI_AREA_SIZE, level.envelope_xsize, level.envelope_ysize, + if (envelope_nr != -1) + textarea_info[id].value = level.envelope_text[envelope_nr]; + + ModifyGadget(gi, GDI_AREA_SIZE, + *counterbutton_info[ED_COUNTER_ID_ENVELOPE_XSIZE].value, + *counterbutton_info[ED_COUNTER_ID_ENVELOPE_YSIZE].value, GDI_END); + MapTextAreaGadget(ED_TEXTAREA_ID_ENVELOPE_INFO); } @@ -5053,8 +6071,7 @@ char *getElementDescriptionFilename(int element) static char *filename = NULL; char basename[MAX_FILENAME_LEN]; - if (filename != NULL) - free(filename); + checked_free(filename); /* 1st try: look for element description file for exactly this element */ sprintf(basename, "%s.txt", element_info[element].token_name); @@ -5073,7 +6090,7 @@ char *getElementDescriptionFilename(int element) return NULL; } -static boolean PrintInfoText(char *text, int font_nr, int screen_line) +static boolean PrintInfoText(char *text, int font_nr, int start_line) { int font_height = getFontHeight(font_nr); int pad_x = ED_SETTINGS_XPOS(0); @@ -5082,26 +6099,54 @@ static boolean PrintInfoText(char *text, int font_nr, int screen_line) int sy = SY + pad_y; int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; - if (screen_line >= max_lines_per_screen) + if (start_line >= max_lines_per_screen) return FALSE; - DrawText(sx, sy + screen_line * font_height, text, font_nr); + DrawText(sx, sy + start_line * font_height, text, font_nr); return TRUE; } -static int PrintElementDescriptionFromFile(char *filename, int screen_line) +#if 1 + +static int PrintElementDescriptionFromFile(char *filename, int start_line) +{ + int font_nr = FONT_TEXT_2; + int font_width = getFontWidth(font_nr); + int font_height = getFontHeight(font_nr); + int pad_x = ED_SETTINGS_XPOS(0); + int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE; + int sx = SX + pad_x; + int sy = SY + pad_y + start_line * font_height; + int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width; + int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; + + return DrawTextFromFile(sx, sy, filename, font_nr, max_chars_per_line, + max_lines_per_screen); +} + +#else + +static int PrintElementDescriptionFromFile(char *filename, int start_line) { int font_nr = FONT_TEXT_2; int font_width = getFontWidth(font_nr); + int font_height = getFontHeight(font_nr); int pad_x = ED_SETTINGS_XPOS(0); + int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE; + int sx = SX + pad_x; + int sy = SY + pad_y; int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width; + int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; + int current_line = start_line; char line[MAX_LINE_LEN]; char buffer[max_chars_per_line + 1]; int buffer_len; - int lines_printed = 0; FILE *file; + if (current_line >= max_lines_per_screen) + return 0; + if (filename == NULL) return 0; @@ -5111,9 +6156,9 @@ static int PrintElementDescriptionFromFile(char *filename, int screen_line) buffer[0] = '\0'; buffer_len = 0; - while(!feof(file)) + while (!feof(file) && current_line < max_lines_per_screen) { - char *line_ptr, *word_ptr; + char *line_ptr; boolean last_line_was_empty = TRUE; /* read next line of input file */ @@ -5137,92 +6182,40 @@ static int PrintElementDescriptionFromFile(char *filename, int screen_line) if (strlen(line) == 0) /* special case: force empty line */ strcpy(line, "\n"); - word_ptr = line; + line_ptr = line; - while (*word_ptr) + while (*line_ptr && current_line < max_lines_per_screen) { - boolean print_buffer = FALSE; - int word_len; - - /* skip leading whitespaces */ - while (*word_ptr == ' ' || *word_ptr == '\t') - word_ptr++; - - line_ptr = word_ptr; - word_len = 0; - - /* look for end of next word */ - while (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != '\0') - { - line_ptr++; - word_len++; - } - - if (word_len == 0) - { - continue; - } - else if (*word_ptr == '\n') /* special case: force empty line */ - { - if (buffer_len == 0) - word_ptr++; - - /* prevent printing of multiple empty lines */ - if (buffer_len > 0 || !last_line_was_empty) - print_buffer = TRUE; - } - else if (word_len < max_chars_per_line - buffer_len) - { - /* word fits into text buffer -- add word */ - - if (buffer_len > 0) - buffer[buffer_len++] = ' '; - - strncpy(&buffer[buffer_len], word_ptr, word_len); - buffer_len += word_len; - buffer[buffer_len] = '\0'; - word_ptr += word_len; - } - else if (buffer_len > 0) - { - /* not enough space left for word in text buffer -- print buffer */ - - print_buffer = TRUE; - } - else - { - /* word does not fit at all into empty text buffer -- cut word */ - - strncpy(buffer, word_ptr, max_chars_per_line); - buffer[max_chars_per_line] = '\0'; - word_ptr += max_chars_per_line; - print_buffer = TRUE; - } - - if (print_buffer) + boolean buffer_filled = RenderLineToBuffer(&line_ptr, + buffer, &buffer_len, + last_line_was_empty, + max_chars_per_line); + if (buffer_filled) { - if (!PrintInfoText(buffer, font_nr, screen_line + lines_printed)) - return lines_printed; + DrawText(sx, sy + current_line * font_height, buffer, font_nr); + current_line++; last_line_was_empty = (buffer_len == 0); - lines_printed++; buffer[0] = '\0'; buffer_len = 0; - print_buffer = FALSE; } } } fclose(file); - if (buffer_len > 0) - if (PrintInfoText(buffer, font_nr, screen_line + lines_printed)) - lines_printed++; + if (buffer_len > 0 && current_line < max_lines_per_screen) + { + DrawText(sx, sy + current_line * font_height, buffer, font_nr); + current_line++; + } - return lines_printed; + return (current_line - start_line); } +#endif + static void DrawPropertiesTabulatorGadgets() { struct GadgetInfo *gd_gi = level_editor_gadget[GADGET_ID_PROPERTIES_INFO]; @@ -5235,10 +6228,11 @@ static void DrawPropertiesTabulatorGadgets() int i; /* draw additional "advanced" tabulator for custom elements */ - if (IS_CUSTOM_ELEMENT(properties_element)) + if (IS_CUSTOM_ELEMENT(properties_element) || + IS_GROUP_ELEMENT(properties_element)) id_last = ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED; - for (i=id_first; i <= id_last; i++) + for (i = id_first; i <= id_last; i++) { int gadget_id = textbutton_info[i].gadget_id; struct GadgetInfo *gi = level_editor_gadget[gadget_id]; @@ -5330,16 +6324,31 @@ static void DrawPropertiesInfo() int screen_line = 0; int i, x, y; +#if DEBUG + if (IS_CUSTOM_ELEMENT(properties_element)) + { + DrawTextF(pad_x, pad_y + screen_line++ * font2_height, FONT_TEXT_3, + "[Custom Element %d]", properties_element - EL_CUSTOM_START + 1); + screen_line++; + } + else if (IS_GROUP_ELEMENT(properties_element)) + { + DrawTextF(pad_x, pad_y + screen_line++ * font2_height, FONT_TEXT_3, + "[Group Element %d]", properties_element - EL_GROUP_START + 1); + screen_line++; + } +#endif + /* ----- print number of elements / percentage of this element in level */ num_elements_in_level = 0; - for (y=0; y to_x) swap_numbers(&from_x, &to_x); - for (x=from_x; x<=to_x; x++) + for (x = from_x; x <= to_x; x++) DrawLineElement(x, y, element, change_level); } else if (from_x == to_x) /* vertical line */ @@ -5723,7 +6799,7 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y, if (from_y > to_y) swap_numbers(&from_y, &to_y); - for (y=from_y; y<=to_y; y++) + for (y = from_y; y <= to_y; y++) DrawLineElement(x, y, element, change_level); } else /* diagonal line */ @@ -5739,7 +6815,7 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y, if (from_x > to_x) swap_number_pairs(&from_x, &from_y, &to_x, &to_y); - for (x=0; x<=len_x; x++) + for (x = 0; x <= len_x; x++) { y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1); DrawLineElement(from_x + x, from_y + y, element, change_level); @@ -5752,7 +6828,7 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y, if (from_y > to_y) swap_number_pairs(&from_x, &from_y, &to_x, &to_y); - for (y=0; y<=len_y; y++) + for (y = 0; y <= len_y; y++) { x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1); DrawLineElement(from_x + x, from_y + y, element, change_level); @@ -5778,7 +6854,7 @@ static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y, if (from_y > to_y) swap_number_pairs(&from_x, &from_y, &to_x, &to_y); - for (y=from_y; y<=to_y; y++) + for (y = from_y; y <= to_y; y++) DrawLine(from_x, y, to_x, y, element, change_level); } @@ -5796,7 +6872,7 @@ static void DrawArcExt(int from_x, int from_y, int to_x2, int to_y2, /* not optimal (some points get drawn twice) but simple, and fast enough for the few points we are drawing */ - for (x=0; x<=radius; x++) + for (x = 0; x <= radius; x++) { int sx, sy, lx, ly; @@ -5811,7 +6887,7 @@ static void DrawArcExt(int from_x, int from_y, int to_x2, int to_y2, DrawLineElement(sx, sy, element, change_level); } - for (y=0; y<=radius; y++) + for (y = 0; y <= radius; y++) { int sx, sy, lx, ly; @@ -5894,6 +6970,7 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, #define CB_BRUSH_TO_CURSOR 1 #define CB_BRUSH_TO_LEVEL 2 #define CB_DELETE_OLD_CURSOR 3 +#define CB_DUMP_BRUSH 4 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int button, int mode) @@ -5905,6 +6982,54 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int new_element = BUTTON_ELEMENT(button); int x, y; + if (mode == CB_DUMP_BRUSH) + { + if (!draw_with_brush) + { + Error(ERR_WARN, "no brush selected"); + + return; + } + + for (y = 0; y < brush_height; y++) + { + for (x = 0; x < brush_width; x++) + { + int element = brush_buffer[x][y]; + int element_mapped = element; + char *element_string = "?"; + int k; + + for (k = 0; forum_sketch_element_mapping[k].element != -1; k++) + { + if (forum_sketch_element_mapping[k].element == element) + { + element_mapped = forum_sketch_element_mapping[k].element_mapped; + break; + } + } + + if (IS_CUSTOM_ELEMENT(element)) + element_mapped = EL_CUSTOM_1; + + for (k = 0; forum_sketch_element_strings[k].element != -1; k++) + { + if (forum_sketch_element_strings[k].element == element_mapped) + { + element_string = forum_sketch_element_strings[k].element_string; + break; + } + } + + printf("`%s", element_string); + } + + printf("\n"); + } + + return; + } + if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush) return; @@ -5924,9 +7049,9 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, from_lx = from_x + level_xpos; from_ly = from_y + level_ypos; - for (y=0; y= num_free_positions) { - for (x=0; x= GADGET_ID_ELEMENT_CONTENT_0 && @@ -6565,12 +7716,18 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) PickDrawingElement(button, custom_element.gfx_element); else if (id == GADGET_ID_CUSTOM_CONTENT) PickDrawingElement(button, custom_element.content[sx][sy]); + else if (id == GADGET_ID_CUSTOM_MOVE_ENTER) + PickDrawingElement(button, custom_element.move_enter_element); + else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE) + PickDrawingElement(button, custom_element.move_leave_element); 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]); else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER) PickDrawingElement(button, custom_element_change.trigger_element); + else if (id == GADGET_ID_GROUP_CONTENT) + PickDrawingElement(button, group_element_info.element[sx]); else if (id == GADGET_ID_RANDOM_BACKGROUND) PickDrawingElement(button, random_placement_background_element); else if (id >= GADGET_ID_ELEMENT_CONTENT_0 && @@ -6626,9 +7783,14 @@ static void HandleCounterButtons(struct GadgetInfo *gi) DrawElementContentAreas(); break; + case ED_COUNTER_ID_GROUP_CONTENT: + DrawGroupElementArea(properties_element); + CopyGroupElementPropertiesToGame(properties_element); + break; + case ED_COUNTER_ID_ENVELOPE_XSIZE: case ED_COUNTER_ID_ENVELOPE_YSIZE: - DrawEnvelopeTextArea(); + DrawEnvelopeTextArea(-1); break; case ED_COUNTER_ID_LEVEL_XSIZE: @@ -6652,7 +7814,7 @@ static void HandleCounterButtons(struct GadgetInfo *gi) counter_id <= ED_COUNTER_ID_CUSTOM_LAST) || (counter_id >= ED_COUNTER_ID_CHANGE_FIRST && counter_id <= ED_COUNTER_ID_CHANGE_LAST)) - CopyCustomElementPropertiesToGame(properties_element); + CopyElementPropertiesToGame(properties_element); } static void HandleTextInputGadgets(struct GadgetInfo *gi) @@ -6663,7 +7825,7 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi) if (type_id == ED_TEXTINPUT_ID_ELEMENT_NAME) { - CopyCustomElementPropertiesToGame(properties_element); + CopyElementPropertiesToGame(properties_element); ModifyEditorElementList(); /* update changed button info text */ } @@ -6692,8 +7854,9 @@ static void HandleSelectboxGadgets(struct GadgetInfo *gi) else if ((type_id >= ED_SELECTBOX_ID_CUSTOM_FIRST && type_id <= ED_SELECTBOX_ID_CUSTOM_LAST) || (type_id >= ED_SELECTBOX_ID_CHANGE_FIRST && - type_id <= ED_SELECTBOX_ID_CHANGE_LAST)) - CopyCustomElementPropertiesToGame(properties_element); + type_id <= ED_SELECTBOX_ID_CHANGE_LAST) || + (type_id == ED_SELECTBOX_ID_GROUP_CHOICE_MODE)) + CopyElementPropertiesToGame(properties_element); } static void HandleTextbuttonGadgets(struct GadgetInfo *gi) @@ -6710,14 +7873,15 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi) } else if (type_id == ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE) { - boolean new_template = (!LevelFileExists(-1)); + char *template_filename = getDefaultLevelFilename(-1); + boolean new_template = !fileExists(template_filename); if (new_template || - Request("Save this tem- plate and kill the old ?", REQ_ASK)) + Request("Save this template and kill the old ?", REQ_ASK)) SaveLevelTemplate(); if (new_template) - Request("Tem- plate saved !", REQ_CONFIRM); + Request("Template saved !", REQ_CONFIRM); } else if (type_id == ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE && custom_element.num_change_pages < MAX_CHANGE_PAGES) @@ -6789,7 +7953,7 @@ static void HandleCheckbuttons(struct GadgetInfo *gi) type_id <= ED_CHECKBUTTON_ID_CHANGE_LAST && type_id != ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE)) { - CopyCustomElementPropertiesToGame(properties_element); + CopyElementPropertiesToGame(properties_element); } if (type_id == ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC) @@ -6798,9 +7962,11 @@ static void HandleCheckbuttons(struct GadgetInfo *gi) } else if (type_id == ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE) { - if (level.use_custom_template && !LevelFileExists(-1)) + char *template_filename = getDefaultLevelFilename(-1); + + if (level.use_custom_template && !fileExists(template_filename)) { - Request("No level tem- plate found !", REQ_CONFIRM); + Request("No level template found !", REQ_CONFIRM); level.use_custom_template = FALSE; ModifyGadget(gi, GDI_CHECKED, FALSE, GDI_END); @@ -6816,6 +7982,9 @@ static void HandleCheckbuttons(struct GadgetInfo *gi) static void HandleControlButtons(struct GadgetInfo *gi) { + static int last_level_drawing_function = GADGET_ID_SINGLE_ITEMS; + static int last_edit_mode = ED_MODE_DRAWING; + static int last_custom_copy_mode = -1; int id = gi->custom_id; int button = gi->event.button; int step = BUTTON_STEPSIZE(button); @@ -6825,8 +7994,11 @@ static void HandleControlButtons(struct GadgetInfo *gi) if (edit_mode == ED_MODE_DRAWING && drawing_function == GADGET_ID_TEXT) DrawLevelText(0, 0, 0, TEXT_END); - if (id < ED_NUM_CTRL1_BUTTONS && id != GADGET_ID_PROPERTIES && - id != GADGET_ID_PICK_ELEMENT && edit_mode != ED_MODE_DRAWING && + if (id < ED_NUM_CTRL1_BUTTONS && + id != GADGET_ID_SINGLE_ITEMS && + id != GADGET_ID_PROPERTIES && + id != GADGET_ID_PICK_ELEMENT && + edit_mode != ED_MODE_DRAWING && drawing_function != GADGET_ID_PICK_ELEMENT && !(GetKeyModState() & KMOD_Control)) { @@ -6834,6 +8006,10 @@ static void HandleControlButtons(struct GadgetInfo *gi) edit_mode = ED_MODE_DRAWING; } + /* element copy mode active, but no element button pressed => deactivate */ + if (last_custom_copy_mode != -1 && id < ED_NUM_CTRL_BUTTONS) + last_custom_copy_mode = -1; + switch (id) { case GADGET_ID_SCROLL_LEFT: @@ -6988,14 +8164,28 @@ static void HandleControlButtons(struct GadgetInfo *gi) properties_element = new_element; DrawPropertiesWindow(); edit_mode = ED_MODE_PROPERTIES; + + last_level_drawing_function = drawing_function; + ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], + MB_LEFTBUTTON); } else { DrawDrawingWindow(); edit_mode = ED_MODE_DRAWING; + + ClickOnGadget(level_editor_gadget[last_level_drawing_function], + MB_LEFTBUTTON); } break; + case GADGET_ID_CUSTOM_COPY_FROM: + case GADGET_ID_CUSTOM_COPY_TO: + case GADGET_ID_CUSTOM_EXCHANGE: + last_custom_copy_mode = id; + last_drawing_function = drawing_function; + break; + case GADGET_ID_UNDO: if (undo_buffer_steps == 0) { @@ -7013,8 +8203,8 @@ static void HandleControlButtons(struct GadgetInfo *gi) (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS; undo_buffer_steps--; - for(x=0; xcustom_id; int sx = gi->event.x; int sy = gi->event.y; @@ -7305,6 +8512,11 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) int max_sx = gi->drawing.area_xsize - 1; int max_sy = gi->drawing.area_ysize - 1; int actual_drawing_function = drawing_function; + int max_infotext_len = getMaxInfoTextLength(); + char infotext[MAX_OUTPUT_LINESIZE + 1]; + char *text; + + infotext[0] = '\0'; /* start with empty info text */ /* pressed Control key: simulate picking element */ if (GetKeyModState() & KMOD_Control) @@ -7352,41 +8564,48 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) switch (actual_drawing_function) { case GADGET_ID_SINGLE_ITEMS: - infotext = "Drawing single items"; + text = "Drawing single items"; break; case GADGET_ID_CONNECTED_ITEMS: - infotext = "Drawing connected items"; + text = "Drawing connected items"; break; case GADGET_ID_LINE: - infotext = "Drawing line"; + text = "Drawing line"; break; case GADGET_ID_ARC: - infotext = "Drawing arc"; + text = "Drawing arc"; break; case GADGET_ID_TEXT: - infotext = "Setting text cursor"; + text = "Setting text cursor"; break; case GADGET_ID_RECTANGLE: - infotext = "Drawing rectangle"; + text = "Drawing rectangle"; break; case GADGET_ID_FILLED_BOX: - infotext = "Drawing filled box"; + text = "Drawing filled box"; break; case GADGET_ID_FLOOD_FILL: - infotext = "Flood fill"; + text = "Flood fill"; break; case GADGET_ID_GRAB_BRUSH: - infotext = "Grabbing brush"; + text = "Grabbing brush"; break; case GADGET_ID_PICK_ELEMENT: - infotext = "Picking element"; + text = "Picking element"; break; default: - infotext = "Drawing position"; + text = "Drawing position"; break; } +#if 1 + if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) + sprintf(infotext, "%s: %d, %d", text, lx, ly); + else + sprintf(infotext, "%s: %d, %d", text, + ABS(lx - start_lx) + 1, ABS(ly - start_ly) + 1); +#else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s: %d, %d", infotext, lx, ly); @@ -7394,13 +8613,21 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s: %d, %d", infotext, ABS(lx - start_lx) + 1, ABS(ly - start_ly) + 1); +#endif } +#if 1 + else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) + strncpy(infotext, getElementInfoText(Feld[lx][ly]), max_infotext_len); + else + sprintf(infotext, "Level position: %d, %d", lx, ly); +#else else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", getElementInfoText(Feld[lx][ly])); else DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "Level position: %d, %d", lx, ly); +#endif } /* misuse this function to draw brush cursor, if needed */ @@ -7414,65 +8641,66 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) } else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) { + int element = EL_EMPTY; + if (id == GADGET_ID_AMOEBA_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(level.amoeba_content)); + element = level.amoeba_content; else if (id == GADGET_ID_CUSTOM_GRAPHIC) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(custom_element.gfx_element)); + element = custom_element.gfx_element; else if (id == GADGET_ID_CUSTOM_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(custom_element.content[sx][sy])); + element = custom_element.content[sx][sy]; + else if (id == GADGET_ID_CUSTOM_MOVE_ENTER) + element = custom_element.move_enter_element; + else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE) + element = custom_element.move_leave_element; else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(custom_element_change.target_element)); + element = custom_element_change.target_element; else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(custom_element_change.content[sx][sy])); + element = custom_element_change.content[sx][sy]; else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(custom_element_change.trigger_element)); + element = custom_element_change.trigger_element; + else if (id == GADGET_ID_GROUP_CONTENT) + element = group_element_info.element[sx]; else if (id == GADGET_ID_RANDOM_BACKGROUND) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(random_placement_background_element)); + element = random_placement_background_element; else if (id >= GADGET_ID_ELEMENT_CONTENT_0 && id <= GADGET_ID_ELEMENT_CONTENT_7) - { - int i = id - GADGET_ID_ELEMENT_CONTENT_0; + element = level.yamyam_content[id - GADGET_ID_ELEMENT_CONTENT_0][sx][sy]; - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s", - getElementInfoText(level.yamyam_content[i][sx][sy])); - } + strncpy(infotext, getElementInfoText(element), max_infotext_len); } else { if (id == GADGET_ID_AMOEBA_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "Amoeba content"); + strcpy(infotext, "Amoeba content"); else if (id == GADGET_ID_CUSTOM_GRAPHIC) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "Custom graphic element"); + strcpy(infotext, "Custom graphic element"); else if (id == GADGET_ID_CUSTOM_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "Custom element content position: %d, %d", sx, sy); + sprintf(infotext, "Custom element content position: %d, %d", sx, sy); + else if (id == GADGET_ID_CUSTOM_MOVE_ENTER) + strcpy(infotext, "Element that can be digged/collected"); + else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE) + strcpy(infotext, "Element that will be left behind"); else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "New element after change"); + strcpy(infotext, "New element after change"); else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "New extended elements after change"); + strcpy(infotext, "New extended elements after change"); else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "Other element triggering change"); + strcpy(infotext, "Other element triggering change"); + else if (id == GADGET_ID_GROUP_CONTENT) + sprintf(infotext, "Group element position: %d", sx + 1); else if (id == GADGET_ID_RANDOM_BACKGROUND) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "Random placement background"); + strcpy(infotext, "Random placement background"); else if (id >= GADGET_ID_ELEMENT_CONTENT_0 && id <= GADGET_ID_ELEMENT_CONTENT_7) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, - "Content area %d position: %d, %d", - id - GADGET_ID_ELEMENT_CONTENT_0 + 1, sx, sy); + sprintf(infotext, "Content area %d position: %d, %d", + id - GADGET_ID_ELEMENT_CONTENT_0 + 1, sx, sy); } + + infotext[max_infotext_len] = '\0'; + + if (strlen(infotext) > 0) + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, infotext); } void RequestExitLevelEditor(boolean ask_if_level_has_changed) @@ -7482,10 +8710,12 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed) Request("Level has changed! Exit without saving ?", REQ_ASK | REQ_STAY_OPEN)) { +#if 1 CloseDoor(DOOR_CLOSE_1); - /* + SetDoorState(DOOR_CLOSE_2); +#else CloseDoor(DOOR_CLOSE_ALL); - */ +#endif game_status = GAME_MODE_MAIN; DrawMainMenu(); }