-#define COMPILE_DATE_STRING "[2003-05-02 17:40]"
+#define COMPILE_DATE_STRING "[2003-05-02 20:55]"
static boolean random_placement_background_restricted = FALSE;
static boolean stick_element_properties_window = FALSE;
static boolean custom_element_properties[NUM_ELEMENT_PROPERTIES];
-static boolean custom_element_changes[42];
-static int custom_element_change_delay[2];
+static boolean custom_element_change_events[NUM_CHANGE_EVENTS];
+static struct CustomElementChangeInfo custom_element_change;
static struct
{
0, 999,
GADGET_ID_CHANGE_DELAY_FIX_DOWN, GADGET_ID_CHANGE_DELAY_FIX_UP,
GADGET_ID_CHANGE_DELAY_FIX_TEXT,
- &custom_element_change_delay[0],
- NULL, "frames (fixed)"
+ &custom_element_change.delay_fixed,
+ NULL, "seconds (fixed)"
},
{
ED_COUNT_CHANGE_DELAY_XPOS, ED_COUNTER_YPOS2(6),
0, 999,
GADGET_ID_CHANGE_DELAY_RND_DOWN, GADGET_ID_CHANGE_DELAY_RND_UP,
GADGET_ID_CHANGE_DELAY_RND_TEXT,
- &custom_element_change_delay[1],
- NULL, "frames (random)"
+ &custom_element_change.delay_random,
+ NULL, "seconds (random)"
}
};
{
ED_SETTINGS_XPOS2, ED_COUNTER_YPOS2(5),
GADGET_ID_CHANGE_DELAY_FIXED,
- &custom_element_changes[0],
+ &custom_element_change_events[CE_DELAY_FIXED],
"delay of", "element changes after fixed delay"
},
{
ED_SETTINGS_XPOS2, ED_COUNTER_YPOS2(6),
GADGET_ID_CHANGE_DELAY_RANDOM,
- &custom_element_changes[1],
+ &custom_element_change_events[CE_DELAY_RANDOM],
"delay of", "element changes after random delay"
}
};
{
int i;
+ i = properties_element - EL_CUSTOM_START;
+ custom_element_change = level.custom_element[i].change;
+
for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
custom_element_properties[i] = HAS_PROPERTY(element, i);
+
+ for (i=0; i < NUM_CHANGE_EVENTS; i++)
+ custom_element_change_events[i] = HAS_CHANGE_EVENT(element, i);
}
static void CopyCustomElementPropertiesToGame(int element)
{
int i;
+ i = properties_element - EL_CUSTOM_START;
+ level.custom_element[i].change = custom_element_change;
+
for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
SET_PROPERTY(element, i, custom_element_properties[i]);
+
+ for (i=0; i < NUM_CHANGE_EVENTS; i++)
+ SET_CHANGE_EVENT(element, i, custom_element_change_events[i]);
}
void DrawLevelEd()
int area_y = ypos / MINI_TILEY;
int area_sx = SX + xpos;
int area_sy = SY + ypos;
- int element = properties_element - EL_CUSTOM_START;
+ int i = properties_element - EL_CUSTOM_START;
if (!IS_CUSTOM_ELEMENT(properties_element))
{
return;
}
- ElementContent[0][0][0] = level.custom_element_successor[element];
+ ElementContent[0][0][0] = level.custom_element[i].change.successor;
DrawElementBorder(area_sx, area_sy, MINI_TILEX, MINI_TILEY);
DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
{
char infotext[MAX_OUTPUT_LINESIZE + 1];
int max_infotext_len = getMaxInfoTextLength();
- int xoffset_above = 0;
- int yoffset_above = -(MINI_TILEX + ED_GADGET_DISTANCE);
int xoffset_right = getCounterGadgetWidth();
int yoffset_right = ED_BORDER_SIZE;
int xoffset_right2 = ED_CHECKBUTTON_XSIZE + 2 * ED_GADGET_DISTANCE;
int yoffset_right2 = ED_BORDER_SIZE;
int i, x, y;
+ CopyCustomElementPropertiesToEditor(properties_element);
+
/* draw stickybutton gadget */
i = ED_CHECKBUTTON_ID_STICK_ELEMENT;
x = checkbutton_info[i].x + xoffset_right2;
/* draw counter gadgets */
for (i=ED_COUNTER_ID_CHANGE_FIRST; i<=ED_COUNTER_ID_CHANGE_LAST; i++)
{
- if (counterbutton_info[i].infotext_above)
- {
- x = counterbutton_info[i].x + xoffset_above;
- y = counterbutton_info[i].y + yoffset_above;
-
- sprintf(infotext, "%s:", counterbutton_info[i].infotext_above);
- infotext[max_infotext_len] = '\0';
- DrawTextF(x, y, FONT_TEXT_1, infotext);
- }
-
if (counterbutton_info[i].infotext_right)
{
x = counterbutton_info[i].x + xoffset_right;
{
int i = properties_element - EL_CUSTOM_START;
- level.custom_element_successor[i] = new_element;
+ level.custom_element[i].change.successor = new_element;
}
else if (id == GADGET_ID_RANDOM_BACKGROUND)
random_placement_background_element = new_element;
default:
break;
}
+
+ if (counter_id >= ED_COUNTER_ID_CHANGE_FIRST &&
+ counter_id <= ED_COUNTER_ID_CHANGE_LAST)
+ CopyCustomElementPropertiesToGame(properties_element);
}
static void HandleTextInputGadgets(struct GadgetInfo *gi)
*checkbutton_info[type_id].value ^= TRUE;
- if (type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
- type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST)
+ if ((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
+ type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) ||
+ (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST &&
+ type_id <= ED_CHECKBUTTON_ID_CHANGE_LAST))
CopyCustomElementPropertiesToGame(properties_element);
}
for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
{
- level.custom_element_successor[i] = EL_EMPTY_SPACE;
+ level.custom_element[i].change.events = CE_BITMASK_DEFAULT;
+ level.custom_element[i].change.successor = EL_EMPTY_SPACE;
+ level.custom_element[i].change.delay_fixed = 0;
+ level.custom_element[i].change.delay_random = 0;
/* start with no properties at all */
#if 1
int i = element - EL_CUSTOM_START;
if (IS_CUSTOM_ELEMENT(element))
- level->custom_element_successor[i] = custom_element_successor;
+ level->custom_element[i].change.successor = custom_element_successor;
else
Error(ERR_WARN, "invalid custom element number %d", element);
}
{
int element = EL_CUSTOM_START + i;
- if (level->custom_element_successor[i] != EL_EMPTY_SPACE)
+ if (level->custom_element[i].change.successor != EL_EMPTY_SPACE)
{
if (check < num_changed_custom_elements)
{
putFile16BitBE(file, element);
- putFile16BitBE(file, level->custom_element_successor[i]);
+ putFile16BitBE(file, level->custom_element[i].change.successor);
}
check++;
/* check for non-standard custom elements and calculate "CUS2" chunk size */
for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
- if (level.custom_element_successor[i] != EL_EMPTY_SPACE)
+ if (level.custom_element[i].change.successor != EL_EMPTY_SPACE)
num_changed_custom_elements2++;
putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED);
static struct ChangingElementInfo changing_element_list[] =
{
- { EL_NUT_BREAKING, EL_EMERALD, 6, NULL, NULL, NULL },
- { EL_PEARL_BREAKING, EL_EMPTY, 8, NULL, NULL, NULL },
- { EL_EXIT_OPENING, EL_EXIT_OPEN, 29, NULL, NULL, NULL },
-
- { EL_SWITCHGATE_OPENING, EL_SWITCHGATE_OPEN, 29, NULL, NULL, NULL },
- { EL_SWITCHGATE_CLOSING, EL_SWITCHGATE_CLOSED, 29, NULL, NULL, NULL },
-
- { EL_TIMEGATE_OPENING, EL_TIMEGATE_OPEN, 29, NULL, NULL, NULL },
- { EL_TIMEGATE_CLOSING, EL_TIMEGATE_CLOSED, 29, NULL, NULL, NULL },
-
- { EL_ACID_SPLASH_LEFT, EL_EMPTY, 8, NULL, NULL, NULL },
- { EL_ACID_SPLASH_RIGHT, EL_EMPTY, 8, NULL, NULL, NULL },
-
- { EL_SP_BUGGY_BASE, EL_SP_BUGGY_BASE_ACTIVATING, 0,
- InitBuggyBase, NULL, NULL },
- { EL_SP_BUGGY_BASE_ACTIVATING,EL_SP_BUGGY_BASE_ACTIVE, 0,
- InitBuggyBase, NULL, NULL },
- { EL_SP_BUGGY_BASE_ACTIVE, EL_SP_BUGGY_BASE, 0,
- InitBuggyBase, WarnBuggyBase, NULL },
-
- { EL_TRAP, EL_TRAP_ACTIVE, 0,
- InitTrap, NULL, ActivateTrap },
- { EL_TRAP_ACTIVE, EL_TRAP, 31,
- NULL, ChangeActiveTrap, NULL },
-
- { EL_ROBOT_WHEEL_ACTIVE, EL_ROBOT_WHEEL, 0,
- InitRobotWheel, RunRobotWheel, StopRobotWheel },
+ {
+ EL_NUT_BREAKING,
+ EL_EMERALD,
+ 6,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_PEARL_BREAKING,
+ EL_EMPTY,
+ 8,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_EXIT_OPENING,
+ EL_EXIT_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_SWITCHGATE_OPENING,
+ EL_SWITCHGATE_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_SWITCHGATE_CLOSING,
+ EL_SWITCHGATE_CLOSED,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_TIMEGATE_OPENING,
+ EL_TIMEGATE_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_TIMEGATE_CLOSING,
+ EL_TIMEGATE_CLOSED,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
- { EL_TIMEGATE_SWITCH_ACTIVE, EL_TIMEGATE_SWITCH, 0,
- InitTimegateWheel, RunTimegateWheel, NULL },
+ {
+ EL_ACID_SPLASH_LEFT,
+ EL_EMPTY,
+ 8,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_ACID_SPLASH_RIGHT,
+ EL_EMPTY,
+ 8,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_SP_BUGGY_BASE,
+ EL_SP_BUGGY_BASE_ACTIVATING,
+ 0,
+ InitBuggyBase,
+ NULL,
+ NULL
+ },
+ {
+ EL_SP_BUGGY_BASE_ACTIVATING,
+ EL_SP_BUGGY_BASE_ACTIVE,
+ 0,
+ InitBuggyBase,
+ NULL,
+ NULL
+ },
+ {
+ EL_SP_BUGGY_BASE_ACTIVE,
+ EL_SP_BUGGY_BASE,
+ 0,
+ InitBuggyBase,
+ WarnBuggyBase,
+ NULL
+ },
+ {
+ EL_TRAP,
+ EL_TRAP_ACTIVE,
+ 0,
+ InitTrap,
+ NULL,
+ ActivateTrap
+ },
+ {
+ EL_TRAP_ACTIVE,
+ EL_TRAP,
+ 31,
+ NULL,
+ ChangeActiveTrap,
+ NULL
+ },
+ {
+ EL_ROBOT_WHEEL_ACTIVE,
+ EL_ROBOT_WHEEL,
+ 0,
+ InitRobotWheel,
+ RunRobotWheel,
+ StopRobotWheel
+ },
+ {
+ EL_TIMEGATE_SWITCH_ACTIVE,
+ EL_TIMEGATE_SWITCH,
+ 0,
+ InitTimegateWheel,
+ RunTimegateWheel,
+ NULL
+ },
- { EL_UNDEFINED, EL_UNDEFINED, -1, NULL }
+ {
+ EL_UNDEFINED,
+ EL_UNDEFINED,
+ -1,
+ NULL,
+ NULL,
+ NULL
+ }
};
static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS];
changing_element[i].post_change_function = NULL;
}
+ /* add changing elements from pre-defined list */
i = 0;
while (changing_element_list[i].base_element != EL_UNDEFINED)
{
i++;
}
+
+ /* add changing elements from custom element configuration */
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ struct CustomElementChangeInfo *change = &level.custom_element[i].change;
+ int element = EL_CUSTOM_START + i;
+
+ /* only add custom elements that change after fixed/random frame delay */
+ if (!IS_CHANGEABLE(element) ||
+ (!HAS_CHANGE_EVENT(element, CE_DELAY_FIXED) &&
+ !HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM)))
+ continue;
+
+ changing_element[element].base_element = element;
+ changing_element[element].next_element = change->successor;
+ changing_element[i].change_delay = 0;
+
+ if (HAS_CHANGE_EVENT(element, CE_DELAY_FIXED))
+ changing_element[element].change_delay +=
+ change->delay_fixed * FRAMES_PER_SECOND;
+
+ if (HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM));
+ /* random frame delay added at runtime for each element individually */
+ }
}
{
int element = Feld[x][y];
+ if (IS_MOVING(x, y)) /* never change moving elements */
+ return;
+
if (MovDelay[x][y] == 0) /* initialize element change */
{
MovDelay[x][y] = changing_element[element].change_delay + 1;
+ if (IS_CUSTOM_ELEMENT(element) &&
+ HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM))
+ {
+ int i = element - EL_CUSTOM_START;
+ int max_random_delay = level.custom_element[i].change.delay_random;
+
+ MovDelay[x][y] += RND(max_random_delay * FRAMES_PER_SECOND);
+ }
+
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
MauerAbleger(x, y);
else if (element == EL_FLAMES)
CheckForDragon(x, y);
+#if 0
else if (IS_AUTO_CHANGING(element))
ChangeElement(x, y);
+#endif
else if (element == EL_EXPLOSION)
; /* drawing of correct explosion animation is handled separately */
else if (IS_ANIMATED(graphic))
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+#if 1
+ if (IS_AUTO_CHANGING(element))
+ ChangeElement(x, y);
+#endif
+
if (IS_BELT_ACTIVE(element))
PlaySoundLevelAction(x, y, ACTION_ACTIVE);
#define EP_BITMASK_DEFAULT 0
#define PROPERTY_BIT(p) (1 << ((p) % 32))
-#define PROPERTY_VAR(e, p) (Properties[e][(p) / 32])
-#define HAS_PROPERTY(e, p) ((PROPERTY_VAR(e, p) & PROPERTY_BIT(p)) != 0)
-#define SET_PROPERTY(e, p, v) ((v) ? \
+#define PROPERTY_VAR(e,p) (Properties[e][(p) / 32])
+#define HAS_PROPERTY(e,p) ((PROPERTY_VAR(e, p) & PROPERTY_BIT(p)) != 0)
+#define SET_PROPERTY(e,p,v) ((v) ? \
(PROPERTY_VAR(e,p) |= PROPERTY_BIT(p)) : \
(PROPERTY_VAR(e,p) &= ~PROPERTY_BIT(p)))
+
+/* values for change events for custom elements */
+#define CE_DELAY_FIXED 0
+#define CE_DELAY_RANDOM 1
+
+#define NUM_CHANGE_EVENTS 2
+
+#define CE_BITMASK_DEFAULT 0
+
+#define CUSTOM_ELEMENT_INFO(e) (level.custom_element[(e) - EL_CUSTOM_START])
+
+#define CH_EVENT_BIT(c) (1 << (c))
+#define CH_EVENT_VAR(e) (CUSTOM_ELEMENT_INFO(e).change.events)
+
+#define HAS_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) && \
+ (CH_EVENT_VAR(e) & CH_EVENT_BIT(c)) != 0)
+#define SET_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ? \
+ ((v) ? \
+ (CH_EVENT_VAR(e) |= CH_EVENT_BIT(c)) : \
+ (CH_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
+
+
/* macros for configurable properties */
#define IS_DIGGABLE(e) HAS_PROPERTY(e, EP_DIGGABLE)
#define IS_COLLECTIBLE(e) HAS_PROPERTY(e, EP_COLLECTIBLE)
int shield_deadly_time_left;
};
+struct CustomElementChangeInfo
+{
+ unsigned long events; /* bitfield for change events */
+
+ short successor; /* new custom element after change */
+
+ int delay_fixed; /* added frame delay before changed (fixed) */
+ int delay_random; /* added frame delay before changed (random) */
+};
+
+struct CustomElementInfo
+{
+ struct CustomElementChangeInfo change;
+};
+
struct LevelInfo
{
int file_version; /* file format version the level is stored with */
boolean gravity;
boolean em_slippery_gems; /* EM style "gems slip from wall" behaviour */
- short custom_element_successor[NUM_CUSTOM_ELEMENTS];
+ struct CustomElementInfo custom_element[NUM_CUSTOM_ELEMENTS];
boolean no_level_file;
};