#define ED_AREA_ELEM_CONTENT5_XPOS (30 * MINI_TILEX + MINI_TILEX / 2)
#define ED_AREA_ELEM_CONTENT5_YPOS (ED_SETTINGS_YPOS(7) + \
ED_GADGET_DISTANCE)
+/* extended custom change target */
+#define ED_AREA_ELEM_CONTENT6_XPOS (29 * MINI_TILEX)
+#define ED_AREA_ELEM_CONTENT6_YPOS (ED_SETTINGS_YPOS(10) + \
+ ED_GADGET_DISTANCE - MINI_TILEY)
/* values for random placement background drawing area */
#define ED_AREA_RANDOM_BACKGROUND_XPOS (29 * MINI_TILEX)
#define GADGET_ID_LEVEL_RANDOM_DOWN (GADGET_ID_COUNTER_FIRST + 9)
#define GADGET_ID_LEVEL_RANDOM_TEXT (GADGET_ID_COUNTER_FIRST + 10)
#define GADGET_ID_LEVEL_RANDOM_UP (GADGET_ID_COUNTER_FIRST + 11)
-#define GADGET_ID_LEVEL_COLLECT_DOWN (GADGET_ID_COUNTER_FIRST + 12)
-#define GADGET_ID_LEVEL_COLLECT_TEXT (GADGET_ID_COUNTER_FIRST + 13)
-#define GADGET_ID_LEVEL_COLLECT_UP (GADGET_ID_COUNTER_FIRST + 14)
+#define GADGET_ID_LEVEL_GEMSLIMIT_DOWN (GADGET_ID_COUNTER_FIRST + 12)
+#define GADGET_ID_LEVEL_GEMSLIMIT_TEXT (GADGET_ID_COUNTER_FIRST + 13)
+#define GADGET_ID_LEVEL_GEMSLIMIT_UP (GADGET_ID_COUNTER_FIRST + 14)
#define GADGET_ID_LEVEL_TIMELIMIT_DOWN (GADGET_ID_COUNTER_FIRST + 15)
#define GADGET_ID_LEVEL_TIMELIMIT_TEXT (GADGET_ID_COUNTER_FIRST + 16)
#define GADGET_ID_LEVEL_TIMELIMIT_UP (GADGET_ID_COUNTER_FIRST + 17)
#define GADGET_ID_ELEMENT_CONTENT_DOWN (GADGET_ID_COUNTER_FIRST + 24)
#define GADGET_ID_ELEMENT_CONTENT_TEXT (GADGET_ID_COUNTER_FIRST + 25)
#define GADGET_ID_ELEMENT_CONTENT_UP (GADGET_ID_COUNTER_FIRST + 26)
-#define GADGET_ID_COLLECT_SCORE_DOWN (GADGET_ID_COUNTER_FIRST + 27)
-#define GADGET_ID_COLLECT_SCORE_TEXT (GADGET_ID_COUNTER_FIRST + 28)
-#define GADGET_ID_COLLECT_SCORE_UP (GADGET_ID_COUNTER_FIRST + 29)
-#define GADGET_ID_COLLECT_GEMCOUNT_DOWN (GADGET_ID_COUNTER_FIRST + 30)
-#define GADGET_ID_COLLECT_GEMCOUNT_TEXT (GADGET_ID_COUNTER_FIRST + 31)
-#define GADGET_ID_COLLECT_GEMCOUNT_UP (GADGET_ID_COUNTER_FIRST + 32)
+#define GADGET_ID_CUSTOM_SCORE_DOWN (GADGET_ID_COUNTER_FIRST + 27)
+#define GADGET_ID_CUSTOM_SCORE_TEXT (GADGET_ID_COUNTER_FIRST + 28)
+#define GADGET_ID_CUSTOM_SCORE_UP (GADGET_ID_COUNTER_FIRST + 29)
+#define GADGET_ID_CUSTOM_GEMCOUNT_DOWN (GADGET_ID_COUNTER_FIRST + 30)
+#define GADGET_ID_CUSTOM_GEMCOUNT_TEXT (GADGET_ID_COUNTER_FIRST + 31)
+#define GADGET_ID_CUSTOM_GEMCOUNT_UP (GADGET_ID_COUNTER_FIRST + 32)
#define GADGET_ID_PUSH_DELAY_FIX_DOWN (GADGET_ID_COUNTER_FIRST + 33)
#define GADGET_ID_PUSH_DELAY_FIX_TEXT (GADGET_ID_COUNTER_FIRST + 34)
#define GADGET_ID_PUSH_DELAY_FIX_UP (GADGET_ID_COUNTER_FIRST + 35)
#define GADGET_ID_CUSTOM_GRAPHIC (GADGET_ID_DRAWING_AREA_FIRST + 10)
#define GADGET_ID_CUSTOM_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 11)
#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 12)
-#define GADGET_ID_CUSTOM_CHANGE_TRIGGER (GADGET_ID_DRAWING_AREA_FIRST + 13)
-#define GADGET_ID_RANDOM_BACKGROUND (GADGET_ID_DRAWING_AREA_FIRST + 14)
+#define GADGET_ID_CUSTOM_CHANGE_CONTENT (GADGET_ID_DRAWING_AREA_FIRST + 13)
+#define GADGET_ID_CUSTOM_CHANGE_TRIGGER (GADGET_ID_DRAWING_AREA_FIRST + 14)
+#define GADGET_ID_RANDOM_BACKGROUND (GADGET_ID_DRAWING_AREA_FIRST + 15)
/* text input identifiers */
-#define GADGET_ID_TEXT_INPUT_FIRST (GADGET_ID_DRAWING_AREA_FIRST + 15)
+#define GADGET_ID_TEXT_INPUT_FIRST (GADGET_ID_DRAWING_AREA_FIRST + 16)
#define GADGET_ID_LEVEL_NAME (GADGET_ID_TEXT_INPUT_FIRST + 0)
#define GADGET_ID_LEVEL_AUTHOR (GADGET_ID_TEXT_INPUT_FIRST + 1)
#define GADGET_ID_CHANGE_PLAYER_ACTION (GADGET_ID_SELECTBOX_FIRST + 10)
#define GADGET_ID_CHANGE_IMPACT_ACTION (GADGET_ID_SELECTBOX_FIRST + 11)
#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 12)
+#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 13)
/* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 13)
+#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 14)
#define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0)
#define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1)
#define GADGET_ID_CUSTOM_USE_GRAPHIC (GADGET_ID_CHECKBUTTON_FIRST + 18)
#define GADGET_ID_CUSTOM_USE_TEMPLATE (GADGET_ID_CHECKBUTTON_FIRST + 19)
#define GADGET_ID_CUSTOM_CAN_CHANGE (GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_CHANGE_BY_PLAYER (GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CHANGE_IMPACT_SMASHED (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CHANGE_BY_OTHER (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CHANGE_USE_CONTENT (GADGET_ID_CHECKBUTTON_FIRST + 21)
+#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 22)
+#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 23)
+#define GADGET_ID_CHANGE_DELAY (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CHANGE_BY_PLAYER (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CHANGE_IMPACT_SMASHED (GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_CHANGE_BY_OTHER (GADGET_ID_CHECKBUTTON_FIRST + 27)
/* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_ELEMENTLIST_FIRST (GADGET_ID_CHECKBUTTON_FIRST + 28)
#define GADGET_ID_ELEMENTLIST_LAST (GADGET_ID_ELEMENTLIST_FIRST + \
ED_NUM_ELEMENTLIST_BUTTONS - 1)
#define ED_COUNTER_ID_SELECT_LEVEL 0
#define ED_COUNTER_ID_LEVEL_XSIZE 1
#define ED_COUNTER_ID_LEVEL_YSIZE 2
-#define ED_COUNTER_ID_LEVEL_COLLECT 3
+#define ED_COUNTER_ID_LEVEL_GEMSLIMIT 3
#define ED_COUNTER_ID_LEVEL_TIMELIMIT 4
#define ED_COUNTER_ID_LEVEL_TIMESCORE 5
#define ED_COUNTER_ID_LEVEL_RANDOM 6
#define ED_COUNTER_ID_ELEMENT_SCORE 7
#define ED_COUNTER_ID_ELEMENT_CONTENT 8
-#define ED_COUNTER_ID_COLLECT_SCORE 9
-#define ED_COUNTER_ID_COLLECT_GEMCOUNT 10
+#define ED_COUNTER_ID_CUSTOM_SCORE 9
+#define ED_COUNTER_ID_CUSTOM_GEMCOUNT 10
#define ED_COUNTER_ID_PUSH_DELAY_FIX 11
#define ED_COUNTER_ID_PUSH_DELAY_RND 12
#define ED_COUNTER_ID_MOVE_DELAY_FIX 13
#define ED_COUNTER_ID_LEVEL_FIRST ED_COUNTER_ID_LEVEL_XSIZE
#define ED_COUNTER_ID_LEVEL_LAST ED_COUNTER_ID_LEVEL_RANDOM
-#define ED_COUNTER_ID_CUSTOM_FIRST ED_COUNTER_ID_COLLECT_SCORE
+#define ED_COUNTER_ID_CUSTOM_FIRST ED_COUNTER_ID_CUSTOM_SCORE
#define ED_COUNTER_ID_CUSTOM_LAST ED_COUNTER_ID_MOVE_DELAY_RND
#define ED_COUNTER_ID_CHANGE_FIRST ED_COUNTER_ID_CHANGE_DELAY_FIX
#define ED_SELECTBOX_ID_CHANGE_PLAYER_ACTION 10
#define ED_SELECTBOX_ID_CHANGE_IMPACT_ACTION 11
#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 12
+#define ED_SELECTBOX_ID_CHANGE_POWER 13
-#define ED_NUM_SELECTBOX 13
+#define ED_NUM_SELECTBOX 14
#define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION
#define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER
#define ED_SELECTBOX_ID_CHANGE_FIRST ED_SELECTBOX_ID_CHANGE_TIME_UNITS
-#define ED_SELECTBOX_ID_CHANGE_LAST ED_SELECTBOX_ID_CHANGE_OTHER_ACTION
+#define ED_SELECTBOX_ID_CHANGE_LAST ED_SELECTBOX_ID_CHANGE_POWER
/* values for textbutton gadgets */
#define ED_TEXTBUTTON_ID_PROPERTIES_INFO 0
#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC 16
#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE 17
#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE 18
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY 19
-#define ED_CHECKBUTTON_ID_CHANGE_BY_PLAYER 20
-#define ED_CHECKBUTTON_ID_CHANGE_IMPACT_SMASHED 21
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER 22
+#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT 19
+#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 20
+#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 21
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY 22
+#define ED_CHECKBUTTON_ID_CHANGE_BY_PLAYER 23
+#define ED_CHECKBUTTON_ID_CHANGE_IMPACT_SMASHED 24
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER 25
-#define ED_NUM_CHECKBUTTONS 23
+#define ED_NUM_CHECKBUTTONS 26
#define ED_CHECKBUTTON_ID_LEVEL_FIRST ED_CHECKBUTTON_ID_DOUBLE_SPEED
#define ED_CHECKBUTTON_ID_LEVEL_LAST ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
{
ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(3),
0, 999,
- GADGET_ID_LEVEL_COLLECT_DOWN, GADGET_ID_LEVEL_COLLECT_UP,
- GADGET_ID_LEVEL_COLLECT_TEXT,
+ GADGET_ID_LEVEL_GEMSLIMIT_DOWN, GADGET_ID_LEVEL_GEMSLIMIT_UP,
+ GADGET_ID_LEVEL_GEMSLIMIT_TEXT,
&level.gems_needed,
"number of emeralds to collect", NULL, NULL
},
{
ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(3),
MIN_SCORE, MAX_SCORE,
- GADGET_ID_COLLECT_SCORE_DOWN, GADGET_ID_COLLECT_SCORE_UP,
- GADGET_ID_COLLECT_SCORE_TEXT,
- &custom_element.collect_score,
+ GADGET_ID_CUSTOM_SCORE_DOWN, GADGET_ID_CUSTOM_SCORE_UP,
+ GADGET_ID_CUSTOM_SCORE_TEXT,
+ &custom_element.score,
NULL, "collect score", NULL
},
{
ED_SETTINGS_XPOS(13) + 10, ED_SETTINGS_YPOS(3),
MIN_GEM_COUNT, MAX_GEM_COUNT,
- GADGET_ID_COLLECT_GEMCOUNT_DOWN, GADGET_ID_COLLECT_GEMCOUNT_UP,
- GADGET_ID_COLLECT_GEMCOUNT_TEXT,
- &custom_element.collect_gem_count,
+ GADGET_ID_CUSTOM_GEMCOUNT_DOWN, GADGET_ID_CUSTOM_GEMCOUNT_UP,
+ GADGET_ID_CUSTOM_GEMCOUNT_TEXT,
+ &custom_element.gem_count,
NULL, "gems", NULL
},
{
}
};
+static struct ValueTextInfo options_access_type[] =
+{
+ { EP_WALKABLE, "walk" },
+ { EP_PASSABLE, "pass" },
+ { -1, NULL }
+};
+static int value_access_type = 0;
+
+static struct ValueTextInfo options_access_layer[] =
+{
+ { EP_ACCESSIBLE_OVER, "over" },
+ { EP_ACCESSIBLE_INSIDE, "inside" },
+ { EP_ACCESSIBLE_UNDER, "under" },
+ { -1, NULL }
+};
+static int value_access_layer = 0;
+
static struct ValueTextInfo options_walk_to_action[] =
{
{ EP_DIGGABLE, "diggable" },
{ -1, NULL }
};
-static struct ValueTextInfo options_consistency[] =
-{
- { EP_CAN_EXPLODE, "can explode" },
- { EP_INDESTRUCTIBLE, "indestructible" },
- { -1, NULL }
-};
-static int value_consistency = 0;
-
-static struct ValueTextInfo options_deadliness[] =
-{
- { EP_DONT_RUN_INTO, "running into" },
- { EP_DONT_COLLIDE_WITH, "colliding with" },
- { EP_DONT_TOUCH, "touching" },
- { -1, NULL }
-};
-static int value_deadliness = 0;
-
static struct ValueTextInfo options_smash_targets[] =
{
{ EP_CAN_SMASH_PLAYER, "player" },
};
static int value_smash_targets = 0;
-static struct ValueTextInfo options_access_type[] =
+static struct ValueTextInfo options_deadliness[] =
{
- { EP_WALKABLE, "walk" },
- { EP_PASSABLE, "pass" },
+ { EP_DONT_RUN_INTO, "running into" },
+ { EP_DONT_COLLIDE_WITH, "colliding with" },
+ { EP_DONT_TOUCH, "touching" },
{ -1, NULL }
};
-static int value_access_type = 0;
+static int value_deadliness = 0;
-static struct ValueTextInfo options_access_layer[] =
+static struct ValueTextInfo options_consistency[] =
{
- { EP_ACCESSIBLE_OVER, "over" },
- { EP_ACCESSIBLE_INSIDE, "inside" },
- { EP_ACCESSIBLE_UNDER, "under" },
+ { EP_CAN_EXPLODE, "can explode" },
+ { EP_INDESTRUCTIBLE, "indestructible" },
{ -1, NULL }
};
-static int value_access_layer = 0;
+static int value_consistency = 0;
static struct ValueTextInfo options_time_units[] =
{
};
static int value_change_other_action = 0;
+static struct ValueTextInfo options_change_power[] =
+{
+ { CP_NON_DESTRUCTIVE, "non-destructive" },
+ { CP_HALF_DESTRUCTIVE, "half-destructive" },
+ { CP_FULL_DESTRUCTIVE, "full-destructive" },
+ { -1, NULL }
+};
+
static struct
{
int x, y;
&value_change_other_action,
NULL, "other element:", "type of other element action"
},
+ {
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(10),
+ GADGET_ID_CHANGE_POWER,
+ -1,
+ options_change_power,
+ &custom_element.change.power,
+ "power:", NULL, "power of extended change"
+ },
};
static struct
&custom_element_change_events[CE_BY_OTHER],
NULL, "element changes by other element"
},
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8),
+ GADGET_ID_CHANGE_USE_EXPLOSION,
+ &custom_element.change.explode,
+ "explode instead of change", "element explodes instead of change"
+ },
+ {
+ ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9),
+ GADGET_ID_CHANGE_USE_CONTENT,
+ &custom_element.change.use_content,
+ "use extended change target:", "element changes to more elements"
+ },
+ {
+ ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(11),
+ GADGET_ID_CHANGE_ONLY_COMPLETE,
+ &custom_element.change.only_complete,
+ "only use complete change", "only use complete extended content"
+ },
{
ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12),
GADGET_ID_CUSTOM_USE_TEMPLATE,
level_editor_gadget[id] = gi;
- /* ... one areas for custom element explosion content ... */
+ /* ... one area for custom element explosion content ... */
id = GADGET_ID_CUSTOM_CONTENT;
gi = CreateGadget(GDI_CUSTOM_ID, id,
GDI_CUSTOM_TYPE_ID, i,
level_editor_gadget[id] = gi;
+ /* ... one area for extended custom element change target content ... */
+ id = GADGET_ID_CUSTOM_CHANGE_CONTENT;
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_X, SX + ED_AREA_ELEM_CONTENT6_XPOS,
+ GDI_Y, SX + ED_AREA_ELEM_CONTENT6_YPOS,
+ GDI_WIDTH, 3 * MINI_TILEX,
+ GDI_HEIGHT, 3 * MINI_TILEY,
+ GDI_TYPE, GD_TYPE_DRAWING_AREA,
+ GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
+ GDI_CALLBACK_ACTION, HandleDrawingAreas,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+
/* ... one for each custom element change trigger element ... */
id = GADGET_ID_CUSTOM_CHANGE_TRIGGER;
gi = CreateGadget(GDI_CUSTOM_ID, id,
DrawElementBorder(area_sx, area_sy, MINI_TILEX, MINI_TILEY, TRUE);
DrawMiniGraphicExt(drawto, gi->x, gi->y,
- el2edimg(custom_element.change.successor));
+ el2edimg(custom_element.change.target_element));
MapDrawingArea(GADGET_ID_CUSTOM_CHANGE_TARGET);
}
+static void DrawCustomChangeContentArea()
+{
+ struct GadgetInfo *gi = level_editor_gadget[GADGET_ID_CUSTOM_CHANGE_CONTENT];
+ int area_sx = SX + ED_AREA_ELEM_CONTENT6_XPOS;
+ int area_sy = SY + ED_AREA_ELEM_CONTENT6_YPOS;
+ int x, y;
+
+ if (!IS_CUSTOM_ELEMENT(properties_element))
+ {
+ /* this should never happen */
+ Error(ERR_WARN, "element %d is no custom element", properties_element);
+
+ return;
+ }
+
+ DrawElementBorder(area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY, TRUE);
+
+ for (y=0; y<3; y++)
+ for (x=0; x<3; x++)
+ DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX,gi->y + y * MINI_TILEY,
+ el2edimg(custom_element.change.content[x][y]));
+
+ MapDrawingArea(GADGET_ID_CUSTOM_CHANGE_CONTENT);
+}
+
static void DrawCustomChangeTriggerArea()
{
struct GadgetInfo *gi = level_editor_gadget[GADGET_ID_CUSTOM_CHANGE_TRIGGER];
/* draw drawing area gadgets */
DrawCustomGraphicElementArea();
DrawCustomChangeTargetArea();
+ DrawCustomChangeContentArea();
DrawCustomChangeTriggerArea();
}
}
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
{
- custom_element.change.successor = new_element;
+ custom_element.change.target_element = new_element;
+ element_info[properties_element] = custom_element;
+ }
+ else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
+ {
+ custom_element.change.content[sx][sy] = new_element;
element_info[properties_element] = custom_element;
}
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
else if (id == GADGET_ID_CUSTOM_CONTENT)
PickDrawingElement(button, custom_element.content[sx][sy]);
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
- PickDrawingElement(button, custom_element.change.successor);
+ PickDrawingElement(button, custom_element.change.target_element);
+ else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
+ PickDrawingElement(button, custom_element.change.content[sx][sy]);
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
PickDrawingElement(button, custom_element.change.trigger);
else if (id == GADGET_ID_RANDOM_BACKGROUND)
else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT)
{
if (id == GADGET_ID_AMOEBA_CONTENT)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(level.amoeba_content));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(level.amoeba_content));
else if (id == GADGET_ID_CUSTOM_GRAPHIC)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(custom_element.use_gfx_element));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(custom_element.gfx_element));
else if (id == GADGET_ID_CUSTOM_CONTENT)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(custom_element.content[sx][sy]));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(custom_element.content[sx][sy]));
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(custom_element.change.successor));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(custom_element.change.target_element));
+ else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(custom_element.change.content[sx][sy]));
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(custom_element.change.trigger));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(custom_element.change.trigger));
else if (id == GADGET_ID_RANDOM_BACKGROUND)
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(random_placement_background_element));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(random_placement_background_element));
else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
id <= GADGET_ID_ELEMENT_CONTENT_7)
{
int i = id - GADGET_ID_ELEMENT_CONTENT_0;
- DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
- "%s", getElementInfoText(level.yamyam_content[i][sx][sy]));
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
+ getElementInfoText(level.yamyam_content[i][sx][sy]));
}
}
else
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
"New element after change");
+ else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
+ DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
+ "New extended elements after change");
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
"Other element triggering change");
static void CheckTriggeredElementChange(int, int);
static void CheckPlayerElementChange(int, int, int, int);
-static void ChangeElementDoIt(int, int, int);
+static void ChangeElementNow(int, int, int);
static void PlaySoundLevel(int, int, int);
static void PlaySoundLevelNearest(int, int, int);
struct ChangingElementInfo
{
- int base_element;
- int next_element;
+ int element;
+ int target_element;
int change_delay;
void (*pre_change_function)(int x, int y);
void (*change_function)(int x, int y);
int element;
int gem_count;
}
-collect_gem_count_list[] =
+gem_count_list[] =
{
{ EL_EMERALD, 1 },
{ EL_BD_DIAMOND, 1 },
{ EL_UNDEFINED, 0 },
};
-static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS];
+static boolean changing_element[MAX_NUM_ELEMENTS];
static unsigned long trigger_events[MAX_NUM_ELEMENTS];
-#define IS_AUTO_CHANGING(e) (changing_element[e].base_element != EL_UNDEFINED)
+#define IS_AUTO_CHANGING(e) (changing_element[e])
#define IS_JUST_CHANGING(x, y) (ChangeDelay[x][y] != 0)
#define IS_CHANGING(x, y) (IS_AUTO_CHANGING(Feld[x][y]) || \
IS_JUST_CHANGING(x, y))
/* initialize changing elements information */
for (i=0; i<MAX_NUM_ELEMENTS; i++)
{
+#if 1
+ element_info[i].change.pre_change_function = NULL;
+ element_info[i].change.change_function = NULL;
+ element_info[i].change.post_change_function = NULL;
+
+ if (!IS_CUSTOM_ELEMENT(i))
+ {
+ element_info[i].change.target_element = EL_EMPTY_SPACE;
+ element_info[i].change.delay_fixed = 0;
+ element_info[i].change.delay_random = 0;
+ element_info[i].change.delay_frames = 1;
+ }
+
+ changing_element[i] = FALSE;
+#else
changing_element[i].base_element = EL_UNDEFINED;
changing_element[i].next_element = EL_UNDEFINED;
changing_element[i].change_delay = -1;
changing_element[i].pre_change_function = NULL;
changing_element[i].change_function = NULL;
changing_element[i].post_change_function = NULL;
+#endif
}
/* add changing elements from pre-defined list */
- for (i=0; changing_element_list[i].base_element != EL_UNDEFINED; i++)
+ for (i=0; changing_element_list[i].element != EL_UNDEFINED; i++)
{
+ int element = changing_element_list[i].element;
struct ChangingElementInfo *ce = &changing_element_list[i];
- int element = ce->base_element;
+ struct ElementChangeInfo *change = &element_info[element].change;
+
+#if 1
+ change->target_element = ce->target_element;
+ change->delay_fixed = ce->change_delay;
+ change->pre_change_function = ce->pre_change_function;
+ change->change_function = ce->change_function;
+ change->post_change_function = ce->post_change_function;
+ changing_element[element] = TRUE;
+#else
changing_element[element].base_element = ce->base_element;
changing_element[element].next_element = ce->next_element;
changing_element[element].change_delay = ce->change_delay;
changing_element[element].pre_change_function = ce->pre_change_function;
changing_element[element].change_function = ce->change_function;
changing_element[element].post_change_function = ce->post_change_function;
+#endif
}
/* add changing elements from custom element configuration */
for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
{
int element = EL_CUSTOM_START + i;
+#if 0
struct ElementChangeInfo *change = &element_info[element].change;
+#endif
/* only add custom elements that change after fixed/random frame delay */
if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, CE_DELAY))
continue;
+#if 1
+ changing_element[element] = TRUE;
+#else
changing_element[element].base_element = element;
- changing_element[element].next_element = change->successor;
+ changing_element[element].next_element = change->target_element;
changing_element[element].change_delay = (change->delay_fixed *
change->delay_frames);
+#endif
}
/* ---------- initialize trigger events ---------------------------------- */
/* initialize gem count values for each element */
for (i=0; i<MAX_NUM_ELEMENTS; i++)
if (!IS_CUSTOM_ELEMENT(i))
- element_info[i].collect_gem_count = 0;
+ element_info[i].gem_count = 0;
/* add gem count values for all elements from pre-defined list */
- for (i=0; collect_gem_count_list[i].element != EL_UNDEFINED; i++)
- element_info[collect_gem_count_list[i].element].collect_gem_count =
- collect_gem_count_list[i].gem_count;
+ for (i=0; gem_count_list[i].element != EL_UNDEFINED; i++)
+ element_info[gem_count_list[i].element].gem_count =
+ gem_count_list[i].gem_count;
}
{
PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
- ChangeElementDoIt(x, y, element_info[element].change.successor);
+ ChangeElementNow(x, y, element);
return;
}
else if (CAN_CHANGE(smashed) &&
HAS_CHANGE_EVENT(smashed, CE_SMASHED))
{
- ChangeElementDoIt(x, y + 1, element_info[smashed].change.successor);
+ ChangeElementNow(x, y + 1, smashed);
}
}
}
DrawLevelFieldCrumbledSand(x, y);
}
-static void ChangeElementDoIt(int x, int y, int element_new)
+static void ChangeElementNowExt(int x, int y, int target_element)
{
- CheckTriggeredElementChange(Feld[x][y], CE_OTHER_CHANGING);
+ if (IS_PLAYER(x, y) && !IS_ACCESSIBLE(target_element))
+ {
+ Bang(x, y);
+ return;
+ }
RemoveField(x, y);
- Feld[x][y] = element_new;
+ Feld[x][y] = target_element;
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
}
}
+static void ChangeElementNow(int x, int y, int element)
+{
+ struct ElementChangeInfo *change = &element_info[element].change;
+
+ CheckTriggeredElementChange(Feld[x][y], CE_OTHER_CHANGING);
+
+ if (change->explode)
+ {
+ Bang(x, y);
+ return;
+ }
+
+ if (change->use_content)
+ {
+ boolean complete_change = TRUE;
+ boolean can_change[3][3];
+ int xx, yy;
+
+ for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++)
+ {
+ boolean half_destructible;
+ int ex = x + xx - 1;
+ int ey = y + yy - 1;
+ int e;
+
+ can_change[xx][yy] = TRUE;
+
+ if (ex == x && ey == y) /* do not check changing element itself */
+ continue;
+
+ if (change->content[xx][yy] == EL_EMPTY_SPACE)
+ {
+ can_change[xx][yy] = FALSE; /* do not change empty borders */
+
+ continue;
+ }
+
+ if (!IN_LEV_FIELD(ex, ey))
+ {
+ can_change[xx][yy] = FALSE;
+ complete_change = FALSE;
+
+ continue;
+ }
+
+ e = Feld[ex][ey];
+
+ half_destructible = (IS_FREE(ex, ey) || IS_DIGGABLE(e));
+
+ if ((change->power <= CP_NON_DESTRUCTIVE && !IS_FREE(ex, ey)) ||
+ (change->power <= CP_HALF_DESTRUCTIVE && !half_destructible) ||
+ (change->power <= CP_FULL_DESTRUCTIVE && IS_INDESTRUCTIBLE(e)))
+ {
+ can_change[xx][yy] = FALSE;
+ complete_change = FALSE;
+ }
+ }
+
+ if (!change->only_complete || complete_change)
+ {
+ for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++)
+ {
+ int ex = x + xx - 1;
+ int ey = y + yy - 1;
+
+ if (can_change[xx][yy])
+ {
+ ChangeElementNowExt(ex, ey, change->content[xx][yy]);
+
+ /* for symmetry reasons, stop newly created border elements */
+ if (ex != x || ey != y)
+ Stop[ex][ey] = TRUE;
+ }
+ }
+
+ return;
+ }
+ }
+
+ ChangeElementNowExt(x, y, change->target_element);
+}
+
static void ChangeElement(int x, int y)
{
int element = Feld[x][y];
+ struct ElementChangeInfo *change = &element_info[element].change;
if (ChangeDelay[x][y] == 0) /* initialize element change */
{
+#if 1
+ ChangeDelay[x][y] = ( change->delay_fixed * change->delay_frames +
+ RND(change->delay_random * change->delay_frames)) + 1;
+#else
ChangeDelay[x][y] = changing_element[element].change_delay + 1;
if (IS_CUSTOM_ELEMENT(element) && HAS_CHANGE_EVENT(element, CE_DELAY))
ChangeDelay[x][y] += RND(max_random_delay * delay_frames);
}
+#endif
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
+#if 1
+ if (change->pre_change_function)
+ change->pre_change_function(x, y);
+#else
if (changing_element[element].pre_change_function)
changing_element[element].pre_change_function(x, y);
+#endif
}
ChangeDelay[x][y]--;
if (IS_ANIMATED(graphic))
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+#if 1
+ if (change->change_function)
+ change->change_function(x, y);
+#else
if (changing_element[element].change_function)
changing_element[element].change_function(x, y);
+#endif
}
else /* finish element change */
{
+#if 0
int next_element = changing_element[element].next_element;
+#endif
if (IS_MOVING(x, y)) /* never change a running system ;-) */
{
return;
}
+#if 1
+ ChangeElementNow(x, y, element);
+
+ if (change->post_change_function)
+ change->post_change_function(x, y);
+#else
if (next_element != EL_UNDEFINED)
- ChangeElementDoIt(x, y, next_element);
+ ChangeElementNow(x, y, next_element);
else
- ChangeElementDoIt(x, y, element_info[element].change.successor);
+ ChangeElementNow(x, y, element_info[element].change.target_element);
if (changing_element[element].post_change_function)
changing_element[element].post_change_function(x, y);
+#endif
}
}
if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, trigger_event))
return;
-#if 1
ChangeDelay[x][y] = 1;
ChangeElement(x, y);
-#else
- ChangeElementDoIt(x, y, element_info[element].change.successor);
-#endif
}
static void PlayerActions(struct PlayerInfo *player, byte player_action)
el2edimg(EL_KEY_1 + key_nr));
redraw_mask |= REDRAW_DOOR_1;
}
- else if (element_info[element].collect_gem_count > 0)
+ else if (element_info[element].gem_count > 0)
{
local_player->gems_still_needed -=
- element_info[element].collect_gem_count;
+ element_info[element].gem_count;
if (local_player->gems_still_needed < 0)
local_player->gems_still_needed = 0;
RaiseScore(level.score[SC_KEY]);
break;
default:
- RaiseScore(element_info[element].collect_score);
+ RaiseScore(element_info[element].score);
break;
}
}
#define EP_PUSHABLE 24
/* values for special configurable properties (depending on level settings) */
-#define EP_EM_SLIPPERY_WALL 25
+#define EP_EM_SLIPPERY_WALL 32
/* values for special graphics properties (no effect on game engine) */
-#define EP_CAN_BE_CRUMBLED 26
+#define EP_CAN_BE_CRUMBLED 33
/* values for pre-defined properties */
-#define EP_PLAYER 27
-#define EP_CAN_PASS_MAGIC_WALL 28
-#define EP_SWITCHABLE 29
-#define EP_BD_ELEMENT 30
-#define EP_SP_ELEMENT 31
-#define EP_SB_ELEMENT 32
-#define EP_GEM 33
-#define EP_FOOD_DARK_YAMYAM 34
-#define EP_FOOD_PENGUIN 35
-#define EP_FOOD_PIG 36
-#define EP_HISTORIC_WALL 37
-#define EP_HISTORIC_SOLID 38
-#define EP_CLASSIC_ENEMY 39
-#define EP_BELT 40
-#define EP_BELT_ACTIVE 41
-#define EP_BELT_SWITCH 42
-#define EP_TUBE 43
-#define EP_KEYGATE 44
-#define EP_AMOEBOID 45
-#define EP_AMOEBALIVE 46
-#define EP_HAS_CONTENT 47
-#define EP_ACTIVE_BOMB 48
-#define EP_INACTIVE 49
+#define EP_PLAYER 34
+#define EP_CAN_PASS_MAGIC_WALL 35
+#define EP_SWITCHABLE 36
+#define EP_BD_ELEMENT 37
+#define EP_SP_ELEMENT 38
+#define EP_SB_ELEMENT 39
+#define EP_GEM 40
+#define EP_FOOD_DARK_YAMYAM 41
+#define EP_FOOD_PENGUIN 42
+#define EP_FOOD_PIG 43
+#define EP_HISTORIC_WALL 44
+#define EP_HISTORIC_SOLID 45
+#define EP_CLASSIC_ENEMY 46
+#define EP_BELT 47
+#define EP_BELT_ACTIVE 48
+#define EP_BELT_SWITCH 49
+#define EP_TUBE 50
+#define EP_KEYGATE 51
+#define EP_AMOEBOID 52
+#define EP_AMOEBALIVE 53
+#define EP_HAS_CONTENT 54
+#define EP_ACTIVE_BOMB 55
+#define EP_INACTIVE 56
/* values for derived properties (determined from properties above) */
-#define EP_ACCESSIBLE_OVER 50
-#define EP_ACCESSIBLE_INSIDE 51
-#define EP_ACCESSIBLE_UNDER 52
-#define EP_WALKABLE 53
-#define EP_PASSABLE 54
-#define EP_ACCESSIBLE 55
-#define EP_SNAPPABLE 56
-#define EP_WALL 57
-#define EP_SOLID_FOR_PUSHING 58
-#define EP_DRAGONFIRE_PROOF 59
-#define EP_EXPLOSION_PROOF 60
-#define EP_CAN_SMASH 61
-#define EP_CAN_EXPLODE 62
+#define EP_ACCESSIBLE_OVER 57
+#define EP_ACCESSIBLE_INSIDE 58
+#define EP_ACCESSIBLE_UNDER 59
+#define EP_WALKABLE 60
+#define EP_PASSABLE 61
+#define EP_ACCESSIBLE 62
+#define EP_SNAPPABLE 63
+#define EP_WALL 64
+#define EP_SOLID_FOR_PUSHING 65
+#define EP_DRAGONFIRE_PROOF 66
+#define EP_EXPLOSION_PROOF 67
+#define EP_CAN_SMASH 68
+#define EP_CAN_EXPLODE 69
/* values for internal purpose only (level editor) */
-#define EP_EXPLODE_RESULT 63
-#define EP_WALK_TO_OBJECT 64
-#define EP_DEADLY 65
+#define EP_EXPLODE_RESULT 70
+#define EP_WALK_TO_OBJECT 71
+#define EP_DEADLY 72
-#define NUM_ELEMENT_PROPERTIES 66
+#define NUM_ELEMENT_PROPERTIES 73
#define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32)
#define EP_BITFIELD_BASE 0
(CH_EVENT_VAR(e) |= CH_EVENT_BIT(c)) : \
(CH_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
+/* values for change power for custom elements */
+#define CP_NON_DESTRUCTIVE 0
+#define CP_HALF_DESTRUCTIVE 1
+#define CP_FULL_DESTRUCTIVE 2
+
/* macros for configurable properties */
#define IS_DIGGABLE(e) HAS_PROPERTY(e, EP_DIGGABLE)
short trigger; /* custom element triggering change */
- short successor; /* new custom element after change */
+ short target_element; /* target element after change */
+
+ int content[3][3]; /* new elements after extended change */
+ boolean use_content; /* use extended change content */
+ boolean only_complete; /* only use complete content */
+ int power; /* power of extended change */
+
+ boolean explode; /* explode instead of change */
+
+ /* functions that are called before, while and after the change of an
+ element -- currently only used for non-custom elements */
+ void (*pre_change_function)(int x, int y);
+ void (*change_function)(int x, int y);
+ void (*post_change_function)(int x, int y);
};
struct ElementInfo
boolean use_gfx_element;
short gfx_element; /* optional custom graphic element */
- int collect_score; /* score value for collecting */
- int collect_gem_count; /* gem count value for collecting */
+ int score; /* score value for collecting */
+ int gem_count; /* gem count value for collecting */
int push_delay_fixed; /* constant frame delay for pushing */
int push_delay_random; /* additional random frame delay for pushing */