if (HAS_CHANGE_EVENT(i, CE_BY_OTHER))
trigger_events[element_info[i].change.trigger] |=
element_info[i].change.events;
+
+ /* set push delay value for all non-custom elements */
+ for (i=0; i<MAX_NUM_ELEMENTS; i++)
+ {
+ if (!IS_CUSTOM_ELEMENT(i))
+ {
+ if (i == EL_SPRING ||
+ i == EL_BALLOON)
+ {
+ element_info[i].push_delay_fixed = 0;
+ element_info[i].push_delay_random = 0;
+ }
+ else if (i == EL_SOKOBAN_OBJECT ||
+ i == EL_SOKOBAN_FIELD_FULL ||
+ i == EL_SATELLITE ||
+ i == EL_SP_DISK_YELLOW)
+ {
+ element_info[i].push_delay_fixed = 2;
+ element_info[i].push_delay_random = 0;
+ }
+ else
+ {
+ element_info[i].push_delay_fixed = 2;
+ element_info[i].push_delay_random = 8;
+ }
+ }
+ }
}
AmoebaNr[x][y] = 0;
JustStopped[x][y] = 0;
Stop[x][y] = FALSE;
+ Pushed[x][y] = FALSE;
ExplodePhase[x][y] = 0;
ExplodeField[x][y] = EX_NO_EXPLOSION;
MovDir[x][y] = 0;
MovDelay[x][y] = 0;
ChangeDelay[x][y] = 0;
+ Pushed[x][y] = FALSE;
}
void RemoveMovingField(int x, int y)
#endif
}
#if 1
+#if 1
+ else if (game.engine_version < RELEASE_IDENT(2,2,0,7) &&
+ CAN_SMASH(element) && Feld[x][y + 1] == EL_BLOCKED &&
+ JustStopped[x][y] && !Pushed[x][y + 1])
+#else
else if (CAN_SMASH(element) && Feld[x][y + 1] == EL_BLOCKED &&
JustStopped[x][y])
+#endif
{
/*
printf("::: %d\n", MovDir[x][y]);
MovPos[x][y] += step;
#if 1
+#if 1
+ if (Pushed[x][y]) /* special case: moving object pushed by player */
+#else
if (pushing) /* special case: moving object pushed by player */
+#endif
#if 1
MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos));
#else
Feld[x][y] = get_next_element(element);
element = Feld[newx][newy] = Store[x][y];
}
+ else if (element == EL_SOKOBAN_OBJECT)
+ {
+ if (Back[x][y])
+ Feld[x][y] = Back[x][y];
+
+ if (Back[newx][newy])
+ Feld[newx][newy] = EL_SOKOBAN_FIELD_FULL;
+
+ Back[x][y] = Back[newx][newy] = 0;
+ }
else if (Store[x][y] == EL_ACID)
{
element = Feld[newx][newy] = EL_ACID;
GfxAction[newx][newy] = GfxAction[x][y]; /* keep action one frame */
GfxRandom[newx][newy] = GfxRandom[x][y]; /* keep same random value */
+ Pushed[x][y] = Pushed[newx][newy] = FALSE;
+
ResetGfxAnimation(x, y); /* reset animation values for old field */
#if 1
if (!CAN_MOVE(element))
MovDir[newx][newy] = 0;
#else
- /*
+
+#if 0
if (CAN_FALL(element) && MovDir[newx][newy] == MV_DOWN)
MovDir[newx][newy] = 0;
- */
-
+#else
if (!CAN_MOVE(element) ||
(element == EL_SPRING && MovDir[newx][newy] == MV_DOWN))
MovDir[newx][newy] = 0;
#endif
+
+#endif
#endif
DrawLevelField(x, y);
return MF_ACTION;
break;
+#if 0
+
/* the following elements cannot be pushed by "snapping" */
case EL_ROCK:
case EL_BOMB:
break;
+#endif
+
case EL_GATE_1:
case EL_GATE_2:
case EL_GATE_3:
return MF_ACTION;
break;
+#if 0
+
#if 0
case EL_SOKOBAN_FIELD_EMPTY:
break;
if (IS_SB_ELEMENT(element))
{
+#if 1
+ if (element == EL_SOKOBAN_FIELD_FULL)
+ {
+ Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
+ local_player->sokobanfields_still_needed++;
+ }
+
+ if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY)
+ {
+ Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY;
+ local_player->sokobanfields_still_needed--;
+ }
+
+ Feld[x][y] = EL_SOKOBAN_OBJECT;
+
+ if (Back[x][y] == Back[x + dx][y + dy])
+ PlaySoundLevelAction(x, y, ACTION_PUSHING);
+ else if (Back[x][y] != 0)
+ PlaySoundLevelElementAction(x, y, EL_SOKOBAN_FIELD_FULL,
+ ACTION_EMPTYING);
+ else
+ PlaySoundLevelElementAction(x + dx, y + dy, EL_SOKOBAN_FIELD_EMPTY,
+ ACTION_FILLING);
+
+ InitMovingField(x, y, (dx < 0 ? MV_LEFT :
+ dx > 0 ? MV_RIGHT :
+ dy < 0 ? MV_UP : MV_DOWN));
+ MovPos[x][y] = (dx != 0 ? dx : dy);
+
+#if 0
+ printf("::: %s -> %s [%s -> %s]\n",
+ element_info[Feld[x][y]].token_name,
+ element_info[Feld[x + dx][y + dy]].token_name,
+ element_info[Back[x][y]].token_name,
+ element_info[Back[x + dx][y + dy]].token_name);
+#endif
+
+#else
if (element == EL_SOKOBAN_FIELD_FULL)
{
Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING);
#endif
}
+#endif
}
else
{
+#if 1
+ InitMovingField(x, y, (dx < 0 ? MV_LEFT :
+ dx > 0 ? MV_RIGHT :
+ dy < 0 ? MV_UP : MV_DOWN));
+ MovPos[x][y] = (dx != 0 ? dx : dy);
+#else
RemoveField(x, y);
- Feld[x+dx][y+dy] = element;
+ Feld[x + dx][y + dy] = element;
+#endif
PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
}
break;
+#endif
+
case EL_PENGUIN:
case EL_PIG:
case EL_DRAGON:
}
else if (IS_PUSHABLE(element))
{
- if (mode == DF_SNAP)
+ if (mode == DF_SNAP && element != EL_BD_ROCK)
return MF_NO_ACTION;
if (CAN_FALL(element) && dy)
return MF_NO_ACTION;
- if (CAN_FALL(element) && IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1))
+ if (CAN_FALL(element) && IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1) &&
+ !(element == EL_SPRING && use_spring_bug))
+ return MF_NO_ACTION;
+
+ if (element == EL_SPRING && MovDir[x][y] != MV_NO_MOVING)
return MF_NO_ACTION;
if (!player->Pushing &&
player->Pushing = TRUE;
- if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy))
+ if (!(IN_LEV_FIELD(x + dx, y + dy) &&
+ (IS_FREE(x + dx, y + dy) ||
+ (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY &&
+ IS_SB_ELEMENT(element)))))
return MF_NO_ACTION;
if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
player->push_delay = FrameCounter;
if (!FrameReached(&player->push_delay, player->push_delay_value) &&
- !(tape.playing && tape.file_version < FILE_VERSION_2_0))
+ !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
+ element != EL_SPRING && element != EL_BALLOON)
return MF_NO_ACTION;
-#if 1
- InitMovingField(x, y, (dx < 0 ? MV_LEFT :
- dx > 0 ? MV_RIGHT :
- dy < 0 ? MV_UP : MV_DOWN));
- MovPos[x][y] = (dx != 0 ? dx : dy);
-#else
- RemoveField(x, y);
- Feld[x + dx][y + dy] = element;
-#endif
+ if (IS_SB_ELEMENT(element))
+ {
+ if (element == EL_SOKOBAN_FIELD_FULL)
+ {
+ Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
+ local_player->sokobanfields_still_needed++;
+ }
+
+ if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY)
+ {
+ Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY;
+ local_player->sokobanfields_still_needed--;
+ }
+
+ Feld[x][y] = EL_SOKOBAN_OBJECT;
+
+ if (Back[x][y] == Back[x + dx][y + dy])
+ PlaySoundLevelAction(x, y, ACTION_PUSHING);
+ else if (Back[x][y] != 0)
+ PlaySoundLevelElementAction(x, y, EL_SOKOBAN_FIELD_FULL,
+ ACTION_EMPTYING);
+ else
+ PlaySoundLevelElementAction(x + dx, y + dy, EL_SOKOBAN_FIELD_EMPTY,
+ ACTION_FILLING);
+
+ if (local_player->sokobanfields_still_needed == 0 &&
+ game.emulation == EMU_SOKOBAN)
+ {
+ player->LevelSolved = player->GameOver = TRUE;
+ PlaySoundLevel(x, y, SND_GAME_SOKOBAN_SOLVING);
+ }
+ }
+ else
+ PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
+
+ InitMovingField(x, y, move_direction);
+
+ if (mode == DF_SNAP)
+ ContinueMoving(x, y);
+ else
+ MovPos[x][y] = (dx != 0 ? dx : dy);
+
+ Pushed[x][y] = TRUE;
+ Pushed[x + dx][y + dy] = TRUE;
-#if 1
if (game.engine_version < RELEASE_IDENT(2,2,0,7))
player->push_delay_value = GET_NEW_PUSH_DELAY(element);
-#else
- player->push_delay_value = 2 + RND(8);
-#endif
-
- DrawLevelField(x + dx, y + dy);
- PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
CheckTriggeredElementChange(element, CE_OTHER_PUSHING);
-#if 1
CheckPlayerElementChange(x, y, element, CE_PUSHED_BY_PLAYER);
-#else
- CheckPlayerElementChange(x + dx, y + dy, element, CE_PUSHED_BY_PLAYER);
-#endif
break;
}