X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=2713e32092363f71e80cc2db49f09fb78f627433;hb=f2ba8f4f956e63e7b22d06d55c05034e5c70c0da;hp=9a7ad5e6b031563653389669f4f6690f500acdce;hpb=fde7b4e29e233aec59de27f74a398c8596fd5766;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index 9a7ad5e6..2713e320 100644 --- a/src/game_mm/mm_game.c +++ b/src/game_mm/mm_game.c @@ -951,6 +951,7 @@ static void DeactivateLaserTargetElement(void) { if (laser.dest_element_last == EL_BOMB_ACTIVE || laser.dest_element_last == EL_MINE_ACTIVE || + laser.dest_element_last == EL_GRAY_BALL_ACTIVE || laser.dest_element_last == EL_GRAY_BALL_OPENING) { int x = laser.dest_element_last_x; @@ -1185,6 +1186,22 @@ void ScanLaser(void) #endif } +static void ScanLaser_FromLastMirror(void) +{ + int start_pos = (laser.num_damages > 0 ? laser.num_damages - 1 : 0); + int i; + + for (i = start_pos; i >= 0; i--) + if (laser.damage[i].is_mirror) + break; + + int start_edge = (i > 0 ? laser.damage[i].edge - 1 : 0); + + DrawLaser(start_edge, DL_LASER_DISABLED); + + ScanLaser(); +} + static void DrawLaserExt(int start_edge, int num_edges, int mode) { int element; @@ -1496,6 +1513,8 @@ 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) { + int skip_count = 0; + // prevent cutting through laser emitter with laser beam if (IS_LASER(element)) return TRUE; @@ -1505,15 +1524,18 @@ boolean HitElement(int element, int hit_mask) { LX += XS; LY += YS; + + skip_count++; } while (ELX == LX/TILEX && ELY == LY/TILEY && LX > 0 && LY > 0); - if (LX/TILEX > ELX || LY/TILEY > ELY) + if ((LX/TILEX > ELX || LY/TILEY > ELY) && skip_count > 1) { /* skipping scan positions to the right and down skips one scan position too much, because this is only the top left scan position of totally four scan positions (plus one to the right, one to the bottom and one to the bottom right) */ + /* ... but only roll back scan position if more than one step done */ LX -= XS; LY -= YS; @@ -1647,11 +1669,13 @@ boolean HitElement(int element, int hit_mask) return TRUE; } - if (element == EL_BOMB || element == EL_MINE) + if (element == EL_BOMB || element == EL_MINE || element == EL_BALL_GRAY) { PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_HITTING); - Tile[ELX][ELY] = (element == EL_BOMB ? EL_BOMB_ACTIVE : EL_MINE_ACTIVE); + Tile[ELX][ELY] = (element == EL_BOMB ? EL_BOMB_ACTIVE : + element == EL_MINE ? EL_MINE_ACTIVE : + EL_GRAY_BALL_ACTIVE); laser.dest_element_last = Tile[ELX][ELY]; laser.dest_element_last_x = ELX; @@ -2458,7 +2482,20 @@ static void OpenSurpriseBall(int x, int y) int delay = 2; if (!MovDelay[x][y]) // next animation frame + { + if (IS_WALL(Store[x][y])) + { + DrawWalls_MM(x, y, Store[x][y]); + + // copy wall tile to spare bitmap for "melting" animation + BlitBitmap(drawto, bitmap_db_field, cSX + x * TILEX, cSY + y * TILEY, + TILEX, TILEY, x * TILEX, y * TILEY); + + DrawElement_MM(x, y, EL_BALL_GRAY); + } + MovDelay[x][y] = 50 * delay; + } if (MovDelay[x][y]) // wait some time before next frame { @@ -2467,11 +2504,22 @@ static void OpenSurpriseBall(int x, int y) if (!(MovDelay[x][y] % delay) && IN_SCR_FIELD(x, y)) { Bitmap *bitmap; - int graphic = el2gfx(Store[x][y]); int gx, gy; int dx = RND(26), dy = RND(26); - getGraphicSource(graphic, 0, &bitmap, &gx, &gy); + if (IS_WALL(Store[x][y])) + { + // copy wall tile from spare bitmap for "melting" animation + bitmap = bitmap_db_field; + gx = x * TILEX; + gy = y * TILEY; + } + else + { + int graphic = el2gfx(Store[x][y]); + + getGraphicSource(graphic, 0, &bitmap, &gx, &gy); + } BlitBitmap(bitmap, drawto, gx + dx, gy + dy, 6, 6, cSX + x * TILEX + dx, cSY + y * TILEY + dy); @@ -2490,7 +2538,7 @@ static void OpenSurpriseBall(int x, int y) InitField(x, y, FALSE); DrawField_MM(x, y); - ScanLaser(); + ScanLaser_FromLastMirror(); } } } @@ -2550,8 +2598,6 @@ static void MeltIce(int x, int y) if (!MovDelay[x][y]) { - int i; - Tile[x][y] = real_element & (wall_mask ^ 0xFF); Store[x][y] = Store2[x][y] = 0; @@ -2560,16 +2606,7 @@ static void MeltIce(int x, int y) if (Tile[x][y] == EL_WALL_ICE) Tile[x][y] = EL_EMPTY; - for (i = (laser.num_damages > 0 ? laser.num_damages - 1 : 0); i >= 0; i--) - if (laser.damage[i].is_mirror) - break; - - if (i > 0) - DrawLaser(laser.damage[i].edge - 1, DL_LASER_DISABLED); - else - DrawLaser(0, DL_LASER_DISABLED); - - ScanLaser(); + ScanLaser_FromLastMirror(); } else if (!(MovDelay[x][y] % delay) && IN_SCR_FIELD(x, y)) { @@ -3301,7 +3338,7 @@ static void GameActions_MM_Ext(void) IS_MIRROR_FIXED(element) || element == EL_PRISM) DrawFieldTwinkle(x, y); - else if (element == EL_GRAY_BALL_OPENING || + else if (element == EL_GRAY_BALL_ACTIVE || element == EL_BOMB_ACTIVE || element == EL_MINE_ACTIVE) DrawFieldAnimated_MM(x, y); @@ -3370,6 +3407,7 @@ static void GameActions_MM_Ext(void) element != EL_MINE && element != EL_MINE_ACTIVE && element != EL_BALL_GRAY && + element != EL_GRAY_BALL_ACTIVE && element != EL_BLOCK_STONE && element != EL_BLOCK_WOOD && element != EL_FUSE_ON && @@ -3494,10 +3532,19 @@ static void GameActions_MM_Ext(void) game_mm.ball_choice_pos++; int new_element = native_mm_level.ball_content[element_pos]; + int new_element_unmapped = unmap_element(new_element); - // randomly rotate newly created game element, if needed - if (native_mm_level.rotate_ball_content) + if (IS_WALL(new_element_unmapped)) + { + // always use completely filled wall element + new_element = new_element_unmapped | 0x000f; + } + else if (native_mm_level.rotate_ball_content && + get_num_elements(new_element) > 1) + { + // randomly rotate newly created game element new_element = get_rotated_element(new_element, RND(16)); + } Store[ELX][ELY] = new_element; Store2[ELX][ELY] = TRUE; @@ -3505,12 +3552,7 @@ static void GameActions_MM_Ext(void) Tile[ELX][ELY] = EL_GRAY_BALL_OPENING; - // !!! CHECK AGAIN: Laser on Polarizer !!! - ScanLaser(); - laser.dest_element_last = Tile[ELX][ELY]; - laser.dest_element_last_x = ELX; - laser.dest_element_last_y = ELY; return; @@ -3643,16 +3685,7 @@ static void GameActions_MM_Ext(void) LY = laser.edge[laser.num_edges].y - cSY2; */ - for (i = (laser.num_damages > 0 ? laser.num_damages - 1 : 0); i >= 0; i--) - if (laser.damage[i].is_mirror) - break; - - if (i > 0) - DrawLaser(laser.damage[i].edge - 1, DL_LASER_DISABLED); - else - DrawLaser(0, DL_LASER_DISABLED); - - ScanLaser(); + ScanLaser_FromLastMirror(); return; }