+ DrawText(x, y + 0 * tilesize, "content", font_nr);
+ DrawText(x, y + 1 * tilesize, "when", font_nr);
+ DrawText(x, y + 2 * tilesize, "smashed", font_nr);
+}
+
+static void DrawMagicBallContentAreas(void)
+{
+ int font_nr = FONT_TEXT_1;
+ int font_height = getFontHeight(font_nr);
+ int tilesize = ED_DRAWINGAREA_TILE_SIZE;
+ int yoffset = (tilesize - font_height) / 2;
+ int x = SX + ED_AREA_MAGIC_BALL_CONTENT_X(3) + 4 * tilesize;
+ int y = SY + ED_AREA_MAGIC_BALL_CONTENT_Y(3) + yoffset;
+ int i;
+
+ // display counter to choose number of element content areas
+ MapCounterButtons(ED_COUNTER_ID_BALL_CONTENT);
+
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
+ {
+ int id = ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 + i;
+
+ if (i < level.num_ball_contents)
+ {
+ MapDrawingArea(id);
+ }
+ else
+ {
+ UnmapDrawingArea(id);
+
+ // delete content areas in case of reducing number of them
+ RemoveElementContentArea(id, font_height);
+ }
+ }
+
+ DrawText(x, y + 0 * tilesize, "generated", font_nr);
+ DrawText(x, y + 1 * tilesize, "when", font_nr);
+ DrawText(x, y + 2 * tilesize, "active", font_nr);
+}
+
+static void DrawAndroidElementArea(void)
+{
+ int id = ED_DRAWING_ID_ANDROID_CONTENT;
+ int num_elements = level.num_android_clone_elements;
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_ANDROID_ELEMENTS;
+ int ysize = 1;
+
+ // display counter to choose number of element areas
+ MapCounterButtons(ED_COUNTER_ID_ANDROID_CONTENT);
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawGroupElementArea(void)
+{
+ int id = ED_DRAWING_ID_GROUP_CONTENT;
+ int num_elements = group_element_info.num_elements;
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_ELEMENTS_IN_GROUP;
+ int ysize = 1;
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawPlayerInitialInventoryArea(int element)
+{
+ int id = ED_DRAWING_ID_INVENTORY_CONTENT;
+ int player_nr = GET_PLAYER_NR(element);
+ int num_elements = level.initial_inventory_size[player_nr];
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_INITIAL_INVENTORY_SIZE;
+ int ysize = 1;
+
+ // determine horizontal position to the right of specified gadget
+ if (drawingarea_info[id].gadget_id_align != GADGET_ID_NONE)
+ sx = (right_gadget_border[drawingarea_info[id].gadget_id_align] +
+ ED_DRAWINGAREA_TEXT_DISTANCE);
+
+ // determine horizontal offset for leading text
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawMMBallContentArea(void)
+{
+ int id = ED_DRAWING_ID_MM_BALL_CONTENT;
+ int num_elements = level.num_mm_ball_contents;
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_MM_BALL_CONTENTS;
+ int ysize = 1;
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawEnvelopeTextArea(int envelope_nr)
+{
+ int id = ED_TEXTAREA_ID_ENVELOPE_INFO;
+ struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id];
+
+ UnmapGadget(gi);
+
+ DrawBackground(gi->x, gi->y,
+ gi->textarea.crop_width, gi->textarea.crop_height);
+
+ if (envelope_nr != -1)
+ textarea_info[id].value = level.envelope[envelope_nr].text;
+
+ ModifyGadget(gi, GDI_AREA_SIZE,
+ *counterbutton_info[ED_COUNTER_ID_ENVELOPE_XSIZE].value,
+ *counterbutton_info[ED_COUNTER_ID_ENVELOPE_YSIZE].value,
+ GDI_END);
+
+ MapTextAreaGadget(ED_TEXTAREA_ID_ENVELOPE_INFO);
+}
+
+static void DrawPropertiesInfo(void)
+{
+ static struct
+ {
+ int value;
+ char *text;
+ }
+ properties[] =
+ {
+ // configurable properties
+
+ { EP_WALKABLE_OVER, "- player can walk over it" },
+ { EP_WALKABLE_INSIDE, "- player can walk inside it" },
+ { EP_WALKABLE_UNDER, "- player can walk under it" },
+ { EP_PASSABLE_OVER, "- player can pass over it" },
+ { EP_PASSABLE_INSIDE, "- player can pass through it" },
+ { EP_PASSABLE_UNDER, "- player can pass under it" },
+ { EP_PROTECTED, "- player is protected by it" },
+
+ { EP_DIGGABLE, "- can be digged away" },
+ { EP_COLLECTIBLE, "- can be collected" },
+ { EP_DROPPABLE, "- can be dropped after collecting" },
+ { EP_THROWABLE, "- can be thrown after collecting" },
+ { EP_PUSHABLE, "- can be pushed" },
+
+ { EP_CAN_FALL, "- can fall" },
+ { EP_CAN_MOVE, "- can move" },
+
+ { EP_CAN_SMASH_PLAYER, "- can smash player" },
+#if 0
+ { EP_CAN_SMASH_ENEMIES, "- can smash good and bad guys" },
+#endif
+ { EP_CAN_SMASH_EVERYTHING, "- can smash everything smashable" },
+
+ { EP_SLIPPERY, "- slippery for falling elements" },
+ { EP_EM_SLIPPERY_WALL, "- slippery for some gems (EM style)" },
+
+ { EP_DONT_RUN_INTO, "- deadly when running into" },
+ { EP_DONT_COLLIDE_WITH, "- deadly when colliding with" },
+ { EP_DONT_GET_HIT_BY, "- deadly when getting hit by" },
+ { EP_DONT_TOUCH, "- deadly when touching" },
+
+ { EP_INDESTRUCTIBLE, "- indestructible" },
+
+ { EP_CAN_EXPLODE_BY_FIRE, "- can explode by fire or explosions" },
+ { EP_CAN_EXPLODE_SMASHED, "- can explode when smashed" },
+ { EP_CAN_EXPLODE_IMPACT, "- can explode on impact" },
+
+ { EP_CAN_CHANGE, "- can change to other element" },
+
+ // pre-defined properties
+ { EP_CAN_PASS_MAGIC_WALL, "- can pass magic walls" },
+ { EP_CAN_PASS_DC_MAGIC_WALL,"- can pass magic walls (DC style)" },
+ { EP_SWITCHABLE, "- can be switched" },
+#if 0
+ { EP_HAS_EDITOR_CONTENT, "- can contain other elements" },
+#endif
+
+ { -1, NULL }
+ };
+ char *filename = getElementDescriptionFilename(properties_element);
+ char *num_elements_text = "In this level: ";
+ char *num_similar_text = "Similar tiles: ";
+ char *properties_text = "Standard properties: ";
+ char *description_text = "Description:";
+ char *no_description_text = "No description available.";
+ char *none_text = "None";
+ float percentage;
+ int num_elements_in_level = 0;
+ int num_similar_in_level = 0;
+ int num_hires_tiles_in_level = 0;
+ int num_standard_properties = 0;
+ int font1_nr = FONT_TEXT_1;
+ int font2_nr = FONT_TEXT_2;
+ int font1_width = getFontWidth(font1_nr);
+ int font1_height = getFontHeight(font1_nr);
+ int font2_height = getFontHeight(font2_nr);
+ int line1_height = font1_height + ED_GADGET_LINE_DISTANCE;
+ int font2_yoffset = (font1_height - font2_height) / 2;
+ int num_elements_text_len = strlen(num_elements_text) * font1_width;
+ int num_similar_text_len = strlen(num_similar_text) * font1_width;
+ int properties_text_len = strlen(properties_text) * font1_width;
+ int xpos = ED_ELEMENT_SETTINGS_X(0);
+ int ypos = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
+ int i, x, y;
+
+ if (setup.editor.show_element_token)
+ {
+ int font3_nr = FONT_TEXT_3;
+ int font3_height = getFontHeight(font3_nr);
+
+ DrawTextF(xpos, ypos, font3_nr,
+ "[%s]", element_info[properties_element].token_name);
+
+ ypos += 2 * font3_height;
+ }
+
+ // ----- print number of elements / percentage of this element in level
+
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ if (Tile[x][y] == properties_element)
+ {
+ num_elements_in_level++;
+ }
+ else if (IS_MM_WALL(Tile[x][y]) &&
+ map_mm_wall_element(Tile[x][y]) == properties_element)
+ {
+ num_hires_tiles_in_level += numHiresTiles(Tile[x][y]);
+ }
+ }
+ }
+
+ percentage = num_elements_in_level * 100.0 / (lev_fieldx * lev_fieldy);
+
+ DrawTextS(xpos, ypos, font1_nr, num_elements_text);
+
+ if (num_hires_tiles_in_level > 0)
+ DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
+ "%d wall tiles", num_hires_tiles_in_level);
+ else if (num_elements_in_level > 0)
+ DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
+ "%d (%.2f %%)", num_elements_in_level, percentage);
+ else
+ DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
+ none_text);
+
+ // ----- print number of similar elements / percentage of them in level
+
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ if (strEqual(element_info[Tile[x][y]].class_name,
+ element_info[properties_element].class_name))
+ {
+ num_similar_in_level++;
+ }
+ }
+ }
+
+ if (num_similar_in_level != num_elements_in_level)
+ {
+ ypos += 1 * MAX(font1_height, font2_height);
+
+ percentage = num_similar_in_level * 100.0 / (lev_fieldx * lev_fieldy);
+
+ DrawTextS(xpos, ypos, font1_nr, num_similar_text);
+
+ if (num_similar_in_level > 0)
+ DrawTextF(xpos + num_similar_text_len, ypos + font2_yoffset, font2_nr,
+ "%d (%.2f %%)", num_similar_in_level, percentage);
+ else
+ DrawTextF(xpos + num_similar_text_len, ypos + font2_yoffset, font2_nr,
+ none_text);
+ }
+
+ ypos += 2 * MAX(font1_height, font2_height);
+
+ // ----- print standard properties of this element
+
+ DrawTextS(xpos, ypos, font1_nr, properties_text);
+
+ ypos += line1_height;
+
+ for (i = 0; properties[i].value != -1; i++)
+ {
+ if (!HAS_PROPERTY(properties_element, properties[i].value))
+ continue;
+
+ DrawTextS(xpos, ypos, font2_nr, properties[i].text);
+
+ ypos += font2_height;
+
+ num_standard_properties++;
+ }
+
+ if (num_standard_properties == 0)
+ {
+ DrawTextS(xpos + properties_text_len, ypos - line1_height + font2_yoffset,
+ font2_nr, none_text);
+
+ ypos -= (line1_height - font1_height);
+ }
+
+ ypos += MAX(font1_height, font2_height);
+
+ // ----- print special description of this element
+
+ PrintInfoText(description_text, font1_nr, xpos, ypos);
+
+ ypos += line1_height;
+
+ if (PrintElementDescriptionFromFile(filename, font2_nr, xpos, ypos) == 0)
+ PrintInfoText(no_description_text, font1_nr, xpos, ypos - line1_height);
+}
+
+#define TEXT_COLLECTING "Score for collecting"
+#define TEXT_COLLECTING_EXTRA "Score for extra diamonds"
+#define TEXT_SMASHING "Score for smashing"
+#define TEXT_SLURPING "Score for slurping robot"
+#define TEXT_CRACKING "Score for cracking"
+#define TEXT_AMOEBA_SPEED "Speed of amoeba growth"
+#define TEXT_AMOEBA_THRESHOED "Size for turning to rocks"
+#define TEXT_AMOEBA_SLOW_TIME "Slow growth time (seconds)"
+#define TEXT_AMOEBA_SLOW_RATE "Slow growth rate (percent)"
+#define TEXT_AMOEBA_FAST_RATE "Fast growth rate (percent)"
+#define TEXT_DURATION "Duration when activated"
+#define TEXT_DELAY_ON "Delay before activating"
+#define TEXT_DELAY_OFF "Delay before deactivating"
+#define TEXT_DELAY_CHANGING "Delay before changing"
+#define TEXT_DELAY_EXPLODING "Delay before exploding"
+#define TEXT_DELAY_MOVING "Delay before moving"
+#define TEXT_BALL_DELAY "Element generation delay"
+#define TEXT_MOVE_SPEED "Speed of android moving"
+#define TEXT_CLONE_SPEED "Speed of android cloning"
+#define TEXT_GAME_OF_LIFE_1 "Min neighbours to survive"
+#define TEXT_GAME_OF_LIFE_2 "Max neighbours to survive"
+#define TEXT_GAME_OF_LIFE_3 "Min neighbours to create"
+#define TEXT_GAME_OF_LIFE_4 "Max neighbours to create"
+#define TEXT_TIME_BONUS "Extra time to solve level"
+#define TEXT_TIME_PENALTY "Time penalty if destroyed"
+#define TEXT_PERMEABILITY_RATE "slime permeability rate"
+#define TEXT_PERMEABILITY_BITS "slime permeability bits"
+#define TEXT_RANDOM_SEED "slime random number seed"
+#define TEXT_ACID_SPREAD_RATE "Spread rate (percent)"
+#define TEXT_BITER_MOVE_DELAY "Move delay (BD frames)"
+#define TEXT_REPLICATION_DELAY "Create delay (BD frames)"
+#define TEXT_HAMMER_BREAK_DELAY "Delay for breaking walls"
+#define TEXT_HAMMER_REAPPEAR_DELAY "Delay for reappearing walls"
+#define TEXT_SKELETONS_NEEDED "Skeletons needed to use pot"
+#define TEXT_SKELETONS_WORTH "Counts as this many diamonds"
+#define TEXT_AUTO_TURN_DELAY "Creatures auto turn delay"
+#define TEXT_GRAVITY_DELAY "Gravity switch change delay"
+
+static struct
+{
+ int element;
+ int *value;
+ char *text;
+ int min_value;
+ int max_value;
+} elements_with_counter[] =
+{
+ { EL_EMERALD, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_BD_DIAMOND, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_BD_DIAMOND, &level.score[SC_DIAMOND_EXTRA], TEXT_COLLECTING_EXTRA },
+ { EL_EMERALD_YELLOW, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_EMERALD_RED, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_EMERALD_PURPLE, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_SP_INFOTRON, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_DIAMOND, &level.score[SC_DIAMOND], TEXT_COLLECTING },
+ { EL_CRYSTAL, &level.score[SC_CRYSTAL], TEXT_COLLECTING },
+ { EL_PEARL, &level.score[SC_PEARL], TEXT_COLLECTING },
+ { EL_BUG, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_RIGHT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_UP, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_LEFT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_DOWN, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_RIGHT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_UP, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_LEFT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_DOWN, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_SP_ELECTRON, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_SPACESHIP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_RIGHT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_DOWN, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_RIGHT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_DOWN, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SP_SNIKSNAK, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_LEFT, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_RIGHT, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_UP, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_DOWN, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_DARK_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_ROBOT, &level.score[SC_ROBOT], TEXT_SMASHING },
+ { EL_PACMAN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_RIGHT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_UP, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_LEFT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_DOWN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_NUT, &level.score[SC_NUT], TEXT_CRACKING },
+ { EL_DYNAMITE, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_EM_DYNAMITE, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_DYNABOMB_INCREASE_NUMBER,&level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_DYNABOMB_INCREASE_SIZE, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_DYNABOMB_INCREASE_POWER, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_SHIELD_NORMAL, &level.score[SC_SHIELD], TEXT_COLLECTING },
+ { EL_SHIELD_DEADLY, &level.score[SC_SHIELD], TEXT_COLLECTING },
+ { EL_EXTRA_TIME, &level.extra_time_score, TEXT_COLLECTING },
+ { EL_KEY_1, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_KEY_2, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_KEY_3, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_KEY_4, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_1, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_2, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_3, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_4, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_5, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_6, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_7, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_8, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_DC_KEY_WHITE, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_MM_KETTLE, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_DF_CELL, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_MM_KEY, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_MM_LIGHTBALL, &level.score[SC_ELEM_BONUS], TEXT_COLLECTING },
+ { EL_MM_PACMAN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_RIGHT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_UP, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_LEFT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_DOWN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_AMOEBA_WET, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_AMOEBA_DRY, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_AMOEBA_FULL, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_BD_AMOEBA, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_EMC_DRIPPER, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_BD_AMOEBA, &level.bd_amoeba_threshold_too_big, TEXT_AMOEBA_THRESHOED },
+ { EL_BD_AMOEBA, &level.bd_amoeba_slow_growth_time, TEXT_AMOEBA_SLOW_TIME },
+ { EL_BD_AMOEBA, &level.bd_amoeba_slow_growth_rate, TEXT_AMOEBA_SLOW_RATE,
+ 0, 100 },
+ { EL_BD_AMOEBA, &level.bd_amoeba_fast_growth_rate, TEXT_AMOEBA_FAST_RATE,
+ 0, 100 },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_threshold_too_big, TEXT_AMOEBA_THRESHOED },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_slow_growth_time, TEXT_AMOEBA_SLOW_TIME },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_slow_growth_rate, TEXT_AMOEBA_SLOW_RATE,
+ 0, 100 },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_fast_growth_rate, TEXT_AMOEBA_FAST_RATE,
+ 0, 100 },
+ { EL_MAGIC_WALL, &level.time_magic_wall, TEXT_DURATION },
+ { EL_BD_MAGIC_WALL, &level.time_magic_wall, TEXT_DURATION },
+ { EL_DC_MAGIC_WALL, &level.time_magic_wall, TEXT_DURATION },
+ { EL_ROBOT_WHEEL, &level.time_wheel, TEXT_DURATION },
+ { EL_TIMEGATE_SWITCH, &level.time_timegate, TEXT_DURATION },
+ { EL_DC_TIMEGATE_SWITCH, &level.time_timegate, TEXT_DURATION },
+ { EL_LIGHT_SWITCH, &level.time_light, TEXT_DURATION },
+ { EL_LIGHT_SWITCH_ACTIVE, &level.time_light, TEXT_DURATION },
+ { EL_SHIELD_NORMAL, &level.shield_normal_time, TEXT_DURATION },
+ { EL_SHIELD_DEADLY, &level.shield_deadly_time, TEXT_DURATION },
+ { EL_BD_CLOCK, &level.bd_clock_extra_time, TEXT_TIME_BONUS,
+ -100, 100 },
+ { EL_BD_VOODOO_DOLL, &level.bd_voodoo_penalty_time, TEXT_TIME_PENALTY,
+ 0, 100 },
+ { EL_BD_SLIME, &level.bd_slime_permeability_rate, TEXT_PERMEABILITY_RATE,
+ 0, 100 },
+ { EL_BD_SLIME, &level.bd_slime_permeability_bits_c64, TEXT_PERMEABILITY_BITS,
+ 0, 255 },
+ { EL_BD_SLIME, &level.bd_slime_random_seed_c64, TEXT_RANDOM_SEED,
+ -1, 65535 },
+ { EL_BD_ACID, &level.bd_acid_spread_rate, TEXT_ACID_SPREAD_RATE,
+ 0, 100 },
+ { EL_BD_BITER, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_RIGHT, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_UP, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_LEFT, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_DOWN, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_REPLICATOR, &level.bd_replicator_create_delay, TEXT_REPLICATION_DELAY,
+ 0, 100 },
+ { EL_BD_PNEUMATIC_HAMMER, &level.bd_hammer_walls_break_delay, TEXT_HAMMER_BREAK_DELAY,
+ 1, 100 },
+ { EL_BD_PNEUMATIC_HAMMER, &level.bd_hammer_walls_reappear_delay, TEXT_HAMMER_REAPPEAR_DELAY,
+ 1, 200 },
+ { EL_BD_POT, &level.bd_num_skeletons_needed_for_pot, TEXT_SKELETONS_NEEDED,
+ 0, 50 },
+ { EL_BD_SKELETON, &level.bd_num_skeletons_needed_for_pot, TEXT_SKELETONS_NEEDED,
+ 0, 50 },
+ { EL_BD_SKELETON, &level.bd_skeleton_worth_num_diamonds, TEXT_SKELETONS_WORTH,
+ 0, 10 },
+ { EL_BD_CREATURE_SWITCH, &level.bd_creatures_auto_turn_delay, TEXT_AUTO_TURN_DELAY },
+ { EL_BD_GRAVITY_SWITCH, &level.bd_gravity_switch_delay, TEXT_GRAVITY_DELAY,
+ 1, 60 },
+ { EL_EXTRA_TIME, &level.extra_time, TEXT_TIME_BONUS },
+ { EL_TIME_ORB_FULL, &level.time_orb_time, TEXT_TIME_BONUS },
+ { EL_GAME_OF_LIFE, &level.game_of_life[0], TEXT_GAME_OF_LIFE_1,0,8 },
+ { EL_GAME_OF_LIFE, &level.game_of_life[1], TEXT_GAME_OF_LIFE_2,0,8 },
+ { EL_GAME_OF_LIFE, &level.game_of_life[2], TEXT_GAME_OF_LIFE_3,0,8 },
+ { EL_GAME_OF_LIFE, &level.game_of_life[3], TEXT_GAME_OF_LIFE_4,0,8 },
+ { EL_BIOMAZE, &level.biomaze[0], TEXT_GAME_OF_LIFE_1,0,8 },
+ { EL_BIOMAZE, &level.biomaze[1], TEXT_GAME_OF_LIFE_2,0,8 },
+ { EL_BIOMAZE, &level.biomaze[2], TEXT_GAME_OF_LIFE_3,0,8 },
+ { EL_BIOMAZE, &level.biomaze[3], TEXT_GAME_OF_LIFE_4,0,8 },
+ { EL_EMC_ANDROID, &level.android_move_time, TEXT_MOVE_SPEED },
+ { EL_EMC_ANDROID, &level.android_clone_time, TEXT_CLONE_SPEED },
+ { EL_EMC_MAGIC_BALL, &level.ball_time, TEXT_BALL_DELAY },
+ { EL_EMC_LENSES, &level.lenses_score, TEXT_COLLECTING },
+ { EL_EMC_MAGNIFIER, &level.magnify_score, TEXT_COLLECTING },
+ { EL_SPRING, &level.slurp_score, TEXT_SLURPING },
+ { EL_SPRING_LEFT, &level.slurp_score, TEXT_SLURPING },
+ { EL_SPRING_RIGHT, &level.slurp_score, TEXT_SLURPING },
+ { EL_EMC_LENSES, &level.lenses_time, TEXT_DURATION },
+ { EL_EMC_MAGNIFIER, &level.magnify_time, TEXT_DURATION },
+ { EL_MM_FUSE_ACTIVE, &level.mm_time_fuse, TEXT_DELAY_OFF },
+ { EL_MM_BOMB, &level.mm_time_bomb, TEXT_DELAY_EXPLODING },
+ { EL_MM_GRAY_BALL, &level.mm_time_ball, TEXT_DELAY_CHANGING },
+ { EL_MM_STEEL_BLOCK, &level.mm_time_block, TEXT_DELAY_MOVING },
+ { EL_MM_WOODEN_BLOCK, &level.mm_time_block, TEXT_DELAY_MOVING },
+
+ { -1, NULL, NULL }
+};
+
+static boolean checkPropertiesConfig(int element)
+{
+ int i;
+
+ // special case: empty space customization only available in R'n'D game engine
+ if (element == EL_EMPTY_SPACE && level.game_engine_type != GAME_ENGINE_TYPE_RND)
+ return FALSE;
+
+ // special case: BD style rock customization only available in BD game engine
+ if (element == EL_BD_ROCK && level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ return FALSE;
+
+ if (IS_GEM(element) ||
+ IS_CUSTOM_ELEMENT(element) ||
+ IS_GROUP_ELEMENT(element) ||
+ IS_EMPTY_ELEMENT(element) ||
+ IS_BALLOON_ELEMENT(element) ||
+ IS_ENVELOPE(element) ||
+ IS_MM_ENVELOPE(element) ||
+ IS_MM_MCDUFFIN(element) ||
+ IS_DF_LASER(element) ||
+ IS_PLAYER_ELEMENT(element) ||
+ IS_BD_PLAYER_ELEMENT(element) ||
+ IS_BD_FIREFLY(properties_element) ||
+ IS_BD_FIREFLY_2(properties_element) ||
+ IS_BD_BUTTERFLY(properties_element) ||
+ IS_BD_BUTTERFLY_2(properties_element) ||
+ IS_BD_STONEFLY(properties_element) ||
+ IS_BD_DRAGONFLY(properties_element) ||
+ IS_BD_EXPANDABLE_WALL(properties_element) ||
+ IS_BD_EXPANDABLE_STEELWALL(properties_element) ||
+ IS_BD_CONVEYOR_BELT(properties_element) ||
+ IS_BD_CONVEYOR_BELT_SWITCH(properties_element) ||
+ IS_SOKOBAN_OBJECT_OR_FIELD(element) ||
+ HAS_EDITOR_CONTENT(element) ||
+ CAN_GROW(element) ||
+ COULD_MOVE_INTO_ACID(element) ||
+ MAYBE_DONT_COLLIDE_WITH(element) ||
+ element == EL_BD_SAND ||
+ element == EL_BD_ROCK ||
+ element == EL_BD_MEGA_ROCK ||
+ element == EL_BD_BOMB ||
+ element == EL_BD_ROCKET_LAUNCHER ||
+ element == EL_BD_NITRO_PACK ||
+ element == EL_BD_SWEET ||
+ element == EL_BD_VOODOO_DOLL ||
+ element == EL_BD_WATER ||
+ element == EL_BD_GRAVITY_SWITCH)
+ {
+ return TRUE;
+ }
+ else
+ {
+ for (i = 0; elements_with_counter[i].element != -1; i++)
+ if (elements_with_counter[i].element == element)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void SetAutomaticNumberOfGemsNeeded(void)
+{
+ int x, y;
+
+ if (!level.auto_count_gems)
+ return;
+
+ level.gems_needed = 0;
+
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ int element = Tile[x][y];
+
+ switch (element)
+ {
+ case EL_EMERALD:
+ case EL_EMERALD_YELLOW:
+ case EL_EMERALD_RED:
+ case EL_EMERALD_PURPLE:
+ case EL_BD_DIAMOND:
+ case EL_WALL_EMERALD:
+ case EL_WALL_EMERALD_YELLOW:
+ case EL_WALL_EMERALD_RED:
+ case EL_WALL_EMERALD_PURPLE:
+ case EL_WALL_BD_DIAMOND:
+ case EL_NUT:
+ case EL_SP_INFOTRON:
+ case EL_MM_KETTLE:
+ case EL_DF_CELL:
+ level.gems_needed++;
+ break;
+
+ case EL_DIAMOND:
+ case EL_WALL_DIAMOND:
+ level.gems_needed += 3;
+ break;
+
+ case EL_PEARL:
+ case EL_WALL_PEARL:
+ level.gems_needed += 5;
+ break;
+
+ case EL_CRYSTAL:
+ case EL_WALL_CRYSTAL:
+ level.gems_needed += 8;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ ModifyEditorCounterValue(ED_COUNTER_ID_LEVEL_GEMSLIMIT, level.gems_needed);
+}
+
+static void DrawPropertiesConfig(void)
+{
+ boolean draw_footer_line = FALSE;
+ int max_num_element_counters = 4;
+ int num_element_counters = 0;
+ int i;
+
+ if (!checkPropertiesConfig(properties_element))
+ {
+ int xpos = ED_ELEMENT_SETTINGS_X(0);
+ int ypos = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
+
+ PrintInfoText("No configuration options available.", FONT_TEXT_1, xpos, ypos);
+
+ return;
+ }
+
+ // check if there are elements where a value can be chosen for
+ for (i = 0; elements_with_counter[i].element != -1; i++)
+ {
+ if (elements_with_counter[i].element != properties_element)
+ continue;
+
+ // special case: score for extra diamonds only available in BD game engine
+ if (elements_with_counter[i].element == EL_BD_DIAMOND &&
+ elements_with_counter[i].value == &level.score[SC_DIAMOND_EXTRA] &&
+ level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ continue;
+
+ // special case: some amoeba counters only available in BD game engine
+ if (elements_with_counter[i].element == EL_BD_AMOEBA &&
+ elements_with_counter[i].value != &level.amoeba_speed &&
+ level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ continue;
+
+ // special case: score for smashing only available in R'n'D game engine
+ if ((IS_BD_FIREFLY(elements_with_counter[i].element) ||
+ IS_BD_BUTTERFLY(elements_with_counter[i].element)) &&
+ (elements_with_counter[i].value == &level.score[SC_BUG] ||
+ elements_with_counter[i].value == &level.score[SC_SPACESHIP]) &&
+ level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ continue;
+
+ // special case: some amoeba counters only available in R'n'D game engine
+ if (elements_with_counter[i].element == EL_BD_AMOEBA &&
+ elements_with_counter[i].value == &level.amoeba_speed &&
+ level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ continue;
+
+ int counter_id = ED_COUNTER_ID_ELEMENT_VALUE1 + num_element_counters;
+
+ counterbutton_info[counter_id].y =
+ ED_ELEMENT_SETTINGS_YPOS((HAS_EDITOR_CONTENT(properties_element) ? 1 : 0) +
+ (CAN_GROW(properties_element) ? 1 : 0) +
+ (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0) +
+ (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 : 0) +
+ (properties_element == EL_BD_VOODOO_DOLL ? 4 : 0) +
+ (properties_element == EL_BD_SLIME ? 1 : 0) +
+ (properties_element == EL_BD_ACID ? 1 : 0) +
+ (properties_element == EL_BD_REPLICATOR ? 1 : 0) +
+ (properties_element == EL_BD_CREATURE_SWITCH ? 1 : 0) +
+ (properties_element == EL_BD_GRAVITY_SWITCH ? 2 : 0) +
+ (properties_element == EL_EMC_MAGIC_BALL ? 2 : 0) +
+ num_element_counters);
+
+ // special case: set magic wall counter for BD game engine separately
+ if (properties_element == EL_BD_MAGIC_WALL && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ counterbutton_info[counter_id].y = ED_ELEMENT_SETTINGS_YPOS(1);
+
+ // special case: set amoeba counters for BD game engine separately
+ if ((properties_element == EL_BD_AMOEBA && level.game_engine_type == GAME_ENGINE_TYPE_BD) ||
+ (properties_element == EL_BD_AMOEBA_2))
+ counterbutton_info[counter_id].y = ED_ELEMENT_SETTINGS_YPOS(3 + num_element_counters);
+
+ // special case: set position for delay counter for reappearing hammered walls
+ if (properties_element == EL_BD_PNEUMATIC_HAMMER && num_element_counters > 0)
+ counterbutton_info[counter_id].y += 1;
+
+ counterbutton_info[counter_id].value = elements_with_counter[i].value;
+ counterbutton_info[counter_id].text_right = elements_with_counter[i].text;
+ counterbutton_info[counter_id].min_value = elements_with_counter[i].min_value;
+ counterbutton_info[counter_id].max_value = elements_with_counter[i].max_value;
+
+ // default: counter values between 0 and 999
+ if (counterbutton_info[counter_id].max_value == 0)
+ counterbutton_info[counter_id].max_value = 999;
+
+ MapCounterButtons(counter_id);
+
+ num_element_counters++;
+ if (num_element_counters >= max_num_element_counters)
+ break;
+ }
+
+ if (properties_element == EL_BD_MAGIC_WALL && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_ZERO_INFINITE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_WAIT_HATCHING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_STOPS_AMOEBA);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_BREAK_SCAN);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_DIAMOND_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_ROCK_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_MEGA_ROCK_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_NUT_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_NITRO_PACK_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_FLYING_DIAMOND_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_FLYING_ROCK_TO);
+ }
+
+ if (HAS_EDITOR_CONTENT(properties_element))
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ if (properties_element == EL_BD_AMOEBA && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_WAIT_FOR_HATCHING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_START_IMMEDIATELY);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_CONTENT_TOO_BIG);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_CONTENT_ENCLOSED);
+ }
+ else if (properties_element == EL_BD_AMOEBA_2)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_WAIT_FOR_HATCHING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_START_IMMEDIATELY);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_2_EXPLODE_BY_AMOEBA);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_TOO_BIG);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_ENCLOSED);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_EXPLODING);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_LOOKS_LIKE);
+ }
+ else if (IS_AMOEBOID(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_AMOEBA_CONTENT);
+ }
+ else if (properties_element == EL_BD_ACID)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_ACID_EATS_ELEMENT);
+ MapDrawingArea(ED_DRAWING_ID_BD_ACID_TURNS_TO_ELEMENT);
+ }
+ else if (IS_BD_BITER(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BITER_EATS_ELEMENT);
+ }
+ else if (properties_element == EL_BD_BLADDER)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BLADDER_CONVERTS_BY_ELEMENT);
+ }
+ else if (properties_element == EL_YAMYAM ||
+ properties_element == EL_YAMYAM_LEFT ||
+ properties_element == EL_YAMYAM_RIGHT ||
+ properties_element == EL_YAMYAM_UP ||
+ properties_element == EL_YAMYAM_DOWN)
+ {
+ DrawYamYamContentAreas();
+ }
+ else if (properties_element == EL_EMC_MAGIC_BALL)
+ {
+ DrawMagicBallContentAreas();
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_RANDOM_BALL_CONTENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_BALL_ACTIVE);
+ }
+ else if (properties_element == EL_EMC_ANDROID)
+ {
+ DrawAndroidElementArea();
+ }
+ else if (properties_element == EL_MM_GRAY_BALL)
+ {
+ MapCounterButtons(ED_COUNTER_ID_MM_BALL_CONTENT);
+ MapSelectboxGadget(ED_SELECTBOX_ID_MM_BALL_CHOICE_MODE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_ROTATE_MM_BALL_CONTENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EXPLODE_MM_BALL);
+
+ DrawMMBallContentArea();
+ }
+ }
+
+ if (IS_PLAYER_ELEMENT(properties_element))
+ {
+ int player_nr = GET_PLAYER_NR(properties_element);
+
+ // these properties can be set for every player individually
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_1)
+ {
+ drawingarea_info[ED_DRAWING_ID_START_ELEMENT].value =
+ &level.start_element[player_nr];
+ drawingarea_info[ED_DRAWING_ID_ARTWORK_ELEMENT].value =
+ &level.artwork_element[player_nr];
+ drawingarea_info[ED_DRAWING_ID_EXPLOSION_ELEMENT].value =
+ &level.explosion_element[player_nr];
+
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_START_ELEMENT].value =
+ &level.use_start_element[player_nr];
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT].value =
+ &level.use_artwork_element[player_nr];
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT].value =
+ &level.use_explosion_element[player_nr];
+ checkbutton_info[ED_CHECKBUTTON_ID_INITIAL_GRAVITY].value =
+ &level.initial_player_gravity[player_nr];
+
+ selectbox_info[ED_SELECTBOX_ID_PLAYER_SPEED].value =
+ &level.initial_player_stepsize[player_nr];
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID);
+ MapCheckbuttonGadget(properties_element == EL_SP_MURPHY ?
+ ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD :
+ ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INSTANT_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SHIFTED_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_LAZY_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_START_ELEMENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_GRAVITY);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SOLVED_BY_ONE_PLAYER);
+
+ MapDrawingArea(ED_DRAWING_ID_START_ELEMENT);
+ MapDrawingArea(ED_DRAWING_ID_ARTWORK_ELEMENT);
+ MapDrawingArea(ED_DRAWING_ID_EXPLOSION_ELEMENT);
+
+ MapSelectboxGadget(ED_SELECTBOX_ID_PLAYER_SPEED);
+ }
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
+ {
+ drawingarea_info[ED_DRAWING_ID_INVENTORY_CONTENT].value =
+ &level.initial_inventory_content[player_nr][0];
+
+ counterbutton_info[ED_COUNTER_ID_INVENTORY_SIZE].value =
+ &level.initial_inventory_size[player_nr];
+
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY].value =
+ &level.use_initial_inventory[player_nr];
+
+ // 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);
+
+ // draw drawing area gadgets
+ DrawPlayerInitialInventoryArea(properties_element);
+ }
+ }
+
+ if (IS_BD_PLAYER_ELEMENT(properties_element))
+ {
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB].y =
+ ED_ELEMENT_SETTINGS_YPOS(2);
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(3);
+ checkbutton_info[ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(4);
+
+ // draw checkbutton gadgets
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_DIAGONAL_MOVEMENTS);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_TOPMOST_PLAYER_ACTIVE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET);
+
+ // draw counter gadgets
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB);
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_BD_SNAP_ELEMENT);
+ }
+
+ if (properties_element == EL_BD_SAND)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_SAND_LOOKS_LIKE);
+ }
+
+ if (properties_element == EL_BD_ROCK && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB].y =
+ ED_ELEMENT_SETTINGS_YPOS(0);
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(1);
+
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB);
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_ROCK_TURNS_TO_ON_FALLING);
+ MapDrawingArea(ED_DRAWING_ID_BD_ROCK_TURNS_TO_ON_IMPACT);
+ }
+
+ if (properties_element == EL_BD_DIAMOND && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_TURNS_TO_ON_FALLING);
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_TURNS_TO_ON_IMPACT);
+ }
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ if (IS_BD_FIREFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_FIREFLY_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPLOSION_TURNS_TO);
+ }
+ else if (IS_BD_FIREFLY_2(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_FIREFLY_2_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPLOSION_TURNS_TO);
+ }
+ else if (IS_BD_BUTTERFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BUTTERFLY_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_BIRTH_TURNS_TO);
+ }
+ else if (IS_BD_BUTTERFLY_2(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BUTTERFLY_2_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_BIRTH_TURNS_TO);
+ }
+ else if (IS_BD_STONEFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_STONEFLY_EXPLODES_TO);
+ }
+ else if (IS_BD_DRAGONFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_DRAGONFLY_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPLOSION_TURNS_TO);
+ }
+ else if (properties_element == EL_BD_BOMB)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BOMB_EXPLOSION_TURNS_TO);
+ }
+ else if (properties_element == EL_BD_NITRO_PACK)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_NITRO_EXPLOSION_TURNS_TO);
+ }
+ }
+
+ if (properties_element == EL_BD_MEGA_ROCK ||
+ properties_element == EL_BD_SWEET)
+ {
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(0);
+ checkbutton_info[ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(1);
+
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET);
+ }
+
+ if (properties_element == EL_BD_VOODOO_DOLL)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_COLLECTS_DIAMONDS);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_HURT_KILLS_PLAYER);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_DIES_BY_ROCK);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_VANISH_BY_EXPLOSION);
+ }
+
+ if (properties_element == EL_BD_SLIME)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_SLIME_IS_PREDICTABLE);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_EATS_ELEMENT_1);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_CONVERTS_TO_ELEMENT_1);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_EATS_ELEMENT_2);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_CONVERTS_TO_ELEMENT_2);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_EATS_ELEMENT_3);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_CONVERTS_TO_ELEMENT_3);
+ }
+
+ if (IS_BD_EXPANDABLE_WALL(properties_element) ||
+ IS_BD_EXPANDABLE_STEELWALL(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CHANGE_EXPANDING_WALL);
+
+ if (IS_BD_EXPANDABLE_WALL(properties_element))
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPANDING_WALL_LOOKS_LIKE);
+ }
+
+ if (properties_element == EL_BD_REPLICATOR)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_REPLICATORS_ACTIVE);
+ }
+
+ if (IS_BD_CONVEYOR_BELT(properties_element) ||
+ IS_BD_CONVEYOR_BELT_SWITCH(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CONVEYOR_BELTS_ACTIVE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CONVEYOR_BELTS_CHANGED);
+ }
+
+ if (properties_element == EL_BD_WATER)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_WATER_CANNOT_FLOW_DOWN);
+ }
+
+ if (properties_element == EL_BD_PNEUMATIC_HAMMER)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_HAMMER_WALLS_REAPPEAR);
+ }
+
+ if (properties_element == EL_BD_ROCKET_LAUNCHER)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_INFINITE_ROCKETS);
+ }
+
+ if (properties_element == EL_BD_CREATURE_SWITCH)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CREATURES_START_BACKWARDS);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CREATURES_TURN_ON_HATCHING);
+ }
+
+ if (properties_element == EL_BD_GRAVITY_SWITCH)
+ {
+ MapSelectboxGadget(ED_SELECTBOX_ID_BD_GRAVITY_DIRECTION);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_GRAVITY_SWITCH_ACTIVE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_GRAVITY_AFFECTS_ALL);
+ }
+
+ if (properties_element == EL_BD_NUT)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_NUT_CONTENT);
+ }
+
+ // special case: slippery walls option for gems only available in R'n'D game engine
+ if (IS_GEM(properties_element) && level.game_engine_type == GAME_ENGINE_TYPE_RND)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS);
+
+ if (properties_element == EL_EM_DYNAMITE)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_EXPLODES_BY_FIRE);
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_RND &&
+ COULD_MOVE_INTO_ACID(properties_element) &&
+ !IS_PLAYER_ELEMENT(properties_element) &&
+ (!IS_CUSTOM_ELEMENT(properties_element) ||
+ edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2))
+ {
+ // set position for checkbutton for "can move into acid"
+ checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].x =
+ ED_ELEMENT_SETTINGS_XPOS(IS_CUSTOM_ELEMENT(properties_element) ? 1 : 0);
+ checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].y =
+ ED_ELEMENT_SETTINGS_YPOS(IS_CUSTOM_ELEMENT(properties_element) ? 7 :
+ IS_BALLOON_ELEMENT(properties_element) ||
+ HAS_EDITOR_CONTENT(properties_element) ? 1 : 0);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID);
+ }
+
+ if (MAYBE_DONT_COLLIDE_WITH(properties_element))
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH);
+
+ if (properties_element == EL_SPRING ||
+ properties_element == EL_SPRING_LEFT ||
+ properties_element == EL_SPRING_RIGHT)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_SPRING_BUG);
+
+ if (properties_element == EL_TIME_ORB_FULL)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_TIME_ORB_BUG);
+
+ if (properties_element == EL_GAME_OF_LIFE ||
+ properties_element == EL_BIOMAZE)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_LIFE_BUGS);
+
+ if (CAN_GROW(properties_element) && level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ {
+ checkbutton_info[ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE].y =
+ ED_ELEMENT_SETTINGS_YPOS(HAS_EDITOR_CONTENT(properties_element) ? 1 : 0);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE);
+ }
+
+ if (properties_element == EL_SOKOBAN_FIELD_EMPTY)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SB_FIELDS_NEEDED);
+
+ if (properties_element == EL_SOKOBAN_OBJECT)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SB_OBJECTS_NEEDED);
+
+ if (properties_element == EL_SOKOBAN_OBJECT ||
+ properties_element == EL_SOKOBAN_FIELD_EMPTY ||
+ properties_element == EL_SOKOBAN_FIELD_FULL)
+ {
+ checkbutton_info[ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN].y =
+ ED_ELEMENT_SETTINGS_XPOS(properties_element == EL_SOKOBAN_FIELD_FULL ?
+ 0 : 1);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN);
+ }
+
+ if (IS_BALLOON_ELEMENT(properties_element))
+ MapSelectboxGadget(ED_SELECTBOX_ID_WIND_DIRECTION);
+
+ if (IS_ENVELOPE(properties_element) ||
+ IS_MM_ENVELOPE(properties_element))
+ {
+ int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE;
+ int counter2_id = ED_COUNTER_ID_ENVELOPE_YSIZE;
+ int button1_id = ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP;
+ int button2_id = ED_CHECKBUTTON_ID_ENVELOPE_CENTERED;
+ int envelope_nr = ENVELOPE_NR(properties_element);
+
+ counterbutton_info[counter1_id].value = &level.envelope[envelope_nr].xsize;
+ counterbutton_info[counter2_id].value = &level.envelope[envelope_nr].ysize;
+
+ checkbutton_info[button1_id].value = &level.envelope[envelope_nr].autowrap;
+ checkbutton_info[button2_id].value = &level.envelope[envelope_nr].centered;
+
+ // display counter to choose size of envelope text area
+ MapCounterButtons(counter1_id);
+ MapCounterButtons(counter2_id);
+
+ // display checkbuttons to choose auto-wrap and alignment properties
+ MapCheckbuttonGadget(button1_id);
+ MapCheckbuttonGadget(button2_id);
+
+ DrawEnvelopeTextArea(envelope_nr);
+ }
+
+ if (IS_MM_MCDUFFIN(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_MM_LASER_RED);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_MM_LASER_GREEN);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_MM_LASER_BLUE);
+ }
+
+ if (IS_DF_LASER(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DF_LASER_RED);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DF_LASER_GREEN);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DF_LASER_BLUE);
+ }
+
+ if (IS_CUSTOM_ELEMENT(properties_element))
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_1)
+ {
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_CUSTOM1_FIRST;
+ i <= ED_CHECKBUTTON_ID_CUSTOM1_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_CUSTOM1_FIRST;
+ i <= ED_COUNTER_ID_CUSTOM1_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_CUSTOM1_FIRST;
+ i <= ED_SELECTBOX_ID_CUSTOM1_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw textbutton gadgets
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_1);
+
+ // draw text input gadgets
+ MapTextInputGadget(ED_TEXTINPUT_ID_ELEMENT_NAME);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+ draw_footer_line = TRUE;
+ }
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
+ {
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_CUSTOM2_FIRST;
+ i <= ED_CHECKBUTTON_ID_CUSTOM2_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_CUSTOM2_FIRST;
+ i <= ED_COUNTER_ID_CUSTOM2_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_CUSTOM2_FIRST;
+ i <= ED_SELECTBOX_ID_CUSTOM2_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_MOVE_ENTER);
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_MOVE_LEAVE);
+ DrawCustomContentArea();
+ }
+ }
+ else if (IS_GROUP_ELEMENT(properties_element))
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ // draw checkbutton gadgets
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE_1);
+
+ // draw counter gadgets
+ MapCounterButtons(ED_COUNTER_ID_GROUP_CONTENT);
+
+ // draw selectbox gadgets
+ MapSelectboxGadget(ED_SELECTBOX_ID_GROUP_CHOICE_MODE);
+
+ // draw textbutton gadgets
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_1);
+
+ // draw drawing area gadgets
+ DrawGroupElementArea();
+
+ // draw text input gadgets
+ MapTextInputGadget(ED_TEXTINPUT_ID_ELEMENT_NAME);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+ draw_footer_line = TRUE;
+ }
+ else if (IS_EMPTY_ELEMENT(properties_element))
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ // draw checkbutton gadgets
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE_1);
+
+ // draw textbutton gadgets
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_1);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+ draw_footer_line = TRUE;
+ }
+
+ // draw little footer border line above CE/GE use/save template gadgets
+ if (draw_footer_line)
+ {
+ struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_PROPERTIES_INFO];
+ struct GadgetDesign *gd = &gd_gi1->alt_design[GD_BUTTON_UNPRESSED];
+ int gd_x = gd->x + gd_gi1->border.width / 2;
+ int gd_y = gd->y + gd_gi1->height - 1;
+ Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y);
+
+ if (tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto,
+ SX + ED_ELEMENT_SETTINGS_X(0),
+ SY + ED_ELEMENT_SETTINGS_Y(14) - ED_SETTINGS_TABS_YOFFSET -
+ ED_TAB_BAR_HEIGHT,
+ getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
+ }
+}
+
+static void DrawPropertiesChangeDrawingAreas(void)
+{
+ if (IS_CUSTOM_ELEMENT(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_TARGET);
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER);
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_CHANGE_ACTION);
+
+ DrawCustomChangeContentArea();
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+static void DrawPropertiesChange(void)
+{
+ int i;
+
+ // needed to initially set selectbox options for special action options
+ setSelectboxSpecialActionOptions();
+
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_CHANGE_FIRST;
+ i <= ED_CHECKBUTTON_ID_CHANGE_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_CHANGE_FIRST;
+ i <= ED_COUNTER_ID_CHANGE_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_CHANGE_FIRST;
+ i <= ED_SELECTBOX_ID_CHANGE_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw textbutton gadgets
+ for (i = ED_TEXTBUTTON_ID_CHANGE_FIRST;
+ i <= ED_TEXTBUTTON_ID_CHANGE_LAST; i++)
+ MapTextbuttonGadget(i);
+
+ // draw graphicbutton gadgets
+ for (i = ED_GRAPHICBUTTON_ID_CHANGE_FIRST;
+ i <= ED_GRAPHICBUTTON_ID_CHANGE_LAST; i++)
+ MapGraphicbuttonGadget(i);
+
+ // draw drawing area gadgets
+ DrawPropertiesChangeDrawingAreas();
+}
+
+static void DrawEditorElementAnimation(int x, int y)
+{
+ int graphic;
+ int frame;
+
+ getEditorGraphicAndFrame(properties_element, &graphic, &frame, FALSE);
+
+ DrawFixedGraphicAnimationExt(drawto, x, y, graphic, frame, NO_MASKING);
+}
+
+static void DrawEditorElementName(int x, int y, int font_nr)
+{
+ char *element_name = getElementInfoText(properties_element);
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int max_text_width = SXSIZE - x - ED_ELEMENT_SETTINGS_X(0);
+ int max_chars_per_line = max_text_width / font_width;
+
+ if (strlen(element_name) <= max_chars_per_line)
+ DrawTextS(x, y, font_nr, element_name);
+ else
+ {
+ char buffer[max_chars_per_line + 1];
+ int next_pos = max_chars_per_line;
+
+ strncpy(buffer, element_name, max_chars_per_line);
+ buffer[max_chars_per_line] = '\0';
+
+ if (element_name[max_chars_per_line] == ' ')
+ next_pos++;
+ else
+ {
+ int i;
+
+ for (i = max_chars_per_line - 1; i >= 0; i--)
+ if (buffer[i] == ' ')
+ break;
+
+ if (strlen(&element_name[i + 1]) <= max_chars_per_line)
+ {
+ buffer[i] = '\0';
+ next_pos = i + 1;
+ }
+ }
+
+ DrawTextS(x, y - font_height / 2, font_nr, buffer);
+
+ strncpy(buffer, &element_name[next_pos], max_chars_per_line);
+ buffer[max_chars_per_line] = '\0';
+
+ DrawTextS(x, y + font_height / 2, font_nr, buffer);
+ }
+}
+
+static void DrawPropertiesWindow(void)
+{
+ struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_INPUT_TEXT];
+ int element_border = graphic_info[IMG_EDITOR_ELEMENT_BORDER].border_size;
+ int border_size = gd->border_size;
+ int font_nr = FONT_TEXT_1;
+ int font_height = getFontHeight(font_nr);
+ int xoffset = TILEX + element_border + 3 * border_size;
+ int yoffset = (TILEY - font_height) / 2;
+ int x1 = editor.settings.element_graphic.x + element_border;
+ int y1 = editor.settings.element_graphic.y + element_border;
+ int x2 = (editor.settings.element_name.x == -1 ? x1 + xoffset :
+ editor.settings.element_name.x);
+ int y2 = (editor.settings.element_name.y == -1 ? y1 + yoffset :
+ editor.settings.element_name.y);
+ char *text = "Element Settings";
+ int font2_nr = FONT_TITLE_1;
+ struct MenuPosInfo *pos = &editor.settings.headline;
+ int sx = SX + ALIGNED_XPOS(pos->x, getTextWidth(text, font2_nr), pos->align);
+ int sy = SY + pos->y;
+
+ stick_element_properties_window = FALSE;
+
+ // make sure that previous properties edit mode exists for this element
+ if (edit_mode_properties > ED_MODE_PROPERTIES_CONFIG_2 &&
+ !IS_CUSTOM_ELEMENT(properties_element))
+ edit_mode_properties = ED_MODE_PROPERTIES_CONFIG_2;
+
+ if (edit_mode_properties > ED_MODE_PROPERTIES_CONFIG &&
+ !IS_PLAYER_ELEMENT(properties_element) &&
+ !IS_CUSTOM_ELEMENT(properties_element))
+ edit_mode_properties = ED_MODE_PROPERTIES_CONFIG;
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG &&
+ (IS_PLAYER_ELEMENT(properties_element) ||
+ IS_CUSTOM_ELEMENT(properties_element)))
+ edit_mode_properties = ED_MODE_PROPERTIES_CONFIG_1;
+
+ CopyElementPropertiesToEditor(properties_element);
+
+ UnmapLevelEditorFieldGadgets();
+ UnmapLevelEditorToolboxDrawingGadgets();
+ UnmapLevelEditorToolboxCustomGadgets();
+
+ MapLevelEditorToolboxCustomGadgetsIfNeeded();
+
+ SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
+ ClearField();
+
+ DrawText(sx, sy, text, font2_nr);
+
+ FrameCounter = 0; // restart animation frame counter
+
+ DrawElementBorder(SX + x1, SY + y1, TILEX, TILEY, FALSE);
+ DrawEditorElementAnimation(SX + x1, SY + y1);
+ DrawEditorElementName(x2, y2, font_nr);
+
+ DrawPropertiesTabulatorGadgets();
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_INFO)
+ DrawPropertiesInfo();
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CHANGE)
+ DrawPropertiesChange();
+ else // (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG[_1|_2])
+ DrawPropertiesConfig();
+}
+
+static void DrawPaletteWindow(void)
+{
+ int i;
+
+ UnmapLevelEditorFieldGadgets();
+
+ SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
+ ClearField();
+
+ // map buttons to select elements
+ for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
+ MapGadget(level_editor_gadget[GADGET_ID_ELEMENTLIST_FIRST + i]);
+ MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL]);
+ MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_UP]);
+ MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_DOWN]);
+}
+
+static void UpdateCustomElementGraphicGadgets(void)
+{
+ int i;
+
+ InitElementPropertiesGfxElement();
+
+ ModifyEditorElementList();
+ RedrawDrawingElements();
+
+ // force redraw of all mapped drawing area gadgets
+ for (i = 0; i < ED_NUM_DRAWING_AREAS; i++)
+ {
+ struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[i].gadget_id];
+
+ if (gi->mapped)
+ MapDrawingArea(i);
+ }
+}
+
+static int getOpenDirectionFromTube(int element)
+{
+ switch (element)
+ {
+ case EL_TUBE_LEFT_UP: return (MV_LEFT | MV_UP);
+ case EL_TUBE_LEFT_DOWN: return (MV_LEFT | MV_DOWN);
+ case EL_TUBE_RIGHT_UP: return (MV_RIGHT | MV_UP);
+ case EL_TUBE_RIGHT_DOWN: return (MV_RIGHT | MV_DOWN);
+ case EL_TUBE_HORIZONTAL: return (MV_HORIZONTAL);
+ case EL_TUBE_HORIZONTAL_UP: return (MV_HORIZONTAL | MV_UP);
+ case EL_TUBE_HORIZONTAL_DOWN: return (MV_HORIZONTAL | MV_DOWN);
+ case EL_TUBE_VERTICAL: return (MV_VERTICAL);
+ case EL_TUBE_VERTICAL_LEFT: return (MV_VERTICAL | MV_LEFT);
+ case EL_TUBE_VERTICAL_RIGHT: return (MV_VERTICAL | MV_RIGHT);
+ case EL_TUBE_ANY: return (MV_ANY_DIRECTION);
+ }
+
+ return MV_NONE;
+}
+
+static int getTubeFromOpenDirection(int direction)
+{
+ switch (direction)
+ {
+ case (MV_LEFT | MV_UP): return EL_TUBE_LEFT_UP;
+ case (MV_LEFT | MV_DOWN): return EL_TUBE_LEFT_DOWN;
+ case (MV_RIGHT | MV_UP): return EL_TUBE_RIGHT_UP;
+ case (MV_RIGHT | MV_DOWN): return EL_TUBE_RIGHT_DOWN;
+ case (MV_HORIZONTAL): return EL_TUBE_HORIZONTAL;
+ case (MV_HORIZONTAL | MV_UP): return EL_TUBE_HORIZONTAL_UP;
+ case (MV_HORIZONTAL | MV_DOWN): return EL_TUBE_HORIZONTAL_DOWN;
+ case (MV_VERTICAL): return EL_TUBE_VERTICAL;
+ case (MV_VERTICAL | MV_LEFT): return EL_TUBE_VERTICAL_LEFT;
+ case (MV_VERTICAL | MV_RIGHT): return EL_TUBE_VERTICAL_RIGHT;
+ case (MV_ANY_DIRECTION): return EL_TUBE_ANY;
+
+ // if only one direction, fall back to simple tube with that direction
+ case (MV_LEFT): return EL_TUBE_HORIZONTAL;
+ case (MV_RIGHT): return EL_TUBE_HORIZONTAL;
+ case (MV_UP): return EL_TUBE_VERTICAL;
+ case (MV_DOWN): return EL_TUBE_VERTICAL;
+ }
+
+ return EL_EMPTY;
+}
+
+static int getTubeFromOpenDirectionNotEmpty(int direction, int element_old)
+{
+ int element_new = getTubeFromOpenDirection(direction);
+
+ return (element_new != EL_EMPTY ? element_new : element_old);
+}
+
+static int getOpenDirectionFromBelt(int element)
+{
+ int belt_dir = getBeltDirFromBeltElement(element);
+
+ return (belt_dir == MV_LEFT ? MV_RIGHT :
+ belt_dir == MV_RIGHT ? MV_LEFT :
+ belt_dir == MV_NONE ? MV_HORIZONTAL : belt_dir);
+}
+
+static int getBeltFromNrAndOpenDirection(int nr, int direction)
+{
+ int belt_dir = (direction == MV_LEFT ? MV_RIGHT :
+ direction == MV_RIGHT ? MV_LEFT :
+ direction == MV_HORIZONTAL ? MV_NONE : direction);
+
+ if (direction == MV_NONE)
+ return EL_EMPTY;
+
+ return getBeltElementFromBeltNrAndBeltDir(nr, belt_dir);
+}
+
+static int getBeltFromNrAndOpenDirectionNotEmpty(int nr, int direction,
+ int element_old)
+{
+ int element_new = getBeltFromNrAndOpenDirection(nr, direction);
+
+ return (element_new != EL_EMPTY ? element_new : element_old);
+}
+
+static int getOpenDirectionFromPool(int element)
+{
+ switch (element)
+ {
+ case EL_ACID_POOL_TOPLEFT: return (MV_DOWN | MV_RIGHT);
+ case EL_ACID_POOL_TOPRIGHT: return (MV_DOWN | MV_LEFT);
+ case EL_ACID_POOL_BOTTOMLEFT: return (MV_UP | MV_RIGHT);
+ case EL_ACID_POOL_BOTTOMRIGHT: return (MV_UP | MV_LEFT);
+ case EL_ACID_POOL_BOTTOM: return (MV_HORIZONTAL | MV_UP);
+ case EL_ACID: return (MV_HORIZONTAL | MV_DOWN);
+ }
+
+ return MV_NONE;
+}
+
+static int getPoolFromOpenDirection(int direction)
+{
+ switch (direction)
+ {
+ case (MV_DOWN | MV_RIGHT): return EL_ACID_POOL_TOPLEFT;
+ case (MV_DOWN | MV_LEFT): return EL_ACID_POOL_TOPRIGHT;
+ case (MV_UP | MV_RIGHT): return EL_ACID_POOL_BOTTOMLEFT;
+ case (MV_UP | MV_LEFT): return EL_ACID_POOL_BOTTOMRIGHT;
+ case (MV_HORIZONTAL | MV_UP): return EL_ACID_POOL_BOTTOM;
+ case (MV_HORIZONTAL | MV_DOWN): return EL_ACID;
+ }
+
+ return EL_EMPTY;
+}
+
+static int getPoolFromOpenDirectionExt(int direction, int help_element)
+{
+ int element = getPoolFromOpenDirection(direction);
+ int help_direction = getOpenDirectionFromPool(help_element);
+
+ if (element == EL_EMPTY)
+ {
+ int help_direction_vertical = help_direction & MV_VERTICAL;
+
+ element = getPoolFromOpenDirection(direction | help_direction_vertical);
+ }
+
+ if (element == EL_EMPTY)
+ {
+ int help_direction_horizontal = help_direction & MV_HORIZONTAL;
+
+ element = getPoolFromOpenDirection(direction | help_direction_horizontal);
+ }
+
+ return element;
+}
+
+static int getPoolFromOpenDirectionNotEmpty(int direction, int element_old)
+{
+ int element_new = getPoolFromOpenDirectionExt(direction, element_old);
+
+ return (element_new != EL_EMPTY ? element_new : element_old);
+}
+
+static int getOpenDirectionFromPillar(int element)
+{
+ switch (element)
+ {
+ case EL_EMC_WALL_1: return (MV_DOWN);
+ case EL_EMC_WALL_2: return (MV_VERTICAL);
+ case EL_EMC_WALL_3: return (MV_UP);
+ }
+
+ return MV_NONE;
+}
+
+static int getPillarFromOpenDirection(int direction)
+{
+ switch (direction)
+ {
+ case (MV_DOWN): return EL_EMC_WALL_1;
+ case (MV_VERTICAL): return EL_EMC_WALL_2;
+ case (MV_UP): return EL_EMC_WALL_3;
+ }
+
+ return EL_EMPTY;
+}
+
+static int getPillarFromOpenDirectionNotEmpty(int direction, int element_old)
+{
+ int element_new = getPillarFromOpenDirection(direction);
+
+ return (element_new != EL_EMPTY ? element_new : element_old);
+}
+
+static int getOpenDirectionFromSteel2(int element)
+{
+ switch (element)
+ {
+ case EL_DC_STEELWALL_2_LEFT: return (MV_RIGHT);
+ case EL_DC_STEELWALL_2_RIGHT: return (MV_LEFT);
+ case EL_DC_STEELWALL_2_TOP: return (MV_DOWN);
+ case EL_DC_STEELWALL_2_BOTTOM: return (MV_UP);
+ case EL_DC_STEELWALL_2_HORIZONTAL: return (MV_HORIZONTAL);
+ case EL_DC_STEELWALL_2_VERTICAL: return (MV_VERTICAL);
+ case EL_DC_STEELWALL_2_MIDDLE: return (MV_ANY_DIRECTION);
+ case EL_DC_STEELWALL_2_SINGLE: return (MV_NONE);
+ }
+
+ return MV_NONE;
+}
+
+static int getSteel2FromOpenDirection(int direction)
+{
+ switch (direction)
+ {
+ case (MV_RIGHT): return EL_DC_STEELWALL_2_LEFT;
+ case (MV_LEFT): return EL_DC_STEELWALL_2_RIGHT;
+ case (MV_DOWN): return EL_DC_STEELWALL_2_TOP;
+ case (MV_UP): return EL_DC_STEELWALL_2_BOTTOM;
+ case (MV_HORIZONTAL): return EL_DC_STEELWALL_2_HORIZONTAL;
+ case (MV_VERTICAL): return EL_DC_STEELWALL_2_VERTICAL;
+ case (MV_ANY_DIRECTION): return EL_DC_STEELWALL_2_MIDDLE;
+ case (MV_NONE): return EL_DC_STEELWALL_2_SINGLE;
+ }
+
+ return EL_EMPTY;
+}
+
+static int getSteel2FromOpenDirectionNotEmpty(int direction, int element_old)
+{
+ int element_new = getSteel2FromOpenDirection(direction);
+
+ return (element_new != EL_EMPTY ? element_new : element_old);
+}
+
+static int getOpenDirectionFromChip(int element)
+{
+ switch (element)
+ {
+ case EL_SP_CHIP_SINGLE: return (MV_NONE);
+ case EL_SP_CHIP_LEFT: return (MV_RIGHT);
+ case EL_SP_CHIP_RIGHT: return (MV_LEFT);
+ case EL_SP_CHIP_TOP: return (MV_DOWN);
+ case EL_SP_CHIP_BOTTOM: return (MV_UP);
+ }
+
+ return MV_NONE;
+}
+
+static int getChipFromOpenDirection(int direction)
+{
+ switch (direction)
+ {
+ case (MV_NONE): return EL_SP_CHIP_SINGLE;
+ case (MV_LEFT): return EL_SP_CHIP_RIGHT;
+ case (MV_RIGHT): return EL_SP_CHIP_LEFT;
+ case (MV_UP): return EL_SP_CHIP_BOTTOM;
+ case (MV_DOWN): return EL_SP_CHIP_TOP;
+ }
+
+ return EL_EMPTY;
+}
+
+static int getChipFromOpenDirectionNotEmpty(int direction, int element_old)
+{
+ int element_new = getChipFromOpenDirection(direction);
+
+ return (element_new != EL_EMPTY ? element_new : element_old);
+}
+
+static int getClosedTube(int x, int y)
+{
+ struct XY *xy = xy_directions;
+ int element_old = IntelliDrawBuffer[x][y];
+ int direction_old = getOpenDirectionFromTube(element_old);
+ int direction_new = MV_NONE;
+ int i;
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
+ {
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int dir = MV_DIR_FROM_BIT(i);
+ int dir_opposite = MV_DIR_OPPOSITE(dir);
+
+ if (IN_LEV_FIELD(xx, yy) && IS_TUBE(IntelliDrawBuffer[xx][yy]) &&
+ (direction_old & dir) &&
+ (getOpenDirectionFromTube(IntelliDrawBuffer[xx][yy]) & dir_opposite))
+ direction_new |= dir;
+ }
+
+ return getTubeFromOpenDirectionNotEmpty(direction_new, element_old);
+}
+
+static int getClosedBelt(int x, int y)
+{
+ struct XY *xy = xy_directions;
+ int element_old = IntelliDrawBuffer[x][y];
+ int nr = getBeltNrFromBeltElement(element_old);
+ int direction_old = getOpenDirectionFromBelt(element_old);
+ int direction_new = MV_NONE;
+ int i;
+
+ for (i = MV_BIT_LEFT; i <= MV_BIT_RIGHT; i++)
+ {
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int dir = MV_DIR_FROM_BIT(i);
+ int dir_opposite = MV_DIR_OPPOSITE(dir);
+
+ if (IN_LEV_FIELD(xx, yy) && IS_BELT(IntelliDrawBuffer[xx][yy]) &&
+ (direction_old & dir) &&
+ (getOpenDirectionFromBelt(IntelliDrawBuffer[xx][yy]) & dir_opposite))
+ direction_new |= dir;
+ }
+
+ return getBeltFromNrAndOpenDirection(nr, direction_new);
+}
+
+static int getClosedPool(int x, int y)
+{
+ struct XY *xy = xy_directions;
+ int element_old = IntelliDrawBuffer[x][y];
+ int direction_old = getOpenDirectionFromPool(element_old);
+ int direction_new = MV_NONE;
+ int i;
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
+ {
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int dir = MV_DIR_FROM_BIT(i);
+ int dir_opposite = MV_DIR_OPPOSITE(dir);
+
+ if (IN_LEV_FIELD(xx, yy) &&
+ IS_ACID_POOL_OR_ACID(IntelliDrawBuffer[xx][yy]) &&
+ (direction_old & dir) &&
+ (getOpenDirectionFromPool(IntelliDrawBuffer[xx][yy]) & dir_opposite))
+ direction_new |= dir;
+ }
+
+ return getPoolFromOpenDirectionNotEmpty(direction_new, element_old);
+}
+
+static int getClosedPillar(int x, int y)
+{
+ struct XY *xy = xy_directions;
+ int element_old = IntelliDrawBuffer[x][y];
+ int direction_old = getOpenDirectionFromPillar(element_old);
+ int direction_new = MV_NONE;
+ int i;
+
+ for (i = MV_BIT_UP; i <= MV_BIT_DOWN; i++)
+ {
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int dir = MV_DIR_FROM_BIT(i);
+ int dir_opposite = MV_DIR_OPPOSITE(dir);
+
+ if (IN_LEV_FIELD(xx, yy) && IS_EMC_PILLAR(IntelliDrawBuffer[xx][yy]) &&
+ (direction_old & dir) &&
+ (getOpenDirectionFromPillar(IntelliDrawBuffer[xx][yy]) & dir_opposite))
+ direction_new |= dir;
+ }
+
+ return getPillarFromOpenDirectionNotEmpty(direction_new, element_old);
+}
+
+static int getClosedSteel2(int x, int y)
+{
+ struct XY *xy = xy_directions;
+ int element_old = IntelliDrawBuffer[x][y];
+ int direction_old = getOpenDirectionFromSteel2(element_old);
+ int direction_new = MV_NONE;
+ int i;
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
+ {
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int dir = MV_DIR_FROM_BIT(i);
+ int dir_opposite = MV_DIR_OPPOSITE(dir);
+
+ if (IN_LEV_FIELD(xx, yy) && IS_DC_STEELWALL_2(IntelliDrawBuffer[xx][yy]) &&
+ (direction_old & dir) &&
+ (getOpenDirectionFromSteel2(IntelliDrawBuffer[xx][yy]) & dir_opposite))
+ direction_new |= dir;
+ }
+
+ return getSteel2FromOpenDirectionNotEmpty(direction_new, element_old);
+}
+
+static int getClosedChip(int x, int y)
+{
+ struct XY *xy = xy_directions;
+ int element_old = IntelliDrawBuffer[x][y];
+ int direction_old = getOpenDirectionFromChip(element_old);
+ int direction_new = MV_NONE;
+ int i;
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
+ {
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int dir = MV_DIR_FROM_BIT(i);
+ int dir_opposite = MV_DIR_OPPOSITE(dir);
+
+ if (IN_LEV_FIELD(xx, yy) && IS_SP_CHIP(IntelliDrawBuffer[xx][yy]) &&
+ (direction_old & dir) &&
+ (getOpenDirectionFromChip(IntelliDrawBuffer[xx][yy]) & dir_opposite))
+ direction_new |= dir;
+ }
+
+ return getChipFromOpenDirectionNotEmpty(direction_new, element_old);
+}
+
+static void SetElementSimpleExt(int x, int y, int dx, int dy, int element,
+ boolean change_level)
+{
+ int sx = x - level_xpos;
+ int sy = y - level_ypos;
+ int old_element = Tile[x][y];
+ int new_element = element;
+ unsigned int new_bitmask = (getDrawModeHiRes() ? (dx + 1) << (dy * 2) : 0x0f);
+ boolean draw_masked = FALSE;
+
+ if (IS_MM_WALL_EDITOR(element))
+ {
+ element = map_mm_wall_element_editor(element) | new_bitmask;
+
+ if (IS_MM_WALL(old_element))
+ element |= MM_WALL_BITS(old_element);
+
+ if (!change_level)
+ draw_masked = TRUE;
+ }
+ else if (IS_MM_WALL(old_element) && element == EL_EMPTY)
+ {
+ int element_changed = old_element & ~new_bitmask;
+
+ if (MM_WALL_BITS(element_changed) != 0)
+ element = element_changed;
+ }
+
+ IntelliDrawBuffer[x][y] = element;
+
+ if (change_level)
+ Tile[x][y] = element;
+
+ if (IN_ED_FIELD(sx, sy))
+ {
+ if (IS_MM_WALL(old_element) && new_element == EL_EMPTY)
+ DrawSizedWallParts_MM(sx, sy, EL_EMPTY, ed_tilesize, FALSE, new_bitmask);
+ else if (draw_masked)
+ DrawEditorElementThruMask(sx, sy, element);
+ else
+ DrawEditorElement(sx, sy, element);
+ }
+}
+
+static void SetElementSimple(int x, int y, int element, boolean change_level)
+{
+ SetElementSimpleExt(x, y, 0, 0, element, change_level);
+}
+
+static void MergeAndCloseNeighbourElements(int x1, int y1, int *element1,
+ int x2, int y2, int *element2,
+ int (*close_function)(int, int),
+ boolean change_level)
+{
+ // set neighbour elements to newly determined connections
+ SetElementSimple(x1, y1, *element1, change_level);
+ SetElementSimple(x2, y2, *element2, change_level);
+
+ // remove all open connections of neighbour elements
+ *element1 = close_function(x1, y1);
+ *element2 = close_function(x2, y2);
+
+ // set neighbour elements to new, minimized connections
+ SetElementSimple(x1, y1, *element1, change_level);
+ SetElementSimple(x2, y2, *element2, change_level);
+}
+
+static void SetElementIntelliDraw(int x, int y, int dx, int dy, int new_element,
+ boolean change_level, int button)
+{
+ struct XY *xy = xy_directions;
+ static int last_x = -1;
+ static int last_y = -1;
+
+ if (new_element == EL_UNDEFINED)
+ {
+ last_x = -1;
+ last_y = -1;
+
+ return;
+ }
+
+ int old_element = IntelliDrawBuffer[x][y];