GADGET_ID_DF_LASER_GREEN,
GADGET_ID_DF_LASER_BLUE,
GADGET_ID_ROTATE_MM_BALL_CONTENT,
+ GADGET_ID_EXPLODE_MM_BALL,
GADGET_ID_CUSTOM_INDESTRUCTIBLE,
GADGET_ID_CUSTOM_CAN_EXPLODE,
GADGET_ID_CUSTOM_EXPLODE_FIRE,
ED_CHECKBUTTON_ID_DF_LASER_GREEN,
ED_CHECKBUTTON_ID_DF_LASER_BLUE,
ED_CHECKBUTTON_ID_ROTATE_MM_BALL_CONTENT,
+ ED_CHECKBUTTON_ID_EXPLODE_MM_BALL,
ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC,
ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE_1,
ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE,
NULL, NULL,
"randomly rotate created content", "randomly rotate newly created content"
},
+ {
+ ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(6),
+ GADGET_ID_EXPLODE_MM_BALL, GADGET_ID_NONE,
+ &level.explode_mm_ball,
+ NULL, NULL,
+ "explode ball instead of melting", "use explosion to release ball content"
+ },
// ---------- element settings: configure 1 (custom elements) ---------------
static int getTabulatorBarWidth(void);
static int getTabulatorBarHeight(void);
static Pixel getTabulatorBarColor(void);
+static int numHiresTiles(int);
static int num_editor_gadgets = 0; // dynamically determined
// find all elements used in current level
for (y = 0; y < lev_fieldy; y++)
+ {
for (x = 0; x < lev_fieldx; x++)
- if (Tile[x][y] < NUM_FILE_ELEMENTS) // should always be true
+ {
+ if (Tile[x][y] >= NUM_FILE_ELEMENTS) // should never happen
+ continue;
+
+ if (IS_MM_WALL(Tile[x][y]))
+ element_found[map_mm_wall_element(Tile[x][y])] = TRUE;
+ else
element_found[Tile[x][y]] = TRUE;
+ }
+ }
*num_elements = 0;
*num_elements = 0;
- // add all elements used in current level (non-custom/group elements)
+ // add all elements used in current level (non-custom/group/empty elements)
for (i = 0; i < NUM_FILE_ELEMENTS; i++)
- if (element_found[i] && !(IS_CUSTOM_ELEMENT(i) || IS_GROUP_ELEMENT(i)))
+ if (element_found[i] && !(IS_CUSTOM_ELEMENT(i) ||
+ IS_GROUP_ELEMENT(i) ||
+ IS_EMPTY_ELEMENT(i)))
(*elements)[(*num_elements)++] = i;
- // add all elements used in current level (custom/group elements)
+ // add all elements used in current level (custom/group/empty elements)
for (i = 0; i < NUM_FILE_ELEMENTS; i++)
- if (element_found[i] && (IS_CUSTOM_ELEMENT(i) || IS_GROUP_ELEMENT(i)))
+ if (element_found[i] && (IS_CUSTOM_ELEMENT(i) ||
+ IS_GROUP_ELEMENT(i) ||
+ IS_EMPTY_ELEMENT(i)))
(*elements)[(*num_elements)++] = i;
while (*num_elements % 4) // pad with empty elements, if needed
{ -1, NULL }
};
char *filename = getElementDescriptionFilename(properties_element);
- char *percentage_text = "In this level: ";
+ 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;
+ 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 font2_height = getFontHeight(font2_nr);
int line1_height = font1_height + ED_GADGET_LINE_DISTANCE;
int font2_yoffset = (font1_height - font2_height) / 2;
- int percentage_text_len = strlen(percentage_text) * font1_width;
+ 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;
// ----- print number of elements / percentage of this element in level
- num_elements_in_level = 0;
- for (y = 0; y < lev_fieldy; y++)
+ 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, percentage_text);
+ DrawTextS(xpos, ypos, font1_nr, num_elements_text);
- if (num_elements_in_level > 0)
- DrawTextF(xpos + percentage_text_len, ypos + font2_yoffset, font2_nr,
+ 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 + percentage_text_len, ypos + font2_yoffset, font2_nr,
+ 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
#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"
{ 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_ON },
+ { 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 },
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();
}
SetElementSimple(x2, y2, *element2, change_level);
}
-static void SetElementIntelliDraw(int x, int y, int new_element,
+static void SetElementIntelliDraw(int x, int y, int dx, int dy, int new_element,
boolean change_level, int button)
{
struct XY *xy = xy_directions;
}
}
- SetElementSimple(x, y, new_element, change_level);
+ if (IS_MM_WALL_EDITOR(new_element))
+ SetElementSimpleExt(x, y, dx, dy, new_element, change_level);
+ else
+ SetElementSimple(x, y, new_element, change_level);
last_x = x;
last_y = y;
for (y = 0; y < lev_fieldy; y++)
IntelliDrawBuffer[x][y] = Tile[x][y];
- SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE, -1);
+ SetElementIntelliDraw(-1, -1, -1, -1, EL_UNDEFINED, FALSE, -1);
}
static boolean draw_mode_hires = FALSE;
return (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY);
}
+static int numHiresTiles(int element)
+{
+ if (!IS_MM_WALL(element))
+ return 1;
+
+ int bits = MM_WALL_BITS(element);
+ int num_bits = 0;
+
+ while (bits)
+ {
+ bits &= bits - 1;
+ num_bits++;
+ }
+
+ return num_bits;
+}
+
static void SetDrawModeHiRes(int element)
{
draw_mode_hires =
{
if (element < 0)
SetElementSimple(x, y, Tile[x][y], change_level);
- else if (GetKeyModState() & KMOD_Shift && !IS_MM_WALL_EDITOR(element))
- SetElementIntelliDraw(x, y, element, change_level, button);
+ else if (GetKeyModState() & KMOD_Shift)
+ SetElementIntelliDraw(x, y, dx, dy, element, change_level, button);
else
SetElementSimpleExt(x, y, dx, dy, element, change_level);
}
static void HandleDrawingAreas(struct GadgetInfo *gi)
{
static boolean started_inside_drawing_area = FALSE;
+ static int last_sx = -1;
+ static int last_sy = -1;
+ static int last_sx2 = -1;
+ static int last_sy2 = -1;
int id = gi->custom_id;
int type_id = gi->custom_type_id;
boolean button_press_event;
if (!button_press_event && !button_release_event)
{
- static int last_sx = -1;
- static int last_sy = -1;
- static int last_sx2 = -1;
- static int last_sy2 = -1;
int old_element = (IN_LEV_FIELD(lx, ly) ? Tile[lx][ly] : EL_UNDEFINED);
boolean hires_drawing = (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
isHiresTileElement(old_element) &&
if ((sx == last_sx && sy == last_sy && !hires_drawing) ||
(sx2 == last_sx2 && sy2 == last_sy2))
return;
-
- last_sx = sx;
- last_sy = sy;
- last_sx2 = sx2;
- last_sy2 = sy2;
}
+ last_sx = sx;
+ last_sy = sy;
+ last_sx2 = sx2;
+ last_sy2 = sy2;
+
if (button_press_event)
started_inside_drawing_area = inside_drawing_area;
{
SetDrawModeHiRes(new_element);
- if (IS_PLAYER_ELEMENT(new_element))
+ if (IS_PLAYER_ELEMENT(new_element) || IS_MM_MCDUFFIN(new_element))
{
// remove player at old position
for (y = 0; y < lev_fieldy; y++)
{
int old_element = Tile[x][y];
- if (IS_PLAYER_ELEMENT(old_element))
+ if (IS_PLAYER_ELEMENT(old_element) &&
+ IS_PLAYER_ELEMENT(new_element))
{
int replaced_with_element =
(old_element == EL_SOKOBAN_FIELD_PLAYER &&
SetElement(x, y, replaced_with_element);
}
+ else if (IS_MM_MCDUFFIN(old_element) &&
+ IS_MM_MCDUFFIN(new_element))
+ {
+ // remove McDuffin at old position
+ SetElement(x, y, EL_EMPTY);
+ }
}
}
}