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(9) + \
+#define ED_AREA_ELEM_CONTENT4a_YPOS (ED_SETTINGS_YPOS(10) + \
ED_GADGET_DISTANCE)
#define ED_AREA_ELEM_CONTENT4b_XPOS (29 * MINI_TILEX)
-#define ED_AREA_ELEM_CONTENT4b_YPOS (ED_SETTINGS_YPOS(9) + \
+#define ED_AREA_ELEM_CONTENT4b_YPOS (ED_SETTINGS_YPOS(10) + \
ED_GADGET_DISTANCE)
/* custom change trigger element */
#define ED_AREA_ELEM_CONTENT5_YPOS (ED_SETTINGS_YPOS(5) + \
#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_CUSTOM_ACCESS_PROTECTED (GADGET_ID_SELECTBOX_FIRST + 11)
-#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 12)
-#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 13)
-#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 14)
-#define GADGET_ID_CHANGE_SIDES (GADGET_ID_SELECTBOX_FIRST + 15)
-#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 16)
-#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 17)
-#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 18)
+#define GADGET_ID_CUSTOM_ACCESS_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 12)
+#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 13)
+#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 14)
+#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 15)
+#define GADGET_ID_CHANGE_SIDES (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 17)
+#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 18)
+#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 19)
/* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 19)
+#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 20)
#define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0)
#define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1)
#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE 0
#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER 1
#define ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED 2
-#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION 3
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 4
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 5
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 6
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 7
-#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 8
-#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 9
-#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 10
-#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 11
-#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 12
-#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 13
-#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 14
-#define ED_SELECTBOX_ID_CHANGE_SIDES 15
-#define ED_SELECTBOX_ID_CHANGE_POWER 16
-#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 17
-#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 18
-
-#define ED_NUM_SELECTBOX 19
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_DIRECTION 3
+#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION 4
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 5
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 6
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 7
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 8
+#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 9
+#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 10
+#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 11
+#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 12
+#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 13
+#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 14
+#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 15
+#define ED_SELECTBOX_ID_CHANGE_SIDES 16
+#define ED_SELECTBOX_ID_CHANGE_POWER 17
+#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 18
+#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 19
+
+#define ED_NUM_SELECTBOX 20
#define ED_SELECTBOX_ID_CUSTOM1_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
#define ED_SELECTBOX_ID_CUSTOM1_LAST ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE
/* ---------- element settings: configure 1 (custom elements) ------------ */
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(6),
MIN_SCORE, MAX_SCORE,
GADGET_ID_CUSTOM_SCORE_DOWN, GADGET_ID_CUSTOM_SCORE_UP,
GADGET_ID_CUSTOM_SCORE_TEXT, GADGET_ID_NONE,
NULL, "score", " "
},
{
- -1, ED_SETTINGS_YPOS(5),
+ -1, ED_SETTINGS_YPOS(6),
MIN_COLLECT_COUNT, MAX_COLLECT_COUNT,
GADGET_ID_CUSTOM_GEMCOUNT_DOWN, GADGET_ID_CUSTOM_GEMCOUNT_UP,
GADGET_ID_CUSTOM_GEMCOUNT_TEXT, GADGET_ID_CUSTOM_SCORE_UP,
NULL, "count", NULL
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(6),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7),
0, 999,
GADGET_ID_PUSH_DELAY_FIX_DOWN, GADGET_ID_PUSH_DELAY_FIX_UP,
GADGET_ID_PUSH_DELAY_FIX_TEXT, GADGET_ID_NONE,
NULL, "push delay", NULL
},
{
- -1, ED_SETTINGS_YPOS(6),
+ -1, ED_SETTINGS_YPOS(7),
0, 999,
GADGET_ID_PUSH_DELAY_RND_DOWN, GADGET_ID_PUSH_DELAY_RND_UP,
GADGET_ID_PUSH_DELAY_RND_TEXT, GADGET_ID_PUSH_DELAY_FIX_UP,
NULL, "+random", NULL
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(11),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(12),
0, 999,
GADGET_ID_MOVE_DELAY_FIX_DOWN, GADGET_ID_MOVE_DELAY_FIX_UP,
GADGET_ID_MOVE_DELAY_FIX_TEXT, GADGET_ID_NONE,
NULL, "move delay", NULL
},
{
- -1, ED_SETTINGS_YPOS(11),
+ -1, ED_SETTINGS_YPOS(12),
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,
GADGET_ID_IGNITION_DELAY_DOWN, GADGET_ID_IGNITION_DELAY_UP,
GADGET_ID_IGNITION_DELAY_TEXT, GADGET_ID_NONE,
&custom_element.ignition_delay,
- NULL, "ignition delay", NULL
+ NULL, "ignition delay", "(by fire)"
},
/* ---------- element settings: configure (group elements) --------------- */
{ -1, NULL }
};
+static struct ValueTextInfo options_access_direction[] =
+{
+ { MV_LEFT, "left" },
+ { MV_RIGHT, "right" },
+ { MV_UP, "up" },
+ { MV_DOWN, "down" },
+ { MV_LEFT | MV_UP, "left + up" },
+ { MV_LEFT | MV_DOWN, "left + down" },
+ { MV_RIGHT | MV_UP, "right + up" },
+ { MV_RIGHT | MV_DOWN, "right + down" },
+ { MV_HORIZONTAL, "horizontal" },
+ { MV_VERTICAL, "vertical" },
+ { MV_HORIZONTAL | MV_UP, "horizontal + up" },
+ { MV_HORIZONTAL | MV_DOWN, "horizontal + down" },
+ { MV_VERTICAL | MV_LEFT, "vertical + left" },
+ { MV_VERTICAL | MV_RIGHT, "vertical + right" },
+ { MV_ALL_DIRECTIONS, "all directions" },
+ { -1, NULL }
+};
+
static struct ValueTextInfo options_walk_to_action[] =
{
{ EP_DIGGABLE, "diggable" },
},
{
ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(4),
+ GADGET_ID_CUSTOM_ACCESS_DIRECTION, GADGET_ID_NONE,
+ -1,
+ options_access_direction,
+ &custom_element.access_direction,
+ "from", NULL, "access direction for this field"
+ },
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(5),
GADGET_ID_CUSTOM_WALK_TO_ACTION, GADGET_ID_NONE,
-1,
options_walk_to_action,
NULL, NULL, "diggable/collectible/pushable"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8),
GADGET_ID_CUSTOM_MOVE_PATTERN, GADGET_ID_NONE,
-1,
options_move_pattern,
"can move", NULL, "element move direction"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9),
GADGET_ID_CUSTOM_MOVE_DIRECTION, GADGET_ID_NONE,
-1,
options_move_direction,
"starts moving", NULL, "initial element move direction"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(10),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(11),
GADGET_ID_CUSTOM_MOVE_STEPSIZE, GADGET_ID_NONE,
-1,
options_move_stepsize,
"move/fall speed", NULL, "speed of element movement"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(10),
GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE, GADGET_ID_NONE,
-1,
options_move_leave_type,
"can dig: can", ":", "leave behind or change element"
},
{
- -1, ED_SETTINGS_YPOS(12),
+ -1, ED_SETTINGS_YPOS(13),
GADGET_ID_CUSTOM_SMASH_TARGETS, GADGET_ID_CUSTOM_CAN_SMASH,
-1,
options_smash_targets,
"can smash", NULL, "elements that can be smashed"
},
{
- ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13),
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(14),
GADGET_ID_CUSTOM_SLIPPERY_TYPE, GADGET_ID_NONE,
-1,
options_slippery_type,
NULL, NULL, "player can walk to or pass this field"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(4),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(5),
GADGET_ID_CUSTOM_WALK_TO_OBJECT, GADGET_ID_NONE,
&custom_element_properties[EP_WALK_TO_OBJECT],
NULL, NULL, "player can dig/collect/push element"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(7),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(8),
GADGET_ID_CUSTOM_CAN_MOVE, GADGET_ID_NONE,
&custom_element_properties[EP_CAN_MOVE],
NULL, NULL, "element can move in some direction"
},
{
- ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13),
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(12),
+ -1, ED_SETTINGS_YPOS(13),
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(13),
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(14),
GADGET_ID_CUSTOM_SLIPPERY, GADGET_ID_NONE,
&custom_element_properties[EP_SLIPPERY],
NULL, NULL, "other elements can fall down from it"
Bang(x, y);
}
-void RelocatePlayer(int x, int y, int element)
+void RelocatePlayer(int x, int y, int element_raw)
{
+ int element = (element_raw == EL_SP_MURPHY ? EL_PLAYER_1 : element_raw);
struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1];
boolean ffwd_delay = (tape.playing && tape.fast_forward);
boolean no_delay = (tape.index_search);
void Explode(int ex, int ey, int phase, int mode)
{
int x, y;
+#if 0
int num_phase = 9;
+#endif
+
+ /* !!! eliminate this variable !!! */
int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
+
+#if 1
+ int last_phase;
+#else
int last_phase = num_phase * delay;
int half_phase = (num_phase / 2) * delay;
int first_phase_after_start = EX_PHASE_START + 1;
+#endif
int border_element;
- int last_phase_TEST = last_phase;
-
if (game.explosions_delayed)
{
ExplodeField[ex][ey] = mode;
{
boolean border_explosion = FALSE;
+#if 1
+ if (IS_PLAYER(x, y) && PLAYERINFO(x, y)->present)
+#else
if (IS_PLAYER(x, y))
+#endif
{
KillHeroUnlessExplosionProtected(x, y);
border_explosion = TRUE;
if (GFX_CRUMBLED(element))
DrawLevelFieldCrumbledSandNeighbours(x, y);
- if (IS_PLAYER(x, y) && !PLAYERINFO(x,y)->present)
+ if (IS_PLAYER(x, y) && !PLAYERINFO(x, y)->present)
StorePlayer[x][y] = 0;
if (ELEM_IS_PLAYER(element))
/* special values for move stepsize for spring and things on conveyor belt */
if (horiz_move)
{
+#if 1
+ if (element == EL_SPRING)
+ step = sign * MOVE_STEPSIZE_NORMAL * 2;
+ else if (CAN_FALL(element) && !CAN_MOVE(element) &&
+ y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+ step = sign * MOVE_STEPSIZE_NORMAL / 2;
+#else
if (CAN_FALL(element) &&
y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
step = sign * MOVE_STEPSIZE_NORMAL / 2;
else if (element == EL_SPRING)
step = sign * MOVE_STEPSIZE_NORMAL * 2;
+#endif
}
return step;
if (CAN_FALL(element) && y < lev_fieldy - 1)
{
- if ((x > 0 && IS_PLAYER(x - 1, y)) ||
- (x < lev_fieldx-1 && IS_PLAYER(x + 1, y)))
+ if ((x > 0 && IS_PLAYER(x - 1, y)) ||
+ (x < lev_fieldx - 1 && IS_PLAYER(x + 1, y)))
if (JustBeingPushed(x, y))
return;
started_moving = TRUE;
}
}
+#if 1
+ else if (IS_BELT_ACTIVE(Feld[x][y + 1]) && !CAN_MOVE(element))
+#else
else if (IS_BELT_ACTIVE(Feld[x][y + 1]))
+#endif
{
boolean left_is_free = (x > 0 && IS_FREE(x - 1, y));
boolean right_is_free = (x < lev_fieldx - 1 && IS_FREE(x + 1, y));
element = Feld[x][y];
}
+#if 1
+ if (page < 0)
+ {
+ boolean change_element = FALSE;
+ int i;
+
+ for (i = 0; i < element_info[element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change = &element_info[element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(trigger_event) &&
+ change->sides & side)
+ {
+ change_element = TRUE;
+ page = i;
+
+ break;
+ }
+ }
+
+ if (!change_element)
+ return FALSE;
+ }
+
+#else
+
+ /* !!! this check misses pages with same event, but different side !!! */
+
if (page < 0)
page = element_info[element].event_page_nr[trigger_event];
if (!(element_info[element].change_page[page].sides & side))
return FALSE;
+#endif
ChangeDelay[x][y] = 1;
ChangeEvent[x][y] = CH_EVENT_BIT(trigger_event);
dx == +1 ? MV_RIGHT :
dy == -1 ? MV_UP :
dy == +1 ? MV_DOWN : MV_NO_MOVING);
+ int opposite_direction = MV_DIR_OPPOSITE(move_direction);
int dig_side = change_sides[MV_DIR_BIT(move_direction)];
int element;
return MF_NO_ACTION; /* tube has no opening in this direction */
}
+ if (IS_CUSTOM_ELEMENT(Feld[jx][jy]) && IS_WALKABLE(Feld[jx][jy]) &&
+ !(element_info[Feld[jx][jy]].access_direction & move_direction))
+ return MF_NO_ACTION; /* field has no opening in this direction */
+
element = Feld[x][y];
if (mode == DF_SNAP && !IS_SNAPPABLE(element) &&
{
int sound_action = ACTION_WALKING;
+ if (IS_CUSTOM_ELEMENT(element) &&
+ !(element_info[element].access_direction & opposite_direction))
+ return MF_NO_ACTION; /* field not accessible from this direction */
+
if (element >= EL_GATE_1 && element <= EL_GATE_4)
{
if (!player->key[element - EL_GATE_1])
if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
return MF_NO_ACTION;
+ if (IS_CUSTOM_ELEMENT(element) &&
+ !(element_info[element].access_direction & opposite_direction))
+ return MF_NO_ACTION; /* field not accessible from this direction */
+
#if 1
if (CAN_MOVE(element)) /* only fixed elements can be passed! */
return MF_NO_ACTION;