else
FadeSetEnterScreen();
- if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged())
+ if (CheckFadeAll())
fade_mask = REDRAW_ALL;
FadeLevelSoundsAndMusic();
ExpireSoundLoops(TRUE);
- FadeOut(fade_mask);
+ if (!level_editor_test_game)
+ FadeOut(fade_mask);
// needed if different viewport properties defined for playing
ChangeViewportPropertiesIfNeeded();
if (network_playing)
SendToServer_MovePlayer(MV_NONE);
- ZX = ZY = -1;
- ExitX = ExitY = -1;
-
FrameCounter = 0;
TimeFrames = 0;
TimePlayed = 0;
ScrollStepSize = 0; // will be correctly initialized by ScrollScreen()
- AllPlayersGone = FALSE;
+ game.robot_wheel_x = -1;
+ game.robot_wheel_y = -1;
+
+ game.exit_x = -1;
+ game.exit_y = -1;
+
+ game.all_players_gone = FALSE;
game.LevelSolved = FALSE;
game.GameOver = FALSE;
+ game.GamePlayed = !tape.playing;
+
game.LevelSolved_GameWon = FALSE;
game.LevelSolved_GameEnd = FALSE;
game.LevelSolved_SaveTape = FALSE;
game.belt_dir_nr[i] = 3; // not moving, next moving left
#if USE_NEW_PLAYER_ASSIGNMENTS
+ // use preferred player also in local single-player mode
+ if (!network.enabled && !game.team_mode)
+ {
+ int old_index_nr = local_player->index_nr;
+ int new_index_nr = setup.network_player_nr;
+
+ if (new_index_nr >= 0 && new_index_nr < MAX_PLAYERS)
+ {
+ stored_player[old_index_nr].connected_locally = FALSE;
+ stored_player[new_index_nr].connected_locally = TRUE;
+ }
+ }
+
for (i = 0; i < MAX_PLAYERS; i++)
{
stored_player[i].connected = FALSE;
int i;
// do not start end game actions before the player stops moving (to exit)
- if (local_player->MovPos)
+ if (local_player->active && local_player->MovPos)
return;
game.LevelSolved_GameWon = TRUE;
if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
{
- if (ExitX >= 0 && ExitY >= 0) // local player has left the level
+ // check if last player has left the level
+ if (game.exit_x >= 0 &&
+ game.exit_y >= 0)
{
+ int x = game.exit_x;
+ int y = game.exit_y;
+ int element = Feld[x][y];
+
// close exit door after last player
- if ((AllPlayersGone &&
- (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
- Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
- Feld[ExitX][ExitY] == EL_STEEL_EXIT_OPEN)) ||
- Feld[ExitX][ExitY] == EL_EM_EXIT_OPEN ||
- Feld[ExitX][ExitY] == EL_EM_STEEL_EXIT_OPEN)
+ if ((game.all_players_gone &&
+ (element == EL_EXIT_OPEN ||
+ element == EL_SP_EXIT_OPEN ||
+ element == EL_STEEL_EXIT_OPEN)) ||
+ element == EL_EM_EXIT_OPEN ||
+ element == EL_EM_STEEL_EXIT_OPEN)
{
- int element = Feld[ExitX][ExitY];
- Feld[ExitX][ExitY] =
+ Feld[x][y] =
(element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING :
element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING:
element == EL_STEEL_EXIT_OPEN ? EL_STEEL_EXIT_CLOSING:
EL_EM_STEEL_EXIT_CLOSING);
- PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
+ PlayLevelSoundElementAction(x, y, element, ACTION_CLOSING);
}
// player disappears
- DrawLevelField(ExitX, ExitY);
+ DrawLevelField(x, y);
}
for (i = 0; i < MAX_PLAYERS; i++)
{
int attr_x = -1, attr_y = -1;
- if (AllPlayersGone)
+ if (game.all_players_gone)
{
- attr_x = ExitX;
- attr_y = ExitY;
+ attr_x = game.exit_x;
+ attr_y = game.exit_y;
}
else
{
}
}
- if (element == EL_ROBOT && ZX >= 0 && ZY >= 0 &&
- (Feld[ZX][ZY] == EL_ROBOT_WHEEL_ACTIVE ||
+ if (element == EL_ROBOT &&
+ game.robot_wheel_x >= 0 &&
+ game.robot_wheel_y >= 0 &&
+ (Feld[game.robot_wheel_x][game.robot_wheel_y] == EL_ROBOT_WHEEL_ACTIVE ||
game.engine_version < VERSION_IDENT(3,1,0,0)))
{
- attr_x = ZX;
- attr_y = ZY;
+ attr_x = game.robot_wheel_x;
+ attr_y = game.robot_wheel_y;
}
if (element == EL_PENGUIN)
MovDir[x][y] = MV_NONE;
if (attr_x < x)
- MovDir[x][y] |= (AllPlayersGone ? MV_RIGHT : MV_LEFT);
+ MovDir[x][y] |= (game.all_players_gone ? MV_RIGHT : MV_LEFT);
else if (attr_x > x)
- MovDir[x][y] |= (AllPlayersGone ? MV_LEFT : MV_RIGHT);
+ MovDir[x][y] |= (game.all_players_gone ? MV_LEFT : MV_RIGHT);
if (attr_y < y)
- MovDir[x][y] |= (AllPlayersGone ? MV_DOWN : MV_UP);
+ MovDir[x][y] |= (game.all_players_gone ? MV_DOWN : MV_UP);
else if (attr_y > y)
- MovDir[x][y] |= (AllPlayersGone ? MV_UP : MV_DOWN);
+ MovDir[x][y] |= (game.all_players_gone ? MV_UP : MV_DOWN);
if (element == EL_ROBOT)
{
int newx, newy;
boolean move_away = (move_pattern == MV_AWAY_FROM_PLAYER);
- if (AllPlayersGone)
+ if (game.all_players_gone)
{
- attr_x = ExitX;
- attr_y = ExitY;
+ attr_x = game.exit_x;
+ attr_y = game.exit_y;
}
else
{
game.friends_still_needed--;
if (!game.friends_still_needed &&
- !game.GameOver && AllPlayersGone)
+ !game.GameOver &&
+ game.all_players_gone)
LevelSolved();
return;
static void StopRobotWheel(int x, int y)
{
- if (ZX == x && ZY == y)
+ if (game.robot_wheel_x == x &&
+ game.robot_wheel_y == y)
{
- ZX = ZY = -1;
-
+ game.robot_wheel_x = -1;
+ game.robot_wheel_y = -1;
game.robot_wheel_active = FALSE;
}
}
return;
}
- if (AllPlayersGone) // do not re-open exit door closed after last player
+ // do not re-open exit door closed after last player
+ if (game.all_players_gone)
return;
Feld[x][y] = EL_EXIT_OPENING;
return;
}
- if (AllPlayersGone) // do not re-open exit door closed after last player
+ // do not re-open exit door closed after last player
+ if (game.all_players_gone)
return;
Feld[x][y] = EL_EM_EXIT_OPENING;
return;
}
- if (AllPlayersGone) // do not re-open exit door closed after last player
+ // do not re-open exit door closed after last player
+ if (game.all_players_gone)
return;
Feld[x][y] = EL_STEEL_EXIT_OPENING;
return;
}
- if (AllPlayersGone) // do not re-open exit door closed after last player
+ // do not re-open exit door closed after last player
+ if (game.all_players_gone)
return;
Feld[x][y] = EL_EM_STEEL_EXIT_OPENING;
return;
}
- if (AllPlayersGone) // do not re-open exit door closed after last player
+ // do not re-open exit door closed after last player
+ if (game.all_players_gone)
return;
Feld[x][y] = EL_SP_EXIT_OPENING;
if (action_arg_player_bits & (1 << i))
ExitPlayer(&stored_player[i]);
- if (AllPlayersGone)
+ if (game.players_still_needed == 0)
LevelSolved();
break;
if (!player->is_moving &&
!player->is_pushing &&
!player->is_dropping_pressed)
- {
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
- SnapField(player, 0, 0); // stop snapping
- }
}
CheckSaveEngineSnapshot(player);
game_em.game_over = TRUE;
- AllPlayersGone = TRUE;
+ game.all_players_gone = TRUE;
}
if (game_em.game_over) // game lost
- AllPlayersGone = TRUE;
+ game.all_players_gone = TRUE;
}
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
{
game_sp.game_over = TRUE;
- AllPlayersGone = TRUE;
+ game.all_players_gone = TRUE;
}
if (game_sp.game_over) // game lost
- AllPlayersGone = TRUE;
+ game.all_players_gone = TRUE;
}
else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
{
game_mm.game_over = TRUE;
- AllPlayersGone = TRUE;
+ game.all_players_gone = TRUE;
}
if (game_mm.game_over) // game lost
- AllPlayersGone = TRUE;
+ game.all_players_gone = TRUE;
}
}
KillPlayer(&stored_player[i]);
}
}
- else if (game.no_time_limit && !AllPlayersGone) // level w/o time limit
+ else if (game.no_time_limit && !game.all_players_gone)
{
game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
}
if (game.LevelSolved && !game.LevelSolved_GameEnd)
GameWon();
- if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
+ if (game.all_players_gone && !TAPE_IS_STOPPED(tape))
TapeStop();
if (game_status != GAME_MODE_PLAYING) // status might have changed
SetVideoFrameDelay(game_frame_delay_value);
+ // (de)activate virtual buttons depending on current game status
+ if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+ {
+ if (game.all_players_gone) // if no players there to be controlled anymore
+ SetOverlayActive(FALSE);
+ else if (!tape.playing) // if game continues after tape stopped playing
+ SetOverlayActive(TRUE);
+ }
+
#if 0
#if 0
// ---------- main game synchronization point ----------
if (tape.recording)
TapeRecordAction(tape_action);
+ // remember if game was played (especially after tape stopped playing)
+ if (!tape.playing && summarized_player_action)
+ game.GamePlayed = TRUE;
+
#if USE_NEW_PLAYER_ASSIGNMENTS
// !!! also map player actions in single player mode !!!
// if (game.team_mode)
DrawAllPlayers();
PlayAllPlayersSound();
- if (local_player->show_envelope != 0 && local_player->MovPos == 0)
+ if (local_player->show_envelope != 0 && (!local_player->active ||
+ local_player->MovPos == 0))
{
ShowEnvelope(local_player->show_envelope - EL_ENVELOPE_1);
{
ExitPlayer(player);
- if ((game.friends_still_needed == 0 ||
- IS_SP_ELEMENT(Feld[jx][jy])) &&
- AllPlayersGone)
+ if (game.players_still_needed == 0 &&
+ (game.friends_still_needed == 0 ||
+ IS_SP_ELEMENT(Feld[jx][jy])))
LevelSolved();
}
for (i = 0; i < MAX_PLAYERS; i++)
KillPlayer(&stored_player[i]);
}
- else if (game.no_time_limit && !AllPlayersGone) // level w/o time limit
+ else if (game.no_time_limit && !game.all_players_gone)
{
game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
RemovePlayer(player);
player->buried = TRUE;
- game.GameOver = TRUE;
+
+ if (game.all_players_gone)
+ game.GameOver = TRUE;
}
void RemovePlayer(struct PlayerInfo *player)
player->present = FALSE;
player->active = FALSE;
+ // required for some CE actions (even if the player is not active anymore)
+ player->MovPos = 0;
+
if (!ExplodeField[jx][jy])
StorePlayer[jx][jy] = 0;
found = TRUE;
if (!found)
- AllPlayersGone = TRUE;
+ {
+ game.all_players_gone = TRUE;
+ game.GameOver = TRUE;
+ }
- ExitX = ZX = jx;
- ExitY = ZY = jy;
+ game.exit_x = game.robot_wheel_x = jx;
+ game.exit_y = game.robot_wheel_y = jy;
}
void ExitPlayer(struct PlayerInfo *player)
if (game.players_still_needed > 0)
game.players_still_needed--;
-
- // also set if some players not yet gone, but not needed to solve level
- if (game.players_still_needed == 0)
- AllPlayersGone = TRUE;
}
static void setFieldForSnapping(int x, int y, int element, int direction)
if (element == EL_ROBOT_WHEEL)
{
Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE;
- ZX = x;
- ZY = y;
+ game.robot_wheel_x = x;
+ game.robot_wheel_y = y;
game.robot_wheel_active = TRUE;
TEST_DrawLevelField(x, y);
{
// closing door required in case of envelope style request dialogs
if (!skip_request)
+ {
+ // prevent short reactivation of overlay buttons while closing door
+ SetOverlayActive(FALSE);
+
CloseDoor(DOOR_CLOSE_1);
+ }
if (network.enabled)
SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER);
void RequestQuitGame(boolean ask_if_really_quit)
{
boolean quick_quit = (!ask_if_really_quit || level_editor_test_game);
- boolean skip_request = AllPlayersGone || quick_quit;
+ boolean skip_request = game.all_players_gone || quick_quit;
RequestQuitGameExt(skip_request, quick_quit,
"Do you really want to quit the game?");
if (game.request_active)
return;
+ // do not ask to play again if game was never actually played
+ if (!game.GamePlayed)
+ return;
+
if (!game_over)
{
last_game_over = FALSE;
boolean checkGameFailed(void)
{
- if (!AllPlayersGone)
- return FALSE;
-
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
return (game_em.game_over && !game_em.level_solved);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(game));
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(tape));
- SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZX));
- SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZY));
- SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitX));
- SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitY));
-
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(FrameCounter));
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeFrames));
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimePlayed));
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize));
- SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone));
-
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt));
SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2));