From ad67feea72c2db12d75bb34b27193eacc00bbaef Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Fri, 11 Jun 2021 17:01:50 +0200 Subject: [PATCH] changed how custom elements change to player if they are walkable Before this change, if a walkable CE changes to the player, the player is placed on the CE, which will be kept under the player (so it does not really change to the player, but just adds the player). This is probably not the expected behaviour when changing a CE to the player (but may make sense when using the "extended change target", placing the player on one of the surrounding elements if they are walkable). This change fixes this behaviour, so by default a CE that "changes to the player" is replaced by the player, and not just adds the player. However, a config option was added to the player element to explicitly request the previous behaviour (which is used by the "Zelda II" level set, for example). --- src/editor.c | 10 ++++++++++ src/files.c | 9 +++++++++ src/game.c | 4 ++++ src/main.h | 1 + 4 files changed, 24 insertions(+) diff --git a/src/editor.c b/src/editor.c index 1713f04d..9fb3157e 100644 --- a/src/editor.c +++ b/src/editor.c @@ -657,6 +657,7 @@ enum GADGET_ID_AUTO_EXIT_SOKOBAN, GADGET_ID_SOLVED_BY_ONE_PLAYER, GADGET_ID_FINISH_DIG_COLLECT, + GADGET_ID_KEEP_WALKABLE_CE, GADGET_ID_CONTINUOUS_SNAPPING, GADGET_ID_BLOCK_SNAP_FIELD, GADGET_ID_BLOCK_LAST_FIELD, @@ -967,6 +968,7 @@ enum ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN, ED_CHECKBUTTON_ID_SOLVED_BY_ONE_PLAYER, ED_CHECKBUTTON_ID_FINISH_DIG_COLLECT, + ED_CHECKBUTTON_ID_KEEP_WALKABLE_CE, ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING, ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD, ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD, @@ -3170,6 +3172,13 @@ static struct NULL, NULL, "CE action on finished dig/collect", "only finished dig/collect triggers CE" }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(4), + GADGET_ID_KEEP_WALKABLE_CE, GADGET_ID_NONE, + &level.keep_walkable_ce, + NULL, NULL, + "keep walkable CE changed to player", "keep CE changing to player if walkable" + }, { ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(9), GADGET_ID_CONTINUOUS_SNAPPING, GADGET_ID_NONE, @@ -10044,6 +10053,7 @@ static void DrawPropertiesConfig(void) // draw checkbutton gadgets MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_FINISH_DIG_COLLECT); + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_KEEP_WALKABLE_CE); // draw counter gadgets MapCounterButtons(ED_COUNTER_ID_INVENTORY_SIZE); diff --git a/src/files.c b/src/files.c index 83efc958..aaafe68a 100644 --- a/src/files.c +++ b/src/files.c @@ -327,6 +327,11 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] = TYPE_BOOLEAN, CONF_VALUE_8_BIT(16), &li.finish_dig_collect, TRUE }, + { + EL_PLAYER_1, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(17), + &li.keep_walkable_ce, FALSE + }, // (these values are different for each player) { @@ -6463,6 +6468,10 @@ static void LoadLevel_InitVersion(struct LevelInfo *level) // CE actions were triggered by unfinished digging/collecting up to 4.2.2.0 if (level->game_version <= VERSION_IDENT(4,2,2,0)) level->finish_dig_collect = FALSE; + + // CE changing to player was kept under the player if walkable up to 4.2.3.1 + if (level->game_version <= VERSION_IDENT(4,2,3,1)) + level->keep_walkable_ce = TRUE; } static void LoadLevel_InitStandardElements(struct LevelInfo *level) diff --git a/src/game.c b/src/game.c index be192e4f..3d99a113 100644 --- a/src/game.c +++ b/src/game.c @@ -10832,6 +10832,10 @@ static boolean ChangeElement(int x, int y, int element, int page) Store[x][y] = EL_EMPTY; } + // special case: element changes to player (and may be kept if walkable) + if (ELEM_IS_PLAYER(target_element) && !level.keep_walkable_ce) + CreateElementFromChange(x, y, EL_EMPTY); + CreateElementFromChange(x, y, target_element); PlayLevelSoundElementAction(x, y, element, ACTION_CHANGING); diff --git a/src/main.h b/src/main.h index 2c2125f4..a77d6eee 100644 --- a/src/main.h +++ b/src/main.h @@ -3213,6 +3213,7 @@ struct LevelInfo boolean auto_exit_sokoban; // automatically finish solved Sokoban levels boolean solved_by_one_player; // level is solved if one player enters exit boolean finish_dig_collect; // only finished dig/collect triggers ce action + boolean keep_walkable_ce; // keep walkable CE if it changes to the player boolean continuous_snapping; // repeated snapping without releasing key boolean block_snap_field; // snapping blocks field to show animation -- 2.34.1