X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Finit.c;h=2167984b663649481289e4d4c0c5f14be1670312;hp=d0422650ab5ee09b34c1b6e5b0d5b57cfd124e6c;hb=ef4236ac56bedd0e83777505c4ed63fbf4a74698;hpb=2176d1de29652bc9e8db1baa283fdc1c4e99e674 diff --git a/src/init.c b/src/init.c index d0422650..2167984b 100644 --- a/src/init.c +++ b/src/init.c @@ -21,7 +21,7 @@ #include "files.h" #include "network.h" #include "netserv.h" -#include "cartoons.h" +#include "anim.h" #include "config.h" #include "conf_e2g.c" /* include auto-generated data structure definitions */ @@ -84,7 +84,11 @@ static int copy_properties[][5] = }; -void DrawInitAnim() +/* forward declaration for internal use */ +static int get_graphic_parameter_value(char *, char *, int); + + +static void DrawInitAnim(void) { struct GraphicInfo *graphic_info_last = graphic_info; int graphic = 0; @@ -93,6 +97,9 @@ void DrawInitAnim() int sync_frame = FrameCounter; int x, y; + /* prevent OS (Windows) from complaining about program not responding */ + CheckQuitEvent(); + if (game_status != GAME_MODE_LOADING) return; @@ -129,7 +136,21 @@ void DrawInitAnim() FrameCounter++; } -void FreeGadgets() +static void DrawProgramInfo(void) +{ + int font1_nr = FC_YELLOW; + int font2_nr = FC_RED; + int font2_height = getFontHeight(font2_nr); + int ypos1 = 20; + int ypos2 = 50; + int ypos3 = WIN_YSIZE - 20 - font2_height; + + DrawInitText(getProgramInitString(), ypos1, font1_nr); + DrawInitText(setup.internal.program_copyright, ypos2, font2_nr); + DrawInitText(setup.internal.program_website, ypos3, font2_nr); +} + +static void FreeGadgets(void) { FreeLevelEditorGadgets(); FreeGameButtons(); @@ -138,7 +159,7 @@ void FreeGadgets() FreeScreenGadgets(); } -void InitGadgets() +void InitGadgets(void) { static boolean gadgets_initialized = FALSE; @@ -164,12 +185,24 @@ inline static void InitElementSmallImagesScaledUp(int graphic) CreateImageWithSmallImages(graphic, g->scale_up_factor, g->tile_size); } -void InitElementSmallImages() +static void InitElementSmallImages(void) { print_timestamp_init("InitElementSmallImages"); static int special_graphics[] = { + IMG_FLAMES_1_LEFT, + IMG_FLAMES_2_LEFT, + IMG_FLAMES_3_LEFT, + IMG_FLAMES_1_RIGHT, + IMG_FLAMES_2_RIGHT, + IMG_FLAMES_3_RIGHT, + IMG_FLAMES_1_UP, + IMG_FLAMES_2_UP, + IMG_FLAMES_3_UP, + IMG_FLAMES_1_DOWN, + IMG_FLAMES_2_DOWN, + IMG_FLAMES_3_DOWN, IMG_EDITOR_ELEMENT_BORDER, IMG_EDITOR_ELEMENT_BORDER_INPUT, IMG_EDITOR_CASCADE_LIST, @@ -183,22 +216,23 @@ void InitElementSmallImages() print_timestamp_time("getImageListPropertyMapping/Size"); print_timestamp_init("InitElementSmallImagesScaledUp (1)"); - /* initialize normal images from static configuration */ + /* initialize normal element images from static configuration */ for (i = 0; element_to_graphic[i].element > -1; i++) InitElementSmallImagesScaledUp(element_to_graphic[i].graphic); print_timestamp_done("InitElementSmallImagesScaledUp (1)"); - /* initialize special images from static configuration */ + /* initialize special element images from static configuration */ for (i = 0; element_to_special_graphic[i].element > -1; i++) InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic); print_timestamp_time("InitElementSmallImagesScaledUp (2)"); - /* initialize images from dynamic configuration (may be elements or other) */ + /* initialize element images from dynamic configuration */ for (i = 0; i < num_property_mappings; i++) - InitElementSmallImagesScaledUp(property_mapping[i].artwork_index); + if (property_mapping[i].base_index < MAX_NUM_ELEMENTS) + InitElementSmallImagesScaledUp(property_mapping[i].artwork_index); print_timestamp_time("InitElementSmallImagesScaledUp (3)"); - /* initialize special images from above list (non-element images) */ + /* initialize special non-element images from above list */ for (i = 0; special_graphics[i] > -1; i++) InitElementSmallImagesScaledUp(special_graphics[i]); print_timestamp_time("InitElementSmallImagesScaledUp (4)"); @@ -206,16 +240,29 @@ void InitElementSmallImages() print_timestamp_done("InitElementSmallImages"); } -void InitScaledImages() +inline static void InitScaledImagesScaledUp(int graphic) { + struct GraphicInfo *g = &graphic_info[graphic]; + + ScaleImage(graphic, g->scale_up_factor); +} + +static void InitScaledImages(void) +{ + struct PropertyMapping *property_mapping = getImageListPropertyMapping(); + int num_property_mappings = getImageListPropertyMappingSize(); int i; /* scale normal images from static configuration, if not already scaled */ for (i = 0; i < NUM_IMAGE_FILES; i++) - ScaleImage(i, graphic_info[i].scale_up_factor); + InitScaledImagesScaledUp(i); + + /* scale images from dynamic configuration, if not already scaled */ + for (i = 0; i < num_property_mappings; i++) + InitScaledImagesScaledUp(property_mapping[i].artwork_index); } -void InitBitmapPointers() +static void InitBitmapPointers(void) { int num_images = getImageListSize(); int i; @@ -226,7 +273,7 @@ void InitBitmapPointers() graphic_info[i].bitmap = graphic_info[i].bitmaps[IMG_BITMAP_STANDARD]; } -void InitImageTextures() +void InitImageTextures(void) { int i, j, k; @@ -300,7 +347,7 @@ static int getFontFromToken(char *token) return FONT_INITIAL_1; } -void InitFontGraphicInfo() +static void InitFontGraphicInfo(void) { static struct FontBitmapInfo *font_bitmap_info = NULL; struct PropertyMapping *property_mapping = getImageListPropertyMapping(); @@ -383,7 +430,7 @@ void InitFontGraphicInfo() int special = property_mapping[i].ext3_index; int graphic = property_mapping[i].artwork_index; - if (font_nr < 0) + if (font_nr < 0 || font_nr >= NUM_FONTS) continue; if (IS_SPECIAL_GFX_ARG(special)) @@ -518,6 +565,11 @@ void InitFontGraphicInfo() font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width; font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height; + font_bitmap_info[font_bitmap_id].offset_x = + graphic_info[graphic].offset_x; + font_bitmap_info[font_bitmap_id].offset_y = + graphic_info[graphic].offset_y; + font_bitmap_info[font_bitmap_id].draw_xoffset = graphic_info[graphic].draw_xoffset; font_bitmap_info[font_bitmap_id].draw_yoffset = @@ -534,7 +586,7 @@ void InitFontGraphicInfo() getFontBitmapID, getFontFromToken); } -void InitGlobalAnimGraphicInfo() +static void InitGlobalAnimGraphicInfo(void) { struct PropertyMapping *property_mapping = getImageListPropertyMapping(); int num_property_mappings = getImageListPropertyMappingSize(); @@ -555,7 +607,7 @@ void InitGlobalAnimGraphicInfo() int j = GLOBAL_ANIM_ID_PART_BASE; int k = GFX_SPECIAL_ARG_DEFAULT; - global_anim_info[i].graphic[j][k] = IMG_GLOBAL_ANIM_1_GFX + i; + global_anim_info[i].graphic[j][k] = IMG_GFX_GLOBAL_ANIM_1 + i; } /* initialize global animation definitions from dynamic configuration */ @@ -578,6 +630,19 @@ void InitGlobalAnimGraphicInfo() special = GFX_SPECIAL_ARG_DEFAULT; global_anim_info[anim_nr].graphic[part_nr][special] = graphic; + + /* fix default value for ".draw_masked" (for backward compatibility) */ + struct GraphicInfo *g = &graphic_info[graphic]; + struct FileInfo *image = getImageListEntryFromImageID(graphic); + char **parameter_raw = image->parameter; + int p = GFX_ARG_DRAW_MASKED; + int draw_masked = get_graphic_parameter_value(parameter_raw[p], + image_config_suffix[p].token, + image_config_suffix[p].type); + + /* if ".draw_masked" parameter is undefined, use default value "TRUE" */ + if (draw_masked == ARG_UNDEFINED_VALUE) + g->draw_masked = TRUE; } #if 0 @@ -593,7 +658,7 @@ void InitGlobalAnimGraphicInfo() #endif } -void InitGlobalAnimSoundInfo() +static void InitGlobalAnimSoundInfo(void) { struct PropertyMapping *property_mapping = getSoundListPropertyMapping(); int num_property_mappings = getSoundListPropertyMappingSize(); @@ -642,7 +707,56 @@ void InitGlobalAnimSoundInfo() #endif } -void InitElementGraphicInfo() +static void InitGlobalAnimMusicInfo(void) +{ + struct PropertyMapping *property_mapping = getMusicListPropertyMapping(); + int num_property_mappings = getMusicListPropertyMappingSize(); + int i, j, k; + + /* always start with reliable default values (no global animation music) */ + for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++) + for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++) + for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++) + global_anim_info[i].music[j][k] = MUS_UNDEFINED; + + /* initialize global animation music definitions from dynamic configuration */ + for (i = 0; i < num_property_mappings; i++) + { + int anim_nr = property_mapping[i].base_index - NUM_MUSIC_PREFIXES; + int part_nr = property_mapping[i].ext1_index - ACTION_PART_1; + int special = property_mapping[i].ext2_index; + int music = property_mapping[i].artwork_index; + + // music uses control definition; map it to position of graphic (artwork) + anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST; + + if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS) + continue; + + /* set animation part to base part, if not specified */ + if (!IS_GLOBAL_ANIM_PART(part_nr)) + part_nr = GLOBAL_ANIM_ID_PART_BASE; + + /* set animation screen to default, if not specified */ + if (!IS_SPECIAL_GFX_ARG(special)) + special = GFX_SPECIAL_ARG_DEFAULT; + + global_anim_info[anim_nr].music[part_nr][special] = music; + } + +#if 0 + printf("::: InitGlobalAnimMusicInfo\n"); + + for (i = 0; i < NUM_GLOBAL_ANIMS; i++) + for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++) + for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++) + if (global_anim_info[i].music[j][k] != MUS_UNDEFINED) + printf("::: - anim %d, part %d, mode %d => %d\n", + i, j, k, global_anim_info[i].music[j][k]); +#endif +} + +static void InitElementGraphicInfo(void) { struct PropertyMapping *property_mapping = getImageListPropertyMapping(); int num_property_mappings = getImageListPropertyMappingSize(); @@ -875,14 +989,12 @@ void InitElementGraphicInfo() (move_dir == MV_BIT_UP && !front_is_left_or_upper) || (move_dir == MV_BIT_RIGHT && front_is_left_or_upper) || (move_dir == MV_BIT_DOWN && front_is_left_or_upper))); - Bitmap *dummy; /* swap frontside and backside graphic tile coordinates, if needed */ if (swap_movement_tiles_always || swap_movement_tiles_autodetected) { /* get current (wrong) backside tile coordinates */ - getFixedGraphicSourceExt(graphic, 0, &dummy, - &src_x_back, &src_y_back, TRUE); + getGraphicSourceXY(graphic, 0, &src_x_back, &src_y_back, TRUE); /* set frontside tile coordinates to backside tile coordinates */ g->src_x = src_x_back; @@ -955,6 +1067,8 @@ void InitElementGraphicInfo() default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act]; if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1) default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act]; + if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].graphic[act] != -1) + default_action_graphic = element_info[EL_MM_DEFAULT].graphic[act]; if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1) default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act]; @@ -962,6 +1076,8 @@ void InitElementGraphicInfo() default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act]; if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1) default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act]; + if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].crumbled[act] != -1) + default_action_crumbled = element_info[EL_MM_DEFAULT].crumbled[act]; /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */ /* !!! make this better !!! */ @@ -1021,7 +1137,7 @@ void InitElementGraphicInfo() UPDATE_BUSY_STATE(); } -void InitElementSpecialGraphicInfo() +static void InitElementSpecialGraphicInfo(void) { struct PropertyMapping *property_mapping = getImageListPropertyMapping(); int num_property_mappings = getImageListPropertyMappingSize(); @@ -1185,6 +1301,11 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, g->anim_delay_random = 0; g->post_delay_fixed = 0; g->post_delay_random = 0; + g->init_event = ANIM_EVENT_DEFAULT; + g->anim_event = ANIM_EVENT_DEFAULT; + g->init_event_action = -1; + g->anim_event_action = -1; + g->draw_masked = FALSE; g->draw_order = 0; g->fade_mode = FADE_MODE_DEFAULT; g->fade_delay = -1; @@ -1284,13 +1405,13 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE) { - anim_frames_per_row = src_image_width / g->tile_size; - anim_frames_per_col = src_image_height / g->tile_size; + anim_frames_per_row = MAX(1, src_image_width / g->tile_size); + anim_frames_per_col = MAX(1, src_image_height / g->tile_size); } else { - anim_frames_per_row = src_image_width / g->width; - anim_frames_per_col = src_image_height / g->height; + anim_frames_per_row = MAX(1, src_image_width / g->width); + anim_frames_per_col = MAX(1, src_image_height / g->height); } g->src_image_width = src_image_width; @@ -1401,6 +1522,16 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE) g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM]; + /* used for global animations */ + if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE) + g->init_event = parameter[GFX_ARG_INIT_EVENT]; + if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE) + g->anim_event = parameter[GFX_ARG_ANIM_EVENT]; + if (parameter[GFX_ARG_INIT_EVENT_ACTION] != ARG_UNDEFINED_VALUE) + g->init_event_action = parameter[GFX_ARG_INIT_EVENT_ACTION]; + if (parameter[GFX_ARG_ANIM_EVENT_ACTION] != ARG_UNDEFINED_VALUE) + g->anim_event_action = parameter[GFX_ARG_ANIM_EVENT_ACTION]; + /* used for toon animations and global animations */ g->step_offset = parameter[GFX_ARG_STEP_OFFSET]; g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET]; @@ -1415,8 +1546,14 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET]; g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET]; - /* this is only used for drawing envelope graphics */ - g->draw_masked = parameter[GFX_ARG_DRAW_MASKED]; + /* use a different default value for global animations and toons */ + if ((graphic >= IMG_GFX_GLOBAL_ANIM_1 && graphic <= IMG_GFX_GLOBAL_ANIM_8) || + (graphic >= IMG_TOON_1 && graphic <= IMG_TOON_20)) + g->draw_masked = TRUE; + + /* this is used for drawing envelopes, global animations and toons */ + if (parameter[GFX_ARG_DRAW_MASKED] != ARG_UNDEFINED_VALUE) + g->draw_masked = parameter[GFX_ARG_DRAW_MASKED]; /* used for toon animations and global animations */ if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE) @@ -1516,7 +1653,7 @@ static void set_cloned_graphic_parameters(int graphic) } } -static void InitGraphicInfo() +static void InitGraphicInfo(void) { int fallback_graphic = IMG_CHAR_EXCLAM; int num_images = getImageListSize(); @@ -1609,10 +1746,10 @@ static void InitGraphicInfo() for (i = 0; i < num_images; i++) { - Bitmap *src_bitmap; + Bitmap *src_bitmap = graphic_info[i].bitmap; int src_x, src_y; int width, height; - int first_frame, last_frame; + int last_frame; int src_bitmap_width, src_bitmap_height; /* now check if no animation frames are outside of the loaded image */ @@ -1630,13 +1767,14 @@ static void InitGraphicInfo() /* check if first animation frame is inside specified bitmap */ - first_frame = 0; - getFixedGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y); - + /* do not use getGraphicSourceXY() here to get position of first frame; */ /* this avoids calculating wrong start position for out-of-bounds frame */ src_x = graphic_info[i].src_x; src_y = graphic_info[i].src_y; + if (program.headless) + continue; + if (src_x < 0 || src_y < 0 || src_x + width > src_bitmap_width || src_y + height > src_bitmap_height) @@ -1646,6 +1784,7 @@ static void InitGraphicInfo() Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename()); Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i)); Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename); + Error(ERR_INFO, "- frame size: %d, %d", width, height); Error(ERR_INFO, "error: first animation frame out of bounds (%d, %d) [%d, %d]", src_x, src_y, src_bitmap_width, src_bitmap_height); @@ -1658,12 +1797,15 @@ static void InitGraphicInfo() Error(ERR_INFO_LINE, "-"); graphic_info[i] = graphic_info[fallback_graphic]; + + /* if first frame out of bounds, do not check last frame anymore */ + continue; } /* check if last animation frame is inside specified bitmap */ last_frame = graphic_info[i].anim_frames - 1; - getFixedGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y); + getGraphicSourceXY(i, last_frame, &src_x, &src_y, FALSE); if (src_x < 0 || src_y < 0 || src_x + width > src_bitmap_width || @@ -1674,10 +1816,10 @@ static void InitGraphicInfo() Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename()); Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i)); Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename); + Error(ERR_INFO, "- frame size: %d, %d", width, height); Error(ERR_INFO, "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]", last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height); - Error(ERR_INFO, "::: %d, %d", width, height); Error(ERR_INFO, "custom graphic rejected for this element/action"); if (i == fallback_graphic) @@ -1691,7 +1833,7 @@ static void InitGraphicInfo() } } -static void InitGraphicCompatibilityInfo() +static void InitGraphicCompatibilityInfo(void) { struct FileInfo *fi_global_door = getImageListEntryFromImageID(IMG_GLOBAL_DOOR); @@ -1723,7 +1865,8 @@ static void InitGraphicCompatibilityInfo() { // printf("::: special treatment needed for token '%s'\n", fi->token); - graphic_info[i].bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap; + graphic_info[i].bitmaps = graphic_info[IMG_GLOBAL_DOOR].bitmaps; + graphic_info[i].bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap; } } } @@ -1732,7 +1875,7 @@ static void InitGraphicCompatibilityInfo() InitGraphicCompatibilityInfo_Doors(); } -static void InitElementSoundInfo() +static void InitElementSoundInfo(void) { struct PropertyMapping *property_mapping = getSoundListPropertyMapping(); int num_property_mappings = getSoundListPropertyMappingSize(); @@ -1813,6 +1956,8 @@ static void InitElementSoundInfo() default_action_sound = element_info[EL_SP_DEFAULT].sound[act]; if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1) default_action_sound = element_info[EL_SB_DEFAULT].sound[act]; + if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].sound[act] != -1) + default_action_sound = element_info[EL_MM_DEFAULT].sound[act]; /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */ /* !!! make this better !!! */ @@ -1834,7 +1979,7 @@ static void InitElementSoundInfo() element_info[copy_properties[i][0]].sound[act]; } -static void InitGameModeSoundInfo() +static void InitGameModeSoundInfo(void) { int i; @@ -1883,7 +2028,7 @@ static void set_sound_parameters(int sound, char **parameter_raw) sound_info[sound].priority = parameter[SND_ARG_PRIORITY]; } -static void InitSoundInfo() +static void InitSoundInfo(void) { int *sound_effect_properties; int num_sounds = getSoundListSize(); @@ -1950,7 +2095,7 @@ static void InitSoundInfo() free(sound_effect_properties); } -static void InitGameModeMusicInfo() +static void InitGameModeMusicInfo(void) { struct PropertyMapping *property_mapping = getMusicListPropertyMapping(); int num_property_mappings = getMusicListPropertyMappingSize(); @@ -1979,8 +2124,8 @@ static void InitGameModeMusicInfo() for (i = 0; i < num_property_mappings; i++) { int prefix = property_mapping[i].base_index; - int gamemode = property_mapping[i].ext1_index; - int level = property_mapping[i].ext2_index; + int gamemode = property_mapping[i].ext2_index; + int level = property_mapping[i].ext3_index; int music = property_mapping[i].artwork_index; if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES) @@ -2033,7 +2178,7 @@ static void set_music_parameters(int music, char **parameter_raw) music_info[music].loop = parameter[MUS_ARG_MODE_LOOP]; } -static void InitMusicInfo() +static void InitMusicInfo(void) { int num_music = getMusicListSize(); int i, j; @@ -2069,7 +2214,7 @@ static void InitMusicInfo() } } -static void ReinitializeGraphics() +static void ReinitializeGraphics(void) { print_timestamp_init("ReinitializeGraphics"); @@ -2109,15 +2254,13 @@ static void ReinitializeGraphics() InitGadgets(); print_timestamp_time("InitGadgets"); - InitToons(); - print_timestamp_time("InitToons"); InitDoors(); print_timestamp_time("InitDoors"); print_timestamp_done("ReinitializeGraphics"); } -static void ReinitializeSounds() +static void ReinitializeSounds(void) { InitSoundInfo(); /* sound properties mapping */ InitElementSoundInfo(); /* element game sound mapping */ @@ -2127,10 +2270,11 @@ static void ReinitializeSounds() InitPlayLevelSound(); /* internal game sound settings */ } -static void ReinitializeMusic() +static void ReinitializeMusic(void) { InitMusicInfo(); /* music properties mapping */ InitGameModeMusicInfo(); /* game mode music mapping */ + InitGlobalAnimMusicInfo(); /* global animation music settings */ } static int get_special_property_bit(int element, int property_bit_nr) @@ -2318,7 +2462,7 @@ void ResolveGroupElement(int group_element) ResolveGroupElementExt(group_element, 0); } -void InitElementPropertiesStatic() +void InitElementPropertiesStatic(void) { static boolean clipboard_elements_initialized = FALSE; @@ -3530,12 +3674,8 @@ void InitElementPropertiesStatic() EL_INVISIBLE_WALL_ACTIVE, EL_SWITCHGATE_SWITCH_UP, EL_SWITCHGATE_SWITCH_DOWN, - EL_DC_SWITCHGATE_SWITCH_UP, - EL_DC_SWITCHGATE_SWITCH_DOWN, EL_TIMEGATE_SWITCH, EL_TIMEGATE_SWITCH_ACTIVE, - EL_DC_TIMEGATE_SWITCH, - EL_DC_TIMEGATE_SWITCH_ACTIVE, EL_EMC_WALL_1, EL_EMC_WALL_2, EL_EMC_WALL_3, @@ -3604,6 +3744,12 @@ void InitElementPropertiesStatic() EL_SIGN_FRANKIE, EL_STEEL_EXIT_CLOSED, EL_STEEL_EXIT_OPEN, + EL_STEEL_EXIT_OPENING, + EL_STEEL_EXIT_CLOSING, + EL_EM_STEEL_EXIT_CLOSED, + EL_EM_STEEL_EXIT_OPEN, + EL_EM_STEEL_EXIT_OPENING, + EL_EM_STEEL_EXIT_CLOSING, EL_DC_STEELWALL_1_LEFT, EL_DC_STEELWALL_1_RIGHT, EL_DC_STEELWALL_1_TOP, @@ -3656,14 +3802,34 @@ void InitElementPropertiesStatic() EL_EM_GATE_2_GRAY_ACTIVE, EL_EM_GATE_3_GRAY_ACTIVE, EL_EM_GATE_4_GRAY_ACTIVE, + EL_EMC_GATE_5, + EL_EMC_GATE_6, + EL_EMC_GATE_7, + EL_EMC_GATE_8, + EL_EMC_GATE_5_GRAY, + EL_EMC_GATE_6_GRAY, + EL_EMC_GATE_7_GRAY, + EL_EMC_GATE_8_GRAY, + EL_EMC_GATE_5_GRAY_ACTIVE, + EL_EMC_GATE_6_GRAY_ACTIVE, + EL_EMC_GATE_7_GRAY_ACTIVE, + EL_EMC_GATE_8_GRAY_ACTIVE, + EL_DC_GATE_WHITE, + EL_DC_GATE_WHITE_GRAY, + EL_DC_GATE_WHITE_GRAY_ACTIVE, + EL_DC_GATE_FAKE_GRAY, EL_SWITCHGATE_OPEN, EL_SWITCHGATE_OPENING, EL_SWITCHGATE_CLOSED, EL_SWITCHGATE_CLOSING, + EL_DC_SWITCHGATE_SWITCH_UP, + EL_DC_SWITCHGATE_SWITCH_DOWN, EL_TIMEGATE_OPEN, EL_TIMEGATE_OPENING, EL_TIMEGATE_CLOSED, EL_TIMEGATE_CLOSING, + EL_DC_TIMEGATE_SWITCH, + EL_DC_TIMEGATE_SWITCH_ACTIVE, EL_TUBE_ANY, EL_TUBE_VERTICAL, EL_TUBE_HORIZONTAL, @@ -3675,6 +3841,9 @@ void InitElementPropertiesStatic() EL_TUBE_LEFT_DOWN, EL_TUBE_RIGHT_UP, EL_TUBE_RIGHT_DOWN, + EL_EXPANDABLE_STEELWALL_HORIZONTAL, + EL_EXPANDABLE_STEELWALL_VERTICAL, + EL_EXPANDABLE_STEELWALL_ANY, -1 }; @@ -4148,6 +4317,8 @@ void InitElementPropertiesStatic() EL_INTERNAL_CASCADE_SP_ACTIVE, EL_INTERNAL_CASCADE_DC_ACTIVE, EL_INTERNAL_CASCADE_DX_ACTIVE, + EL_INTERNAL_CASCADE_MM_ACTIVE, + EL_INTERNAL_CASCADE_DF_ACTIVE, EL_INTERNAL_CASCADE_CHARS_ACTIVE, EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE, EL_INTERNAL_CASCADE_CE_ACTIVE, @@ -4169,6 +4340,8 @@ void InitElementPropertiesStatic() EL_INTERNAL_CASCADE_SP, EL_INTERNAL_CASCADE_DC, EL_INTERNAL_CASCADE_DX, + EL_INTERNAL_CASCADE_MM, + EL_INTERNAL_CASCADE_DF, EL_INTERNAL_CASCADE_CHARS, EL_INTERNAL_CASCADE_STEEL_CHARS, EL_INTERNAL_CASCADE_CE, @@ -4411,8 +4584,8 @@ void InitElementPropertiesEngine(int engine_version) if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION) SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE); else - SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) && - IS_INDESTRUCTIBLE(i))); + SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_INDESTRUCTIBLE(i) && + i != EL_ACID)); /* ---------- EXPLOSION_PROOF ------------------------------------------ */ if (i == EL_FLAMES) @@ -4566,26 +4739,7 @@ void InitElementPropertiesEngine(int engine_version) InitElementGraphicInfo(); } -void InitElementPropertiesAfterLoading(int engine_version) -{ - int i; - - /* set some other uninitialized values of custom elements in older levels */ - if (engine_version < VERSION_IDENT(3,1,0,0)) - { - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - { - int element = EL_CUSTOM_START + i; - - element_info[element].access_direction = MV_ALL_DIRECTIONS; - - element_info[element].explosion_delay = 17; - element_info[element].ignition_delay = 8; - } - } -} - -void InitElementPropertiesGfxElement() +void InitElementPropertiesGfxElement(void) { int i; @@ -4597,7 +4751,7 @@ void InitElementPropertiesGfxElement() } } -static void InitGlobal() +static void InitGlobal(void) { int graphic; int i; @@ -4613,6 +4767,16 @@ static void InitGlobal() element_info[i].editor_description= element_name_info[i].editor_description; } + for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS + 1; i++) + { + /* check if global_anim_name_info defined for each entry in "main.h" */ + if (i < NUM_GLOBAL_ANIM_TOKENS && + global_anim_name_info[i].token_name == NULL) + Error(ERR_EXIT, "undefined 'global_anim_name_info' entry for anim %d", i); + + global_anim_info[i].token_name = global_anim_name_info[i].token_name; + } + /* create hash from image config list */ image_config_hash = newSetupFileHash(); for (i = 0; image_config[i].token != NULL; i++) @@ -4716,6 +4880,7 @@ static void InitGlobal() global.create_images_dir = NULL; global.frames_per_second = 0; + global.show_frames_per_second = FALSE; global.border_status = GAME_MODE_LOADING; global.anim_status = global.anim_status_next = GAME_MODE_LOADING; @@ -4723,7 +4888,7 @@ static void InitGlobal() global.use_envelope_request = FALSE; } -void Execute_Command(char *command) +static void Execute_Command(char *command) { int i; @@ -4844,13 +5009,17 @@ void Execute_Command(char *command) } else if (strPrefix(command, "autotest ") || strPrefix(command, "autoplay ") || - strPrefix(command, "autoffwd ")) + strPrefix(command, "autoffwd ") || + strPrefix(command, "autowarp ")) { char *str_ptr = getStringCopy(&command[9]); /* read command parameters */ - global.autoplay_mode = (strPrefix(command, "autotest") ? AUTOPLAY_TEST : - strPrefix(command, "autoplay") ? AUTOPLAY_PLAY : - strPrefix(command, "autoffwd") ? AUTOPLAY_FFWD : 0); + global.autoplay_mode = + (strPrefix(command, "autotest") ? AUTOPLAY_MODE_TEST : + strPrefix(command, "autoplay") ? AUTOPLAY_MODE_PLAY : + strPrefix(command, "autoffwd") ? AUTOPLAY_MODE_FFWD : + strPrefix(command, "autowarp") ? AUTOPLAY_MODE_WARP : + AUTOPLAY_MODE_NONE); while (*str_ptr != '\0') /* continue parsing string */ { @@ -4883,6 +5052,9 @@ void Execute_Command(char *command) while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0') str_ptr++; } + + if (global.autoplay_mode == AUTOPLAY_MODE_TEST) + program.headless = TRUE; } else if (strPrefix(command, "convert ")) { @@ -4897,6 +5069,8 @@ void Execute_Command(char *command) *str_ptr++ = '\0'; /* terminate leveldir string */ global.convert_level_nr = atoi(str_ptr); /* get level_nr value */ } + + program.headless = TRUE; } else if (strPrefix(command, "create images ")) { @@ -4916,24 +5090,33 @@ void Execute_Command(char *command) { Error(ERR_EXIT_HELP, "unrecognized command '%s'", command); } + + /* disable networking if any valid command was recognized */ + options.network = setup.network_mode = FALSE; } -static void InitSetup() +static void InitSetup(void) { LoadSetup(); /* global setup info */ + LoadSetup_AutoSetup(); /* global auto setup info */ /* set some options from setup file */ if (setup.options.verbose) options.verbose = TRUE; + + if (setup.debug.show_frames_per_second) + global.show_frames_per_second = TRUE; } -static void InitGameInfo() +static void InitGameInfo(void) { game.restart_level = FALSE; + game.restart_game_message = NULL; + game.request_active = FALSE; } -static void InitPlayerInfo() +static void InitPlayerInfo(void) { int i; @@ -4941,12 +5124,15 @@ static void InitPlayerInfo() local_player = &stored_player[0]; for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].connected = FALSE; + { + stored_player[i].connected_locally = FALSE; + stored_player[i].connected_network = FALSE; + } - local_player->connected = TRUE; + local_player->connected_locally = TRUE; } -static void InitArtworkInfo() +static void InitArtworkInfo(void) { LoadArtworkInfo(); } @@ -4972,14 +5158,15 @@ static char *get_level_id_suffix(int id_nr) return id_suffix; } -static void InitArtworkConfig() +static void InitArtworkConfig(void) { static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + NUM_GLOBAL_ANIM_TOKENS + 1]; static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + NUM_GLOBAL_ANIM_TOKENS + 1]; - static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1]; + static char *music_id_prefix[NUM_MUSIC_PREFIXES + + NUM_GLOBAL_ANIM_TOKENS + 1]; static char *action_id_suffix[NUM_ACTIONS + 1]; static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1]; static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1]; @@ -4989,6 +5176,10 @@ static void InitArtworkConfig() { "name", "sort_priority", + "program_title", + "program_copyright", + "program_company", + NULL }; static char **ignore_image_tokens; @@ -5055,7 +5246,10 @@ static void InitArtworkConfig() for (i = 0; i < NUM_MUSIC_PREFIXES; i++) music_id_prefix[i] = music_prefix_info[i].prefix; - music_id_prefix[NUM_MUSIC_PREFIXES] = NULL; + for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++) + music_id_prefix[NUM_MUSIC_PREFIXES + i] = + global_anim_info[i].token_name; + music_id_prefix[NUM_MUSIC_PREFIXES + NUM_GLOBAL_ANIM_TOKENS] = NULL; for (i = 0; i < NUM_ACTIONS; i++) action_id_suffix[i] = element_action_info[i].suffix; @@ -5080,18 +5274,29 @@ static void InitArtworkConfig() sound_id_prefix, action_id_suffix, dummy, special_id_suffix, ignore_sound_tokens); InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix, - music_id_prefix, special_id_suffix, level_id_suffix, - dummy, ignore_music_tokens); + music_id_prefix, action_id_suffix, special_id_suffix, + level_id_suffix, ignore_music_tokens); } -static void InitMixer() +static void InitMixer(void) { OpenAudio(); StartMixer(); } -void InitGfxBuffers() +static void InitVideoOverlay(void) +{ + // if virtual buttons are not loaded from setup file, repeat initializing + // virtual buttons grid with default values now that video is initialized + if (!setup.touch.grid_initialized) + InitSetup(); + + InitTileCursorInfo(); + InitOverlayInfo(); +} + +void InitGfxBuffers(void) { static int win_xsize_last = -1; static int win_ysize_last = -1; @@ -5100,19 +5305,18 @@ void InitGfxBuffers() if (WIN_XSIZE != win_xsize_last || WIN_YSIZE != win_ysize_last) { - /* may contain content for cross-fading -- only re-create if changed */ - ReCreateBitmap(&bitmap_db_store, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); - ReCreateBitmap(&bitmap_db_cross, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + /* used to temporarily store the backbuffer -- only re-create if changed */ + ReCreateBitmap(&bitmap_db_store_1, WIN_XSIZE, WIN_YSIZE); + ReCreateBitmap(&bitmap_db_store_2, WIN_XSIZE, WIN_YSIZE); win_xsize_last = WIN_XSIZE; win_ysize_last = WIN_YSIZE; } - ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE, DEFAULT_DEPTH); - ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE, DEFAULT_DEPTH); - ReCreateBitmap(&bitmap_db_door_1, 3 * DXSIZE, DYSIZE, DEFAULT_DEPTH); - ReCreateBitmap(&bitmap_db_door_2, 3 * VXSIZE, VYSIZE, DEFAULT_DEPTH); - ReCreateBitmap(&bitmap_db_toons, FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH); + ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE); + ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE); + ReCreateBitmap(&bitmap_db_door_1, 3 * DXSIZE, DYSIZE); + ReCreateBitmap(&bitmap_db_door_2, 3 * VXSIZE, VYSIZE); /* initialize screen properties */ InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE, @@ -5132,13 +5336,12 @@ void InitGfxBuffers() InitGfxBuffers_SP(); } -void InitGfx() +static void InitGfx(void) { struct GraphicInfo *graphic_info_last = graphic_info; char *filename_font_initial = NULL; char *filename_anim_initial = NULL; Bitmap *bitmap_font_initial = NULL; - int font_height; int i, j; /* determine settings for initial font (for displaying startup messages) */ @@ -5189,12 +5392,7 @@ void InitGfx() InitFontGraphicInfo(); - font_height = getFontHeight(FC_RED); - - DrawInitText(getProgramInitString(), 20, FC_YELLOW); - DrawInitText(setup.internal.program_copyright, 50, FC_RED); - DrawInitText(setup.internal.program_website, WIN_YSIZE - 20 - font_height, - FC_RED); + DrawProgramInfo(); DrawInitText("Loading graphics", 120, FC_GREEN); @@ -5289,8 +5487,9 @@ void InitGfx() InitMenuDesignSettings_Static(); InitGfxDrawBusyAnimFunction(DrawInitAnim); - InitGfxDrawGlobalAnimFunction(DrawGlobalAnim); + InitGfxDrawGlobalAnimFunction(DrawGlobalAnimations); InitGfxDrawGlobalBorderFunction(DrawMaskedBorderToTarget); + InitGfxDrawTileCursorFunction(DrawTileCursor); gfx.fade_border_source_status = global.border_status; gfx.fade_border_target_status = global.border_status; @@ -5300,38 +5499,40 @@ void InitGfx() init_last = init; } -void InitGfxBackground() +static void InitGfxBackground(void) { fieldbuffer = bitmap_db_field; - SetDrawtoField(DRAW_BACKBUFFER); + SetDrawtoField(DRAW_TO_BACKBUFFER); ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE); redraw_mask = REDRAW_ALL; } -static void InitLevelInfo() +static void InitLevelInfo(void) { LoadLevelInfo(); /* global level info */ LoadLevelSetup_LastSeries(); /* last played series info */ LoadLevelSetup_SeriesInfo(); /* last played level info */ if (global.autoplay_leveldir && - global.autoplay_mode != AUTOPLAY_TEST) + global.autoplay_mode != AUTOPLAY_MODE_TEST) { leveldir_current = getTreeInfoFromIdentifier(leveldir_first, global.autoplay_leveldir); if (leveldir_current == NULL) leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); } + + SetLevelSetInfo(leveldir_current->identifier, level_nr); } -static void InitLevelArtworkInfo() +static void InitLevelArtworkInfo(void) { LoadLevelArtworkInfo(); } -static void InitImages() +static void InitImages(void) { print_timestamp_init("InitImages"); @@ -5388,6 +5589,9 @@ static void InitImages() ReinitializeGraphics(); print_timestamp_time("ReinitializeGraphics"); + LoadMenuDesignSettings_AfterGraphics(); + print_timestamp_time("LoadMenuDesignSettings_AfterGraphics"); + UPDATE_BUSY_STATE(); print_timestamp_done("InitImages"); @@ -5431,32 +5635,58 @@ static void InitMusic(char *identifier) print_timestamp_done("InitMusic"); } -static void InitArtworkDone() +static void InitArtworkDone(void) { + if (program.headless) + return; + InitGlobalAnimations(); } -void InitNetworkServer() +static void InitNetworkSettings(void) { -#if defined(NETWORK_AVALIABLE) - int nr_wanted; -#endif + boolean network_enabled = (options.network || setup.network_mode); + char *network_server = (options.server_host != NULL ? options.server_host : + setup.network_server_hostname); + + if (strEqual(network_server, STR_NETWORK_AUTO_DETECT)) + network_server = NULL; + + InitNetworkInfo(network_enabled, + FALSE, + options.serveronly, + network_server, + options.server_port); +} - if (!options.network) +void InitNetworkServer(void) +{ + if (!network.enabled || network.connected) return; -#if defined(NETWORK_AVALIABLE) - nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED); + LimitScreenUpdates(FALSE); - if (!ConnectToServer(options.server_host, options.server_port)) - Error(ERR_EXIT, "cannot connect to network game server"); + if (game_status == GAME_MODE_LOADING) + DrawProgramInfo(); - SendToServer_PlayerName(setup.player_name); - SendToServer_ProtocolVersion(); + if (!ConnectToServer(network.server_host, network.server_port)) + { + network.enabled = FALSE; - if (nr_wanted) - SendToServer_NrWanted(nr_wanted); -#endif + setup.network_mode = FALSE; + } + else + { + SendToServer_ProtocolVersion(); + SendToServer_PlayerName(setup.player_name); + SendToServer_NrWanted(setup.network_player_nr + 1); + + network.connected = TRUE; + } + + /* short time to recognize result of network initialization */ + if (game_status == GAME_MODE_LOADING) + Delay_WithScreenUpdates(1000); } static boolean CheckArtworkConfigForCustomElements(char *filename) @@ -5532,7 +5762,7 @@ static boolean CheckArtworkTypeForRedefinedCustomElements(int type) return redefined_ce_found; } -static void InitOverrideArtwork() +static void InitOverrideArtwork(void) { boolean redefined_ce_found = FALSE; @@ -5733,7 +5963,7 @@ void ReloadCustomArtwork(int force_reload) LimitScreenUpdates(FALSE); } -void KeyboardAutoRepeatOffUnlessAutoplay() +void KeyboardAutoRepeatOffUnlessAutoplay(void) { if (global.autoplay_leveldir == NULL) KeyboardAutoRepeatOff(); @@ -5741,6 +5971,10 @@ void KeyboardAutoRepeatOffUnlessAutoplay() void DisplayExitMessage(char *format, va_list ap) { + // also check for initialized video (headless flag may be temporarily unset) + if (program.headless || !video.initialized) + return; + // check if draw buffer and fonts for exit message are already available if (drawto == NULL || font_initial[NUM_INITIAL_FONTS - 1].bitmap == NULL) return; @@ -5804,7 +6038,7 @@ void DisplayExitMessage(char *format, va_list ap) /* OpenAll() */ /* ========================================================================= */ -void OpenAll() +void OpenAll(void) { print_timestamp_init("OpenAll"); @@ -5820,13 +6054,17 @@ void OpenAll() print_timestamp_time("[init setup/config stuff (1)]"); + InitScoresInfo(); + if (options.execute_command) Execute_Command(options.execute_command); - if (options.serveronly) + InitNetworkSettings(); + + if (network.serveronly) { #if defined(PLATFORM_UNIX) - NetworkServer(options.server_port, options.serveronly); + NetworkServer(network.server_port, TRUE); #else Error(ERR_WARN, "networking only supported in Unix version"); #endif @@ -5852,10 +6090,10 @@ void OpenAll() print_timestamp_time("[init setup/config stuff]"); + InitVideoDefaults(); InitVideoDisplay(); InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); - - InitEventFilter(FilterEvents); + InitVideoOverlay(); print_timestamp_time("[init video stuff]"); @@ -5893,6 +6131,7 @@ void OpenAll() em_open_all(); sp_open_all(); + mm_open_all(); if (global.autoplay_leveldir) { @@ -5910,6 +6149,8 @@ void OpenAll() return; } + InitNetworkServer(); + SetGameStatus(GAME_MODE_MAIN); FadeSetEnterScreen(); @@ -5922,8 +6163,6 @@ void OpenAll() DrawMainMenu(); - InitNetworkServer(); - #if 0 Error(ERR_DEBUG, "::: SDL_GetBasePath() == '%s'", SDL_GetBasePath()); @@ -5935,10 +6174,10 @@ void OpenAll() Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStoragePath() == '%s'", SDL_AndroidGetExternalStoragePath()); Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStorageState() == '%s'", - (SDL_AndroidGetExternalStorageState() == - SDL_ANDROID_EXTERNAL_STORAGE_READ ? "read" : - SDL_AndroidGetExternalStorageState() == - SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "write" : "not available")); + (SDL_AndroidGetExternalStorageState() & + SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "writable" : + SDL_AndroidGetExternalStorageState() & + SDL_ANDROID_EXTERNAL_STORAGE_READ ? "readable" : "not available")); #endif #endif } @@ -5969,7 +6208,7 @@ void CloseAllAndExit(int exit_value) CloseVideoDisplay(); ClosePlatformDependentStuff(); - if (exit_value != 0) + if (exit_value != 0 && !options.execute_command) { /* fall back to default level set (current set may have caused an error) */ SaveLevelSetup_LastSeries_Deactivate();