#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x))
#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE)
-#define LEVEL_CHUNK_CUS4_SIZE(x) (48 + 48 + (x) * 48)
+#define LEVEL_CHUNK_CUS4_SIZE(x) (96 + (x) * 48)
/* file identifier strings */
#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x"
#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0)
-#define CONF_VALUE_SCORE_1 (CONF_MASK_1_BYTE | 1)
-#define CONF_VALUE_SCORE_2 (CONF_MASK_1_BYTE | 2)
-#define CONF_VALUE_SCORE_3 (CONF_MASK_1_BYTE | 3)
-#define CONF_VALUE_SCORE_4 (CONF_MASK_1_BYTE | 4)
-#define CONF_VALUE_TIME_1 (CONF_MASK_1_BYTE | 5)
-#define CONF_VALUE_TIME_2 (CONF_MASK_1_BYTE | 6)
-#define CONF_VALUE_TIME_3 (CONF_MASK_1_BYTE | 7)
-#define CONF_VALUE_TIME_4 (CONF_MASK_1_BYTE | 8)
-#define CONF_VALUE_SWITCH_1 (CONF_MASK_1_BYTE | 9)
-#define CONF_VALUE_SWITCH_2 (CONF_MASK_1_BYTE | 10)
-#define CONF_VALUE_SWITCH_3 (CONF_MASK_1_BYTE | 11)
-#define CONF_VALUE_SWITCH_4 (CONF_MASK_1_BYTE | 12)
-#define CONF_VALUE_USE_BUG_1 (CONF_MASK_1_BYTE | 13)
-#define CONF_VALUE_USE_BUG_2 (CONF_MASK_1_BYTE | 14)
-#define CONF_VALUE_USE_BUG_3 (CONF_MASK_1_BYTE | 15)
-#define CONF_VALUE_USE_BUG_4 (CONF_MASK_1_BYTE | 16)
+#define CONF_VALUE_INTEGER_1 (CONF_MASK_1_BYTE | 1)
+#define CONF_VALUE_INTEGER_2 (CONF_MASK_1_BYTE | 2)
+#define CONF_VALUE_INTEGER_3 (CONF_MASK_1_BYTE | 3)
+#define CONF_VALUE_INTEGER_4 (CONF_MASK_1_BYTE | 4)
+#define CONF_VALUE_BOOLEAN_1 (CONF_MASK_1_BYTE | 5)
+#define CONF_VALUE_BOOLEAN_2 (CONF_MASK_1_BYTE | 6)
+#define CONF_VALUE_BOOLEAN_3 (CONF_MASK_1_BYTE | 7)
+#define CONF_VALUE_BOOLEAN_4 (CONF_MASK_1_BYTE | 8)
#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1)
#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2)
+#define CONF_VALUE_ELEMENT_3 (CONF_MASK_2_BYTE | 3)
+#define CONF_VALUE_ELEMENT_4 (CONF_MASK_2_BYTE | 4)
#define CONF_VALUE_CONTENT_1 (CONF_MASK_MULTI_BYTES | 1)
#define CONF_VALUE_CONTENT_8 (CONF_MASK_MULTI_BYTES | 2)
-#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_SWITCH_1 && \
- (x) <= CONF_VALUE_USE_BUG_4)
+#define CONF_VALUE_INTEGER(x) ((x) >= CONF_VALUE_INTEGER_1 && \
+ (x) <= CONF_VALUE_INTEGER_4)
+
+#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_BOOLEAN_1 && \
+ (x) <= CONF_VALUE_BOOLEAN_4)
#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \
(x) == CONF_MASK_2_BYTE ? 2 : \
int element;
int type;
void *value;
+ int default_value;
} element_conf[] =
{
- /* 1-byte values */
- { EL_EMC_ANDROID, CONF_VALUE_TIME_1, &li.android_move_time },
- { EL_EMC_ANDROID, CONF_VALUE_TIME_2, &li.android_clone_time },
- { EL_EMC_MAGIC_BALL, CONF_VALUE_TIME_1, &li.ball_time },
- { EL_EMC_LENSES, CONF_VALUE_SCORE_1, &li.lenses_score },
- { EL_EMC_LENSES, CONF_VALUE_TIME_1, &li.lenses_time },
- { EL_EMC_MAGNIFIER, CONF_VALUE_SCORE_1, &li.magnify_score },
- { EL_EMC_MAGNIFIER, CONF_VALUE_TIME_1, &li.magnify_time },
- { EL_ROBOT, CONF_VALUE_SCORE_2, &li.slurp_score },
-
- /* multi-byte values */
- { EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENT_8, &li.ball_content },
-
- { -1, -1, NULL },
+ /* ---------- 1-byte values ---------------------------------------------- */
+ {
+ EL_EMC_ANDROID, CONF_VALUE_INTEGER_1,
+ &li.android_move_time, 10
+ },
+ {
+ EL_EMC_ANDROID, CONF_VALUE_INTEGER_2,
+ &li.android_clone_time, 10
+ },
+ {
+ EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1,
+ &li.ball_time, 10
+ },
+ {
+ EL_EMC_LENSES, CONF_VALUE_INTEGER_1,
+ &li.lenses_score, 10
+ },
+ {
+ EL_EMC_LENSES, CONF_VALUE_INTEGER_2,
+ &li.lenses_time, 10
+ },
+ {
+ EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_1,
+ &li.magnify_score, 10
+ },
+ {
+ EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_2,
+ &li.magnify_time, 10
+ },
+ {
+ EL_ROBOT, CONF_VALUE_INTEGER_1,
+ &li.slurp_score, 10
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_1,
+ &li.game_of_life[0], 2
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_2,
+ &li.game_of_life[1], 3
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_3,
+ &li.game_of_life[2], 3
+ },
+ {
+ EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_4,
+ &li.game_of_life[3], 3
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_1,
+ &li.biomaze[0], 2
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_2,
+ &li.biomaze[1], 3
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_3,
+ &li.biomaze[2], 3
+ },
+ {
+ EL_BIOMAZE, CONF_VALUE_INTEGER_4,
+ &li.biomaze[3], 3
+ },
+ {
+ EL_BALLOON, CONF_VALUE_INTEGER_1,
+ &li.wind_direction_initial, MV_NONE
+ },
+ {
+ EL_TIMEGATE_SWITCH, CONF_VALUE_INTEGER_1,
+ &li.time_timegate, 10
+ },
+ {
+ EL_LIGHT_SWITCH_ACTIVE, CONF_VALUE_INTEGER_1,
+ &li.time_light, 10
+ },
+ {
+ EL_SHIELD_NORMAL, CONF_VALUE_INTEGER_1,
+ &li.shield_normal_time, 10
+ },
+ {
+ EL_SHIELD_DEADLY, CONF_VALUE_INTEGER_1,
+ &li.shield_deadly_time, 10
+ },
+ {
+ EL_EXTRA_TIME, CONF_VALUE_INTEGER_1,
+ &li.extra_time, 10
+ },
+ {
+ EL_TIME_ORB_FULL, CONF_VALUE_INTEGER_1,
+ &li.time_orb_time, 10
+ },
+ {
+ EL_TIME_ORB_FULL, CONF_VALUE_BOOLEAN_1,
+ &li.use_time_orb_bug, FALSE
+ },
+
+ /* ---------- multi-byte values ------------------------------------------ */
+ {
+ EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENT_8,
+ &li.ball_content, EL_EMPTY
+ },
+
+ {
+ -1, -1,
+ NULL, -1
+ },
};
static struct
/* level file functions */
/* ========================================================================= */
+static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level)
+{
+ int i;
+
+ li = *level; /* copy level information into temporary buffer */
+
+ for (i = 0; element_conf[i].element != -1; i++)
+ {
+ int default_value = element_conf[i].default_value;
+ int type = element_conf[i].type;
+ int bytes = type & CONF_MASK_BYTES;
+
+ if (bytes != CONF_MASK_MULTI_BYTES)
+ {
+ if (CONF_VALUE_BOOLEAN(type))
+ *(boolean *)(element_conf[i].value) = default_value;
+ else
+ *(int *) (element_conf[i].value) = default_value;
+ }
+ else if (type == CONF_VALUE_CONTENT_8)
+ {
+ struct Content *content = (struct Content *)(element_conf[i].value);
+ int c, x, y;
+
+ for (c = 0; c < MAX_ELEMENT_CONTENTS; c++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ content[c].e[x][y] = default_value;
+ }
+ }
+
+ *level = li; /* copy temporary buffer back to level information */
+}
+
void setElementChangePages(struct ElementInfo *ei, int change_pages)
{
int change_page_size = sizeof(struct ElementChangeInfo);
static boolean clipboard_elements_initialized = FALSE;
int i, j, x, y;
+ setLevelInfoToDefaultsFromConfigList(level);
setLevelInfoToDefaults_EM();
level->native_em_level = &native_em_level;
level->time_magic_wall = 10;
level->time_wheel = 10;
+#if 0
level->time_light = 10;
level->time_timegate = 10;
+#endif
level->amoeba_content = EL_DIAMOND;
+ level->game_of_life[0] = 2;
+ level->game_of_life[1] = 3;
+ level->game_of_life[2] = 3;
+ level->game_of_life[3] = 3;
+
+ level->biomaze[0] = 2;
+ level->biomaze[1] = 3;
+ level->biomaze[2] = 3;
+ level->biomaze[3] = 3;
+
level->double_speed = FALSE;
level->initial_gravity = FALSE;
level->em_slippery_gems = FALSE;
level->dont_collide_with_bits = ~0; /* always deadly when colliding */
level->use_spring_bug = FALSE;
+ level->use_time_orb_bug = FALSE;
+
level->use_step_counter = FALSE;
/* values for the new EMC elements */
+#if 0
level->android_move_time = 10;
level->android_clone_time = 10;
- level->ball_random = FALSE;
- level->ball_state_initial = FALSE;
level->ball_time = 10;
level->lenses_score = 10;
- level->magnify_score = 10;
- level->slurp_score = 10;
level->lenses_time = 10;
+ level->magnify_score = 10;
level->magnify_time = 10;
- level->wind_direction_initial = MV_NO_MOVING;
+ level->slurp_score = 10;
+ level->wind_direction_initial = MV_NONE;
+#endif
+ level->ball_random = FALSE;
+ level->ball_state_initial = FALSE;
+#if 0
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
level->ball_content[i].e[x][y] = EL_EMPTY;
+#endif
for (i = 0; i < 16; i++)
level->android_array[i] = FALSE;
for (i = 0; i < MAX_NUM_ELEMENTS; i++)
{
int element = i;
+ struct ElementInfo *ei = &element_info[element];
/* never initialize clipboard elements after the very first time */
if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
continue;
- setElementChangePages(&element_info[element], 1);
- setElementChangeInfoToDefaults(element_info[element].change);
+ setElementChangePages(ei, 1);
+ setElementChangeInfoToDefaults(ei->change);
if (IS_CUSTOM_ELEMENT(element) ||
IS_GROUP_ELEMENT(element) ||
IS_INTERNAL_ELEMENT(element))
{
for (j = 0; j < MAX_ELEMENT_NAME_LEN + 1; j++)
- element_info[element].description[j] = '\0';
+ ei->description[j] = '\0';
- if (element_info[element].custom_description != NULL)
- strncpy(element_info[element].description,
- element_info[element].custom_description,MAX_ELEMENT_NAME_LEN);
+ if (ei->custom_description != NULL)
+ strncpy(ei->description, ei->custom_description,MAX_ELEMENT_NAME_LEN);
else
- strcpy(element_info[element].description,
- element_info[element].editor_description);
+ strcpy(ei->description, ei->editor_description);
- element_info[element].use_gfx_element = FALSE;
- element_info[element].gfx_element = EL_EMPTY_SPACE;
+ ei->use_gfx_element = FALSE;
+ ei->gfx_element = EL_EMPTY_SPACE;
- element_info[element].modified_settings = FALSE;
+ ei->modified_settings = FALSE;
}
if (IS_CUSTOM_ELEMENT(element) ||
IS_INTERNAL_ELEMENT(element))
{
- element_info[element].access_direction = MV_ALL_DIRECTIONS;
+ ei->access_direction = MV_ALL_DIRECTIONS;
- element_info[element].collect_score_initial = 10; /* special default */
- element_info[element].collect_count_initial = 1; /* special default */
+ ei->collect_score_initial = 10; /* special default */
+ ei->collect_count_initial = 1; /* special default */
- element_info[element].push_delay_fixed = -1; /* initialize later */
- element_info[element].push_delay_random = -1; /* initialize later */
- element_info[element].drop_delay_fixed = 0;
- element_info[element].drop_delay_random = 0;
- element_info[element].move_delay_fixed = 0;
- element_info[element].move_delay_random = 0;
+ ei->ce_value_fixed_initial = 0;
+ ei->ce_value_random_initial = 0;
+ ei->use_last_ce_value = FALSE;
- element_info[element].move_pattern = MV_ALL_DIRECTIONS;
- element_info[element].move_direction_initial = MV_START_AUTOMATIC;
- element_info[element].move_stepsize = TILEX / 8;
+ ei->push_delay_fixed = -1; /* initialize later */
+ ei->push_delay_random = -1; /* initialize later */
+ ei->drop_delay_fixed = 0;
+ ei->drop_delay_random = 0;
+ ei->move_delay_fixed = 0;
+ ei->move_delay_random = 0;
- element_info[element].move_enter_element = EL_EMPTY_SPACE;
- element_info[element].move_leave_element = EL_EMPTY_SPACE;
- element_info[element].move_leave_type = LEAVE_TYPE_UNLIMITED;
+ ei->move_pattern = MV_ALL_DIRECTIONS;
+ ei->move_direction_initial = MV_START_AUTOMATIC;
+ ei->move_stepsize = TILEX / 8;
- element_info[element].slippery_type = SLIPPERY_ANY_RANDOM;
+ ei->move_enter_element = EL_EMPTY_SPACE;
+ ei->move_leave_element = EL_EMPTY_SPACE;
+ ei->move_leave_type = LEAVE_TYPE_UNLIMITED;
- element_info[element].explosion_type = EXPLODES_3X3;
- element_info[element].explosion_delay = 16;
- element_info[element].ignition_delay = 8;
+ ei->slippery_type = SLIPPERY_ANY_RANDOM;
+
+ ei->explosion_type = EXPLODES_3X3;
+ ei->explosion_delay = 16;
+ ei->ignition_delay = 8;
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- element_info[element].content.e[x][y] = EL_EMPTY_SPACE;
+ ei->content.e[x][y] = EL_EMPTY_SPACE;
- element_info[element].access_type = 0;
- element_info[element].access_layer = 0;
- element_info[element].access_protected = 0;
- element_info[element].walk_to_action = 0;
- element_info[element].smash_targets = 0;
- element_info[element].deadliness = 0;
+ ei->access_type = 0;
+ ei->access_layer = 0;
+ ei->access_protected = 0;
+ ei->walk_to_action = 0;
+ ei->smash_targets = 0;
+ ei->deadliness = 0;
- element_info[element].can_explode_by_fire = FALSE;
- element_info[element].can_explode_smashed = FALSE;
- element_info[element].can_explode_impact = FALSE;
+ ei->can_explode_by_fire = FALSE;
+ ei->can_explode_smashed = FALSE;
+ ei->can_explode_impact = FALSE;
- element_info[element].current_change_page = 0;
+ ei->current_change_page = 0;
/* start with no properties at all */
for (j = 0; j < NUM_EP_BITFIELDS; j++)
if (IS_GROUP_ELEMENT(element) ||
IS_INTERNAL_ELEMENT(element))
{
+ struct ElementGroupInfo *group;
+
/* initialize memory for list of elements in group */
- if (element_info[element].group == NULL)
- element_info[element].group =
- checked_malloc(sizeof(struct ElementGroupInfo));
+ if (ei->group == NULL)
+ ei->group = checked_malloc(sizeof(struct ElementGroupInfo));
+
+ group = ei->group;
for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++)
- element_info[element].group->element[j] = EL_EMPTY_SPACE;
+ group->element[j] = EL_EMPTY_SPACE;
/* default: only one element in group */
- element_info[element].group->num_elements = 1;
+ group->num_elements = 1;
- element_info[element].group->choice_mode = ANIM_RANDOM;
+ group->choice_mode = ANIM_RANDOM;
}
}
for (i = 0; i < num_changed_custom_elements; i++)
{
int element = getFile16BitBE(file);
+ struct ElementInfo *ei = &element_info[element];
unsigned long event_bits;
if (!IS_CUSTOM_ELEMENT(element))
}
for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
- element_info[element].description[j] = getFile8Bit(file);
- element_info[element].description[MAX_ELEMENT_NAME_LEN] = 0;
+ ei->description[j] = getFile8Bit(file);
+ ei->description[MAX_ELEMENT_NAME_LEN] = 0;
Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file);
/* some free bytes for future properties and padding */
ReadUnusedBytesFromFile(file, 7);
- element_info[element].use_gfx_element = getFile8Bit(file);
- element_info[element].gfx_element =
- getMappedElement(getFile16BitBE(file));
+ ei->use_gfx_element = getFile8Bit(file);
+ ei->gfx_element = getMappedElement(getFile16BitBE(file));
- element_info[element].collect_score_initial = getFile8Bit(file);
- element_info[element].collect_count_initial = getFile8Bit(file);
+ ei->collect_score_initial = getFile8Bit(file);
+ ei->collect_count_initial = getFile8Bit(file);
- element_info[element].push_delay_fixed = getFile16BitBE(file);
- element_info[element].push_delay_random = getFile16BitBE(file);
- element_info[element].move_delay_fixed = getFile16BitBE(file);
- element_info[element].move_delay_random = getFile16BitBE(file);
+ ei->push_delay_fixed = getFile16BitBE(file);
+ ei->push_delay_random = getFile16BitBE(file);
+ ei->move_delay_fixed = getFile16BitBE(file);
+ ei->move_delay_random = getFile16BitBE(file);
- element_info[element].move_pattern = getFile16BitBE(file);
- element_info[element].move_direction_initial = getFile8Bit(file);
- element_info[element].move_stepsize = getFile8Bit(file);
+ ei->move_pattern = getFile16BitBE(file);
+ ei->move_direction_initial = getFile8Bit(file);
+ ei->move_stepsize = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- element_info[element].content.e[x][y] =
- getMappedElement(getFile16BitBE(file));
+ ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
event_bits = getFile32BitBE(file);
for (j = 0; j < NUM_CHANGE_EVENTS; j++)
if (event_bits & (1 << j))
- element_info[element].change->has_event[j] = TRUE;
+ ei->change->has_event[j] = TRUE;
- element_info[element].change->target_element =
- getMappedElement(getFile16BitBE(file));
+ ei->change->target_element = getMappedElement(getFile16BitBE(file));
- element_info[element].change->delay_fixed = getFile16BitBE(file);
- element_info[element].change->delay_random = getFile16BitBE(file);
- element_info[element].change->delay_frames = getFile16BitBE(file);
+ ei->change->delay_fixed = getFile16BitBE(file);
+ ei->change->delay_random = getFile16BitBE(file);
+ ei->change->delay_frames = getFile16BitBE(file);
- element_info[element].change->trigger_element =
- getMappedElement(getFile16BitBE(file));
+ ei->change->trigger_element = getMappedElement(getFile16BitBE(file));
- element_info[element].change->explode = getFile8Bit(file);
- element_info[element].change->use_target_content = getFile8Bit(file);
- element_info[element].change->only_if_complete = getFile8Bit(file);
- element_info[element].change->use_random_replace = getFile8Bit(file);
+ ei->change->explode = getFile8Bit(file);
+ ei->change->use_target_content = getFile8Bit(file);
+ ei->change->only_if_complete = getFile8Bit(file);
+ ei->change->use_random_replace = getFile8Bit(file);
- element_info[element].change->random_percentage = getFile8Bit(file);
- element_info[element].change->replace_when = getFile8Bit(file);
+ ei->change->random_percentage = getFile8Bit(file);
+ ei->change->replace_when = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- element_info[element].change->target_content.e[x][y] =
+ ei->change->target_content.e[x][y] =
getMappedElement(getFile16BitBE(file));
- element_info[element].slippery_type = getFile8Bit(file);
+ ei->slippery_type = getFile8Bit(file);
/* some free bytes for future properties and padding */
ReadUnusedBytesFromFile(file, LEVEL_CPART_CUS3_UNUSED);
/* mark that this custom element has been modified */
- element_info[element].modified_settings = TRUE;
+ ei->modified_settings = TRUE;
}
return chunk_size;
int element;
int i, j, x, y;
+ /* ---------- custom element base property values (96 bytes) ------------- */
+
element = getFile16BitBE(file);
if (!IS_CUSTOM_ELEMENT(element))
ei->num_change_pages = getFile8Bit(file);
- /* some free bytes for future base property values and padding */
- ReadUnusedBytesFromFile(file, 5);
-
chunk_size_expected = LEVEL_CHUNK_CUS4_SIZE(ei->num_change_pages);
if (chunk_size_expected != chunk_size)
{
- ReadUnusedBytesFromFile(file, chunk_size - 48);
+ ReadUnusedBytesFromFile(file, chunk_size - 43);
return chunk_size_expected;
}
- /* read custom property values */
+ ei->ce_value_fixed_initial = getFile16BitBE(file);
+ ei->ce_value_random_initial = getFile16BitBE(file);
+ ei->use_last_ce_value = getFile8Bit(file);
ei->use_gfx_element = getFile8Bit(file);
ei->gfx_element = getMappedElement(getFile16BitBE(file));
/* some free bytes for future custom property values and padding */
ReadUnusedBytesFromFile(file, 1);
- /* read change property values */
+ /* ---------- change page property values (48 bytes) --------------------- */
setElementChangePages(ei, ei->num_change_pages);
if (level->game_version < VERSION_IDENT(2,2,0,0))
level->use_spring_bug = TRUE;
+ /* time orb caused limited time in endless time levels before 3.1.2 */
+ if (level->game_version < VERSION_IDENT(3,1,2,0))
+ level->use_time_orb_bug = TRUE;
+
/* only few elements were able to actively move into acid before 3.1.0 */
/* trigger settings did not exist before 3.1.0; set to default "any" */
if (level->game_version < VERSION_IDENT(3,1,0,0))
int element = EL_CUSTOM_START + i;
/* order of checking and copying events to be mapped is important */
- for (j = CE_BY_OTHER_ACTION; j >= CE_COUNT_AT_ZERO; j--)
+ for (j = CE_BY_OTHER_ACTION; j >= CE_VALUE_GETS_ZERO; j--)
{
if (HAS_CHANGE_EVENT(element, j - 2))
{
int element = EL_CUSTOM_START + i;
struct ElementInfo *ei = &element_info[element];
- if (ei->access_direction == MV_NO_DIRECTIONS)
+ if (ei->access_direction == MV_NO_DIRECTION)
ei->access_direction = MV_ALL_DIRECTIONS;
#if 0
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
- if (element_info[element].modified_settings)
+ if (ei->modified_settings)
{
if (check < num_changed_custom_elements)
{
putFile16BitBE(file, element);
for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
- putFile8Bit(file, element_info[element].description[j]);
+ putFile8Bit(file, ei->description[j]);
putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
/* some free bytes for future properties and padding */
WriteUnusedBytesToFile(file, 7);
- putFile8Bit(file, element_info[element].use_gfx_element);
- putFile16BitBE(file, element_info[element].gfx_element);
+ putFile8Bit(file, ei->use_gfx_element);
+ putFile16BitBE(file, ei->gfx_element);
- putFile8Bit(file, element_info[element].collect_score_initial);
- putFile8Bit(file, element_info[element].collect_count_initial);
+ putFile8Bit(file, ei->collect_score_initial);
+ putFile8Bit(file, ei->collect_count_initial);
- putFile16BitBE(file, element_info[element].push_delay_fixed);
- putFile16BitBE(file, element_info[element].push_delay_random);
- putFile16BitBE(file, element_info[element].move_delay_fixed);
- putFile16BitBE(file, element_info[element].move_delay_random);
+ putFile16BitBE(file, ei->push_delay_fixed);
+ putFile16BitBE(file, ei->push_delay_random);
+ putFile16BitBE(file, ei->move_delay_fixed);
+ putFile16BitBE(file, ei->move_delay_random);
- putFile16BitBE(file, element_info[element].move_pattern);
- putFile8Bit(file, element_info[element].move_direction_initial);
- putFile8Bit(file, element_info[element].move_stepsize);
+ putFile16BitBE(file, ei->move_pattern);
+ putFile8Bit(file, ei->move_direction_initial);
+ putFile8Bit(file, ei->move_stepsize);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file, element_info[element].content.e[x][y]);
+ putFile16BitBE(file, ei->content.e[x][y]);
- putFile32BitBE(file, element_info[element].change->events);
+ putFile32BitBE(file, ei->change->events);
- putFile16BitBE(file, element_info[element].change->target_element);
+ putFile16BitBE(file, ei->change->target_element);
- putFile16BitBE(file, element_info[element].change->delay_fixed);
- putFile16BitBE(file, element_info[element].change->delay_random);
- putFile16BitBE(file, element_info[element].change->delay_frames);
+ putFile16BitBE(file, ei->change->delay_fixed);
+ putFile16BitBE(file, ei->change->delay_random);
+ putFile16BitBE(file, ei->change->delay_frames);
- putFile16BitBE(file, element_info[element].change->trigger_element);
+ putFile16BitBE(file, ei->change->trigger_element);
- putFile8Bit(file, element_info[element].change->explode);
- putFile8Bit(file, element_info[element].change->use_target_content);
- putFile8Bit(file, element_info[element].change->only_if_complete);
- putFile8Bit(file, element_info[element].change->use_random_replace);
+ putFile8Bit(file, ei->change->explode);
+ putFile8Bit(file, ei->change->use_target_content);
+ putFile8Bit(file, ei->change->only_if_complete);
+ putFile8Bit(file, ei->change->use_random_replace);
- putFile8Bit(file, element_info[element].change->random_percentage);
- putFile8Bit(file, element_info[element].change->replace_when);
+ putFile8Bit(file, ei->change->random_percentage);
+ putFile8Bit(file, ei->change->replace_when);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file,element_info[element].change->content.e[x][y]);
+ putFile16BitBE(file, ei->change->content.e[x][y]);
- putFile8Bit(file, element_info[element].slippery_type);
+ putFile8Bit(file, ei->slippery_type);
/* some free bytes for future properties and padding */
WriteUnusedBytesToFile(file, LEVEL_CPART_CUS3_UNUSED);
struct ElementInfo *ei = &element_info[element];
int i, j, x, y;
+ /* ---------- custom element base property values (96 bytes) ------------- */
+
putFile16BitBE(file, element);
for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
putFile8Bit(file, ei->num_change_pages);
- /* some free bytes for future base property values and padding */
- WriteUnusedBytesToFile(file, 5);
-
- /* write custom property values */
+ putFile16BitBE(file, ei->ce_value_fixed_initial);
+ putFile16BitBE(file, ei->ce_value_random_initial);
+ putFile8Bit(file, ei->use_last_ce_value);
putFile8Bit(file, ei->use_gfx_element);
putFile16BitBE(file, ei->gfx_element);
/* some free bytes for future custom property values and padding */
WriteUnusedBytesToFile(file, 1);
- /* write change property values */
+ /* ---------- change page property values (48 bytes) --------------------- */
for (i = 0; i < ei->num_change_pages; i++)
{
putFile16BitBE(file, group->element[i]);
}
-static int SaveLevel_CONF_Value(FILE *file, int element, int type, int value)
+static int SaveLevel_CONF_Value(FILE *file, int pos)
{
+ int default_value = element_conf[pos].default_value;
+ int element = element_conf[pos].element;
+ int type = element_conf[pos].type;
int bytes = type & CONF_MASK_BYTES;
+ void *value_ptr = element_conf[pos].value;
+ int value = (CONF_VALUE_BOOLEAN(type) ? *(boolean *)value_ptr :
+ *(int *)value_ptr);
int num_bytes = 0;
+ boolean modified = FALSE;
+
+ /* check if any settings have been modified before saving them */
+ if (value != default_value)
+ modified = TRUE;
+
+ if (!modified) /* do not save unmodified default settings */
+ return 0;
if (bytes == CONF_MASK_MULTI_BYTES)
- Error(ERR_EXIT, "SaveLevel_CONF_INT: invalid type CONF_MASK_MULTI_BYTES");
+ Error(ERR_EXIT, "SaveLevel_CONF_Value: cannot save multi-byte values");
num_bytes += putFile16BitBE(file, element);
num_bytes += putFile8Bit(file, type);
return num_bytes;
}
-static int SaveLevel_CONF_Content(FILE *file, int element, int type,
- struct Content *content, int num_contents)
+static int SaveLevel_CONF_Content(FILE *file, int pos, int num_contents)
{
+ struct Content *content = (struct Content *)(element_conf[pos].value);
+ int default_value = element_conf[pos].default_value;
+ int element = element_conf[pos].element;
+ int type = element_conf[pos].type;
int num_bytes = 0;
+ boolean modified = FALSE;
int i, x, y;
+ /* check if any settings have been modified before saving them */
+ for (i = 0; i < num_contents; i++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ if (content[i].e[x][y] != default_value)
+ modified = TRUE;
+
+ if (!modified) /* do not save unmodified default settings */
+ return 0;
+
num_bytes += putFile16BitBE(file, element);
num_bytes += putFile8Bit(file, type);
num_bytes += putFile16BitBE(file, num_contents * CONF_CONTENT_NUM_BYTES);
for (i = 0; element_conf[i].element != -1; i++)
{
- int element = element_conf[i].element;
- int type = element_conf[i].type;
- void *value = element_conf[i].value;
+ int type = element_conf[i].type;
int bytes = type & CONF_MASK_BYTES;
- if (bytes == CONF_MASK_MULTI_BYTES)
- {
- if (type == CONF_VALUE_CONTENT_8)
- {
- struct Content *content = (struct Content *)value;
-
- chunk_size += SaveLevel_CONF_Content(file, element, type,
- content, MAX_ELEMENT_CONTENTS);
- }
- else
- Error(ERR_WARN, "cannot save CONF value for element %d", element);
- }
- else
- {
- int value_int = (CONF_VALUE_BOOLEAN(type) ? *(boolean *)value :
- *(int *)value);
-
- chunk_size += SaveLevel_CONF_Value(file, element, type, value_int);
- }
+ if (bytes != CONF_MASK_MULTI_BYTES)
+ chunk_size += SaveLevel_CONF_Value(file, i);
+ else if (type == CONF_VALUE_CONTENT_8)
+ chunk_size += SaveLevel_CONF_Content(file, i, MAX_ELEMENT_CONTENTS);
}
return chunk_size;
conf_chunk_size = SaveLevel_CONF(NULL, level); /* get chunk size */
- putFileChunkBE(file, "CONF", conf_chunk_size);
- SaveLevel_CONF(file, level);
+ /* check for non-default configuration settings to be saved in CONF chunk */
+ if (conf_chunk_size > 0)
+ {
+ putFileChunkBE(file, "CONF", conf_chunk_size);
+ SaveLevel_CONF(file, level);
+ }
fclose(file);
for (j = 0; j < MAX_PLAYERS; j++)
{
- tape->pos[i].action[j] = MV_NO_MOVING;
+ tape->pos[i].action[j] = MV_NONE;
if (tape->player_participates[j])
tape->pos[i].action[j] = getFile8Bit(file);
/* delay part */
for (j = 0; j < MAX_PLAYERS; j++)
- tape->pos[i].action[j] = MV_NO_MOVING;
+ tape->pos[i].action[j] = MV_NONE;
tape->pos[i].delay--;
i++;