#include "files.h"
#include "tape.h"
#include "network.h"
+#include "anim.h"
/* DEBUG SETTINGS */
/* redraw game control buttons */
RedrawGameButtons();
- game_status = GAME_MODE_PSEUDO_PANEL;
+ SetGameStatus(GAME_MODE_PSEUDO_PANEL);
for (i = 0; i < NUM_GAME_PANEL_CONTROLS; i++)
{
redraw_mask |= REDRAW_DOOR_1;
}
- game_status = GAME_MODE_PLAYING;
+ SetGameStatus(GAME_MODE_PLAYING);
}
void UpdateAndDisplayGameControlValues()
for (i = 0; i < MAX_PLAYERS; i++)
game.snapshot.last_action[i] = 0;
game.snapshot.changed_action = FALSE;
+ game.snapshot.collected_item = FALSE;
game.snapshot.mode =
(strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
SNAPSHOT_MODE_EVERY_STEP :
strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
- SNAPSHOT_MODE_EVERY_MOVE : SNAPSHOT_MODE_OFF);
+ SNAPSHOT_MODE_EVERY_MOVE :
+ strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_COLLECT) ?
+ SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
}
int get_num_special_action(int element, int action_first, int action_last)
// required here to update video display before fading (FIX THIS)
DrawMaskedBorder(REDRAW_DOOR_2);
- game_status = GAME_MODE_PLAYING;
-
if (!game.restart_level)
CloseDoor(DOOR_CLOSE_1);
+ SetGameStatus(GAME_MODE_PLAYING);
+
/* needed if different viewport properties defined for playing */
ChangeViewportPropertiesIfNeeded();
if (CheckIfGlobalBorderHasChanged())
fade_mask = REDRAW_ALL;
- FadeOut(fade_mask);
+ FadeSoundsAndMusic();
- OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+ ExpireSoundLoops(TRUE);
+
+ FadeOut(fade_mask);
ClearField();
+ OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
DrawCompleteVideoDisplay();
InitGameEngine();
if (level_editor_test_game)
{
- game_status = GAME_MODE_MAIN;
+ SetGameStatus(GAME_MODE_MAIN);
DrawMainMenu();
if (!local_player->LevelSolved_SaveScore)
{
- game_status = GAME_MODE_MAIN;
+ SetGameStatus(GAME_MODE_MAIN);
DrawMainMenu();
if ((hi_pos = NewHiScore()) >= 0)
{
- game_status = GAME_MODE_SCORES;
+ SetGameStatus(GAME_MODE_SCORES);
DrawHallOfFame(hi_pos);
}
else
{
- game_status = GAME_MODE_MAIN;
+ SetGameStatus(GAME_MODE_MAIN);
if (raise_level)
{
void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
boolean center_screen, boolean quick_relocation)
{
+ unsigned int frame_delay_value_old = GetVideoFrameDelay();
boolean ffwd_delay = (tape.playing && tape.fast_forward);
boolean no_delay = (tape.warp_forward);
int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
int wait_delay_value = (no_delay ? 0 : frame_delay_value);
+ int new_scroll_x, new_scroll_y;
if (level.lazy_relocation && IN_VIS_FIELD(SCREENX(x), SCREENY(y)))
{
- RedrawPlayfield();
- }
- else if (quick_relocation)
- {
- if (!level.shifted_relocation || center_screen)
- {
- /* quick relocation (without scrolling), with centering of screen */
-
- scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left :
- x > SBX_Right + MIDPOSX ? SBX_Right :
- x - MIDPOSX);
-
- scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
- y > SBY_Lower + MIDPOSY ? SBY_Lower :
- y - MIDPOSY);
- }
- else
- {
- /* quick relocation (without scrolling), but do not center screen */
-
- int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left :
- old_x > SBX_Right + MIDPOSX ? SBX_Right :
- old_x - MIDPOSX);
+ /* case 1: quick relocation inside visible screen (without scrolling) */
- int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
- old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
- old_y - MIDPOSY);
+ RedrawPlayfield();
- int offset_x = x + (scroll_x - center_scroll_x);
- int offset_y = y + (scroll_y - center_scroll_y);
+ return;
+ }
- scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left :
- offset_x > SBX_Right + MIDPOSX ? SBX_Right :
- offset_x - MIDPOSX);
+ if (!level.shifted_relocation || center_screen)
+ {
+ /* relocation _with_ centering of screen */
- scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
- offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
- offset_y - MIDPOSY);
- }
+ new_scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left :
+ x > SBX_Right + MIDPOSX ? SBX_Right :
+ x - MIDPOSX);
- RedrawPlayfield();
+ new_scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
+ y > SBY_Lower + MIDPOSY ? SBY_Lower :
+ y - MIDPOSY);
}
else
{
- int scroll_xx, scroll_yy;
+ /* relocation _without_ centering of screen */
- if (!level.shifted_relocation || center_screen)
- {
- /* visible relocation (with scrolling), with centering of screen */
+ int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left :
+ old_x > SBX_Right + MIDPOSX ? SBX_Right :
+ old_x - MIDPOSX);
- scroll_xx = (x < SBX_Left + MIDPOSX ? SBX_Left :
- x > SBX_Right + MIDPOSX ? SBX_Right :
- x - MIDPOSX);
+ int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+ old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+ old_y - MIDPOSY);
- scroll_yy = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
- y > SBY_Lower + MIDPOSY ? SBY_Lower :
- y - MIDPOSY);
- }
- else
- {
- /* visible relocation (with scrolling), but do not center screen */
+ int offset_x = x + (scroll_x - center_scroll_x);
+ int offset_y = y + (scroll_y - center_scroll_y);
- int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left :
- old_x > SBX_Right + MIDPOSX ? SBX_Right :
- old_x - MIDPOSX);
+ new_scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left :
+ offset_x > SBX_Right + MIDPOSX ? SBX_Right :
+ offset_x - MIDPOSX);
- int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
- old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
- old_y - MIDPOSY);
+ new_scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+ offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+ offset_y - MIDPOSY);
+ }
- int offset_x = x + (scroll_x - center_scroll_x);
- int offset_y = y + (scroll_y - center_scroll_y);
+ if (quick_relocation)
+ {
+ /* case 2: quick relocation (redraw without visible scrolling) */
- scroll_xx = (offset_x < SBX_Left + MIDPOSX ? SBX_Left :
- offset_x > SBX_Right + MIDPOSX ? SBX_Right :
- offset_x - MIDPOSX);
+ scroll_x = new_scroll_x;
+ scroll_y = new_scroll_y;
- scroll_yy = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
- offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
- offset_y - MIDPOSY);
- }
+ RedrawPlayfield();
- ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
+ return;
+ }
- while (scroll_x != scroll_xx || scroll_y != scroll_yy)
- {
- int dx = 0, dy = 0;
- int fx = FX, fy = FY;
+ /* case 3: visible relocation (with scrolling to new position) */
- dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
- dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
+ ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
- if (dx == 0 && dy == 0) /* no scrolling needed at all */
- break;
+ SetVideoFrameDelay(wait_delay_value);
- scroll_x -= dx;
- scroll_y -= dy;
+ while (scroll_x != new_scroll_x || scroll_y != new_scroll_y)
+ {
+ int dx = 0, dy = 0;
+ int fx = FX, fy = FY;
- fx += dx * TILEX / 2;
- fy += dy * TILEY / 2;
+ 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);
- ScrollLevel(dx, dy);
- DrawAllPlayers();
+ if (dx == 0 && dy == 0) /* no scrolling needed at all */
+ break;
- /* scroll in two steps of half tile size to make things smoother */
- BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
- Delay(wait_delay_value);
+ scroll_x -= dx;
+ scroll_y -= dy;
- /* scroll second step to align at full tile size */
- BackToFront();
- Delay(wait_delay_value);
- }
+ fx += dx * TILEX / 2;
+ fy += dy * TILEY / 2;
+ ScrollLevel(dx, dy);
DrawAllPlayers();
- BackToFront();
- Delay(wait_delay_value);
+
+ /* scroll in two steps of half tile size to make things smoother */
+ BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
+
+ /* scroll second step to align at full tile size */
+ BlitScreenToBitmap(window);
}
+
+ DrawAllPlayers();
+ BackToFront();
+
+ SetVideoFrameDelay(frame_delay_value_old);
}
void RelocatePlayer(int jx, int jy, int el_player_raw)
DrawPlayer(player);
- BackToFront();
- Delay(wait_delay_value);
+ BackToFront_WithFrameDelay(wait_delay_value);
}
DrawPlayer(player); /* needed here only to cleanup last field */
{
local_player->gems_still_needed = action_arg_number_new;
+ game.snapshot.collected_item = TRUE;
+
game_panel_controls[GAME_PANEL_GEMS].value =
local_player->gems_still_needed;
void GameActions()
{
+#if 0
static unsigned int game_frame_delay = 0;
+#endif
unsigned int game_frame_delay_value;
byte *recorded_player_action;
byte summarized_player_action = 0;
if (tape.playing && tape.warp_forward && !tape.pausing)
game_frame_delay_value = 0;
+ SetVideoFrameDelay(game_frame_delay_value);
+
+#if 0
#if 0
/* ---------- main game synchronization point ---------- */
/* ---------- main game synchronization point ---------- */
WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
+#endif
#endif
if (network_playing && !network_player_action_received)
SendToServer_MovePlayer(summarized_player_action);
#endif
+ // summarize all actions at local players mapped input device position
+ // (this allows using different input devices in single player mode)
if (!options.network && !game.team_mode)
- local_player->effective_action = summarized_player_action;
+ stored_player[map_player_action[local_player->index_nr]].effective_action =
+ summarized_player_action;
if (tape.recording &&
setup.team_mode &&
#if USE_NEW_PLAYER_ASSIGNMENTS
// !!! also map player actions in single player mode !!!
// if (game.team_mode)
+ if (1)
{
byte mapped_action[MAX_PLAYERS];
AdvanceFrameAndPlayerCounters(player->index_nr);
DrawAllPlayers();
- BackToFront();
+ BackToFront_WithFrameDelay(0);
}
player->move_delay_value = original_move_delay_value;
if (local_player->gems_still_needed < 0)
local_player->gems_still_needed = 0;
+ game.snapshot.collected_item = TRUE;
+
game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
DisplayGameControlValues();
SCAN_PLAYFIELD(xx, yy)
{
if (Feld[xx][yy] == EL_SP_DISK_YELLOW)
+ {
Bang(xx, yy);
+ }
else if (Feld[xx][yy] == EL_SP_TERMINAL)
+ {
Feld[xx][yy] = EL_SP_TERMINAL_ACTIVE;
+
+ ResetGfxAnimation(xx, yy);
+ TEST_DrawLevelField(xx, yy);
+ }
}
}
else if (IS_BELT_SWITCH(element))
#endif
{
if (quick_quit)
- {
FadeSkipNextFadeIn();
- game_status = GAME_MODE_MAIN;
+ SetGameStatus(GAME_MODE_MAIN);
- DrawMainMenu();
- }
- else
- {
- game_status = GAME_MODE_MAIN;
-
- DrawMainMenu();
- }
+ DrawMainMenu();
}
}
else /* continue playing the game */
(initial_snapshot ||
(game.snapshot.mode == SNAPSHOT_MODE_EVERY_STEP) ||
(game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE &&
- game.snapshot.changed_action));
+ game.snapshot.changed_action) ||
+ (game.snapshot.mode == SNAPSHOT_MODE_EVERY_COLLECT &&
+ game.snapshot.collected_item));
game.snapshot.changed_action = FALSE;
+ game.snapshot.collected_item = FALSE;
if (game.snapshot.mode == SNAPSHOT_MODE_OFF ||
tape.quick_resume ||
} gamebutton_info[NUM_GAME_BUTTONS] =
{
{
- IMG_GAME_BUTTON_GFX_STOP, &game.button.stop,
+ IMG_GFX_GAME_BUTTON_STOP, &game.button.stop,
GAME_CTRL_ID_STOP, "stop game"
},
{
- IMG_GAME_BUTTON_GFX_PAUSE, &game.button.pause,
+ IMG_GFX_GAME_BUTTON_PAUSE, &game.button.pause,
GAME_CTRL_ID_PAUSE, "pause game"
},
{
- IMG_GAME_BUTTON_GFX_PLAY, &game.button.play,
+ IMG_GFX_GAME_BUTTON_PLAY, &game.button.play,
GAME_CTRL_ID_PLAY, "play game"
},
{
- IMG_GAME_BUTTON_GFX_UNDO, &game.button.undo,
+ IMG_GFX_GAME_BUTTON_UNDO, &game.button.undo,
GAME_CTRL_ID_UNDO, "undo step"
},
{
- IMG_GAME_BUTTON_GFX_REDO, &game.button.redo,
+ IMG_GFX_GAME_BUTTON_REDO, &game.button.redo,
GAME_CTRL_ID_REDO, "redo step"
},
{
- IMG_GAME_BUTTON_GFX_SAVE, &game.button.save,
+ IMG_GFX_GAME_BUTTON_SAVE, &game.button.save,
GAME_CTRL_ID_SAVE, "save game"
},
{
- IMG_GAME_BUTTON_GFX_PAUSE2, &game.button.pause2,
+ IMG_GFX_GAME_BUTTON_PAUSE2, &game.button.pause2,
GAME_CTRL_ID_PAUSE2, "pause game"
},
{
- IMG_GAME_BUTTON_GFX_LOAD, &game.button.load,
+ IMG_GFX_GAME_BUTTON_LOAD, &game.button.load,
GAME_CTRL_ID_LOAD, "load game"
},
{
- IMG_GAME_BUTTON_GFX_SOUND_MUSIC, &game.button.sound_music,
+ IMG_GFX_GAME_BUTTON_SOUND_MUSIC, &game.button.sound_music,
SOUND_CTRL_ID_MUSIC, "background music on/off"
},
{
- IMG_GAME_BUTTON_GFX_SOUND_LOOPS, &game.button.sound_loops,
+ IMG_GFX_GAME_BUTTON_SOUND_LOOPS, &game.button.sound_loops,
SOUND_CTRL_ID_LOOPS, "sound loops on/off"
},
{
- IMG_GAME_BUTTON_GFX_SOUND_SIMPLE, &game.button.sound_simple,
+ IMG_GFX_GAME_BUTTON_SOUND_SIMPLE, &game.button.sound_simple,
SOUND_CTRL_ID_SIMPLE, "normal sounds on/off"
}
};
static void HandleGameButtonsExt(int id, int button)
{
+ static boolean game_undo_executed = FALSE;
int steps = BUTTON_STEPSIZE(button);
boolean handle_game_buttons =
(game_status == GAME_MODE_PLAYING ||
}
else
TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
+ game_undo_executed = FALSE;
+
break;
case GAME_CTRL_ID_PLAY:
break;
case GAME_CTRL_ID_UNDO:
+ // Important: When using "save snapshot when collecting an item" mode,
+ // load last (current) snapshot for first "undo" after pressing "pause"
+ // (else the last-but-one snapshot would be loaded, because the snapshot
+ // pointer already points to the last snapshot when pressing "pause",
+ // which is fine for "every step/move" mode, but not for "every collect")
+ if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_COLLECT &&
+ !game_undo_executed)
+ steps--;
+
+ game_undo_executed = TRUE;
+
GameUndo(steps);
break;