X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=1c261a00b951a036d28cedd0f28ba1c5466a6f2e;hb=c6bdf2fa014d0a3dd50260a409704e487e73e572;hp=415935a4ed98f9772989edf5f8bd2c6f62b2f0c6;hpb=44daf525cec5664a3de0ce6e7516cd6c0081cf5b;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index 415935a4..1c261a00 100644 --- a/src/tools.c +++ b/src/tools.c @@ -19,6 +19,7 @@ #include "cartoons.h" #include "network.h" #include "tape.h" +#include "screens.h" /* select level set with EMC X11 graphics before activating EM GFX debugging */ @@ -240,6 +241,10 @@ void DrawMaskedBorder_ALL() void DrawMaskedBorder(int redraw_mask) { + /* do not draw masked screen borders when displaying title screens */ + if (effectiveGameStatus() == GAME_MODE_TITLE) + return; + if (redraw_mask & REDRAW_ALL) DrawMaskedBorder_ALL(); else @@ -314,18 +319,16 @@ void BackToFront() SyncDisplay(); -#if 1 + /* prevent drawing masked border to backbuffer when using playfield buffer */ if (game_status != GAME_MODE_PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER || buffer == backbuffer) DrawMaskedBorder(redraw_mask); -#endif + else + DrawMaskedBorder(redraw_mask & REDRAW_DOORS); if (redraw_mask & REDRAW_ALL) { -#if 0 - DrawMaskedBorder(REDRAW_ALL); -#endif BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); redraw_mask = REDRAW_NONE; @@ -358,6 +361,7 @@ void BackToFront() { if (buffer != backbuffer) { + /* copy playfield buffer to backbuffer to add masked border */ BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY); DrawMaskedBorder(REDRAW_FIELD); } @@ -583,10 +587,30 @@ void FadeCrossSaveBackbuffer() BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); } +void SetWindowBackgroundImageIfDefined(int graphic) +{ + if (graphic_info[graphic].bitmap) + SetWindowBackgroundBitmap(graphic_info[graphic].bitmap); +} + void SetMainBackgroundImageIfDefined(int graphic) { if (graphic_info[graphic].bitmap) - SetMainBackgroundImage(graphic); + SetMainBackgroundBitmap(graphic_info[graphic].bitmap); +} + +void SetDoorBackgroundImageIfDefined(int graphic) +{ + if (graphic_info[graphic].bitmap) + SetDoorBackgroundBitmap(graphic_info[graphic].bitmap); +} + +void SetWindowBackgroundImage(int graphic) +{ + SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL : + graphic_info[graphic].bitmap ? + graphic_info[graphic].bitmap : + graphic_info[IMG_BACKGROUND].bitmap); } void SetMainBackgroundImage(int graphic) @@ -699,6 +723,39 @@ void SetBorderElement() } } +void FloodFillLevel(int from_x, int from_y, int fill_element, + short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY], + int max_fieldx, int max_fieldy) +{ + int i,x,y; + int old_element; + static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } }; + static int safety = 0; + + /* check if starting field still has the desired content */ + if (field[from_x][from_y] == fill_element) + return; + + safety++; + + if (safety > max_fieldx * max_fieldy) + Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug."); + + old_element = field[from_x][from_y]; + field[from_x][from_y] = fill_element; + + for (i = 0; i < 4; i++) + { + x = from_x + check[i][0]; + y = from_y + check[i][1]; + + if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element) + FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy); + } + + safety--; +} + void SetRandomAnimationValue(int x, int y) { gfx.anim_random_frame = GfxRandom[x][y]; @@ -1366,13 +1423,17 @@ void DrawScreenField(int x, int y) boolean cut_mode = NO_CUTTING; if (element == EL_QUICKSAND_EMPTYING || + element == EL_QUICKSAND_FAST_EMPTYING || element == EL_MAGIC_WALL_EMPTYING || element == EL_BD_MAGIC_WALL_EMPTYING || + element == EL_DC_MAGIC_WALL_EMPTYING || element == EL_AMOEBA_DROPPING) cut_mode = CUT_ABOVE; else if (element == EL_QUICKSAND_FILLING || + element == EL_QUICKSAND_FAST_FILLING || element == EL_MAGIC_WALL_FILLING || - element == EL_BD_MAGIC_WALL_FILLING) + element == EL_BD_MAGIC_WALL_FILLING || + element == EL_DC_MAGIC_WALL_FILLING) cut_mode = CUT_BELOW; if (cut_mode == CUT_ABOVE) @@ -1414,8 +1475,10 @@ void DrawScreenField(int x, int y) content_old = Store[oldx][oldy]; if (element_old == EL_QUICKSAND_EMPTYING || + element_old == EL_QUICKSAND_FAST_EMPTYING || element_old == EL_MAGIC_WALL_EMPTYING || element_old == EL_BD_MAGIC_WALL_EMPTYING || + element_old == EL_DC_MAGIC_WALL_EMPTYING || element_old == EL_AMOEBA_DROPPING) cut_mode = CUT_ABOVE; @@ -1562,9 +1625,17 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++) DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr); +#if 1 + DrawTextBuffer(SX + sx + font_width, SY + sy + font_height, + level.envelope[envelope_nr].text, font_nr, max_xsize, + xsize - 2, ysize - 2, mask_mode, + level.envelope[envelope_nr].autowrap, + level.envelope[envelope_nr].centered, FALSE); +#else DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height, level.envelope[envelope_nr].text, font_nr, max_xsize, xsize - 2, ysize - 2, mask_mode); +#endif redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; BackToFront(); @@ -1694,7 +1765,7 @@ static void DrawPreviewLevelExt(int from_x, int from_y) int real_preview_xsize = MIN(level_xsize, preview.xsize); int real_preview_ysize = MIN(level_ysize, preview.ysize); int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align); - int dst_y = SY + preview.y; + int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign); int x, y; DrawBackground(dst_x, dst_y, preview_width, preview_height); @@ -1728,7 +1799,7 @@ static void DrawPreviewLevelExt(int from_x, int from_y) #define MICROLABEL_IMPORTED_BY_HEAD 6 #define MICROLABEL_IMPORTED_BY 7 -static int getMaxTextLength(struct MenuPosInfo *pos, int font_nr) +static int getMaxTextLength(struct TextPosInfo *pos, int font_nr) { int max_text_width = SXSIZE; int font_width = getFontWidth(font_nr); @@ -1745,9 +1816,18 @@ static int getMaxTextLength(struct MenuPosInfo *pos, int font_nr) static void DrawPreviewLevelLabelExt(int mode) { - struct MenuPosInfo *pos = &menu.main.text.level_info_2; + struct TextPosInfo *pos = &menu.main.text.level_info_2; char label_text[MAX_OUTPUT_LINESIZE + 1]; int max_len_label_text; +#if 1 + int font_nr = pos->font; + int i; + + if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD || + mode == MICROLABEL_IMPORTED_FROM_HEAD || + mode == MICROLABEL_IMPORTED_BY_HEAD) + font_nr = pos->font_alt; +#else int font_nr = FONT_TEXT_2; int i; @@ -1755,6 +1835,7 @@ static void DrawPreviewLevelLabelExt(int mode) mode == MICROLABEL_IMPORTED_FROM_HEAD || mode == MICROLABEL_IMPORTED_BY_HEAD) font_nr = FONT_TEXT_3; +#endif #if 1 max_len_label_text = getMaxTextLength(pos, font_nr); @@ -1762,6 +1843,11 @@ static void DrawPreviewLevelLabelExt(int mode) max_len_label_text = SXSIZE / getFontWidth(font_nr); #endif +#if 1 + if (pos->chars != -1) + max_len_label_text = pos->chars; +#endif + for (i = 0; i < max_len_label_text; i++) label_text[i] = ' '; label_text[max_len_label_text] = '\0'; @@ -1816,8 +1902,10 @@ void DrawPreviewLevel(boolean restart) int level_ysize = lev_fieldy + (show_level_border ? 2 : 0); int last_game_status = game_status; /* save current game status */ +#if 0 /* force PREVIEW font on preview level */ game_status = GAME_MODE_PSEUDO_PREVIEW; +#endif if (restart) { @@ -1848,9 +1936,13 @@ void DrawPreviewLevel(boolean restart) if (leveldir_current->name) { - struct MenuPosInfo *pos = &menu.main.text.level_info_1; + struct TextPosInfo *pos = &menu.main.text.level_info_1; char label_text[MAX_OUTPUT_LINESIZE + 1]; +#if 1 + int font_nr = pos->font; +#else int font_nr = FONT_TEXT_1; +#endif #if 1 int max_len_label_text = getMaxTextLength(pos, font_nr); #else @@ -1861,6 +1953,11 @@ void DrawPreviewLevel(boolean restart) int lxpos, lypos; #endif +#if 1 + if (pos->chars != -1) + max_len_label_text = pos->chars; +#endif + strncpy(label_text, leveldir_current->name, max_len_label_text); label_text[max_len_label_text] = '\0'; @@ -2473,7 +2570,11 @@ boolean Request(char *text, unsigned int req_state) if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN) { max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN; +#if 1 + font_nr = FONT_TEXT_1; +#else font_nr = FONT_LEVEL_NUMBER; +#endif break; } @@ -2524,7 +2625,7 @@ boolean Request(char *text, unsigned int req_state) /* clear door drawing field */ DrawBackground(DX, DY, DXSIZE, DYSIZE); - /* force DOOR font on preview level */ + /* force DOOR font inside door area */ game_status = GAME_MODE_PSEUDO_DOOR; /* write text for request */ @@ -2719,6 +2820,23 @@ boolean Request(char *text, unsigned int req_state) result = 0; } +#if 1 + + if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd) + { + HandleGameActions(); + BackToFront(); + } + else + { + DoAnimation(); + + if (!PendingEvent()) /* delay only if no pending events */ + Delay(10); + } + +#else + DoAnimation(); #if 1 @@ -2727,6 +2845,8 @@ boolean Request(char *text, unsigned int req_state) #else /* don't eat all CPU time */ Delay(10); +#endif + #endif } @@ -4440,19 +4560,19 @@ em_object_mapping_list[] = }, { Xexit, TRUE, FALSE, - EL_EXIT_CLOSED, -1, -1 + EL_EM_EXIT_CLOSED, -1, -1 }, { Xexit_1, TRUE, FALSE, - EL_EXIT_OPEN, -1, -1 + EL_EM_EXIT_OPEN, -1, -1 }, { Xexit_2, FALSE, FALSE, - EL_EXIT_OPEN, -1, -1 + EL_EM_EXIT_OPEN, -1, -1 }, { Xexit_3, FALSE, FALSE, - EL_EXIT_OPEN, -1, -1 + EL_EM_EXIT_OPEN, -1, -1 }, { Xdynamite, TRUE, FALSE, @@ -5361,10 +5481,14 @@ int get_next_element(int element) { case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL; case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY; + case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL; + case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY; case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL; case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE; case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL; case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE; + case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL; + case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE; case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET; default: return element; @@ -5469,6 +5593,115 @@ int font2baseimg(int font_nr) return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT]; } +int getBeltNrFromBeltElement(int element) +{ + return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 : + element < EL_CONVEYOR_BELT_3_LEFT ? 1 : + element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3); +} + +int getBeltNrFromBeltActiveElement(int element) +{ + return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 : + element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 : + element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3); +} + +int getBeltNrFromBeltSwitchElement(int element) +{ + return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 : + element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 : + element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3); +} + +int getBeltDirNrFromBeltElement(int element) +{ + static int belt_base_element[4] = + { + EL_CONVEYOR_BELT_1_LEFT, + EL_CONVEYOR_BELT_2_LEFT, + EL_CONVEYOR_BELT_3_LEFT, + EL_CONVEYOR_BELT_4_LEFT + }; + + int belt_nr = getBeltNrFromBeltElement(element); + int belt_dir_nr = element - belt_base_element[belt_nr]; + + return (belt_dir_nr % 3); +} + +int getBeltDirNrFromBeltSwitchElement(int element) +{ + static int belt_base_element[4] = + { + EL_CONVEYOR_BELT_1_SWITCH_LEFT, + EL_CONVEYOR_BELT_2_SWITCH_LEFT, + EL_CONVEYOR_BELT_3_SWITCH_LEFT, + EL_CONVEYOR_BELT_4_SWITCH_LEFT + }; + + int belt_nr = getBeltNrFromBeltSwitchElement(element); + int belt_dir_nr = element - belt_base_element[belt_nr]; + + return (belt_dir_nr % 3); +} + +int getBeltDirFromBeltElement(int element) +{ + static int belt_move_dir[3] = + { + MV_LEFT, + MV_NONE, + MV_RIGHT + }; + + int belt_dir_nr = getBeltDirNrFromBeltElement(element); + + return belt_move_dir[belt_dir_nr]; +} + +int getBeltDirFromBeltSwitchElement(int element) +{ + static int belt_move_dir[3] = + { + MV_LEFT, + MV_NONE, + MV_RIGHT + }; + + int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element); + + return belt_move_dir[belt_dir_nr]; +} + +int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir) +{ + static int belt_base_element[4] = + { + EL_CONVEYOR_BELT_1_LEFT, + EL_CONVEYOR_BELT_2_LEFT, + EL_CONVEYOR_BELT_3_LEFT, + EL_CONVEYOR_BELT_4_LEFT + }; + int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1); + + return belt_base_element[belt_nr] + belt_dir_nr; +} + +int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir) +{ + static int belt_base_element[4] = + { + EL_CONVEYOR_BELT_1_SWITCH_LEFT, + EL_CONVEYOR_BELT_2_SWITCH_LEFT, + EL_CONVEYOR_BELT_3_SWITCH_LEFT, + EL_CONVEYOR_BELT_4_SWITCH_LEFT + }; + int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1); + + return belt_base_element[belt_nr] + belt_dir_nr; +} + int getNumActivePlayers_EM() { int num_players = 0; @@ -5507,10 +5740,94 @@ unsigned int InitRND(long seed) return InitEngineRandom_RND(seed); } +#if 1 +static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX]; +static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX]; +#endif + +void ResetGfxAnimation_EM(int x, int y, int tile) +{ + GfxFrame[x][y] = 0; +} + +void getGraphicSourceObjectExt_EM(int tile, int frame_em, + Bitmap **src_bitmap, int *src_x, int *src_y, + int x, int y) +{ + int element = object_mapping[tile].element_rnd; + int action = object_mapping[tile].action; + int direction = object_mapping[tile].direction; + boolean is_backside = object_mapping[tile].is_backside; + boolean action_removing = (action == ACTION_DIGGING || + action == ACTION_SNAPPING || + action == ACTION_COLLECTING); + int effective_element = (frame_em > 0 ? element : + is_backside ? EL_EMPTY : + action_removing ? EL_EMPTY : + element); + int graphic = (direction == MV_NONE ? + el_act2img(effective_element, action) : + el_act_dir2img(effective_element, action, direction)); + struct GraphicInfo *g = &graphic_info[graphic]; + int sync_frame; + + if (graphic_info[graphic].anim_global_sync) + sync_frame = FrameCounter; + else + sync_frame = 7 - frame_em; + + SetRandomAnimationValue(x, y); + + int frame = getAnimationFrame(g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame); + + getGraphicSourceExt(graphic, frame, src_bitmap, src_x, src_y, FALSE); +} + +void getGraphicSourcePlayerExt_EM(int player_nr, int anim, int frame_em, + Bitmap **src_bitmap, int *src_x, int *src_y) +{ + int element = player_mapping[player_nr][anim].element_rnd; + int action = player_mapping[player_nr][anim].action; + int direction = player_mapping[player_nr][anim].direction; + int graphic = (direction == MV_NONE ? + el_act2img(element, action) : + el_act_dir2img(element, action, direction)); + struct GraphicInfo *g = &graphic_info[graphic]; + int sync_frame; + + InitPlayerGfxAnimation(&stored_player[player_nr], action, direction); + + stored_player[player_nr].StepFrame = 7 - frame_em; + + sync_frame = stored_player[player_nr].Frame; + +#if 0 + printf("::: %d: %d, %d [%d]\n", + player_nr, + stored_player[player_nr].Frame, + stored_player[player_nr].StepFrame, + FrameCounter); +#endif + + int frame = getAnimationFrame(g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame); + + getGraphicSourceExt(graphic, frame, src_bitmap, src_x, src_y, FALSE); +} + void InitGraphicInfo_EM(void) { +#if 0 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX]; struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX]; +#endif int i, j, p; #if DEBUG_EM_GFX @@ -6057,7 +6374,7 @@ void InitGraphicInfo_EM(void) g->anim_start_frame, sync_frame); - getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE); + getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE); g_em->bitmap = src_bitmap; g_em->src_x = src_x; @@ -6128,10 +6445,8 @@ void InitGraphicInfo_EM(void) #endif } -void PlayMenuSound() +void PlayMenuSoundExt(int sound) { - int sound = menu.sound[game_status]; - if (sound == SND_UNDEFINED) return; @@ -6145,6 +6460,11 @@ void PlayMenuSound() PlaySound(sound); } +void PlayMenuSound() +{ + PlayMenuSoundExt(menu.sound[game_status]); +} + void PlayMenuSoundStereo(int sound, int stereo_position) { if (sound == SND_UNDEFINED) @@ -6160,10 +6480,8 @@ void PlayMenuSoundStereo(int sound, int stereo_position) PlaySoundStereo(sound, stereo_position); } -void PlayMenuSoundIfLoop() +void PlayMenuSoundIfLoopExt(int sound) { - int sound = menu.sound[game_status]; - if (sound == SND_UNDEFINED) return; @@ -6175,16 +6493,41 @@ void PlayMenuSoundIfLoop() PlaySoundLoop(sound); } -void PlayMenuMusic() +void PlayMenuSoundIfLoop() { - int music = menu.music[game_status]; + PlayMenuSoundIfLoopExt(menu.sound[game_status]); +} +void PlayMenuMusicExt(int music) +{ if (music == MUS_UNDEFINED) return; + if (!setup.sound_music) + return; + PlayMusic(music); } +void PlayMenuMusic() +{ + PlayMenuMusicExt(menu.music[game_status]); +} + +void PlaySoundActivating() +{ +#if 0 + PlaySound(SND_MENU_ITEM_ACTIVATING); +#endif +} + +void PlaySoundSelecting() +{ +#if 0 + PlaySound(SND_MENU_ITEM_SELECTING); +#endif +} + void ToggleFullscreenIfNeeded() { boolean change_fullscreen = (setup.fullscreen !=