X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=b1bbc43ef9b1810ee19e6e098094fa688be6486d;hb=fa8aab99c2bf447a57ea1914ac98030455c49bad;hp=627cafc0ffe01e5450844a0fc13771da008b127c;hpb=78a2d1d2a6926a1e101bd5e21b667c81cfd230bb;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 627cafc0..b1bbc43e 100644 --- a/src/files.c +++ b/src/files.c @@ -1771,10 +1771,12 @@ static void setLevelInfoToDefaults_Level(struct LevelInfo *level) setConfigToDefaultsFromConfigList(chunk_config_INFO); *level = li; // copy temporary buffer back to level data + setLevelInfoToDefaults_BD(); setLevelInfoToDefaults_EM(); setLevelInfoToDefaults_SP(); setLevelInfoToDefaults_MM(); + level->native_bd_level = &native_bd_level; level->native_em_level = &native_em_level; level->native_sp_level = &native_sp_level; level->native_mm_level = &native_mm_level; @@ -1903,8 +1905,7 @@ static void setLevelInfoToDefaults_Elements(struct LevelInfo *level) setElementChangeInfoToDefaults(ei->change); if (IS_CUSTOM_ELEMENT(element) || - IS_GROUP_ELEMENT(element) || - IS_INTERNAL_ELEMENT(element)) + IS_GROUP_ELEMENT(element)) { setElementDescriptionToDefault(ei); @@ -2100,6 +2101,13 @@ static int getFileTypeFromBasename(char *basename) strchr(basename, '%') == NULL) return LEVEL_FILE_TYPE_SB; + // check for typical filename of a Boulder Dash (GDash) level package file + if (strSuffixLower(basename, ".bd") || + strSuffixLower(basename, ".bdr") || + strSuffixLower(basename, ".brc") || + strSuffixLower(basename, ".gds")) + return LEVEL_FILE_TYPE_BD; + // ---------- try to determine file type from filesize ---------- checked_free(filename); @@ -2890,7 +2898,7 @@ static int LoadLevel_CUS3(File *file, int chunk_size, struct LevelInfo *level) ei->change->delay_random = getFile16BitBE(file); ei->change->delay_frames = getFile16BitBE(file); - ei->change->initial_trigger_element= getMappedElement(getFile16BitBE(file)); + ei->change->initial_trigger_element = getMappedElement(getFile16BitBE(file)); ei->change->explode = getFile8Bit(file); ei->change->use_target_content = getFile8Bit(file); @@ -3649,6 +3657,136 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, } +// ---------------------------------------------------------------------------- +// functions for loading BD level +// ---------------------------------------------------------------------------- + +static void CopyNativeLevel_RND_to_BD(struct LevelInfo *level) +{ + struct LevelInfo_BD *level_bd = level->native_bd_level; + GdCave *cave = NULL; // will be changed below + int cave_w = MIN(level->fieldx, MAX_PLAYFIELD_WIDTH); + int cave_h = MIN(level->fieldy, MAX_PLAYFIELD_HEIGHT); + int i, x, y; + + setLevelInfoToDefaults_BD_Ext(cave_w, cave_h); + + // cave and map newly allocated when set to defaults above + cave = level_bd->cave; + + for (i = 0; i < 5; i++) + { + cave->level_time[i] = level->time; + cave->level_diamonds[i] = level->gems_needed; + cave->level_magic_wall_time[i] = level->time_magic_wall; + cave->level_timevalue[i] = level->score[SC_TIME_BONUS]; + } + + cave->diamond_value = level->score[SC_DIAMOND]; + cave->extra_diamond_value = level->score[SC_DIAMOND]; + + cave->level_speed[0] = 160; // set cave speed + + strncpy(cave->name, level->name, sizeof(GdString)); + cave->name[sizeof(GdString) - 1] = '\0'; + + for (x = 0; x < cave->w; x++) + for (y = 0; y < cave->h; y++) + cave->map[y][x] = map_element_RND_to_BD(level->field[x][y]); +} + +static void CopyNativeLevel_BD_to_RND(struct LevelInfo *level) +{ + struct LevelInfo_BD *level_bd = level->native_bd_level; + GdCave *cave = level_bd->cave; + int bd_level_nr = level_bd->level_nr; + int x, y; + + level->fieldx = MIN(cave->w, MAX_LEV_FIELDX); + level->fieldy = MIN(cave->h, MAX_LEV_FIELDY); + + level->time = cave->level_time[bd_level_nr]; + level->gems_needed = cave->level_diamonds[bd_level_nr]; + level->time_magic_wall = cave->level_magic_wall_time[bd_level_nr]; + + level->score[SC_TIME_BONUS] = cave->level_timevalue[bd_level_nr]; + level->score[SC_DIAMOND] = cave->diamond_value; + + strncpy(level->name, cave->name, MAX_LEVEL_NAME_LEN); + level->name[MAX_LEVEL_NAME_LEN] = '\0'; + + for (x = 0; x < level->fieldx; x++) + for (y = 0; y < level->fieldy; y++) + level->field[x][y] = map_element_BD_to_RND(cave->map[y][x]); +} + +static void setTapeInfoToDefaults(void); + +static void CopyNativeTape_BD_to_RND(struct LevelInfo *level) +{ + struct LevelInfo_BD *level_bd = level->native_bd_level; + GdCave *cave = level_bd->cave; + GdReplay *replay = level_bd->replay; + int i; + + if (replay == NULL) + return; + + // always start with reliable default values + setTapeInfoToDefaults(); + + tape.level_nr = level_nr; // (currently not used) + tape.random_seed = replay->seed; + + TapeSetDateFromIsoDateString(replay->date); + + tape.counter = 0; + tape.pos[tape.counter].delay = 0; + + tape.bd_replay = TRUE; + + // all time calculations only used to display approximate tape time + int cave_speed = cave->speed; + int milliseconds_game = 0; + int milliseconds_elapsed = 20; + + for (i = 0; i < replay->movements->len; i++) + { + int replay_action = replay->movements->data[i]; + int tape_action = map_action_BD_to_RND(replay_action); + byte action[MAX_TAPE_ACTIONS] = { tape_action }; + boolean success = 0; + + while (1) + { + success = TapeAddAction(action); + + milliseconds_game += milliseconds_elapsed; + + if (milliseconds_game >= cave_speed) + { + milliseconds_game -= cave_speed; + + break; + } + } + + tape.counter++; + tape.pos[tape.counter].delay = 0; + tape.pos[tape.counter].action[0] = 0; + + if (!success) + { + Warn("BD replay truncated: size exceeds maximum tape size %d", MAX_TAPE_LEN); + + break; + } + } + + TapeHaltRecording(); +} + + // ---------------------------------------------------------------------------- // functions for loading EM level // ---------------------------------------------------------------------------- @@ -4107,8 +4245,6 @@ static void CopyNativeTape_RND_to_SP(struct LevelInfo *level) demo->is_available = TRUE; } -static void setTapeInfoToDefaults(void); - static void CopyNativeTape_SP_to_RND(struct LevelInfo *level) { struct LevelInfo_SP *level_sp = level->native_sp_level; @@ -6060,7 +6196,6 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, boolean invalid_playfield_char = FALSE; boolean load_xsb_to_ces = check_special_flags("load_xsb_to_ces"); int file_level_nr = 0; - int line_nr = 0; int x = 0, y = 0; // initialized to make compilers happy last_comment[0] = '\0'; @@ -6102,10 +6237,6 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, if (!getStringFromFile(file, line, MAX_LINE_LEN)) break; - // check if line was completely read and is terminated by line break - if (strlen(line) > 0 && line[strlen(line) - 1] == '\n') - line_nr++; - // cut trailing line break (this can be newline and/or carriage return) for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--) if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0') @@ -6290,6 +6421,20 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level, // functions for handling native levels // ------------------------------------------------------------------------- +static void LoadLevelFromFileInfo_BD(struct LevelInfo *level, + struct LevelFileInfo *level_file_info, + boolean level_info_only) +{ + int pos = 0; + + // determine position of requested level inside level package + if (level_file_info->packed) + pos = level_file_info->nr - leveldir_current->first_level; + + if (!LoadNativeLevel_BD(level_file_info->filename, pos, level_info_only)) + level->no_valid_file = TRUE; +} + static void LoadLevelFromFileInfo_EM(struct LevelInfo *level, struct LevelFileInfo *level_file_info, boolean level_info_only) @@ -6322,7 +6467,9 @@ static void LoadLevelFromFileInfo_MM(struct LevelInfo *level, void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) { - if (level->game_engine_type == GAME_ENGINE_TYPE_EM) + if (level->game_engine_type == GAME_ENGINE_TYPE_BD) + CopyNativeLevel_RND_to_BD(level); + else if (level->game_engine_type == GAME_ENGINE_TYPE_EM) CopyNativeLevel_RND_to_EM(level); else if (level->game_engine_type == GAME_ENGINE_TYPE_SP) CopyNativeLevel_RND_to_SP(level); @@ -6332,7 +6479,9 @@ void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) { - if (level->game_engine_type == GAME_ENGINE_TYPE_EM) + if (level->game_engine_type == GAME_ENGINE_TYPE_BD) + CopyNativeLevel_BD_to_RND(level); + else if (level->game_engine_type == GAME_ENGINE_TYPE_EM) CopyNativeLevel_EM_to_RND(level); else if (level->game_engine_type == GAME_ENGINE_TYPE_SP) CopyNativeLevel_SP_to_RND(level); @@ -6342,16 +6491,40 @@ void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) void SaveNativeLevel(struct LevelInfo *level) { - if (level->game_engine_type == GAME_ENGINE_TYPE_SP) + // saving native level files only supported for some game engines + if (level->game_engine_type != GAME_ENGINE_TYPE_BD && + level->game_engine_type != GAME_ENGINE_TYPE_SP) + return; + + char *file_ext = (level->game_engine_type == GAME_ENGINE_TYPE_BD ? "bd" : + level->game_engine_type == GAME_ENGINE_TYPE_SP ? "sp" : ""); + char *basename = getSingleLevelBasenameExt(level->file_info.nr, file_ext); + char *filename = getLevelFilenameFromBasename(basename); + + if (fileExists(filename) && !Request("Native level file already exists! Overwrite it?", REQ_ASK)) + return; + + boolean success = FALSE; + + if (level->game_engine_type == GAME_ENGINE_TYPE_BD) { - char *basename = getSingleLevelBasenameExt(level->file_info.nr, "sp"); - char *filename = getLevelFilenameFromBasename(basename); + CopyNativeLevel_RND_to_BD(level); + // CopyNativeTape_RND_to_BD(level); + success = SaveNativeLevel_BD(filename); + } + else if (level->game_engine_type == GAME_ENGINE_TYPE_SP) + { CopyNativeLevel_RND_to_SP(level); CopyNativeTape_RND_to_SP(level); - SaveNativeLevel_SP(filename); + success = SaveNativeLevel_SP(filename); } + + if (success) + Request("Native level file saved!", REQ_CONFIRM); + else + Request("Failed to save native level file!", REQ_CONFIRM); } @@ -6372,6 +6545,11 @@ static void LoadLevelFromFileInfo(struct LevelInfo *level, LoadLevelFromFileInfo_RND(level, level_file_info, level_info_only); break; + case LEVEL_FILE_TYPE_BD: + LoadLevelFromFileInfo_BD(level, level_file_info, level_info_only); + level->game_engine_type = GAME_ENGINE_TYPE_BD; + break; + case LEVEL_FILE_TYPE_EM: LoadLevelFromFileInfo_EM(level, level_file_info, level_info_only); level->game_engine_type = GAME_ENGINE_TYPE_EM; @@ -6404,6 +6582,9 @@ static void LoadLevelFromFileInfo(struct LevelInfo *level, if (level->no_valid_file) setLevelInfoToDefaults(level, level_info_only, FALSE); + if (check_special_flags("use_native_bd_game_engine")) + level->game_engine_type = GAME_ENGINE_TYPE_BD; + if (level->game_engine_type == GAME_ENGINE_TYPE_UNKNOWN) level->game_engine_type = GAME_ENGINE_TYPE_RND; @@ -8134,7 +8315,7 @@ static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape) byte action = tape->pos[i].action[0]; int k, num_moves = 0; - for (k = 0; k<4; k++) + for (k = 0; k < 4; k++) { if (action & joy_dir[k]) { @@ -8424,10 +8605,15 @@ void LoadSolutionTape(int nr) LoadTapeFromFilename(filename); - if (TAPE_IS_EMPTY(tape) && - level.game_engine_type == GAME_ENGINE_TYPE_SP && - level.native_sp_level->demo.is_available) - CopyNativeTape_SP_to_RND(&level); + if (TAPE_IS_EMPTY(tape)) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_BD && + level.native_bd_level->replay != NULL) + CopyNativeTape_BD_to_RND(&level); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP && + level.native_sp_level->demo.is_available) + CopyNativeTape_SP_to_RND(&level); + } } void LoadScoreTape(char *score_tape_basename, int nr) @@ -9490,6 +9676,10 @@ static struct TokenInfo global_setup_tokens[] = TYPE_SWITCH, &setup.toons, "toons" }, + { + TYPE_SWITCH, + &setup.global_animations, "global_animations" + }, { TYPE_SWITCH, &setup.scroll_delay, "scroll_delay" @@ -9634,6 +9824,22 @@ static struct TokenInfo global_setup_tokens[] = TYPE_INTEGER, &setup.game_frame_delay, "game_frame_delay" }, + { + TYPE_SWITCH, + &setup.bd_skip_uncovering, "bd_skip_uncovering" + }, + { + TYPE_SWITCH, + &setup.bd_skip_hatching, "bd_skip_hatching" + }, + { + TYPE_SWITCH, + &setup.bd_scroll_delay, "bd_scroll_delay" + }, + { + TYPE_SWITCH3, + &setup.bd_smooth_movements, "bd_smooth_movements" + }, { TYPE_SWITCH, &setup.sp_show_border_elements, "sp_show_border_elements" @@ -9838,6 +10044,10 @@ static struct TokenInfo editor_cascade_setup_tokens[] = TYPE_SWITCH, &setup.editor_cascade.el_bd, "editor.cascade.el_bd" }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_bd_native, "editor.cascade.el_bd_native" + }, { TYPE_SWITCH, &setup.editor_cascade.el_em, "editor.cascade.el_em" @@ -10409,6 +10619,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->sound_music = TRUE; si->sound_simple = TRUE; si->toons = TRUE; + si->global_animations = TRUE; si->scroll_delay = TRUE; si->forced_scroll_delay = FALSE; si->scroll_delay_value = STD_SCROLL_DELAY; @@ -10445,6 +10656,10 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->prefer_extra_panel_items = TRUE; si->game_speed_extended = FALSE; si->game_frame_delay = GAME_FRAME_DELAY; + si->bd_skip_uncovering = FALSE; + si->bd_skip_hatching = FALSE; + si->bd_scroll_delay = TRUE; + si->bd_smooth_movements = AUTO; si->sp_show_border_elements = FALSE; si->small_game_graphics = FALSE; si->show_load_save_buttons = FALSE; @@ -10526,6 +10741,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->touch.overlay_buttons = FALSE; si->editor.el_boulderdash = TRUE; + si->editor.el_boulderdash_native = TRUE; si->editor.el_emerald_mine = TRUE; si->editor.el_emerald_mine_club = TRUE; si->editor.el_more = TRUE; @@ -10585,7 +10801,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) for (i = 0; i < MAX_PLAYERS; i++) { si->input[i].use_joystick = FALSE; - si->input[i].joy.device_name=getStringCopy(getDeviceNameFromJoystickNr(i)); + si->input[i].joy.device_name = getStringCopy(getDeviceNameFromJoystickNr(i)); si->input[i].joy.xleft = JOYSTICK_XLEFT; si->input[i].joy.xmiddle = JOYSTICK_XMIDDLE; si->input[i].joy.xright = JOYSTICK_XRIGHT; @@ -10699,6 +10915,7 @@ static void setSetupInfoToDefaults_ServerSetup(struct SetupInfo *si) static void setSetupInfoToDefaults_EditorCascade(struct SetupInfo *si) { si->editor_cascade.el_bd = TRUE; + si->editor_cascade.el_bd_native = TRUE; si->editor_cascade.el_em = TRUE; si->editor_cascade.el_emc = TRUE; si->editor_cascade.el_rnd = TRUE; @@ -11527,8 +11744,9 @@ static boolean string_has_parameter(char *s, char *s_contained) char next_char = s[strlen(s_contained)]; // check if next character is delimiter or whitespace - return (next_char == ',' || next_char == '\0' || - next_char == ' ' || next_char == '\t' ? TRUE : FALSE); + if (next_char == ',' || next_char == '\0' || + next_char == ' ' || next_char == '\t') + return TRUE; } // check if string contains another parameter string after a comma @@ -11546,6 +11764,85 @@ static boolean string_has_parameter(char *s, char *s_contained) return string_has_parameter(substring, s_contained); } +static int get_anim_parameter_value_ce(char *s) +{ + char *s_ptr = s; + char *pattern_1 = "ce_change:custom_"; + char *pattern_2 = ".page_"; + int pattern_1_len = strlen(pattern_1); + char *matching_char = strstr(s_ptr, pattern_1); + int result = ANIM_EVENT_NONE; + + if (matching_char == NULL) + return ANIM_EVENT_NONE; + + result = ANIM_EVENT_CE_CHANGE; + + s_ptr = matching_char + pattern_1_len; + + // check for custom element number ("custom_X", "custom_XX" or "custom_XXX") + if (*s_ptr >= '0' && *s_ptr <= '9') + { + int gic_ce_nr = (*s_ptr++ - '0'); + + if (*s_ptr >= '0' && *s_ptr <= '9') + { + gic_ce_nr = 10 * gic_ce_nr + (*s_ptr++ - '0'); + + if (*s_ptr >= '0' && *s_ptr <= '9') + gic_ce_nr = 10 * gic_ce_nr + (*s_ptr++ - '0'); + } + + if (gic_ce_nr < 1 || gic_ce_nr > NUM_CUSTOM_ELEMENTS) + return ANIM_EVENT_NONE; + + // custom element stored as 0 to 255 + gic_ce_nr--; + + result |= gic_ce_nr << ANIM_EVENT_CE_BIT; + } + else + { + // invalid custom element number specified + + return ANIM_EVENT_NONE; + } + + // check for change page number ("page_X" or "page_XX") (optional) + if (strPrefix(s_ptr, pattern_2)) + { + s_ptr += strlen(pattern_2); + + if (*s_ptr >= '0' && *s_ptr <= '9') + { + int gic_page_nr = (*s_ptr++ - '0'); + + if (*s_ptr >= '0' && *s_ptr <= '9') + gic_page_nr = 10 * gic_page_nr + (*s_ptr++ - '0'); + + if (gic_page_nr < 1 || gic_page_nr > MAX_CHANGE_PAGES) + return ANIM_EVENT_NONE; + + // change page stored as 1 to 32 (0 means "all change pages") + + result |= gic_page_nr << ANIM_EVENT_PAGE_BIT; + } + else + { + // invalid animation part number specified + + return ANIM_EVENT_NONE; + } + } + + // discard result if next character is neither delimiter nor whitespace + if (!(*s_ptr == ',' || *s_ptr == '\0' || + *s_ptr == ' ' || *s_ptr == '\t')) + return ANIM_EVENT_NONE; + + return result; +} + static int get_anim_parameter_value(char *s) { int event_value[] = @@ -11571,6 +11868,11 @@ static int get_anim_parameter_value(char *s) int result = ANIM_EVENT_NONE; int i; + result = get_anim_parameter_value_ce(s); + + if (result != ANIM_EVENT_NONE) + return result; + for (i = 0; i < ARRAY_SIZE(event_value); i++) { matching_char = strstr(s_ptr, pattern_1[i]); @@ -11704,7 +12006,7 @@ static int get_anim_action_parameter_value(char *token) { if (isURL(token)) { - result = get_hash_from_key(token); // unsigned int => int + result = get_hash_from_string(token); // unsigned int => int result = ABS(result); // may be negative now result += (result < MAX_IMAGE_FILES ? MAX_IMAGE_FILES : 0); @@ -11740,6 +12042,8 @@ int get_parameter_value(char *value_raw, char *suffix, int type) strEqual(value, "lower") ? POS_LOWER : strEqual(value, "bottom") ? POS_BOTTOM : strEqual(value, "any") ? POS_ANY : + strEqual(value, "ce") ? POS_CE : + strEqual(value, "ce_trigger") ? POS_CE_TRIGGER : strEqual(value, "last") ? POS_LAST : POS_UNDEFINED); } else if (strEqual(suffix, ".align")) @@ -11773,6 +12077,7 @@ int get_parameter_value(char *value_raw, char *suffix, int type) string_has_parameter(value, "centered") ? ANIM_CENTERED : string_has_parameter(value, "all") ? ANIM_ALL : string_has_parameter(value, "tiled") ? ANIM_TILED : + string_has_parameter(value, "level_nr") ? ANIM_LEVEL_NR : ANIM_DEFAULT); if (string_has_parameter(value, "once")) @@ -11803,7 +12108,7 @@ int get_parameter_value(char *value_raw, char *suffix, int type) else if (strEqual(suffix, ".class")) { result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE : - get_hash_from_key(value)); + get_hash_from_string(value)); } else if (strEqual(suffix, ".style")) { @@ -11829,11 +12134,16 @@ int get_parameter_value(char *value_raw, char *suffix, int type) if (string_has_parameter(value, "multiple_actions")) result |= STYLE_MULTIPLE_ACTIONS; + + if (string_has_parameter(value, "consume_ce_event")) + result |= STYLE_CONSUME_CE_EVENT; } else if (strEqual(suffix, ".fade_mode")) { result = (string_has_parameter(value, "none") ? FADE_MODE_NONE : string_has_parameter(value, "fade") ? FADE_MODE_FADE : + string_has_parameter(value, "fade_in") ? FADE_MODE_FADE_IN : + string_has_parameter(value, "fade_out") ? FADE_MODE_FADE_OUT : string_has_parameter(value, "crossfade") ? FADE_MODE_CROSSFADE : string_has_parameter(value, "melt") ? FADE_MODE_MELT : string_has_parameter(value, "curtain") ? FADE_MODE_CURTAIN : @@ -12345,6 +12655,45 @@ static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics(void) } } +static void InitMenuDesignSettings_PreviewPlayers_Ext(SetupFileHash *hash, + boolean initialize) +{ + // special case: check if network and preview player positions are redefined, + // to compare this later against the main menu level preview being redefined + struct TokenIntPtrInfo menu_config_players[] = + { + { "main.network_players.x", &menu.main.network_players.redefined }, + { "main.network_players.y", &menu.main.network_players.redefined }, + { "main.preview_players.x", &menu.main.preview_players.redefined }, + { "main.preview_players.y", &menu.main.preview_players.redefined }, + { "preview.x", &preview.redefined }, + { "preview.y", &preview.redefined } + }; + int i; + + if (initialize) + { + for (i = 0; i < ARRAY_SIZE(menu_config_players); i++) + *menu_config_players[i].value = FALSE; + } + else + { + for (i = 0; i < ARRAY_SIZE(menu_config_players); i++) + if (getHashEntry(hash, menu_config_players[i].token) != NULL) + *menu_config_players[i].value = TRUE; + } +} + +static void InitMenuDesignSettings_PreviewPlayers(void) +{ + InitMenuDesignSettings_PreviewPlayers_Ext(NULL, TRUE); +} + +static void InitMenuDesignSettings_PreviewPlayers_FromHash(SetupFileHash *hash) +{ + InitMenuDesignSettings_PreviewPlayers_Ext(hash, FALSE); +} + static void LoadMenuDesignSettingsFromFilename(char *filename) { static struct TitleFadingInfo tfi; @@ -12686,28 +13035,12 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) } } - // special case: check if network and preview player positions are redefined, - // to compare this later against the main menu level preview being redefined - struct TokenIntPtrInfo menu_config_players[] = - { - { "main.network_players.x", &menu.main.network_players.redefined }, - { "main.network_players.y", &menu.main.network_players.redefined }, - { "main.preview_players.x", &menu.main.preview_players.redefined }, - { "main.preview_players.y", &menu.main.preview_players.redefined }, - { "preview.x", &preview.redefined }, - { "preview.y", &preview.redefined } - }; - - for (i = 0; i < ARRAY_SIZE(menu_config_players); i++) - *menu_config_players[i].value = FALSE; - - for (i = 0; i < ARRAY_SIZE(menu_config_players); i++) - if (getHashEntry(setup_file_hash, menu_config_players[i].token) != NULL) - *menu_config_players[i].value = TRUE; - // read (and overwrite with) values that may be specified in config file InitMenuDesignSettings_FromHash(setup_file_hash, TRUE); + // special case: check if network and preview player positions are redefined + InitMenuDesignSettings_PreviewPlayers_FromHash(setup_file_hash); + freeSetupFileHash(setup_file_hash); } @@ -12717,6 +13050,7 @@ void LoadMenuDesignSettings(void) InitMenuDesignSettings_Static(); InitMenuDesignSettings_SpecialPreProcessing(); + InitMenuDesignSettings_PreviewPlayers(); if (!GFX_OVERRIDE_ARTWORK(ARTWORK_TYPE_GRAPHICS)) { @@ -12740,6 +13074,65 @@ void LoadMenuDesignSettings_AfterGraphics(void) InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics(); } +void InitSoundSettings_FromHash(SetupFileHash *setup_file_hash, + boolean ignore_defaults) +{ + int i; + + for (i = 0; sound_config_vars[i].token != NULL; i++) + { + char *value = getHashEntry(setup_file_hash, sound_config_vars[i].token); + + // (ignore definitions set to "[DEFAULT]" which are already initialized) + if (ignore_defaults && strEqual(value, ARG_DEFAULT)) + continue; + + if (value != NULL) + *sound_config_vars[i].value = + get_token_parameter_value(sound_config_vars[i].token, value); + } +} + +void InitSoundSettings_Static(void) +{ + // always start with reliable default values from static default config + InitSoundSettings_FromHash(sound_config_hash, FALSE); +} + +static void LoadSoundSettingsFromFilename(char *filename) +{ + SetupFileHash *setup_file_hash; + + if ((setup_file_hash = loadSetupFileHash(filename)) == NULL) + return; + + // read (and overwrite with) values that may be specified in config file + InitSoundSettings_FromHash(setup_file_hash, TRUE); + + freeSetupFileHash(setup_file_hash); +} + +void LoadSoundSettings(void) +{ + char *filename_base = UNDEFINED_FILENAME, *filename_local; + + InitSoundSettings_Static(); + + if (!GFX_OVERRIDE_ARTWORK(ARTWORK_TYPE_SOUNDS)) + { + // first look for special settings configured in level series config + filename_base = getCustomArtworkLevelConfigFilename(ARTWORK_TYPE_SOUNDS); + + if (fileExists(filename_base)) + LoadSoundSettingsFromFilename(filename_base); + } + + filename_local = getCustomArtworkConfigFilename(ARTWORK_TYPE_SOUNDS); + + if (filename_local != NULL && !strEqual(filename_base, filename_local)) + LoadSoundSettingsFromFilename(filename_local); +} + void LoadUserDefinedEditorElementList(int **elements, int *num_elements) { char *filename = getEditorSetupFilename();