X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=e822706ff9a00902ee49de8dc9fd5115aef8d05a;hb=b0f18dbef013a0a3174ffd22cb468896b9db86fd;hp=571c9094240bd8b4a0019a50fcbc1ade8dc746c9;hpb=a4248791dc5c536bd346033d20e1f41f27ecd945;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index 571c9094..e822706f 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,10 @@ 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.level_solved = FALSE; game_mm.game_over = FALSE; game_mm.game_over_cause = 0; @@ -740,7 +757,11 @@ void InitGameActions_MM(void) SetTileCursorXY(laser.start_edge.x, laser.start_edge.y); SetTileCursorActive(TRUE); + // restart all delay counters after initially cycling game elements + ResetFrameCounter(&rotate_delay); + ResetFrameCounter(&pacman_delay); ResetFrameCounter(&energy_delay); + ResetFrameCounter(&overload_delay); } static void FadeOutLaser(void) @@ -804,6 +825,13 @@ void AddLaserEdge(int lx, int ly) void AddDamagedField(int ex, int ey) { + // prevent adding the same field position again + if (laser.num_damages > 0 && + laser.damage[laser.num_damages - 1].x == ex && + laser.damage[laser.num_damages - 1].y == ey && + laser.damage[laser.num_damages - 1].edge == laser.num_edges) + return; + laser.damage[laser.num_damages].is_mirror = FALSE; laser.damage[laser.num_damages].angle = laser.current_angle; laser.damage[laser.num_damages].edge = laser.num_edges; @@ -941,7 +969,8 @@ 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 @@ -1027,6 +1056,8 @@ void ScanLaser(void) hit_mask, LX, LY, ELX, ELY); #endif + last_element = element; + element = Tile[ELX][ELY]; laser.dest_element = element; @@ -1045,6 +1076,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)) @@ -1103,6 +1140,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 @@ -1448,6 +1493,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 { @@ -1614,9 +1663,11 @@ boolean HitElement(int element, int hit_mask) element == EL_KEY || element == EL_LIGHTBALL || element == EL_PACMAN || - IS_PACMAN(element)) + IS_PACMAN(element) || + IS_ENVELOPE(element)) { - if (!IS_PACMAN(element)) + if (!IS_PACMAN(element) && + !IS_ENVELOPE(element)) Bang_MM(ELX, ELY); if (element == EL_PACMAN) @@ -1644,6 +1695,10 @@ boolean HitElement(int element, int hit_mask) { DeletePacMan(ELX, ELY); } + else if (IS_ENVELOPE(element)) + { + Tile[ELX][ELY] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(Tile[ELX][ELY]); + } RaiseScoreElement_MM(element); @@ -2433,6 +2488,42 @@ static void OpenSurpriseBall(int x, int y) } } +static void OpenEnvelope(int x, int y) +{ + int num_frames = 8; // seven frames plus final empty space + + if (!MovDelay[x][y]) // next animation frame + MovDelay[x][y] = num_frames; + + if (MovDelay[x][y]) // wait some time before next frame + { + int nr = ENVELOPE_OPENING_NR(Tile[x][y]); + + MovDelay[x][y]--; + + if (MovDelay[x][y] > 0 && IN_SCR_FIELD(x, y)) + { + int graphic = el_act2gfx(EL_ENVELOPE_1 + nr, MM_ACTION_COLLECTING); + int frame = num_frames - MovDelay[x][y] - 1; + + DrawGraphicAnimation_MM(x, y, graphic, frame); + + laser.redraw = TRUE; + } + + if (MovDelay[x][y] == 0) + { + Tile[x][y] = EL_EMPTY; + + DrawField_MM(x, y); + + ScanLaser(); + + ShowEnvelope_MM(nr); + } + } +} + static void MeltIce(int x, int y) { int frames = 5; @@ -2515,33 +2606,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) @@ -2924,6 +3025,12 @@ boolean ClickElement(int x, int y, int button) element_clicked = TRUE; } + else if (IS_ENVELOPE(element)) + { + Tile[x][y] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(element); + + element_clicked = TRUE; + } click_delay.value = (new_button ? CLICK_DELAY_FIRST : CLICK_DELAY); new_button = FALSE; @@ -3006,8 +3113,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 @@ -3015,12 +3120,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) @@ -3181,12 +3287,22 @@ static void GameActions_MM_Ext(void) OpenExit(x, y); else if (element == EL_GRAY_BALL_OPENING) OpenSurpriseBall(x, y); + else if (IS_ENVELOPE_OPENING(element)) + OpenEnvelope(x, y); else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_ICE) 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(); @@ -3375,7 +3491,7 @@ static void GameActions_MM_Ext(void) int new_element = native_mm_level.ball_content[element_pos]; - Store[ELX][ELY] = new_element + RND(get_num_elements(new_element)); + Store[ELX][ELY] = get_rotated_element(new_element, RND(16)); Store2[ELX][ELY] = TRUE; }