JustStopped[x][y] = 0;
Stop[x][y] = FALSE;
Pushed[x][y] = FALSE;
+ Changing[x][y] = FALSE;
ExplodePhase[x][y] = 0;
ExplodeField[x][y] = EX_NO_EXPLOSION;
{
int center_element = Feld[ex][ey];
+#if 0
+ /* --- This is only really needed (and now handled) in "Impact()". --- */
+ /* do not explode moving elements that left the explode field in time */
+ if (game.engine_version >= RELEASE_IDENT(2,2,0,7) &&
+ center_element == EL_EMPTY && (mode == EX_NORMAL || mode == EX_CENTER))
+ return;
+#endif
+
+ if (mode == EX_NORMAL || mode == EX_CENTER)
+ PlaySoundLevelAction(ex, ey, ACTION_EXPLODING);
+
/* remove things displayed in background while burning dynamite */
if (!IS_INDESTRUCTIBLE(Back[ex][ey]))
Back[ex][ey] = 0;
if (IS_MOVING(x, y) || IS_BLOCKED(x, y))
{
element = MovingOrBlocked2Element(x, y);
- RemoveMovingField(x, y);
+
+ if (!IS_EXPLOSION_PROOF(element))
+ RemoveMovingField(x, y);
}
+#if 1
+
#if 1
if (IS_EXPLOSION_PROOF(element))
continue;
+#else
+ /* indestructible elements can only explode in center (but not flames) */
+ if ((IS_EXPLOSION_PROOF(element) && (x != ex || y != ey)) ||
+ element == EL_FLAMES)
+ continue;
+#endif
+
#else
if ((IS_INDESTRUCTIBLE(element) &&
(game.engine_version < VERSION_IDENT(2,2,0) ||
}
/* save walkable background elements while explosion on same tile */
+#if 1
if (IS_INDESTRUCTIBLE(element))
Back[x][y] = element;
+#else
+ if (IS_INDESTRUCTIBLE(element) && IS_WALKABLE(element))
+ Back[x][y] = element;
+#endif
/* ignite explodable elements reached by other explosion */
if (element == EL_EXPLOSION)
player->element_nr);
}
+#if 0
#if 1
PlaySoundLevelAction(x, y, ACTION_EXPLODING);
#else
else
PlaySoundLevel(x, y, SND_ELEMENT_EXPLODING);
#endif
+#endif
#if 0
if (IS_PLAYER(x, y)) /* remove objects that might cause smaller explosion */
Feld[x][y] = EL_TIMEGATE_SWITCH_ACTIVE;
}
+inline static int getElementMoveStepsize(int x, int y)
+{
+ int element = Feld[x][y];
+ int direction = MovDir[x][y];
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int horiz_move = (dx != 0);
+ int sign = (horiz_move ? dx : dy);
+ int step = sign * element_info[element].move_stepsize;
+
+ /* special values for move stepsize for spring and things on conveyor belt */
+ if (horiz_move)
+ {
+ if (CAN_FALL(element) &&
+ y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+ step = sign * MOVE_STEPSIZE_NORMAL / 2;
+ else if (element == EL_SPRING)
+ step = sign * MOVE_STEPSIZE_NORMAL * 2;
+ }
+
+ return step;
+}
+
void Impact(int x, int y)
{
boolean lastline = (y == lev_fieldy-1);
object_hit = (!IS_FREE(x, y + 1) && (!IS_MOVING(x, y + 1) ||
MovDir[x][y + 1] != MV_DOWN ||
MovPos[x][y + 1] <= TILEY / 2));
+
+ /* do not smash moving elements that left the smashed field in time */
+ if (game.engine_version >= RELEASE_IDENT(2,2,0,7) && IS_MOVING(x, y + 1) &&
+ ABS(MovPos[x][y + 1] + getElementMoveStepsize(x, y + 1)) >= TILEX)
+ object_hit = FALSE;
+
if (object_hit)
smashed = MovingOrBlocked2Element(x, y + 1);
Bang(x, y + 1);
return;
}
+#if 0
+ else if (CAN_SMASH_ENEMIES(element) && IS_CLASSIC_ENEMY(smashed))
+ {
+ Bang(x, y + 1);
+ return;
+ }
+#endif
else if (CAN_SMASH_EVERYTHING(element))
{
if (IS_CLASSIC_ENEMY(smashed) ||
if (Stop[x][y])
return;
- GfxAction[x][y] = ACTION_DEFAULT;
+ /* !!! this should be handled more generic (not only for more) !!! */
+ if (element != EL_MOLE && GfxAction[x][y] != ACTION_DIGGING)
+ GfxAction[x][y] = ACTION_DEFAULT;
if (CAN_FALL(element) && y < lev_fieldy - 1)
{
{
Feld[newx][newy] = EL_AMOEBA_SHRINKING;
PlaySoundLevel(x, y, SND_MOLE_DIGGING);
+
+ ResetGfxAnimation(x, y);
+ GfxAction[x][y] = ACTION_DIGGING;
+ DrawLevelField(x, y);
+
MovDelay[newx][newy] = 0; /* start amoeba shrinking delay */
return; /* wait for shrinking amoeba */
}
int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
int newx = x + dx, newy = y + dy;
int nextx = newx + dx, nexty = newy + dy;
- int horiz_move = (dx != 0);
- int sign = (horiz_move ? dx : dy);
- int step = sign * element_info[element].move_stepsize;
boolean pushed = Pushed[x][y];
- /* special values for move stepsize for spring and things on conveyor belt */
- if (horiz_move)
- {
- if (CAN_FALL(element) &&
- y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
- step = sign * MOVE_STEPSIZE_NORMAL / 2;
- else if (element == EL_SPRING)
- step = sign * MOVE_STEPSIZE_NORMAL * 2;
- }
-
- MovPos[x][y] += step;
+ MovPos[x][y] += getElementMoveStepsize(x, y);
if (pushed) /* special case: moving object pushed by player */
MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos));
if (CAN_BE_CRUMBLED(Feld[x][y]))
DrawLevelFieldCrumbledSandNeighbours(x, y);
+
+ TestIfBadThingTouchesHero(x, y);
+ TestIfPlayerTouchesCustomElement(x, y);
+ TestIfElementTouchesCustomElement(x, y);
}
static void ChangeElementNow(int x, int y, int element)
{
struct ElementChangeInfo *change = &element_info[element].change;
+ /* prevent CheckTriggeredElementChange() from looping */
+ Changing[x][y] = TRUE;
+
CheckTriggeredElementChange(x, y, Feld[x][y], CE_OTHER_IS_CHANGING);
+ Changing[x][y] = FALSE;
+
if (change->explode)
{
Bang(x, y);
e = Feld[ex][ey];
+ if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
+ e = MovingOrBlocked2Element(ex, ey);
+
half_destructible = (IS_FREE(ex, ey) || IS_DIGGABLE(e));
if ((change->power <= CP_NON_DESTRUCTIVE && !IS_FREE(ex, ey)) ||
if (can_change[xx][yy] && (!change->use_random_change ||
RND(change->random) == 0))
{
+ if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
+ RemoveMovingField(ex, ey);
+
ChangeElementNowExt(ex, ey, change->content[xx][yy]);
/* for symmetry reasons, stop newly created border elements */
if (x == lx && y == ly) /* do not change trigger element itself */
continue;
+ if (Changing[x][y]) /* do not change just changing elements */
+ continue;
+
if (Feld[x][y] == i)
{
ChangeDelay[x][y] = 1;
#if 1
graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
#if 0
- if (element == EL_PACMAN)
- printf("::: %d, %d, %d\n",
- IS_ANIMATED(graphic), IS_MOVING(x, y), Stop[x][y]);
+ if (element == EL_MOLE)
+ printf("::: %d, %d, %d [%d]\n",
+ IS_ANIMATED(graphic), IS_MOVING(x, y), Stop[x][y],
+ GfxAction[x][y]);
#endif
#if 0
if (element == EL_YAMYAM)
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
#if 0
- if (element == EL_YAMYAM)
+ if (element == EL_MOLE)
printf("::: %d, %d\n", graphic, GfxFrame[x][y]);
#endif
}