From: Holger Schemel Date: Sat, 21 Feb 2004 16:57:12 +0000 (+0100) Subject: rnd-20040221-1-src X-Git-Tag: 3.1.0^2~69 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=7993378f9ae3ba83d8d420be8a7f5c81859e1750 rnd-20040221-1-src * "spring push bug" reintroduced as configurable element property --- diff --git a/ChangeLog b/ChangeLog index e2a771a2..da30093f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2004-02-21 + * "spring push bug" reintroduced as configurable element property + 2004-02-17 * fixed bug which caused all CE change pages to be ignored which had the same change event, but used a different element side diff --git a/src/conftime.h b/src/conftime.h index 693dd203..8b877d77 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2004-02-18 20:22]" +#define COMPILE_DATE_STRING "[2004-02-21 13:33]" diff --git a/src/editor.c b/src/editor.c index 9cd163a5..4a96432c 100644 --- a/src/editor.c +++ b/src/editor.c @@ -109,9 +109,9 @@ #define ED_SETTINGS_YOFFSET (3 * MINI_TILEY / 2) #define ED_SETTINGS_XPOS(n) (ED_SETTINGS_XSTART + \ - n * ED_SETTINGS_XOFFSET) + (n) * ED_SETTINGS_XOFFSET) #define ED_SETTINGS_YPOS(n) (ED_SETTINGS_YSTART + \ - n * ED_SETTINGS_YOFFSET) + (n) * ED_SETTINGS_YOFFSET) #define ED_SETTINGS1_YPOS MINI_TILEY #define ED_SETTINGS2_XPOS MINI_TILEX @@ -121,9 +121,9 @@ #define ED_COUNTER_YSTART (ED_SETTINGS1_YPOS + 2 * TILEY) #define ED_COUNTER_YDISTANCE (3 * MINI_TILEY) #define ED_COUNTER_YPOS(n) (ED_COUNTER_YSTART + \ - n * ED_COUNTER_YDISTANCE) + (n) * ED_COUNTER_YDISTANCE) #define ED_COUNTER2_YPOS(n) (ED_COUNTER_YSTART + \ - n * ED_COUNTER_YDISTANCE - 2) + (n) * ED_COUNTER_YDISTANCE - 2) /* values for element content drawing areas */ /* amoeba content */ @@ -133,9 +133,9 @@ /* yamyam content */ #define ED_AREA_YAMYAM_CONTENT_XPOS(n) (2 * MINI_TILEX + \ - 5 * (n % 4) * MINI_TILEX) -#define ED_AREA_YAMYAM_CONTENT_YPOS(n) (22 * MINI_TILEY + \ - 6 * (n / 4) * MINI_TILEY) + 5 * ((n) % 4) * MINI_TILEX) +#define ED_AREA_YAMYAM_CONTENT_YPOS(n) (17 * MINI_TILEY + \ + 6 * ((n) / 4) * MINI_TILEY) /* custom change target */ #define ED_AREA_ELEM_CONTENT2_YPOS (ED_SETTINGS_YPOS(1) + \ @@ -505,32 +505,34 @@ #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_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) +#define GADGET_ID_USE_SPRING_BUG (GADGET_ID_CHECKBUTTON_FIRST + 7) +#define GADGET_ID_BLOCK_LAST_FIELD (GADGET_ID_CHECKBUTTON_FIRST + 8) +#define GADGET_ID_SP_BLOCK_LAST_FIELD (GADGET_ID_CHECKBUTTON_FIRST + 9) +#define GADGET_ID_CAN_MOVE_INTO_ACID (GADGET_ID_CHECKBUTTON_FIRST + 10) +#define GADGET_ID_CUSTOM_EXPLODE_RESULT (GADGET_ID_CHECKBUTTON_FIRST + 11) +#define GADGET_ID_CUSTOM_EXPLODE_FIRE (GADGET_ID_CHECKBUTTON_FIRST + 12) +#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 13) +#define GADGET_ID_CUSTOM_EXPLODE_IMPACT (GADGET_ID_CHECKBUTTON_FIRST + 14) +#define GADGET_ID_CUSTOM_WALK_TO_OBJECT (GADGET_ID_CHECKBUTTON_FIRST + 15) +#define GADGET_ID_CUSTOM_DEADLY (GADGET_ID_CHECKBUTTON_FIRST + 16) +#define GADGET_ID_CUSTOM_CAN_MOVE (GADGET_ID_CHECKBUTTON_FIRST + 17) +#define GADGET_ID_CUSTOM_CAN_FALL (GADGET_ID_CHECKBUTTON_FIRST + 18) +#define GADGET_ID_CUSTOM_CAN_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 19) +#define GADGET_ID_CUSTOM_SLIPPERY (GADGET_ID_CHECKBUTTON_FIRST + 20) +#define GADGET_ID_CUSTOM_ACCESSIBLE (GADGET_ID_CHECKBUTTON_FIRST + 21) +#define GADGET_ID_CUSTOM_USE_GRAPHIC (GADGET_ID_CHECKBUTTON_FIRST + 22) +#define GADGET_ID_CUSTOM_USE_TEMPLATE (GADGET_ID_CHECKBUTTON_FIRST + 23) +#define GADGET_ID_CUSTOM_CAN_CHANGE (GADGET_ID_CHECKBUTTON_FIRST + 24) +#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 25) +#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 26) +#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 27) +#define GADGET_ID_CHANGE_USE_RANDOM (GADGET_ID_CHECKBUTTON_FIRST + 28) +#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 29) +#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 30) +#define GADGET_ID_CHANGE_BY_OTHER_ACT (GADGET_ID_CHECKBUTTON_FIRST + 31) /* gadgets for buttons in element list */ -#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 30) +#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 32) #define GADGET_ID_ELEMENTLIST_LAST (GADGET_ID_ELEMENTLIST_FIRST + \ ED_NUM_ELEMENTLIST_BUTTONS - 1) @@ -689,31 +691,33 @@ #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_BLOCK_LAST_FIELD 5 -#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD 6 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 7 -#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 8 -#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 9 -#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 10 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 11 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 12 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 13 -#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 14 -#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 15 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT 16 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 17 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 18 -#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 19 -#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 20 -#define ED_CHECKBUTTON_ID_CHANGE_DELAY 21 -#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 22 -#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 23 -#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 24 -#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 25 -#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 26 -#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 27 - -#define ED_NUM_CHECKBUTTONS 28 +#define ED_CHECKBUTTON_ID_USE_SPRING_BUG 5 +#define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD 6 +#define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD 7 +#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID 8 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 9 +#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 10 +#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE 11 +#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT 12 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE 13 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL 14 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH 15 +#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY 16 +#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY 17 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT 18 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE 19 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 20 +#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT 21 +#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 22 +#define ED_CHECKBUTTON_ID_CHANGE_DELAY 23 +#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 24 +#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT 25 +#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 26 +#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 27 +#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 28 +#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM 29 + +#define ED_NUM_CHECKBUTTONS 30 #define ED_CHECKBUTTON_ID_LEVEL_FIRST ED_CHECKBUTTON_ID_DOUBLE_SPEED #define ED_CHECKBUTTON_ID_LEVEL_LAST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED @@ -943,7 +947,7 @@ static struct NULL, NULL, NULL }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(6), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(3), MIN_ELEMENT_CONTENTS, MAX_ELEMENT_CONTENTS, GADGET_ID_ELEMENT_CONTENT_DOWN, GADGET_ID_ELEMENT_CONTENT_UP, GADGET_ID_ELEMENT_CONTENT_TEXT, GADGET_ID_NONE, @@ -1799,6 +1803,13 @@ static struct NULL, "slip down from certain flat walls","use EM style slipping behaviour" }, + { + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0), + GADGET_ID_USE_SPRING_BUG, GADGET_ID_NONE, + &level.use_spring_bug, + NULL, + "use spring pushing bug", "use odd spring pushing behaviour" + }, { ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0), GADGET_ID_BLOCK_LAST_FIELD, GADGET_ID_NONE, @@ -1807,12 +1818,19 @@ static struct "block last field when moving", "player blocks last field when moving" }, { - ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(4), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0), GADGET_ID_SP_BLOCK_LAST_FIELD, GADGET_ID_NONE, &level.sp_block_last_field, NULL, "block last field when moving", "player blocks last field when moving" }, + { + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(0), + GADGET_ID_CAN_MOVE_INTO_ACID, GADGET_ID_NONE, + &custom_element_properties[EP_CAN_MOVE_INTO_ACID], + NULL, + "can move into acid", "element can move into acid pool" + }, /* ---------- element settings: configure 1 (custom elements) ----------- */ @@ -2143,7 +2161,7 @@ static void DrawDrawingWindow(); static void DrawLevelInfoWindow(); static void DrawPropertiesWindow(); static void UpdateCustomElementGraphicGadgets(); -static boolean checkPropertiesConfig(); +static boolean checkPropertiesConfig(int); static void CopyLevelToUndoBuffer(int); static void HandleDrawingAreas(struct GadgetInfo *); static void HandleCounterButtons(struct GadgetInfo *); @@ -5073,10 +5091,14 @@ static void MapCheckbuttonGadget(int id) int x_right = gi->x + gi->width + xoffset_right; int y = gi->y + yoffset; - /* special case needed for "sticky" gadget */ - ModifyGadget(gi, GDI_CHECKED, *checkbutton_info[id].value, - GDI_Y, SY + checkbutton_info[id].y, GDI_END); - y = gi->y + yoffset; + /* special case needed for "stickybutton" and "can move into acid" gadgets */ + if (id == ED_CHECKBUTTON_ID_STICK_ELEMENT || + id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID) + { + ModifyGadget(gi, GDI_CHECKED, *checkbutton_info[id].value, + GDI_Y, SY + checkbutton_info[id].y, GDI_END); + y = gi->y + yoffset; + } if (checkbutton_info[id].text_left) DrawText(x_left, y, checkbutton_info[id].text_left, FONT_TEXT_1); @@ -5640,12 +5662,26 @@ static void CopyGroupElementPropertiesToEditor(int element) custom_element = element_info[element]; /* needed for description */ } +static void CopyClassicElementPropertiesToEditor(int element) +{ + if (COULD_MOVE_INTO_ACID(element)) + { + int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID); + + if (bit_nr > -1) + custom_element_properties[EP_CAN_MOVE_INTO_ACID] = + ((level.can_move_into_acid & (1 << bit_nr)) != 0); + } +} + static void CopyElementPropertiesToEditor(int element) { if (IS_CUSTOM_ELEMENT(element)) CopyCustomElementPropertiesToEditor(element); else if (IS_GROUP_ELEMENT(element)) CopyGroupElementPropertiesToEditor(element); + else + CopyClassicElementPropertiesToEditor(element); } static void CopyCustomElementPropertiesToGame(int element) @@ -5794,12 +5830,30 @@ static void CopyGroupElementPropertiesToGame(int element) element_info[element].modified_settings = TRUE; } +static void CopyClassicElementPropertiesToGame(int element) +{ + if (COULD_MOVE_INTO_ACID(element)) + { + int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID); + + if (bit_nr > -1) + { + level.can_move_into_acid &= ~(1 << bit_nr); + + if (custom_element_properties[EP_CAN_MOVE_INTO_ACID]) + level.can_move_into_acid |= (1 << bit_nr); + } + } +} + static void CopyElementPropertiesToGame(int element) { if (IS_CUSTOM_ELEMENT(element)) CopyCustomElementPropertiesToGame(element); else if (IS_GROUP_ELEMENT(element)) CopyGroupElementPropertiesToGame(element); + else + CopyClassicElementPropertiesToGame(element); } void DrawLevelEd() @@ -6564,19 +6618,23 @@ static struct { EL_DIAMOND, &level.score[SC_DIAMOND], TEXT_COLLECTING }, { EL_CRYSTAL, &level.score[SC_CRYSTAL], TEXT_COLLECTING }, { EL_PEARL, &level.score[SC_PEARL], TEXT_COLLECTING }, + { EL_BUG, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BUG_RIGHT, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BUG_UP, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BUG_LEFT, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BUG_DOWN, &level.score[SC_BUG], TEXT_SMASHING }, + { EL_BD_BUTTERFLY, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BD_BUTTERFLY_RIGHT,&level.score[SC_BUG], TEXT_SMASHING }, { EL_BD_BUTTERFLY_UP, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BD_BUTTERFLY_LEFT, &level.score[SC_BUG], TEXT_SMASHING }, { EL_BD_BUTTERFLY_DOWN, &level.score[SC_BUG], TEXT_SMASHING }, { EL_SP_ELECTRON, &level.score[SC_BUG], TEXT_SMASHING }, + { EL_SPACESHIP, &level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_SPACESHIP_RIGHT, &level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_SPACESHIP_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_SPACESHIP_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_SPACESHIP_DOWN, &level.score[SC_SPACESHIP], TEXT_SMASHING }, + { EL_BD_FIREFLY, &level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_BD_FIREFLY_RIGHT,&level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_BD_FIREFLY_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING }, { EL_BD_FIREFLY_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING }, @@ -6585,6 +6643,7 @@ static struct { EL_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING }, { EL_DARK_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING }, { EL_ROBOT, &level.score[SC_ROBOT], TEXT_SMASHING }, + { EL_PACMAN, &level.score[SC_PACMAN], TEXT_SMASHING }, { EL_PACMAN_RIGHT, &level.score[SC_PACMAN], TEXT_SMASHING }, { EL_PACMAN_UP, &level.score[SC_PACMAN], TEXT_SMASHING }, { EL_PACMAN_LEFT, &level.score[SC_PACMAN], TEXT_SMASHING }, @@ -6621,20 +6680,22 @@ static struct { -1, NULL, NULL } }; -static boolean checkPropertiesConfig() +static boolean checkPropertiesConfig(int element) { int i; - if (IS_GEM(properties_element) || - IS_CUSTOM_ELEMENT(properties_element) || - IS_GROUP_ELEMENT(properties_element) || - IS_ENVELOPE(properties_element) || - ELEM_IS_PLAYER(properties_element) || - HAS_CONTENT(properties_element)) + if (IS_GEM(element) || + IS_CUSTOM_ELEMENT(element) || + IS_GROUP_ELEMENT(element) || + IS_ENVELOPE(element) || + ELEM_IS_PLAYER(element) || + HAS_CONTENT(element) || + COULD_MOVE_INTO_ACID(element) || + element == EL_SPRING) return TRUE; else for (i = 0; elements_with_counter[i].element != -1; i++) - if (elements_with_counter[i].element == properties_element) + if (elements_with_counter[i].element == element) return TRUE; return FALSE; @@ -6644,7 +6705,7 @@ static void DrawPropertiesConfig() { int i; - if (!checkPropertiesConfig()) + if (!checkPropertiesConfig(properties_element)) { PrintInfoText("No configuration options available.", FONT_TEXT_1, 0); @@ -6658,10 +6719,9 @@ static void DrawPropertiesConfig() { int counter_id = ED_COUNTER_ID_ELEMENT_SCORE; - if (HAS_CONTENT(properties_element)) /* needs stickybutton */ - counterbutton_info[counter_id].y = ED_SETTINGS_YPOS(1); - else - counterbutton_info[counter_id].y = ED_SETTINGS_YPOS(0); + counterbutton_info[counter_id].y = + ED_SETTINGS_YPOS((HAS_CONTENT(properties_element) ? 1 : 0) + + (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0)); counterbutton_info[counter_id].value = elements_with_counter[i].value; counterbutton_info[counter_id].text_right= elements_with_counter[i].text; @@ -6683,14 +6743,26 @@ static void DrawPropertiesConfig() DrawElementContentAreas(); } - if (IS_GEM(properties_element)) - MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS); - if (ELEM_IS_PLAYER(properties_element)) MapCheckbuttonGadget(properties_element == EL_SP_MURPHY ? ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD : ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD); + if (IS_GEM(properties_element)) + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS); + + if (COULD_MOVE_INTO_ACID(properties_element) && + !IS_CUSTOM_ELEMENT(properties_element)) + { + checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].y = + ED_SETTINGS_YPOS(HAS_CONTENT(properties_element) ? 1 : 0); + + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID); + } + + if (properties_element == EL_SPRING) + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_SPRING_BUG); + if (IS_ENVELOPE(properties_element)) { int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE; @@ -8137,11 +8209,12 @@ static void HandleCheckbuttons(struct GadgetInfo *gi) *checkbutton_info[type_id].value ^= TRUE; - if (((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST && - type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) || - (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST && - type_id <= ED_CHECKBUTTON_ID_CHANGE_LAST)) && - type_id != ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE) + if (type_id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID || + (((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST && + type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) || + (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST && + type_id <= ED_CHECKBUTTON_ID_CHANGE_LAST)) && + type_id != ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE)) { CopyElementPropertiesToGame(properties_element); } diff --git a/src/files.c b/src/files.c index 356d8a4b..52116aa9 100644 --- a/src/files.c +++ b/src/files.c @@ -29,7 +29,7 @@ #define CHUNK_SIZE_NONE -1 /* do not write chunk size */ #define FILE_VERS_CHUNK_SIZE 8 /* size of file version chunk */ #define LEVEL_HEADER_SIZE 80 /* size of level file header */ -#define LEVEL_HEADER_UNUSED 11 /* unused level header bytes */ +#define LEVEL_HEADER_UNUSED 10 /* unused level header bytes */ #define LEVEL_CHUNK_CNT2_SIZE 160 /* size of level CNT2 chunk */ #define LEVEL_CHUNK_CNT2_UNUSED 11 /* unused CNT2 chunk bytes */ #define LEVEL_CHUNK_CNT3_HEADER 16 /* size of level CNT3 header */ @@ -121,6 +121,14 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change) change->post_change_function = NULL; } +static void setMoveIntoAcid(struct LevelInfo *level, int element) +{ + int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID); + + if (bit_nr > -1) + level->can_move_into_acid |= (1 << bit_nr); +} + static void setLevelInfoToDefaults(struct LevelInfo *level) { int i, j, x, y; @@ -141,17 +149,24 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->time = 100; level->gems_needed = 0; + level->amoeba_speed = 10; + level->time_magic_wall = 10; level->time_wheel = 10; level->time_light = 10; level->time_timegate = 10; + level->amoeba_content = EL_DIAMOND; + level->double_speed = FALSE; level->initial_gravity = FALSE; level->em_slippery_gems = FALSE; level->block_last_field = FALSE; level->sp_block_last_field = TRUE; + level->use_spring_bug = FALSE; + + level->can_move_into_acid = ~0; /* everything can move into acid */ level->use_custom_template = FALSE; @@ -639,6 +654,8 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level) level->block_last_field = (getFile8Bit(file) == 1 ? TRUE : FALSE); level->sp_block_last_field = (getFile8Bit(file) == 1 ? TRUE : FALSE); + level->use_spring_bug = (getFile8Bit(file) == 1 ? TRUE : FALSE); + ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED); return chunk_size; @@ -2021,6 +2038,19 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) /* Default behaviour for EM style gems was "slippery" only in 2.0.1 */ if (level->game_version == VERSION_IDENT(2,0,1,0)) level->em_slippery_gems = TRUE; + + if (level->game_version < VERSION_IDENT(2,2,0,0)) + level->use_spring_bug = TRUE; + + if (level->game_version < VERSION_IDENT(3,0,9,0)) + { + level->can_move_into_acid = 0; /* nothing can move into acid */ + + setMoveIntoAcid(level, EL_ROBOT); + setMoveIntoAcid(level, EL_SATELLITE); + setMoveIntoAcid(level, EL_PENGUIN); + setMoveIntoAcid(level, EL_BALLOON); + } } else { @@ -2287,6 +2317,8 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) putFile8Bit(file, (level->block_last_field ? 1 : 0)); putFile8Bit(file, (level->sp_block_last_field ? 1 : 0)); + putFile8Bit(file, (level->use_spring_bug ? 1 : 0)); + WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED); } @@ -2814,6 +2846,7 @@ void DumpLevel(struct LevelInfo *level) printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no")); printf("Player blocks last field: %s\n", (level->block_last_field ? "yes" : "no")); printf("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no")); + printf("use spring bug: %s\n", (level->use_spring_bug ? "yes" : "no")); printf_line("-", 79); } diff --git a/src/game.c b/src/game.c index c81c8603..5da67f0d 100644 --- a/src/game.c +++ b/src/game.c @@ -862,6 +862,36 @@ static void InitField(int x, int y, boolean init_game) } } +static inline void InitField_WithBug1(int x, int y, boolean init_game) +{ + InitField(x, y, init_game); + + /* not needed to call InitMovDir() -- already done by InitField()! */ + if (game.engine_version < VERSION_IDENT(3,0,9,0) && + CAN_MOVE(Feld[x][y])) + InitMovDir(x, y); +} + +static inline void InitField_WithBug2(int x, int y, boolean init_game) +{ + int old_element = Feld[x][y]; + + InitField(x, y, init_game); + + /* not needed to call InitMovDir() -- already done by InitField()! */ + if (game.engine_version < VERSION_IDENT(3,0,9,0) && + CAN_MOVE(old_element) && + (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN)) + InitMovDir(x, y); + + /* this case is in fact a combination of not less than three bugs: + first, it calls InitMovDir() for elements that can move, although this is + already done by InitField(); then, it checks the element that was at this + field _before_ the call to InitField() (which can change it) + + */ +} + void DrawGameDoorValues() { int i, j; @@ -2866,11 +2896,21 @@ void Explode(int ex, int ey, int phase, int mode) ChangeDelay[x][y] = 0; ChangePage[x][y] = -1; +#if 1 + InitField_WithBug2(x, y, FALSE); +#else InitField(x, y, FALSE); #if 1 /* !!! not needed !!! */ +#if 1 + if (game.engine_version < VERSION_IDENT(3,0,9,0) && + CAN_MOVE(Feld[x][y]) && Feld[x][y] != EL_MOLE) + InitMovDir(x, y); +#else if (CAN_MOVE(element)) InitMovDir(x, y); +#endif +#endif #endif DrawLevelField(x, y); @@ -4347,7 +4387,9 @@ static boolean JustBeingPushed(int x, int y) void StartMoving(int x, int y) { +#if 0 boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0,0)); +#endif boolean started_moving = FALSE; /* some elements can fall _and_ move */ int element = Feld[x][y]; @@ -4544,7 +4586,7 @@ void StartMoving(int x, int y) Impact(x, y); } - else if (IS_FREE(x, y + 1) && element == EL_SPRING && use_spring_bug) + else if (IS_FREE(x, y + 1) && element == EL_SPRING && level.use_spring_bug) { if (MovDir[x][y] == MV_NO_MOVING) { @@ -5228,22 +5270,22 @@ void ContinueMoving(int x, int y) int nextx = newx + dx, nexty = newy + dy; #endif #if 1 - boolean pushed = (Pushed[x][y] && IS_PLAYER(x, y)); + boolean pushed_by_player = (Pushed[x][y] && IS_PLAYER(x, y)); boolean pushed_by_conveyor = (Pushed[x][y] && !IS_PLAYER(x, y)); #else - boolean pushed = Pushed[x][y]; + boolean pushed_by_player = Pushed[x][y]; #endif MovPos[x][y] += getElementMoveStepsize(x, y); #if 0 - if (pushed && IS_PLAYER(x, y)) + if (pushed_by_player && IS_PLAYER(x, y)) { /* special case: moving object pushed by player */ MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos)); } #else - if (pushed) /* special case: moving object pushed by player */ + if (pushed_by_player) /* special case: moving object pushed by player */ MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos)); #endif @@ -5397,7 +5439,7 @@ void ContinueMoving(int x, int y) Stop[newx][newy] = TRUE; /* ignore this element until the next frame */ /* prevent pushed element from moving on in pushed direction */ - if (pushed && CAN_MOVE(element) && + if (pushed_by_player && CAN_MOVE(element) && element_info[element].move_pattern & MV_ANY_DIRECTION && !(element_info[element].move_pattern & direction)) TurnRound(newx, newy); @@ -5409,7 +5451,7 @@ void ContinueMoving(int x, int y) MovDir[newx][newy] = 0; #endif - if (!pushed) /* special case: moving object pushed by player */ + if (!pushed_by_player) { WasJustMoving[newx][newy] = 3; @@ -6439,9 +6481,13 @@ static void ChangeElementNowExt(int x, int y, int target_element) if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS) MovDir[x][y] = previous_move_direction; +#if 1 + InitField_WithBug1(x, y, FALSE); +#else InitField(x, y, FALSE); if (CAN_MOVE(Feld[x][y])) InitMovDir(x, y); +#endif DrawLevelField(x, y); @@ -7239,7 +7285,19 @@ void GameActions() #endif #if 1 + /* for downwards compatibility, the following code emulates a fixed bug that + occured when pushing elements (causing elements that just made their last + pushing step to already (if possible) make their first falling step in the + same game frame, which is bad); this code is also needed to use the famous + "spring push bug" which is used in older levels and might be wanted to be + used also in newer levels, but in this case the buggy pushing code is only + affecting the "spring" element and no other elements */ + +#if 1 + if (game.engine_version < VERSION_IDENT(2,2,0,7) || level.use_spring_bug) +#else if (game.engine_version < VERSION_IDENT(2,2,0,7)) +#endif { for (i = 0; i < MAX_PLAYERS; i++) { @@ -7247,8 +7305,15 @@ void GameActions() int x = player->jx; int y = player->jy; +#if 1 + if (player->active && player->is_pushing && player->is_moving && + IS_MOVING(x, y) && + (game.engine_version < VERSION_IDENT(2,2,0,7) || + Feld[x][y] == EL_SPRING)) +#else if (player->active && player->is_pushing && player->is_moving && IS_MOVING(x, y)) +#endif { ContinueMoving(x, y); @@ -8972,7 +9037,9 @@ int DigField(struct PlayerInfo *player, CH_SIDE_BOTTOM, /* moving up */ CH_SIDE_TOP, /* moving down */ }; +#if 0 boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0,0)); +#endif int jx = oldx, jy = oldy; int dx = x - jx, dy = y - jy; int nextx = x + dx, nexty = y + dy; @@ -9386,7 +9453,7 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; if (CAN_FALL(element) && IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1) && - !(element == EL_SPRING && use_spring_bug)) + !(element == EL_SPRING && level.use_spring_bug)) return MF_NO_ACTION; #if 1 @@ -9803,9 +9870,13 @@ boolean DropElement(struct PlayerInfo *player) if (Feld[jx][jy] == new_element) /* uninitialized unless CE change */ { +#if 1 + InitField_WithBug1(jx, jy, FALSE); +#else InitField(jx, jy, FALSE); if (CAN_MOVE(Feld[jx][jy])) InitMovDir(jx, jy); +#endif } new_element = Feld[jx][jy]; diff --git a/src/init.c b/src/init.c index a7bb5979..e0d97cca 100644 --- a/src/init.c +++ b/src/init.c @@ -2935,6 +2935,13 @@ void InitElementPropertiesStatic() EL_PACMAN_LEFT, EL_PACMAN_RIGHT, EL_PACMAN_UP, EL_PACMAN_DOWN }, +#if 1 + { + EL_MOLE, + EL_MOLE_LEFT, EL_MOLE_RIGHT, + EL_MOLE_UP, EL_MOLE_DOWN + }, +#endif { -1, -1, -1, -1, -1 @@ -3021,6 +3028,7 @@ void InitElementPropertiesEngine(int engine_version) EP_ACTIVE_BOMB, EP_ACCESSIBLE, + -1 }; @@ -3162,6 +3170,9 @@ void InitElementPropertiesEngine(int engine_version) SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) || i == EL_BLACK_ORB)); + /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */ + SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (CAN_MOVE(i) && i != EL_SPRING)); + /* ---------- SP_PORT -------------------------------------------------- */ SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) && IS_PASSABLE_INSIDE(i))); @@ -3273,6 +3284,69 @@ void InitElementPropertiesEngine(int engine_version) InitElementGraphicInfo(); } +int get_special_property_bit(int element, int base_property_bit) +{ + static struct + { + int element; + int bit_nr; + } pb_can_move_into_acid[] = + { + { EL_BUG, 0 }, + { EL_BUG_LEFT, 0 }, + { EL_BUG_RIGHT, 0 }, + { EL_BUG_UP, 0 }, + { EL_BUG_DOWN, 0 }, + { EL_SPACESHIP, 0 }, + { EL_SPACESHIP_LEFT, 0 }, + { EL_SPACESHIP_RIGHT, 0 }, + { EL_SPACESHIP_UP, 0 }, + { EL_SPACESHIP_DOWN, 0 }, + { EL_BD_BUTTERFLY, 1 }, + { EL_BD_BUTTERFLY_LEFT, 1 }, + { EL_BD_BUTTERFLY_RIGHT, 1 }, + { EL_BD_BUTTERFLY_UP, 1 }, + { EL_BD_BUTTERFLY_DOWN, 1 }, + { EL_BD_FIREFLY, 1 }, + { EL_BD_FIREFLY_LEFT, 1 }, + { EL_BD_FIREFLY_RIGHT, 1 }, + { EL_BD_FIREFLY_UP, 1 }, + { EL_BD_FIREFLY_DOWN, 1 }, + { EL_YAMYAM, 2 }, + { EL_DARK_YAMYAM, 2 }, + { EL_ROBOT, 3 }, + { EL_PACMAN, 4 }, + { EL_PACMAN_LEFT, 4 }, + { EL_PACMAN_RIGHT, 4 }, + { EL_PACMAN_UP, 4 }, + { EL_PACMAN_DOWN, 4 }, + { EL_MOLE, 4 }, + { EL_MOLE_LEFT, 4 }, + { EL_MOLE_RIGHT, 4 }, + { EL_MOLE_UP, 4 }, + { EL_MOLE_DOWN, 4 }, + { EL_PENGUIN, 5 }, + { EL_PIG, 6 }, + { EL_DRAGON, 6 }, + { EL_SATELLITE, 7 }, + { EL_SP_SNIKSNAK, 8 }, + { EL_SP_ELECTRON, 8 }, + { EL_BALLOON, 9 }, + + { -1, 0 }, + }; + int i; + + if (base_property_bit != EP_CAN_MOVE_INTO_ACID) + return -1; + + for (i = 0; pb_can_move_into_acid[i].element != -1; i++) + if (pb_can_move_into_acid[i].element == element) + return pb_can_move_into_acid[i].bit_nr; + + return -1; +} + static void InitGlobal() { global.autoplay_leveldir = NULL; diff --git a/src/init.h b/src/init.h index 79880f11..7440123f 100644 --- a/src/init.h +++ b/src/init.h @@ -18,6 +18,7 @@ void InitElementPropertiesStatic(void); void InitElementPropertiesEngine(int); +int get_special_property_bit(int, int); void ReloadCustomArtwork(int); diff --git a/src/main.c b/src/main.c index 5e5e5f67..5729b931 100644 --- a/src/main.c +++ b/src/main.c @@ -658,7 +658,7 @@ struct ElementInfo element_info[MAX_NUM_ELEMENTS + 1] = { "black_orb", "black_orb", - "bomb" + "black orb bomb" }, { "amoeba_to_diamond", diff --git a/src/main.h b/src/main.h index d87087a2..3036ea42 100644 --- a/src/main.h +++ b/src/main.h @@ -88,6 +88,7 @@ #define EP_PUSHABLE 24 #define EP_CAN_EXPLODE_DYNA 25 #define EP_PROTECTED 26 +#define EP_CAN_MOVE_INTO_ACID 27 /* values for pre-defined properties */ #define EP_PLAYER 32 @@ -139,13 +140,14 @@ #define EP_SP_PORT 72 #define EP_CAN_EXPLODE_BY_DRAGONFIRE 73 #define EP_CAN_EXPLODE_BY_EXPLOSION 74 +#define EP_COULD_MOVE_INTO_ACID 75 /* values for internal purpose only (level editor) */ -#define EP_EXPLODE_RESULT 75 -#define EP_WALK_TO_OBJECT 76 -#define EP_DEADLY 77 +#define EP_EXPLODE_RESULT 76 +#define EP_WALK_TO_OBJECT 77 +#define EP_DEADLY 78 -#define NUM_ELEMENT_PROPERTIES 78 +#define NUM_ELEMENT_PROPERTIES 79 #define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32) #define EP_BITFIELD_BASE 0 @@ -310,6 +312,7 @@ #define IS_PUSHABLE(e) HAS_PROPERTY(e, EP_PUSHABLE) #define CAN_EXPLODE_DYNA(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_DYNA) #define IS_PROTECTED(e) HAS_PROPERTY(e, EP_PROTECTED) +#define CAN_MOVE_INTO_ACID(e) HAS_PROPERTY(e, EP_CAN_MOVE_INTO_ACID) /* macros for special configurable properties */ #define IS_EM_SLIPPERY_WALL(e) HAS_PROPERTY(e, EP_EM_SLIPPERY_WALL) @@ -363,6 +366,7 @@ HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_DRAGONFIRE) #define CAN_EXPLODE_BY_EXPLOSION(e) \ HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_EXPLOSION) +#define COULD_MOVE_INTO_ACID(e) HAS_PROPERTY(e, EP_COULD_MOVE_INTO_ACID) /* special macros used in game engine */ #define IS_CUSTOM_ELEMENT(e) ((e) >= EL_CUSTOM_START && \ @@ -1376,26 +1380,37 @@ struct LevelInfo boolean encoding_16bit_amoeba; /* amoeba contains 16-bit elements */ int fieldx, fieldy; + int time; int gems_needed; + char name[MAX_LEVEL_NAME_LEN + 1]; char author[MAX_LEVEL_AUTHOR_LEN + 1]; + char envelope_text[4][MAX_ENVELOPE_TEXT_LEN + 1]; int envelope_xsize[4], envelope_ysize[4]; + int score[LEVEL_SCORE_ELEMENTS]; + int yamyam_content[MAX_ELEMENT_CONTENTS][3][3]; int num_yamyam_contents; + int amoeba_speed; int amoeba_content; + int time_magic_wall; int time_wheel; int time_light; int time_timegate; + + int can_move_into_acid; /* bits indicate property for element groups */ + boolean double_speed; boolean initial_gravity; boolean em_slippery_gems; /* EM style "gems slip from wall" behaviour */ boolean block_last_field; /* player blocks previous field while moving */ boolean sp_block_last_field; /* player blocks previous field while moving */ + boolean use_spring_bug; /* for compatibility with old levels */ short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY];