+2004-01-18
+ * custom elements can change (limited) or leave (unlimited) elements
+
+2004-01-17
+ * added new start movement type "previous" for continued CE movement
+ * added new start movement type "random" for random CE movement start
+
+2004-01-17
+ * added new element "sokoban_field_player" needed for Sokoban levels
+ (thanks to Ed Booker for pointing this out!)
+
+2004-01-15
+ * added elements that can be digged or left behind by custom elements
+
+2004-01-12
+ * added group elements for multiple matches and random element creation
+
+2004-01-11
+ * fixed some graphical errors displayed in old levels
+
+2004-01-10
+ * fixed wrong double speed movement after passing closing gates
2004-01-03
- * level loader can now load native Emerald Mine levels
+ * added level loader for loading native Emerald Mine levels
2004-01-02
* changes for "shooting" style CE movement
-#define COMPILE_DATE_STRING "[2004-01-17 15:38]"
+#define COMPILE_DATE_STRING "[2004-01-18 11:28]"
#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_SIDES (GADGET_ID_SELECTBOX_FIRST + 13)
-#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 14)
-#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 15)
+#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)
/* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 17)
#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_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_SIDES 13
-#define ED_SELECTBOX_ID_CHANGE_POWER 14
-#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 15
-
-#define ED_NUM_SELECTBOX 16
+#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_NUM_SELECTBOX 17
#define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
#define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM_CONSISTENCY
{ -1, NULL }
};
+static struct ValueTextInfo options_move_leave_type[] =
+{
+ { LEAVE_TYPE_UNLIMITED, "leave behind" },
+ { LEAVE_TYPE_LIMITED, "change to" },
+ { -1, NULL }
+};
+
static struct ValueTextInfo options_smash_targets[] =
{
{ EP_CAN_SMASH_PLAYER, "player" },
&custom_element.move_stepsize,
"move/fall speed", NULL, "speed of element movement"
},
+ {
+ 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,
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_ENTER,
- "can leave behind:", NULL, NULL
+ GADGET_ID_CUSTOM_MOVE_LEAVE, GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE,
+ NULL, NULL, NULL
},
/* ---------- custom change target --------------------------------------- */
element_info[element].move_stepsize = TILEX / 8;
element_info[element].move_enter_element = EL_EMPTY_SPACE;
element_info[element].move_leave_element = EL_EMPTY_SPACE;
+ element_info[element].move_leave_type = LEAVE_TYPE_UNLIMITED;
element_info[element].slippery_type = SLIPPERY_ANY_RANDOM;
ei->move_enter_element = checkLevelElement(getFile16BitBE(file));
ei->move_leave_element = checkLevelElement(getFile16BitBE(file));
+ ei->move_leave_type = getFile8Bit(file);
/* some free bytes for future custom property values and padding */
- ReadUnusedBytesFromFile(file, 8);
+ ReadUnusedBytesFromFile(file, 7);
/* read change property values */
putFile16BitBE(file, ei->move_enter_element);
putFile16BitBE(file, ei->move_leave_element);
+ putFile8Bit(file, ei->move_leave_type);
/* some free bytes for future custom property values and padding */
- WriteUnusedBytesToFile(file, 8);
+ WriteUnusedBytesToFile(file, 7);
/* write change property values */
element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
}
+ /* ---------- initialize move dig/leave ---------------------------------- */
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ element_info[i].can_leave_element = FALSE;
+ element_info[i].can_leave_element_last = FALSE;
+ }
+
/* ---------- initialize gem count --------------------------------------- */
/* initialize gem count values for each element */
move_direction_initial = MV_AUTOMATIC;
}
- if (move_direction_initial & MV_ANY_DIRECTION)
+ if (move_direction_initial == MV_RANDOM)
+ MovDir[x][y] = 1 << RND(4);
+ else if (move_direction_initial & MV_ANY_DIRECTION)
MovDir[x][y] = move_direction_initial;
- else if (move_direction_initial == MV_RANDOM ||
- move_pattern == MV_ALL_DIRECTIONS ||
+ else if (move_pattern == MV_ALL_DIRECTIONS ||
move_pattern == MV_TURNING_LEFT ||
move_pattern == MV_TURNING_RIGHT ||
move_pattern == MV_TURNING_LEFT_RIGHT ||
)
{
+ int new_element = Feld[newx][newy];
+
#if 0
printf("::: '%s' digs '%s' [%d]\n",
element_info[element].token_name,
if (!IS_FREE(newx, newy))
{
- int new_element = Feld[newx][newy];
- int sound;
+ int action = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
+ IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
+ ACTION_BREAKING);
/* no element can dig solid indestructible elements */
if (IS_INDESTRUCTIBLE(new_element) &&
DrawLevelField(newx, newy);
}
- sound = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
- IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
- ACTION_BREAKING);
-
- PlayLevelSoundAction(x, y, sound);
+ PlayLevelSoundAction(x, y, action);
}
+ if (new_element == element_info[element].move_enter_element)
+ element_info[element].can_leave_element = TRUE;
+
if (move_pattern & MV_MAZE_RUNNER_STYLE)
{
RunnerVisit[x][y] = FrameCounter;
void ContinueMoving(int x, int y)
{
int element = Feld[x][y];
+ struct ElementInfo *ei = &element_info[element];
int direction = MovDir[x][y];
int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
ResetGfxAnimation(x, y); /* reset animation values for old field */
#if 1
- if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y))
+ if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y) &&
+ ei->move_leave_element != EL_EMPTY &&
+ (ei->move_leave_type == LEAVE_TYPE_UNLIMITED ||
+ ei->can_leave_element_last))
{
- int new_element = element_info[element].move_leave_element;
-
- Feld[x][y] = new_element;
-
- if (new_element != EL_EMPTY)
- {
- InitField(x, y, FALSE);
-
- TestIfElementTouchesCustomElement(x, y);
+ Feld[x][y] = ei->move_leave_element;
+ InitField(x, y, FALSE);
- if (GFX_CRUMBLED(new_element))
- DrawLevelFieldCrumbledSandNeighbours(x, y);
- }
+ if (GFX_CRUMBLED(Feld[x][y]))
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
}
+
+ ei->can_leave_element_last = ei->can_leave_element;
+ ei->can_leave_element = FALSE;
#endif
#if 0
Impact(x, newy);
#if 1
- TestIfElementTouchesCustomElement(x, y); /* for empty space */
+ TestIfElementTouchesCustomElement(x, y); /* empty or new element */
#endif
#if 0
#define MV_TURNING_RANDOM (1 << MV_BIT_TURNING_RANDOM)
#define MV_PREVIOUS (1 << MV_BIT_PREVIOUS)
+/* values for elements left behind by custom elements */
+#define LEAVE_TYPE_UNLIMITED 0
+#define LEAVE_TYPE_LIMITED 1
+
/* values for slippery property for custom elements */
#define SLIPPERY_ANY_RANDOM 0
#define SLIPPERY_ANY_LEFT_RIGHT 1
int move_stepsize; /* step size element moves with */
int move_enter_element; /* element that can be entered (and removed) */
int move_leave_element; /* element that can be left behind */
+ int move_leave_type; /* change (limited) or leave (unlimited) */
int slippery_type; /* how/where other elements slip away */
boolean in_group[NUM_GROUP_ELEMENTS];
+ boolean can_leave_element; /* element can leave other element behind */
+ boolean can_leave_element_last;
+
/* ---------- internal values used in level editor ---------- */
int access_type; /* walkable or passable */