void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
{
- int x, y;
+ int i, x, y;
change->can_change = FALSE;
- change->events = CE_BITMASK_DEFAULT;
+ for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+ change->has_event[i] = FALSE;
change->trigger_player = CH_PLAYER_ANY;
change->trigger_side = CH_SIDE_ANY;
change->random_percentage = 100;
change->replace_when = CP_WHEN_EMPTY;
+ change->use_action = FALSE;
+ change->action_type = CA_NO_ACTION;
+ change->action_mode = CA_MODE_UNDEFINED;
+ change->action_arg = CA_ARG_UNDEFINED;
+
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
change->target_content[x][y] = EL_EMPTY_SPACE;
level->block_last_field = FALSE; /* EM does not block by default */
level->sp_block_last_field = TRUE; /* SP blocks the last field */
+
+#if 0 /* !!! THIS IS NOT A LEVEL SETTING => LOGIC MOVED TO "game.c" !!! */
level->block_delay = 8; /* when blocking, block 8 frames */
level->sp_block_delay = 9; /* SP indeed blocks 9 frames, not 8 */
+#endif
level->can_move_into_acid_bits = ~0; /* everything can move into acid */
level->dont_collide_with_bits = ~0; /* always deadly when colliding */
element_info[element].explosion_delay = 16;
element_info[element].ignition_delay = 8;
+ element_info[element].counter_initial = 0;
+ element_info[element].counter = 0;
+
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
element_info[element].content[x][y] = EL_EMPTY_SPACE;
for (i = 0; i < num_changed_custom_elements; i++)
{
int element = getFile16BitBE(file);
+ unsigned long event_bits;
if (!IS_CUSTOM_ELEMENT(element))
{
element_info[element].content[x][y] =
getMappedElement(getFile16BitBE(file));
- element_info[element].change->events = getFile32BitBE(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;
element_info[element].change->target_element =
getMappedElement(getFile16BitBE(file));
struct ElementInfo *ei;
int chunk_size_expected;
int element;
- int i, x, y;
+ int i, j, x, y;
element = getFile16BitBE(file);
for (i = 0; i < ei->num_change_pages; i++)
{
struct ElementChangeInfo *change = &ei->change_page[i];
+ unsigned long event_bits;
/* always start with reliable default values */
setElementChangeInfoToDefaults(change);
- change->events = getFile32BitBE(file);
+ event_bits = getFile32BitBE(file);
+ for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+ if (event_bits & (1 << j))
+ change->has_event[j] = TRUE;
change->target_element = getMappedElement(getFile16BitBE(file));
change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ?
CH_PAGE_ANY : (1 << change->trigger_page));
+#if 1
+ change->use_action = getFile8Bit(file);
+ change->action_type = getFile8Bit(file);
+ change->action_mode = getFile8Bit(file);
+ change->action_arg = getFile16BitBE(file);
+
+ /* some free bytes for future change property values and padding */
+ ReadUnusedBytesFromFile(file, 1);
+#else
/* some free bytes for future change property values and padding */
ReadUnusedBytesFromFile(file, 6);
+#endif
#else
level->use_spring_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 i, j;
+ /* correct "can move into acid" settings (all zero in old levels) */
+
level->can_move_into_acid_bits = 0; /* nothing can move into acid */
level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, TRUE);
+ /* correct trigger settings (stored as zero == "none" in old levels) */
+
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
int element = EL_CUSTOM_START + i;
}
}
+#if 0 /* !!! MOVED TO "game.c", BECAUSE CAN CHANGE INSIDE LEVEL EDITOR !!! */
#if 1 /* USE_NEW_BLOCK_STYLE */
/* blocking the last field when moving was corrected in version 3.1.1 */
if (level->game_version < VERSION_IDENT(3,1,1,0))
level->sp_block_last_field = TRUE;
}
#endif
+#endif
+
}
else /* always use the latest game engine version */
{
int i, j, x, y;
/* map custom element change events that have changed in newer versions
- (these following values were accidentally changed in version 3.0.1) */
+ (these following values were accidentally changed in version 3.0.1)
+ (this seems to be needed only for 'ab_levelset3' and 'ab_levelset4') */
if (level->game_version <= VERSION_IDENT(3,0,0,0))
{
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
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_BY_PLAYER_OBSOLETE; j--)
+ for (j = CE_BY_OTHER_ACTION; j >= CE_COUNT_AT_ZERO; j--)
{
if (HAS_CHANGE_EVENT(element, j - 2))
{
}
/* order of checking and copying events to be mapped is important */
- for (j = CE_OTHER_GETS_COLLECTED; j >= CE_HITTING_SOMETHING; j--)
+ for (j = CE_PLAYER_COLLECTS_X; j >= CE_HITTING_SOMETHING; j--)
{
if (HAS_CHANGE_EVENT(element, j - 1))
{
}
}
+#if 0
+ /* !!! TESTS SHOWED THAT THIS CODE SEGMENT IS NOT NEEDED FOR ANY LEVEL !!! */
+
/* some custom element change events get mapped since version 3.0.3 */
- for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+#if 1
+ if (level->game_version >= VERSION_IDENT(3,0,3,0) &&
+ level->game_version <= VERSION_IDENT(3,2,0,3))
+#endif
{
- int element = EL_CUSTOM_START + i;
-
- if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) ||
- HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE))
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
- SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
- SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
+ int element = EL_CUSTOM_START + i;
- SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
+ if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) ||
+ HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE))
+ {
+ SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
+ SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
+
+ SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
+ }
}
}
+#endif
/* initialize "can_change" field for old levels with only one change page */
if (level->game_version <= VERSION_IDENT(3,0,2,0))
}
/* correct custom element values (for old levels without these options) */
- for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ if (level->game_version < VERSION_IDENT(3,1,1,0))
{
- int element = EL_CUSTOM_START + i;
- struct ElementInfo *ei = &element_info[element];
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
- if (ei->access_direction == MV_NO_MOVING)
- ei->access_direction = MV_ALL_DIRECTIONS;
+ if (ei->access_direction == MV_NO_MOVING)
+ ei->access_direction = MV_ALL_DIRECTIONS;
- for (j = 0; j < ei->num_change_pages; j++)
- {
- struct ElementChangeInfo *change = &ei->change_page[j];
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ struct ElementChangeInfo *change = &ei->change_page[j];
- if (change->trigger_side == CH_SIDE_NONE)
- change->trigger_side = CH_SIDE_ANY;
+ if (change->trigger_side == CH_SIDE_NONE)
+ change->trigger_side = CH_SIDE_ANY;
+ }
}
}
static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
{
struct ElementInfo *ei = &element_info[element];
- int i, x, y;
+ int i, j, x, y;
putFile16BitBE(file, element);
for (i = 0; i < ei->num_change_pages; i++)
{
struct ElementChangeInfo *change = &ei->change_page[i];
+ unsigned long event_bits = 0;
+
+ for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+ if (change->has_event[j])
+ event_bits |= (1 << j);
- putFile32BitBE(file, change->events);
+ putFile32BitBE(file, event_bits);
putFile16BitBE(file, change->target_element);
putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE :
log_2(change->trigger_page)));
+#if 1
+
+ putFile8Bit(file, change->use_action);
+ putFile8Bit(file, change->action_type);
+ putFile8Bit(file, change->action_mode);
+ putFile16BitBE(file, change->action_arg);
+
+ /* some free bytes for future change property values and padding */
+ WriteUnusedBytesToFile(file, 1);
+#else
/* some free bytes for future change property values and padding */
WriteUnusedBytesToFile(file, 6);
+#endif
#else
for (i = 0; i < tape->length; i++)
{
- if (i >= MAX_TAPELEN)
+ if (i >= MAX_TAPE_LEN)
break;
for (j = 0; j < MAX_PLAYERS; j++)
InitTapeDirectory(leveldir_current->subdir);
/* if a tape still exists, ask to overwrite it */
- if (access(filename, F_OK) == 0)
+ if (fileExists(filename))
{
new_tape = FALSE;
if (!Request("Replace old tape ?", REQ_ASK))
tape.changed = FALSE;
if (new_tape)
- Request("tape saved !", REQ_CONFIRM);
+ Request("Tape saved !", REQ_CONFIRM);
}
void DumpTape(struct TapeInfo *tape)
for (i = 0; i < tape->length; i++)
{
- if (i >= MAX_TAPELEN)
+ if (i >= MAX_TAPE_LEN)
break;
printf("%03d: ", i);
#define SETUP_TOKEN_QUICK_DOORS 10
#define SETUP_TOKEN_TEAM_MODE 11
#define SETUP_TOKEN_HANDICAP 12
-#define SETUP_TOKEN_TIME_LIMIT 13
-#define SETUP_TOKEN_FULLSCREEN 14
-#define SETUP_TOKEN_ASK_ON_ESCAPE 15
-#define SETUP_TOKEN_GRAPHICS_SET 16
-#define SETUP_TOKEN_SOUNDS_SET 17
-#define SETUP_TOKEN_MUSIC_SET 18
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 19
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 20
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 21
-
-#define NUM_GLOBAL_SETUP_TOKENS 22
+#define SETUP_TOKEN_SKIP_LEVELS 13
+#define SETUP_TOKEN_TIME_LIMIT 14
+#define SETUP_TOKEN_FULLSCREEN 15
+#define SETUP_TOKEN_ASK_ON_ESCAPE 16
+#define SETUP_TOKEN_GRAPHICS_SET 17
+#define SETUP_TOKEN_SOUNDS_SET 18
+#define SETUP_TOKEN_MUSIC_SET 19
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 20
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 21
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 22
+
+#define NUM_GLOBAL_SETUP_TOKENS 23
/* editor setup */
#define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0
{ TYPE_SWITCH, &si.quick_doors, "quick_doors" },
{ TYPE_SWITCH, &si.team_mode, "team_mode" },
{ TYPE_SWITCH, &si.handicap, "handicap" },
+ { TYPE_SWITCH, &si.skip_levels, "skip_levels" },
{ TYPE_SWITCH, &si.time_limit, "time_limit" },
{ TYPE_SWITCH, &si.fullscreen, "fullscreen" },
{ TYPE_SWITCH, &si.ask_on_escape, "ask_on_escape" },
si->quick_doors = FALSE;
si->team_mode = FALSE;
si->handicap = TRUE;
+ si->skip_levels = TRUE;
si->time_limit = TRUE;
si->fullscreen = FALSE;
si->ask_on_escape = TRUE;
{
char *value = getHashEntry(element_hash, list->token);
- if (value)
+ if (value == NULL) /* try to find obsolete token mapping */
+ {
+ char *mapped_token = get_mapped_token(list->token);
+
+ if (mapped_token != NULL)
+ {
+ value = getHashEntry(element_hash, mapped_token);
+
+ free(mapped_token);
+ }
+ }
+
+ if (value != NULL)
{
(*elements)[(*num_elements)++] = atoi(value);
}