}
}
-static void InitField(int x, int y)
+static void InitField(int x, int y, boolean init_game)
{
int element = Tile[x][y];
case EL_KETTLE:
case EL_CELL:
- if (native_mm_level.auto_count_kettles)
+ if (init_game && native_mm_level.auto_count_kettles)
game_mm.kettles_still_needed++;
break;
}
else if (IS_MCDUFFIN(element) || IS_LASER(element))
{
- laser.start_edge.x = x;
- laser.start_edge.y = y;
- laser.start_angle = get_element_angle(element);
+ if (init_game)
+ {
+ laser.start_edge.x = x;
+ laser.start_edge.y = y;
+ laser.start_angle = get_element_angle(element);
+ }
if (IS_MCDUFFIN(element))
{
Store[x][y] = Store2[x][y] = 0;
Stop[x][y] = FALSE;
- InitField(x, y);
+ InitField(x, y, TRUE);
}
}
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)
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;
// 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;
{
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;
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)
{
DeletePacMan(ELX, ELY);
}
+ else if (IS_ENVELOPE(element))
+ {
+ Tile[ELX][ELY] = EL_ENVELOPE_1_OPENING + ENVELOPE_NR(Tile[ELX][ELY]);
+ }
RaiseScoreElement_MM(element);
BlitBitmap(bitmap, drawto, gx + dx, gy + dy, 6, 6,
cSX + x * TILEX + dx, cSY + y * TILEY + dy);
+ laser.redraw = TRUE;
+
MarkTileDirty(x, y);
}
{
Tile[x][y] = Store[x][y];
Store[x][y] = Store2[x][y] = 0;
+ MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
+
+ InitField(x, y, FALSE);
+ DrawField_MM(x, y);
+
+ ScanLaser();
+ }
+ }
+}
+
+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);
}
}
}
Tile[x][y] = center_element;
}
- if (center_element == EL_BOMB_ACTIVE || IS_MCDUFFIN(center_element))
- Store[x][y] = center_element;
- else
- Store[x][y] = EL_EMPTY;
-
+ Store[x][y] = center_element;
Store2[x][y] = mode;
Tile[x][y] = EL_EXPLODING_OPAQUE;
- GfxElement[x][y] = center_element;
+
+ GfxElement[x][y] = (center_element == EL_BOMB_ACTIVE ? EL_BOMB :
+ IS_MCDUFFIN(center_element) ? EL_MCDUFFIN :
+ center_element);
MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
InitLaser();
Bang_MM(laser.start_edge.x, laser.start_edge.y);
- Store[x][y] = EL_EMPTY;
GameOver_MM(GAME_OVER_DELAYED);
}
else if (IS_MCDUFFIN(Store[x][y]))
{
- Store[x][y] = EL_EMPTY;
-
GameOver_MM(GAME_OVER_BOMB);
}
- Tile[x][y] = Store[x][y];
+ Tile[x][y] = EL_EMPTY;
+
Store[x][y] = Store2[x][y] = 0;
MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
- InitField(x, y);
+ InitField(x, y, FALSE);
DrawField_MM(x, y);
}
else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
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;
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
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)
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)
int new_element = native_mm_level.ball_content[element_pos];
- Store[ELX][ELY] = new_element + RND(get_num_elements(new_element));
+ // randomly rotate newly created game element, if needed
+ if (native_mm_level.rotate_ball_content)
+ new_element = get_rotated_element(new_element, RND(16));
+
+ Store[ELX][ELY] = new_element;
Store2[ELX][ELY] = TRUE;
}