X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=20e27068ffa641502bc60d230642c3fe62f10563;hb=6d26e1e4259343003f378829a3f18ee5f7e7cdcd;hp=c9712c9b2639521de4f612d63795cd249aaefc3a;hpb=75a80bb5e95a67ae6343e15e8b835056b6862615;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index c9712c9b..20e27068 100644 --- a/src/game_mm/mm_game.c +++ b/src/game_mm/mm_game.c @@ -433,9 +433,9 @@ static void SetLaserColor(int brightness) pen_ray = GetPixelFromRGB(window, - (native_mm_level.laser_red ? color_max : color_up), - (native_mm_level.laser_green ? color_down : color_min), - (native_mm_level.laser_blue ? color_down : color_min)); + (game_mm.laser_red ? color_max : color_up), + (game_mm.laser_green ? color_down : color_min), + (game_mm.laser_blue ? color_down : color_min)); } static void InitMovDir_MM(int x, int y) @@ -538,6 +538,19 @@ static void InitField(int x, int y) laser.start_edge.x = x; laser.start_edge.y = y; laser.start_angle = get_element_angle(element); + + if (IS_MCDUFFIN(element)) + { + game_mm.laser_red = native_mm_level.mm_laser_red; + game_mm.laser_green = native_mm_level.mm_laser_green; + game_mm.laser_blue = native_mm_level.mm_laser_blue; + } + else + { + game_mm.laser_red = native_mm_level.df_laser_red; + game_mm.laser_green = native_mm_level.df_laser_green; + game_mm.laser_blue = native_mm_level.df_laser_blue; + } } break; @@ -627,6 +640,12 @@ void InitGameEngine_MM(void) game_mm.num_keys = 0; game_mm.ball_choice_pos = 0; + game_mm.laser_red = FALSE; + game_mm.laser_green = FALSE; + game_mm.laser_blue = TRUE; + + game_mm.lightball_rnd = TRUE; + game_mm.level_solved = FALSE; game_mm.game_over = FALSE; game_mm.game_over_cause = 0; @@ -697,6 +716,8 @@ void InitGameActions_MM(void) InitLaser(); + game_mm.lightball_rnd = FALSE; + for (i = 0; i <= num_init_game_frames; i++) { if (i == num_init_game_frames) @@ -732,6 +753,8 @@ void InitGameActions_MM(void) #endif } + game_mm.lightball_rnd = TRUE; + ScanLaser(); if (game_mm.kettles_still_needed == 0) @@ -941,13 +964,18 @@ static void DeactivateLaserTargetElement(void) void ScanLaser(void) { - int element; + int element = EL_EMPTY; + int last_element = EL_EMPTY; int end = 0, rf = laser.num_edges; // do not scan laser again after the game was lost for whatever reason if (game_mm.game_over) return; + // do not scan laser if fuse is off + if (laser.fuse_off) + return; + DeactivateLaserTargetElement(); laser.overloaded = FALSE; @@ -1023,6 +1051,8 @@ void ScanLaser(void) hit_mask, LX, LY, ELX, ELY); #endif + last_element = element; + element = Tile[ELX][ELY]; laser.dest_element = element; @@ -1041,6 +1071,12 @@ void ScanLaser(void) ELX, ELY, element); #endif + // special case: leaving fixed MM steel grid (upwards) with non-90° angle + if (element == EL_EMPTY && + IS_GRID_STEEL(last_element) && + laser.current_angle % 4) // angle is not 90° + element = last_element; + if (element == EL_EMPTY) { if (!HitOnlyAnEdge(hit_mask)) @@ -1099,6 +1135,14 @@ void ScanLaser(void) if (rf) DrawLaser(rf - 1, DL_LASER_ENABLED); rf = laser.num_edges; + + if (!IS_DF_WALL_STEEL(element)) + { + // only used for scanning DF steel walls; reset for all other elements + last_LX = 0; + last_LY = 0; + last_hit_mask = 0; + } } #if 0 @@ -1325,6 +1369,13 @@ static void DrawLaserExt(int start_edge, int num_edges, int mode) void DrawLaser(int start_edge, int mode) { + // do not draw laser if fuse is off + if (laser.fuse_off && mode == DL_LASER_ENABLED) + return; + + if (mode == DL_LASER_DISABLED) + DeactivateLaserTargetElement(); + if (laser.num_edges - start_edge < 0) { Warn("DrawLaser: laser.num_edges - start_edge < 0"); @@ -1437,6 +1488,10 @@ boolean HitElement(int element, int hit_mask) // this is more precise: check if laser would go through the center if ((ELX * TILEX + 14 - LX) * YS != (ELY * TILEY + 14 - LY) * XS) { + // prevent cutting through laser emitter with laser beam + if (IS_LASER(element)) + return TRUE; + // skip the whole element before continuing the scan do { @@ -2504,33 +2559,43 @@ static void GrowAmoeba(int x, int y) } static void DrawFieldAnimated_MM(int x, int y) +{ + DrawField_MM(x, y); + + laser.redraw = TRUE; +} + +static void DrawFieldAnimatedIfNeeded_MM(int x, int y) { int element = Tile[x][y]; + int graphic = el2gfx(element); - if (IS_BLOCKED(x, y)) + if (!getGraphicInfo_NewFrame(x, y, graphic)) return; DrawField_MM(x, y); - if (IS_MIRROR(element) || - IS_MIRROR_FIXED(element) || - element == EL_PRISM) + laser.redraw = TRUE; +} + +static void DrawFieldTwinkle(int x, int y) +{ + if (MovDelay[x][y] != 0) // wait some time before next frame { - if (MovDelay[x][y] != 0) // wait some time before next frame - { - MovDelay[x][y]--; + MovDelay[x][y]--; - if (MovDelay[x][y] != 0) - { - int graphic = IMG_TWINKLE_WHITE; - int frame = getGraphicAnimationFrame(graphic, 10 - MovDelay[x][y]); + DrawField_MM(x, y); - DrawGraphicThruMask_MM(SCREENX(x), SCREENY(y), graphic, frame); - } + if (MovDelay[x][y] != 0) + { + int graphic = IMG_TWINKLE_WHITE; + int frame = getGraphicAnimationFrame(graphic, 10 - MovDelay[x][y]); + + DrawGraphicThruMask_MM(SCREENX(x), SCREENY(y), graphic, frame); } - } - laser.redraw = TRUE; + laser.redraw = TRUE; + } } static void Explode_MM(int x, int y, int phase, int mode) @@ -2995,8 +3060,6 @@ void RotateMirror(int x, int y, int button) IS_POLAR(Tile[x][y]) || IS_POLAR_CROSS(Tile[x][y])) && x == ELX && y == ELY) { - check = 0; - if (IS_BEAMER(Tile[x][y])) { #if 0 @@ -3004,12 +3067,13 @@ void RotateMirror(int x, int y, int button) LX, LY, laser.beamer_edge, laser.beamer[1].num); #endif -#if 0 - laser.num_edges--; -#endif + if (check == 1) + laser.num_edges--; } ScanLaser(); + + check = 0; } if (check == 2) @@ -3174,8 +3238,16 @@ static void GameActions_MM_Ext(void) MeltIce(x, y); else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA) GrowAmoeba(x, y); - else + else if (IS_MIRROR(element) || + IS_MIRROR_FIXED(element) || + element == EL_PRISM) + DrawFieldTwinkle(x, y); + else if (element == EL_GRAY_BALL_OPENING || + element == EL_BOMB_ACTIVE || + element == EL_MINE_ACTIVE) DrawFieldAnimated_MM(x, y); + else if (!IS_BLOCKED(x, y)) + DrawFieldAnimatedIfNeeded_MM(x, y); } AutoRotateMirrors();