for (i = 0; i < element_info[element].num_change_pages; i++)
{
- content = element_info[element].change_page[i].content[xx][yy];
+ content= element_info[element].change_page[i].target_content[xx][yy];
is_player = ELEM_IS_PLAYER(content);
if (is_player && (found_rating < 1 || element < found_element))
boolean no_delay = (tape.index_search);
int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
int wait_delay_value = (no_delay ? 0 : frame_delay_value);
-#if 1
int old_jx, old_jy;
-#endif
if (player->GameOver) /* do not reanimate dead player */
return;
-#if 1
RemoveField(x, y); /* temporarily remove newly placed player */
DrawLevelField(x, y);
-#endif
if (player->present)
{
player->is_moving = FALSE;
}
-#if 1
old_jx = player->jx;
old_jy = player->jy;
-#endif
Feld[x][y] = element;
InitPlayerField(x, y, element, TRUE);
-#if 0
- if (player == local_player)
+ if (player != local_player) /* do not visually relocate other players */
+ return;
+
+ if (level.instant_relocation)
{
#if 1
+ int offset = (setup.scroll_delay ? 3 : 0);
+ int jx = local_player->jx;
+ int jy = local_player->jy;
+
+ if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
+ {
+ scroll_x = (local_player->jx < SBX_Left + MIDPOSX ? SBX_Left :
+ local_player->jx > SBX_Right + MIDPOSX ? SBX_Right :
+ local_player->jx - MIDPOSX);
+ scroll_y = (local_player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
+ local_player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
+ local_player->jy - MIDPOSY);
+ }
+ else
+ {
+ if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
+ (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
+ scroll_x = jx - MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
+
+ if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
+ (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
+ scroll_y = jy - MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
+
+ /* don't scroll over playfield boundaries */
+ if (scroll_x < SBX_Left || scroll_x > SBX_Right)
+ scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
+
+ /* don't scroll over playfield boundaries */
+ if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
+ scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
+ }
+#else
scroll_x += (local_player->jx - old_jx);
scroll_y += (local_player->jy - old_jy);
/* don't scroll over playfield boundaries */
if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
-
-#else
- scroll_x = (local_player->jx < SBX_Left + MIDPOSX ? SBX_Left :
- local_player->jx > SBX_Right + MIDPOSX ? SBX_Right :
- local_player->jx - MIDPOSX);
-
- scroll_y = (local_player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
- local_player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
- local_player->jy - MIDPOSY);
#endif
RedrawPlayfield(TRUE, 0,0,0,0);
-#if 0
- DrawAllPlayers();
- BackToFront();
-#endif
}
+ else
+ {
+#if 1
+ int offset = (setup.scroll_delay ? 3 : 0);
+ int jx = local_player->jx;
+ int jy = local_player->jy;
+ int scroll_xx = -999, scroll_yy = -999;
+
+ ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
+ while (scroll_xx != scroll_x || scroll_yy != scroll_y)
+ {
+ int dx = 0, dy = 0;
+ int fx = FX, fy = FY;
+
+ scroll_xx = (local_player->jx < SBX_Left + MIDPOSX ? SBX_Left :
+ local_player->jx > SBX_Right + MIDPOSX ? SBX_Right :
+ local_player->jx - MIDPOSX);
+
+ scroll_yy = (local_player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
+ local_player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
+ local_player->jy - MIDPOSY);
+
+ dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
+ dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
+
+#if 1
+ if (dx == 0 && dy == 0) /* no scrolling needed at all */
+ break;
#else
+ if (scroll_xx == scroll_x && scroll_yy == scroll_y)
+ break;
+#endif
- if (player == local_player)
- {
+ scroll_x -= dx;
+ scroll_y -= dy;
+
+ fx += dx * TILEX / 2;
+ fy += dy * TILEY / 2;
+
+ ScrollLevel(dx, dy);
+ DrawAllPlayers();
+
+ /* scroll in two steps of half tile size to make things smoother */
+ BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
+ FlushDisplay();
+ Delay(wait_delay_value);
+
+ /* scroll second step to align at full tile size */
+ BackToFront();
+ Delay(wait_delay_value);
+ }
+#else
int scroll_xx = -999, scroll_yy = -999;
+ ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
+
while (scroll_xx != scroll_x || scroll_yy != scroll_y)
{
int dx = 0, dy = 0;
dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
+#if 1
+ if (dx == 0 && dy == 0) /* no scrolling needed at all */
+ break;
+#else
+ if (scroll_xx == scroll_x && scroll_yy == scroll_y)
+ break;
+#endif
+
scroll_x -= dx;
scroll_y -= dy;
BackToFront();
Delay(wait_delay_value);
}
- }
#endif
+ }
}
void Explode(int ex, int ey, int phase, int mode)
return TRUE;
}
- if (change->use_content)
+ if (change->use_target_content)
{
- boolean complete_change = TRUE;
- boolean can_change[3][3];
+ boolean complete_replace = TRUE;
+ boolean can_replace[3][3];
int xx, yy;
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3 ; xx++)
{
- boolean half_destructible;
+ boolean is_empty;
+ boolean is_diggable;
+ boolean is_destructible;
int ex = x + xx - 1;
int ey = y + yy - 1;
+ int content_element = change->target_content[xx][yy];
int e;
- can_change[xx][yy] = TRUE;
+ can_replace[xx][yy] = TRUE;
if (ex == x && ey == y) /* do not check changing element itself */
continue;
- if (change->content[xx][yy] == EL_EMPTY_SPACE)
+ if (content_element == EL_EMPTY_SPACE)
{
- can_change[xx][yy] = FALSE; /* do not change empty borders */
+ can_replace[xx][yy] = FALSE; /* do not replace border with space */
continue;
}
if (!IN_LEV_FIELD(ex, ey))
{
- can_change[xx][yy] = FALSE;
- complete_change = FALSE;
+ can_replace[xx][yy] = FALSE;
+ complete_replace = FALSE;
continue;
}
if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
e = MovingOrBlocked2Element(ex, ey);
+#if 1
+ is_empty = (IS_FREE(ex, ey) || (IS_PLAYER(ex, ey) &&
+ IS_WALKABLE(content_element)));
+ is_diggable = (is_empty || IS_DIGGABLE(e));
+ is_destructible = (is_empty || !IS_INDESTRUCTIBLE(e));
+
+ can_replace[xx][yy] =
+ ((change->replace_when == CP_WHEN_EMPTY && is_empty) ||
+ (change->replace_when == CP_WHEN_DIGGABLE && is_diggable) ||
+ (change->replace_when == CP_WHEN_DESTRUCTIBLE && is_destructible));
+
+ if (!can_replace[xx][yy])
+ complete_replace = FALSE;
+#else
+ empty_for_element = (IS_FREE(ex, ey) || (IS_FREE_OR_PLAYER(ex, ey) &&
+ IS_WALKABLE(content_element)));
+#if 1
+ half_destructible = (empty_for_element || IS_DIGGABLE(e));
+#else
half_destructible = (IS_FREE(ex, ey) || IS_DIGGABLE(e));
+#endif
- if ((change->power <= CP_NON_DESTRUCTIVE && !IS_FREE(ex, ey)) ||
- (change->power <= CP_HALF_DESTRUCTIVE && !half_destructible) ||
- (change->power <= CP_FULL_DESTRUCTIVE && IS_INDESTRUCTIBLE(e)))
+ if ((change->replace_when <= CP_WHEN_EMPTY && !empty_for_element) ||
+ (change->replace_when <= CP_WHEN_DIGGABLE && !half_destructible) ||
+ (change->replace_when <= CP_WHEN_DESTRUCTIBLE && IS_INDESTRUCTIBLE(e)))
{
- can_change[xx][yy] = FALSE;
- complete_change = FALSE;
+ can_replace[xx][yy] = FALSE;
+ complete_replace = FALSE;
}
+#endif
}
- if (!change->only_complete || complete_change)
+ if (!change->only_if_complete || complete_replace)
{
boolean something_has_changed = FALSE;
- if (change->only_complete && change->use_random_change &&
- RND(100) < change->random)
+ if (change->only_if_complete && change->use_random_replace &&
+ RND(100) < change->random_percentage)
return FALSE;
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3 ; xx++)
{
int ex = x + xx - 1;
int ey = y + yy - 1;
+ int content_element;
- if (can_change[xx][yy] && (!change->use_random_change ||
- RND(100) < change->random))
+ if (can_replace[xx][yy] && (!change->use_random_replace ||
+ RND(100) < change->random_percentage))
{
if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
RemoveMovingField(ex, ey);
ChangeEvent[ex][ey] = ChangeEvent[x][y];
- target_element = GET_TARGET_ELEMENT(change->content[xx][yy], change);
+ content_element = change->target_content[xx][yy];
+ target_element = GET_TARGET_ELEMENT(content_element, change);
ChangeElementNowExt(ex, ey, target_element);
{
if (jx != old_jx) /* player has moved horizontally */
{
- if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
+ if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
(player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
scroll_x = jx-MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x);
/* don't scroll against the player's moving direction */
- if ((player->MovDir == MV_LEFT && scroll_x > old_scroll_x) ||
+ if ((player->MovDir == MV_LEFT && scroll_x > old_scroll_x) ||
(player->MovDir == MV_RIGHT && scroll_x < old_scroll_x))
scroll_x = old_scroll_x;
}
else /* player has moved vertically */
{
- if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
+ if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
(player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
scroll_y = jy-MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y);
/* don't scroll against the player's moving direction */
- if ((player->MovDir == MV_UP && scroll_y > old_scroll_y) ||
+ if ((player->MovDir == MV_UP && scroll_y > old_scroll_y) ||
(player->MovDir == MV_DOWN && scroll_y < old_scroll_y))
scroll_y = old_scroll_y;
}
player->is_dropping = FALSE;
-#if 1
+#if 0
+ /* !!! ENABLE THIS FOR OLD VERSIONS !!! */
{
static int trigger_sides[4][2] =
{
player->LevelSolved = player->GameOver = TRUE;
}
-#if 0
+#if 1
/* !!! ENABLE THIS FOR NEW VERSIONS !!! */
+ /* this breaks one level: "machine", level 000 */
{
static int trigger_sides[4][2] =
{