GADGET_ID_SB_OBJECTS_NEEDED,
GADGET_ID_AUTO_EXIT_SOKOBAN,
GADGET_ID_SOLVED_BY_ONE_PLAYER,
+ GADGET_ID_FINISH_DIG_COLLECT,
GADGET_ID_CONTINUOUS_SNAPPING,
GADGET_ID_BLOCK_SNAP_FIELD,
GADGET_ID_BLOCK_LAST_FIELD,
ED_CHECKBUTTON_ID_SB_OBJECTS_NEEDED,
ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN,
ED_CHECKBUTTON_ID_SOLVED_BY_ONE_PLAYER,
+ ED_CHECKBUTTON_ID_FINISH_DIG_COLLECT,
ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING,
ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD,
ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD,
NULL, NULL,
"only one player must enter exit", "level solved by first player in exit"
},
+ {
+ ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(3),
+ GADGET_ID_FINISH_DIG_COLLECT, GADGET_ID_NONE,
+ &level.finish_dig_collect,
+ NULL, NULL,
+ "CE action on finished dig/collect", "only finished dig/collect triggers CE"
+ },
{
ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(9),
GADGET_ID_CONTINUOUS_SNAPPING, GADGET_ID_NONE,
// draw checkbutton gadgets
MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_FINISH_DIG_COLLECT);
// draw counter gadgets
MapCounterButtons(ED_COUNTER_ID_INVENTORY_SIZE);
static int getInvisibleActiveFromInvisibleElement(int);
static int getInvisibleFromInvisibleActiveElement(int);
+static void TestFieldAfterSnapping(int, int, int, int, int);
+
static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
// for detection of endless loops, caused by custom element programming
player->shield_normal_time_left = 0;
player->shield_deadly_time_left = 0;
+ player->last_removed_element = EL_UNDEFINED;
+
player->inventory_infinite_element = EL_UNDEFINED;
player->inventory_size = 0;
MovDelay[x][y]--;
if (MovDelay[x][y] <= 0)
{
+ int element = Store[x][y];
+ int move_direction = MovDir[x][y];
+ int player_index_bit = Store2[x][y];
+
+ Store[x][y] = 0;
+ Store2[x][y] = 0;
+
RemoveField(x, y);
TEST_DrawLevelField(x, y);
- TestIfElementTouchesCustomElement(x, y); // for empty space
+ TestFieldAfterSnapping(x, y, element, move_direction, player_index_bit);
}
}
if (!player->is_pushing)
TestIfElementTouchesCustomElement(jx, jy); // for empty space
+ if (level.finish_dig_collect &&
+ (player->is_digging || player->is_collecting))
+ {
+ int last_element = player->last_removed_element;
+ int move_direction = player->MovDir;
+ int enter_side = MV_DIR_OPPOSITE(move_direction);
+ int change_event = (player->is_digging ? CE_PLAYER_DIGS_X :
+ CE_PLAYER_COLLECTS_X);
+
+ CheckTriggeredElementChangeByPlayer(jx, jy, last_element, change_event,
+ player->index_bit, enter_side);
+
+ player->last_removed_element = EL_UNDEFINED;
+ }
+
if (!player->active)
RemovePlayer(player);
}
game.players_still_needed--;
}
-static void setFieldForSnapping(int x, int y, int element, int direction)
+static void SetFieldForSnapping(int x, int y, int element, int direction,
+ int player_index_bit)
{
struct ElementInfo *ei = &element_info[element];
int direction_bit = MV_DIR_TO_BIT(direction);
Tile[x][y] = EL_ELEMENT_SNAPPING;
MovDelay[x][y] = MOVE_DELAY_NORMAL_SPEED + 1 - 1;
+ MovDir[x][y] = direction;
+ Store[x][y] = element;
+ Store2[x][y] = player_index_bit;
ResetGfxAnimation(x, y);
GfxFrame[x][y] = -1;
}
+static void TestFieldAfterSnapping(int x, int y, int element, int direction,
+ int player_index_bit)
+{
+ TestIfElementTouchesCustomElement(x, y); // for empty space
+
+ if (level.finish_dig_collect)
+ {
+ int dig_side = MV_DIR_OPPOSITE(direction);
+
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
+ player_index_bit, dig_side);
+ }
+}
+
/*
=============================================================================
checkDiagonalPushing()
PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
- CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X,
- player->index_bit, dig_side);
+ // use old behaviour for old levels (digging)
+ if (!level.finish_dig_collect)
+ {
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X,
+ player->index_bit, dig_side);
- // if digging triggered player relocation, finish digging tile
- if (mode == DF_DIG && (player->jx != jx || player->jy != jy))
- setFieldForSnapping(x, y, element, move_direction);
+ // if digging triggered player relocation, finish digging tile
+ if (mode == DF_DIG && (player->jx != jx || player->jy != jy))
+ SetFieldForSnapping(x, y, element, move_direction, player->index_bit);
+ }
if (mode == DF_SNAP)
{
if (level.block_snap_field)
- setFieldForSnapping(x, y, element, move_direction);
+ SetFieldForSnapping(x, y, element, move_direction, player->index_bit);
else
- TestIfElementTouchesCustomElement(x, y); // for empty space
+ TestFieldAfterSnapping(x, y, element, move_direction, player->index_bit);
- CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
- player->index_bit, dig_side);
+ // use old behaviour for old levels (snapping)
+ if (!level.finish_dig_collect)
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
+ player->index_bit, dig_side);
}
}
else if (player_can_move_or_snap && IS_COLLECTIBLE(element))
RaiseScoreElement(element);
PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING);
- if (is_player)
+ // use old behaviour for old levels (collecting)
+ if (!level.finish_dig_collect && is_player)
{
CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_COLLECTS_X,
player->index_bit, dig_side);
// if collecting triggered player relocation, finish collecting tile
if (mode == DF_DIG && (player->jx != jx || player->jy != jy))
- setFieldForSnapping(x, y, element, move_direction);
+ SetFieldForSnapping(x, y, element, move_direction, player->index_bit);
}
if (mode == DF_SNAP)
{
if (level.block_snap_field)
- setFieldForSnapping(x, y, element, move_direction);
+ SetFieldForSnapping(x, y, element, move_direction, player->index_bit);
else
- TestIfElementTouchesCustomElement(x, y); // for empty space
+ TestFieldAfterSnapping(x, y, element, move_direction, player->index_bit);
- CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
- player->index_bit, dig_side);
+ // use old behaviour for old levels (snapping)
+ if (!level.finish_dig_collect)
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
+ player->index_bit, dig_side);
}
}
else if (player_can_move_or_snap && IS_PUSHABLE(element))
{
player->is_collecting = !player->is_digging;
player->is_active = TRUE;
+
+ player->last_removed_element = element;
}
}