X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=b68f6be1e470eb6295ba830bc6f8c2611fc4f6e2;hp=71740a8f4931186bbcd5a08847518cef733528d5;hb=719b72db403d64e84dc9c90388f7e6fd43a77d7b;hpb=b165e8970f5f3d8f9972433960785f31b9a11723 diff --git a/src/game.c b/src/game.c index 71740a8f..b68f6be1 100644 --- a/src/game.c +++ b/src/game.c @@ -3358,14 +3358,15 @@ void InitGame(void) 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(); @@ -3401,6 +3402,7 @@ void InitGame(void) player->action = 0; player->effective_action = 0; player->programmed_action = 0; + player->snap_action = 0; player->mouse_action.lx = 0; player->mouse_action.ly = 0; @@ -3566,6 +3568,8 @@ void InitGame(void) game.LevelSolved = FALSE; game.GameOver = FALSE; + game.GamePlayed = !tape.playing; + game.LevelSolved_GameWon = FALSE; game.LevelSolved_GameEnd = FALSE; game.LevelSolved_SaveTape = FALSE; @@ -3735,6 +3739,19 @@ void InitGame(void) 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; @@ -4501,7 +4518,7 @@ 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; @@ -5256,11 +5273,8 @@ static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, while (scroll_x != new_scroll_x || scroll_y != new_scroll_y) { - int dx = 0, dy = 0; - int fx = FX, fy = FY; - - dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0); - dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0); + int dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0); + int dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0); if (dx == 0 && dy == 0) // no scrolling needed at all break; @@ -5268,14 +5282,19 @@ static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, scroll_x -= dx; scroll_y -= dy; - fx += dx * TILEX / 2; - fy += dy * TILEY / 2; + // set values for horizontal/vertical screen scrolling (half tile size) + int dir_x = (dx != 0 ? MV_HORIZONTAL : 0); + int dir_y = (dy != 0 ? MV_VERTICAL : 0); + int pos_x = dx * TILEX / 2; + int pos_y = dy * TILEY / 2; + int fx = getFieldbufferOffsetX_RND(dir_x, pos_x); + int fy = getFieldbufferOffsetY_RND(dir_y, pos_y); 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); + BlitScreenToBitmapExt_RND(window, fx, fy); // scroll second step to align at full tile size BlitScreenToBitmap(window); @@ -11042,10 +11061,7 @@ static void CheckSingleStepMode(struct PlayerInfo *player) if (!player->is_moving && !player->is_pushing && !player->is_dropping_pressed) - { TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); - SnapField(player, 0, 0); // stop snapping - } } CheckSaveEngineSnapshot(player); @@ -11483,6 +11499,10 @@ static void GameActionsExt(void) 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) @@ -11976,7 +11996,8 @@ void GameActions_RND(void) element == EL_DC_MAGIC_WALL_FULL || element == EL_DC_MAGIC_WALL_ACTIVE || element == EL_DC_MAGIC_WALL_EMPTYING) && - ABS(x-jx) + ABS(y-jy) < ABS(magic_wall_x-jx) + ABS(magic_wall_y-jy)) + ABS(x - jx) + ABS(y - jy) < + ABS(magic_wall_x - jx) + ABS(magic_wall_y - jy)) { magic_wall_x = x; magic_wall_y = y; @@ -12158,7 +12179,8 @@ void GameActions_RND(void) 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); @@ -12493,7 +12515,6 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) game.centered_player_nr == -1)) { int old_scroll_x = scroll_x, old_scroll_y = scroll_y; - int offset = game.scroll_delay_value; if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy))) { @@ -12505,15 +12526,19 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) } else { + int offset = game.scroll_delay_value; + if (jx != old_jx) // player has moved horizontally { - 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); + int offset_x = offset * (player->MovDir == MV_LEFT ? +1 : -1); + int new_scroll_x = jx - MIDPOSX + offset_x; + + if ((player->MovDir == MV_LEFT && scroll_x > new_scroll_x) || + (player->MovDir == MV_RIGHT && scroll_x < new_scroll_x)) + scroll_x = new_scroll_x; // 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); + scroll_x = MIN(MAX(SBX_Left, scroll_x), SBX_Right); // don't scroll more than one field at a time scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x); @@ -12525,13 +12550,15 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) } else // player has moved vertically { - 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); + int offset_y = offset * (player->MovDir == MV_UP ? +1 : -1); + int new_scroll_y = jy - MIDPOSY + offset_y; + + if ((player->MovDir == MV_UP && scroll_y > new_scroll_y) || + (player->MovDir == MV_DOWN && scroll_y < new_scroll_y)) + scroll_y = new_scroll_y; // 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); + scroll_y = MIN(MAX(SBY_Upper, scroll_y), SBY_Lower); // don't scroll more than one field at a time scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y); @@ -13445,6 +13472,9 @@ 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; @@ -14967,7 +14997,12 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message) { // 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); @@ -15032,6 +15067,10 @@ void CheckGameOver(void) 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;