return element;
}
-static void IncrementPlayerSokobanFieldsNeeded(void)
+static void IncrementSokobanFieldsNeeded(void)
{
if (level.sb_fields_needed)
- local_player->sokoban_fields_still_needed++;
+ game.sokoban_fields_still_needed++;
}
-static void IncrementPlayerSokobanObjectsNeeded(void)
+static void IncrementSokobanObjectsNeeded(void)
{
if (level.sb_objects_needed)
- local_player->sokoban_objects_still_needed++;
+ game.sokoban_objects_still_needed++;
}
-static void DecrementPlayerSokobanFieldsNeeded(void)
+static void DecrementSokobanFieldsNeeded(void)
{
- if (local_player->sokoban_fields_still_needed > 0)
- local_player->sokoban_fields_still_needed--;
+ if (game.sokoban_fields_still_needed > 0)
+ game.sokoban_fields_still_needed--;
}
-static void DecrementPlayerSokobanObjectsNeeded(void)
+static void DecrementSokobanObjectsNeeded(void)
{
- if (local_player->sokoban_objects_still_needed > 0)
- local_player->sokoban_objects_still_needed--;
+ if (game.sokoban_objects_still_needed > 0)
+ game.sokoban_objects_still_needed--;
}
static void InitPlayerField(int x, int y, int element, boolean init_game)
break;
case EL_SOKOBAN_FIELD_EMPTY:
- IncrementPlayerSokobanFieldsNeeded();
+ IncrementSokobanFieldsNeeded();
break;
case EL_SOKOBAN_OBJECT:
- IncrementPlayerSokobanObjectsNeeded();
+ IncrementSokobanObjectsNeeded();
break;
case EL_STONEBLOCK:
break;
case EL_LAMP:
- local_player->lights_still_needed++;
+ game.lights_still_needed++;
break;
case EL_PENGUIN:
- local_player->friends_still_needed++;
+ game.friends_still_needed++;
break;
case EL_PIG:
level.native_sp_level->game_sp->score :
level.game_engine_type == GAME_ENGINE_TYPE_MM ?
game_mm.score :
- local_player->score);
+ game.score);
int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
level.native_em_level->lev->required :
level.game_engine_type == GAME_ENGINE_TYPE_SP ?
level.native_sp_level->game_sp->infotrons_still_needed :
level.game_engine_type == GAME_ENGINE_TYPE_MM ?
game_mm.kettles_still_needed :
- local_player->gems_still_needed);
+ game.gems_still_needed);
int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
level.native_em_level->lev->required > 0 :
level.game_engine_type == GAME_ENGINE_TYPE_SP ?
level.game_engine_type == GAME_ENGINE_TYPE_MM ?
game_mm.kettles_still_needed > 0 ||
game_mm.lights_still_needed > 0 :
- local_player->gems_still_needed > 0 ||
- local_player->sokoban_fields_still_needed > 0 ||
- local_player->sokoban_objects_still_needed > 0 ||
- local_player->lights_still_needed > 0);
+ game.gems_still_needed > 0 ||
+ game.sokoban_fields_still_needed > 0 ||
+ game.sokoban_objects_still_needed > 0 ||
+ game.lights_still_needed > 0);
int health = (game.LevelSolved ?
game.LevelSolved_CountingHealth :
level.game_engine_type == GAME_ENGINE_TYPE_MM ?
MM_HEALTH(game_mm.laser_overload_value) :
- local_player->health);
+ game.health);
UpdatePlayfieldElementCount();
(local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
game_panel_controls[GAME_PANEL_PENGUINS].value =
- local_player->friends_still_needed;
+ game.friends_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
- local_player->sokoban_objects_still_needed;
+ game.sokoban_objects_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
- local_player->sokoban_fields_still_needed;
+ game.sokoban_fields_still_needed;
game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
(game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
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();
player->killed = FALSE;
player->reanimated = FALSE;
+ player->buried = FALSE;
player->action = 0;
player->effective_action = 0;
player->effective_mouse_action.button = 0;
player->effective_mouse_action.button_hint = 0;
- player->score = 0;
- player->score_final = 0;
-
- player->health = MAX_HEALTH;
- player->health_final = MAX_HEALTH;
-
- player->gems_still_needed = level.gems_needed;
- player->sokoban_fields_still_needed = 0;
- player->sokoban_objects_still_needed = 0;
- player->lights_still_needed = 0;
- player->players_still_needed = 0;
- player->friends_still_needed = 0;
-
for (j = 0; j < MAX_NUM_KEYS; j++)
player->key[j] = FALSE;
DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
SnapField(player, 0, 0);
- player->GameOver = FALSE;
-
map_player_action[i] = i;
}
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.switchgate_pos = 0;
game.wind_direction = level.wind_direction_initial;
+ game.score = 0;
+ game.score_final = 0;
+
+ game.health = MAX_HEALTH;
+ game.health_final = MAX_HEALTH;
+
+ game.gems_still_needed = level.gems_needed;
+ game.sokoban_fields_still_needed = 0;
+ game.sokoban_objects_still_needed = 0;
+ game.lights_still_needed = 0;
+ game.players_still_needed = 0;
+ game.friends_still_needed = 0;
+
game.lenses_time_left = 0;
game.magnify_time_left = 0;
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;
for (i = 0; i < MAX_PLAYERS; i++)
if (stored_player[i].active)
- local_player->players_still_needed++;
+ game.players_still_needed++;
if (level.solved_by_one_player)
- local_player->players_still_needed = 1;
+ game.players_still_needed = 1;
// when recording the game, store which players take part in the game
if (tape.recording)
static void LevelSolved(void)
{
if (level.game_engine_type == GAME_ENGINE_TYPE_RND &&
- local_player->players_still_needed > 0)
+ game.players_still_needed > 0)
return;
game.LevelSolved = TRUE;
+ game.GameOver = TRUE;
- local_player->GameOver = TRUE;
-
- local_player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
- level.native_em_level->lev->score :
- level.game_engine_type == GAME_ENGINE_TYPE_MM ?
- game_mm.score :
- local_player->score);
- local_player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
- MM_HEALTH(game_mm.laser_overload_value) :
- local_player->health);
+ game.score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+ level.native_em_level->lev->score :
+ level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+ game_mm.score :
+ game.score);
+ game.health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+ MM_HEALTH(game_mm.laser_overload_value) :
+ game.health);
game.LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : TimeLeft);
- game.LevelSolved_CountingScore = local_player->score_final;
- game.LevelSolved_CountingHealth = local_player->health_final;
+ game.LevelSolved_CountingScore = game.score_final;
+ game.LevelSolved_CountingHealth = game.health_final;
}
void GameWon(void)
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;
game_over_delay_3 = game_over_delay_value_3;
time = time_final = (game.no_time_limit ? TimePlayed : TimeLeft);
- score = score_final = local_player->score_final;
- health = health_final = local_player->health_final;
+ score = score_final = game.score_final;
+ health = health_final = game.health_final;
if (level.score[SC_TIME_BONUS] > 0)
{
game_over_delay_2 = game_over_delay_value_2;
}
- local_player->score_final = score_final;
- local_player->health_final = health_final;
+ game.score_final = score_final;
+ game.health_final = health_final;
}
if (level_editor_test_game)
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++)
LoadScore(level_nr);
if (strEqual(setup.player_name, EMPTY_PLAYER_NAME) ||
- local_player->score_final < highscore[MAX_SCORE_ENTRIES - 1].Score)
+ game.score_final < highscore[MAX_SCORE_ENTRIES - 1].Score)
return -1;
- for (k = 0; k < MAX_SCORE_ENTRIES; k++)
+ for (k = 0; k < MAX_SCORE_ENTRIES; k++)
{
- if (local_player->score_final > highscore[k].Score)
+ if (game.score_final > highscore[k].Score)
{
// player has made it to the hall of fame
strncpy(highscore[k].Name, setup.player_name, MAX_PLAYER_NAME_LEN);
highscore[k].Name[MAX_PLAYER_NAME_LEN] = '\0';
- highscore[k].Score = local_player->score_final;
+ highscore[k].Score = game.score_final;
position = k;
break;
int enter_side = enter_side_horiz | enter_side_vert;
int leave_side = leave_side_horiz | leave_side_vert;
- if (player->GameOver) // do not reanimate dead player
+ if (player->buried) // do not reanimate dead player
return;
if (!player_relocated) // no need to relocate the player
{
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
{
if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
DrawGraphicThruMask(SCREENX(newx),SCREENY(newy), el2img(element), 0);
- local_player->friends_still_needed--;
- if (!local_player->friends_still_needed &&
- !local_player->GameOver && AllPlayersGone)
+ game.friends_still_needed--;
+ if (!game.friends_still_needed &&
+ !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;
}
}
static void CheckExit(int x, int y)
{
- if (local_player->gems_still_needed > 0 ||
- local_player->sokoban_fields_still_needed > 0 ||
- local_player->sokoban_objects_still_needed > 0 ||
- local_player->lights_still_needed > 0)
+ if (game.gems_still_needed > 0 ||
+ game.sokoban_fields_still_needed > 0 ||
+ game.sokoban_objects_still_needed > 0 ||
+ game.lights_still_needed > 0)
{
int element = Feld[x][y];
int graphic = el2img(element);
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;
static void CheckExitEM(int x, int y)
{
- if (local_player->gems_still_needed > 0 ||
- local_player->sokoban_fields_still_needed > 0 ||
- local_player->sokoban_objects_still_needed > 0 ||
- local_player->lights_still_needed > 0)
+ if (game.gems_still_needed > 0 ||
+ game.sokoban_fields_still_needed > 0 ||
+ game.sokoban_objects_still_needed > 0 ||
+ game.lights_still_needed > 0)
{
int element = Feld[x][y];
int graphic = el2img(element);
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;
static void CheckExitSteel(int x, int y)
{
- if (local_player->gems_still_needed > 0 ||
- local_player->sokoban_fields_still_needed > 0 ||
- local_player->sokoban_objects_still_needed > 0 ||
- local_player->lights_still_needed > 0)
+ if (game.gems_still_needed > 0 ||
+ game.sokoban_fields_still_needed > 0 ||
+ game.sokoban_objects_still_needed > 0 ||
+ game.lights_still_needed > 0)
{
int element = Feld[x][y];
int graphic = el2img(element);
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;
static void CheckExitSteelEM(int x, int y)
{
- if (local_player->gems_still_needed > 0 ||
- local_player->sokoban_fields_still_needed > 0 ||
- local_player->sokoban_objects_still_needed > 0 ||
- local_player->lights_still_needed > 0)
+ if (game.gems_still_needed > 0 ||
+ game.sokoban_fields_still_needed > 0 ||
+ game.sokoban_objects_still_needed > 0 ||
+ game.lights_still_needed > 0)
{
int element = Feld[x][y];
int graphic = el2img(element);
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;
static void CheckExitSP(int x, int y)
{
- if (local_player->gems_still_needed > 0)
+ if (game.gems_still_needed > 0)
{
int element = Feld[x][y];
int graphic = el2img(element);
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;
action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CE_DELAY_VALUE(change) :
action_arg == CA_ARG_NUMBER_LEVEL_TIME ? level_time_value :
- action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? local_player->gems_still_needed :
- action_arg == CA_ARG_NUMBER_LEVEL_SCORE ? local_player->score :
+ action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? game.gems_still_needed :
+ action_arg == CA_ARG_NUMBER_LEVEL_SCORE ? game.score :
action_arg == CA_ARG_ELEMENT_CV_TARGET ? GET_NEW_CE_VALUE(target_element):
action_arg == CA_ARG_ELEMENT_CV_TRIGGER ? change->actual_trigger_ce_value:
action_arg == CA_ARG_ELEMENT_CV_ACTION ? GET_NEW_CE_VALUE(action_element):
-1);
int action_arg_number_old =
- (action_type == CA_SET_LEVEL_GEMS ? local_player->gems_still_needed :
+ (action_type == CA_SET_LEVEL_GEMS ? game.gems_still_needed :
action_type == CA_SET_LEVEL_TIME ? TimeLeft :
- action_type == CA_SET_LEVEL_SCORE ? local_player->score :
+ action_type == CA_SET_LEVEL_SCORE ? game.score :
action_type == CA_SET_CE_VALUE ? CustomValue[x][y] :
action_type == CA_SET_CE_SCORE ? ei->collect_score :
0);
case CA_SET_LEVEL_SCORE:
{
- local_player->score = action_arg_number_new;
+ game.score = action_arg_number_new;
- game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
+ game_panel_controls[GAME_PANEL_SCORE].value = game.score;
DisplayGameControlValues();
case CA_SET_LEVEL_GEMS:
{
- local_player->gems_still_needed = action_arg_number_new;
+ game.gems_still_needed = action_arg_number_new;
game.snapshot.collected_item = TRUE;
- game_panel_controls[GAME_PANEL_GEMS].value =
- local_player->gems_still_needed;
+ game_panel_controls[GAME_PANEL_GEMS].value = game.gems_still_needed;
DisplayGameControlValues();
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 ((local_player->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;
PlayLevelSoundElementAction(jx, jy, player->artwork_element, ACTION_DYING);
PlayLevelSound(jx, jy, SND_GAME_LOSING);
- player->GameOver = TRUE;
RemovePlayer(player);
+
+ player->buried = 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)
DrawPlayer(player); // needed here only to cleanup last field
RemovePlayer(player);
- if (local_player->players_still_needed > 0)
- local_player->players_still_needed--;
-
- // also set if some players not yet gone, but not needed to solve level
- if (local_player->players_still_needed == 0)
- AllPlayersGone = TRUE;
+ if (game.players_still_needed > 0)
+ game.players_still_needed--;
}
static void setFieldForSnapping(int x, int y, int element, int direction)
}
else if (collect_count > 0)
{
- local_player->gems_still_needed -= collect_count;
- if (local_player->gems_still_needed < 0)
- local_player->gems_still_needed = 0;
+ game.gems_still_needed -= collect_count;
+ if (game.gems_still_needed < 0)
+ game.gems_still_needed = 0;
game.snapshot.collected_item = TRUE;
- game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
+ game_panel_controls[GAME_PANEL_GEMS].value = game.gems_still_needed;
DisplayGameControlValues();
}
{
Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
- IncrementPlayerSokobanFieldsNeeded();
- IncrementPlayerSokobanObjectsNeeded();
+ IncrementSokobanFieldsNeeded();
+ IncrementSokobanObjectsNeeded();
}
if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY)
{
Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY;
- DecrementPlayerSokobanFieldsNeeded();
- DecrementPlayerSokobanObjectsNeeded();
+ DecrementSokobanFieldsNeeded();
+ DecrementSokobanObjectsNeeded();
// sokoban object was pushed from empty field to sokoban field
if (Back[x][y] == EL_EMPTY)
ACTION_FILLING);
if (sokoban_task_solved &&
- local_player->sokoban_fields_still_needed == 0 &&
- local_player->sokoban_objects_still_needed == 0 &&
+ game.sokoban_fields_still_needed == 0 &&
+ game.sokoban_objects_still_needed == 0 &&
(game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
{
- local_player->players_still_needed = 0;
+ game.players_still_needed = 0;
LevelSolved();
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);
else if (element == EL_LAMP)
{
Feld[x][y] = EL_LAMP_ACTIVE;
- local_player->lights_still_needed--;
+ game.lights_still_needed--;
ResetGfxAnimation(x, y);
TEST_DrawLevelField(x, y);
void RaiseScore(int value)
{
- local_player->score += value;
+ game.score += value;
- game_panel_controls[GAME_PANEL_SCORE].value = local_player->score;
+ game_panel_controls[GAME_PANEL_SCORE].value = game.score;
DisplayGameControlValues();
}
{
// 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)
else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
return (game_mm.game_over && !game_mm.level_solved);
else // GAME_ENGINE_TYPE_RND
- return (local_player->GameOver && !game.LevelSolved);
+ return (game.GameOver && !game.LevelSolved);
}
boolean checkGameEnded(void)
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));