From c4dd9e14b72b528e82bc018fe2fa76b784221584 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 14 Mar 2006 01:42:11 +0100 Subject: [PATCH] rnd-20060314-1-src * added player focus switching to level tape recording and re-playing --- ChangeLog | 3 + src/conftime.h | 2 +- src/engines.h | 5 + src/events.c | 11 +- src/game.c | 119 +++++++++++++++++++++- src/game.h | 219 +++++++++++++++++++++++++++++++--------- src/game_em/display.h | 3 + src/game_em/graphics.c | 51 +++++----- src/game_em/synchro_1.c | 6 +- src/libgame/system.h | 10 ++ src/main.c | 1 + src/main.h | 203 +------------------------------------ src/screens.c | 8 ++ src/tape.c | 37 ++++++- src/tape.h | 44 +++++++- src/tools.c | 2 + src/tools.h | 1 + 17 files changed, 441 insertions(+), 284 deletions(-) diff --git a/ChangeLog b/ChangeLog index 51d4a414..817ca24a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2006-03-14 + * added player focus switching to level tape recording and re-playing + 2006-03-13 * fixed some bugs in player focus switching in EMC and RND game engine diff --git a/src/conftime.h b/src/conftime.h index f69b18c9..46e25f2b 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2006-03-13 02:03]" +#define COMPILE_DATE_STRING "[2006-03-14 01:37]" diff --git a/src/engines.h b/src/engines.h index 55352e0f..e64f0f22 100644 --- a/src/engines.h +++ b/src/engines.h @@ -21,14 +21,19 @@ /* functions and definitions exported from main program to game_em */ /* ========================================================================= */ +#include "game.h" + extern void SetBitmaps_EM(Bitmap **); extern void UpdateEngineValues(int, int); extern void DrawAllGameValues(int, int, int, int, int); +#if 0 extern void setCenteredPlayerNr_EM(int); extern int getCenteredPlayerNr_EM(); extern void setSetCenteredPlayer_EM(boolean); extern boolean getSetCenteredPlayer_EM(); +#endif + extern int getNumActivePlayers_EM(); extern int getGameFrameDelay_EM(int); diff --git a/src/events.c b/src/events.c index e8f20556..49d3b1a0 100644 --- a/src/events.c +++ b/src/events.c @@ -544,10 +544,7 @@ static void HandleKeysSpecial(Key key) { #ifdef DEBUG if (is_string_suffix(cheat_input, ".q")) - for (i = 0; i < MAX_INVENTORY_SIZE; i++) - if (local_player->inventory_size < MAX_INVENTORY_SIZE) - local_player->inventory_element[local_player->inventory_size++] = - EL_DYNAMITE; + DEBUG_SetMaximumDynamite(); #endif } else if (game_status == GAME_MODE_EDITOR) @@ -713,6 +710,12 @@ void HandleKey(Key key, int key_status) { game.centered_player_nr_next = centered_player_nr_next; game.set_centered_player = TRUE; + + if (tape.recording) + { + tape.centered_player_nr_next = game.centered_player_nr_next; + tape.set_centered_player = TRUE; + } } } diff --git a/src/game.c b/src/game.c index 18432748..f23555b3 100644 --- a/src/game.c +++ b/src/game.c @@ -333,6 +333,32 @@ static void PlayLevelMusic(); static void MapGameButtons(); static void HandleGameButtons(struct GadgetInfo *); +int AmoebeNachbarNr(int, int); +void AmoebeUmwandeln(int, int); +void ContinueMoving(int, int); +void Bang(int, int); +void InitMovDir(int, int); +void InitAmoebaNr(int, int); +int NewHiScore(void); + +void TestIfGoodThingHitsBadThing(int, int, int); +void TestIfBadThingHitsGoodThing(int, int, int); +void TestIfPlayerTouchesBadThing(int, int); +void TestIfPlayerRunsIntoBadThing(int, int, int); +void TestIfBadThingTouchesPlayer(int, int); +void TestIfBadThingRunsIntoPlayer(int, int, int); +void TestIfFriendTouchesBadThing(int, int); +void TestIfBadThingTouchesFriend(int, int); +void TestIfBadThingTouchesOtherBadThing(int, int); + +void KillPlayer(struct PlayerInfo *); +void BuryPlayer(struct PlayerInfo *); +void RemovePlayer(struct PlayerInfo *); + +boolean SnapField(struct PlayerInfo *, int, int); +boolean DropElement(struct PlayerInfo *); + + static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; @@ -690,6 +716,18 @@ static int playfield_scan_delta_y = 1; (x) >= 0 && (x) <= lev_fieldx - 1; \ (x) += playfield_scan_delta_x) \ +#ifdef DEBUG +void DEBUG_SetMaximumDynamite() +{ + int i; + + for (i = 0; i < MAX_INVENTORY_SIZE; i++) + if (local_player->inventory_size < MAX_INVENTORY_SIZE) + local_player->inventory_element[local_player->inventory_size++] = + EL_DYNAMITE; +} +#endif + static void InitPlayfieldScanModeVars() { if (game.use_reverse_scan_direction) @@ -8847,10 +8885,12 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting) /* special case for sleeping Murphy when leaning against non-free tile */ if (!IN_LEV_FIELD(player->jx - 1, player->jy) || - Feld[player->jx - 1][player->jy] != EL_EMPTY) + (Feld[player->jx - 1][player->jy] != EL_EMPTY && + !IS_MOVING(player->jx - 1, player->jy))) move_dir = MV_LEFT; else if (!IN_LEV_FIELD(player->jx + 1, player->jy) || - Feld[player->jx + 1][player->jy] != EL_EMPTY) + (Feld[player->jx + 1][player->jy] != EL_EMPTY && + !IS_MOVING(player->jx + 1, player->jy))) move_dir = MV_RIGHT; else player->is_sleeping = FALSE; @@ -9087,6 +9127,7 @@ void GameActions() InitPlayfieldScanModeVars(); +#if 0 if (game.set_centered_player) { boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND(); @@ -9151,6 +9192,7 @@ void GameActions() game.set_centered_player = FALSE; } +#endif #if USE_ONE_MORE_CHANGE_PER_FRAME if (game.engine_version >= VERSION_IDENT(3,2,0,7)) @@ -9185,6 +9227,79 @@ void GameActions() recorded_player_action = (tape.playing ? TapePlayAction() : NULL); +#if 1 + if (tape.set_centered_player) + { + game.centered_player_nr_next = tape.centered_player_nr_next; + game.set_centered_player = TRUE; + } + + if (game.set_centered_player) + { + boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND(); + + /* switching to "all players" only possible if all players fit to screen */ + if (game.centered_player_nr_next == -1 && !all_players_fit_to_screen) + { + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; + } + + /* do not switch focus to non-existing (or non-active) player */ + if (game.centered_player_nr_next >= 0 && + !stored_player[game.centered_player_nr_next].active) + { + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; + } + } + + if (game.set_centered_player && + ScreenMovPos == 0) /* screen currently aligned at tile position */ + { +#if 0 + struct PlayerInfo *player; + int player_nr = game.centered_player_nr_next; +#endif + int sx, sy; + + if (game.centered_player_nr_next == -1) + { + setScreenCenteredToAllPlayers(&sx, &sy); + } + else + { + sx = stored_player[game.centered_player_nr_next].jx; + sy = stored_player[game.centered_player_nr_next].jy; + } + +#if 0 + player = &stored_player[player_nr]; + + if (!player->active) + game.centered_player_nr_next = game.centered_player_nr; + + sx = player->jx; + sy = player->jy; +#endif + +#if 0 + if (game.centered_player_nr != game.centered_player_nr_next) +#endif + { +#if 1 + DrawRelocateScreen(sx, sy, MV_NONE, TRUE, setup.quick_switch); +#else + DrawRelocatePlayer(player, setup.quick_switch); +#endif + + game.centered_player_nr = game.centered_player_nr_next; + } + + game.set_centered_player = FALSE; + } +#endif + #if 1 /* !!! CHECK THIS (tape.pausing is always FALSE here!) !!! */ if (recorded_player_action == NULL && tape.pausing) diff --git a/src/game.h b/src/game.h index 9d736792..927dade7 100644 --- a/src/game.h +++ b/src/game.h @@ -14,7 +14,178 @@ #ifndef GAME_H #define GAME_H -#include "main.h" + +#define MAX_INVENTORY_SIZE 1000 +#define STD_NUM_KEYS 4 +#define MAX_NUM_KEYS 8 + + +struct GameInfo +{ + /* values for engine initialization */ + int default_push_delay_fixed; + int default_push_delay_random; + + /* constant within running game */ + int engine_version; + int emulation; + int initial_move_delay; + int initial_move_delay_value; + int initial_push_delay_value; + + /* flags to handle bugs in and changes between different engine versions */ + /* (for the latest engine version, these flags should always be "FALSE") */ + boolean use_change_when_pushing_bug; + boolean use_block_last_field_bug; + boolean max_num_changes_per_frame; + boolean use_reverse_scan_direction; + + /* variable within running game */ + int yamyam_content_nr; + boolean magic_wall_active; + int magic_wall_time_left; + int light_time_left; + int timegate_time_left; + int belt_dir[4]; + int belt_dir_nr[4]; + int switchgate_pos; + int wind_direction; + boolean gravity; + boolean explosions_delayed; + boolean envelope_active; + +#if 1 + /* values for the new EMC elements */ + int lenses_time_left; + int magnify_time_left; + boolean ball_state; + int ball_content_nr; +#endif + + /* values for player idle animation (no effect on engine) */ + int player_boring_delay_fixed; + int player_boring_delay_random; + int player_sleeping_delay_fixed; + int player_sleeping_delay_random; + + /* values for special game initialization control */ + boolean restart_level; + + /* values for special game control */ + int centered_player_nr; + int centered_player_nr_next; + boolean set_centered_player; +}; + +struct PlayerInfo +{ + boolean present; /* player present in level playfield */ + boolean connected; /* player connected (locally or via network) */ + boolean active; /* player present and connected */ + + int index_nr; /* player number (0 to 3) */ + int index_bit; /* player number bit (1 << 0 to 1 << 3) */ + int element_nr; /* element (EL_PLAYER_1 to EL_PLAYER_4) */ + int client_nr; /* network client identifier */ + + byte action; /* action from local input device */ + byte effective_action; /* action acknowledged from network server + or summarized over all configured input + devices when in single player mode */ + byte programmed_action; /* action forced by game itself (like moving + through doors); overrides other actions */ + + int jx, jy, last_jx, last_jy; + int MovDir, MovPos, GfxDir, GfxPos; + int Frame, StepFrame; + + int GfxAction; + + boolean use_murphy; + int artwork_element; + + boolean block_last_field; + int block_delay_adjustment; /* needed for different engine versions */ + + boolean can_fall_into_acid; + + boolean LevelSolved, GameOver; + + int last_move_dir; + + boolean is_waiting; + boolean is_moving; + boolean is_auto_moving; + boolean is_digging; + boolean is_snapping; + boolean is_collecting; + boolean is_pushing; + boolean is_switching; + boolean is_dropping; + boolean is_dropping_pressed; + + boolean is_bored; + boolean is_sleeping; + + boolean cannot_move; + + int frame_counter_bored; + int frame_counter_sleeping; + + int anim_delay_counter; + int post_delay_counter; + + int dir_waiting; + int action_waiting, last_action_waiting; + int special_action_bored; + int special_action_sleeping; + + int num_special_action_bored; + int num_special_action_sleeping; + + int switch_x, switch_y; + int drop_x, drop_y; + + int show_envelope; + + int move_delay; + int move_delay_value; + int move_delay_value_next; + int move_delay_reset_counter; + + int push_delay; + int push_delay_value; + + unsigned long actual_frame_counter; + + int drop_delay; + int drop_pressed_delay; + + int step_counter; + + int score; + int gems_still_needed; + int sokobanfields_still_needed; + int lights_still_needed; + int friends_still_needed; + int key[MAX_NUM_KEYS]; + int dynabomb_count, dynabomb_size, dynabombs_left, dynabomb_xl; + int shield_normal_time_left; + int shield_deadly_time_left; + + int inventory_element[MAX_INVENTORY_SIZE]; + int inventory_infinite_element; + int inventory_size; +}; + + +extern struct GameInfo game; +extern struct PlayerInfo stored_player[], *local_player; + + +#ifdef DEBUG +void DEBUG_SetMaximumDynamite(); +#endif void GetPlayerConfig(void); @@ -25,62 +196,16 @@ void InitGameSound(); void InitGame(void); void UpdateEngineValues(int, int); - -void InitMovDir(int, int); -void InitAmoebaNr(int, int); void GameWon(void); -int NewHiScore(void); void InitPlayerGfxAnimation(struct PlayerInfo *, int, int); -void InitMovingField(int, int, int); void Moving2Blocked(int, int, int *, int *); void Blocked2Moving(int, int, int *, int *); -int MovingOrBlocked2Element(int, int); -void RemoveMovingField(int, int); void DrawDynamite(int, int); -void CheckDynamite(int, int); -void Explode(int, int, int, int); -void DynaExplode(int, int); -void Bang(int, int); -void Blurb(int, int); -void Impact(int, int); -void StartMoving(int, int); -void ContinueMoving(int, int); -int AmoebeNachbarNr(int, int); -void AmoebeUmwandeln(int, int); -void AmoebeUmwandelnBD(int, int, int); -void AmoebeWaechst(int, int); -void AmoebeAbleger(int, int); -void Life(int, int); -void Ablenk(int, int); -void Blubber(int, int); -void NussKnacken(int, int); -void SiebAktivieren(int, int, int); -void AusgangstuerPruefen(int, int); -void AusgangstuerOeffnen(int, int); -void AusgangstuerBlinken(int, int); -void EdelsteinFunkeln(int, int); -void MauerWaechst(int, int); -void MauerAbleger(int, int); void GameActions(void); void ScrollLevel(int, int); -void TestIfGoodThingHitsBadThing(int, int, int); -void TestIfBadThingHitsGoodThing(int, int, int); -void TestIfPlayerTouchesBadThing(int, int); -void TestIfPlayerRunsIntoBadThing(int, int, int); -void TestIfBadThingTouchesPlayer(int, int); -void TestIfBadThingRunsIntoPlayer(int, int, int); -void TestIfFriendTouchesBadThing(int, int); -void TestIfBadThingTouchesFriend(int, int); -void TestIfBadThingTouchesOtherBadThing(int, int); -void KillPlayer(struct PlayerInfo *); -void BuryPlayer(struct PlayerInfo *); -void RemovePlayer(struct PlayerInfo *); -boolean SnapField(struct PlayerInfo *, int, int); -boolean DropElement(struct PlayerInfo *); - void InitPlayLevelSound(); void PlayLevelSound_EM(int, int, int, int); diff --git a/src/game_em/display.h b/src/game_em/display.h index f6a82af4..9079feea 100644 --- a/src/game_em/display.h +++ b/src/game_em/display.h @@ -42,7 +42,10 @@ #define SYSIZE (SCR_FIELDY * TILEY) #if 1 + +#if 0 #define FRAMES_PER_SECOND 50 +#endif #define ROUNDED_DIVIDE(x, y) (((x) + (y) - 1) / (y)) diff --git a/src/game_em/graphics.c b/src/game_em/graphics.c index 331491cf..3b18584c 100644 --- a/src/game_em/graphics.c +++ b/src/game_em/graphics.c @@ -40,11 +40,13 @@ static int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE]; static boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +#if 0 #if 1 int centered_player_nr; #else static int centered_player_nr; #endif +#endif /* copy the entire screen to the window at the scroll position */ @@ -458,9 +460,11 @@ void game_initscreen(void) frame = 6; - centered_player_nr = getCenteredPlayerNr_EM(); +#if 0 + game.centered_player_nr = getCenteredPlayerNr_EM(); +#endif - player_nr = (centered_player_nr != -1 ? centered_player_nr : 0); + player_nr = (game.centered_player_nr != -1 ? game.centered_player_nr : 0); screen_x = VALID_SCREEN_X(PLAYER_SCREEN_X(player_nr)); screen_y = VALID_SCREEN_Y(PLAYER_SCREEN_Y(player_nr)); @@ -655,8 +659,10 @@ void RedrawPlayfield_EM(boolean force_redraw) #if 0 boolean scrolling = (screen_x % TILEX != 0 || screen_y % TILEY != 0); #endif - boolean set_centered_player = getSetCenteredPlayer_EM(); - int centered_player_nr_next = getCenteredPlayerNr_EM(); +#if 0 + boolean game.set_centered_player = getSetCenteredPlayer_EM(); + int game.centered_player_nr_next = getCenteredPlayerNr_EM(); +#endif int offset = (setup.scroll_delay ? 3 : 0) * TILEX; int offset_x = offset; int offset_y = offset; @@ -665,28 +671,23 @@ void RedrawPlayfield_EM(boolean force_redraw) int x, y, sx, sy; int i; - if (set_centered_player) + if (game.set_centered_player) { boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen(); /* switching to "all players" only possible if all players fit to screen */ - if (centered_player_nr_next == -1 && !all_players_fit_to_screen) + if (game.centered_player_nr_next == -1 && !all_players_fit_to_screen) { - centered_player_nr_next = centered_player_nr; - setCenteredPlayerNr_EM(centered_player_nr); - - set_centered_player = FALSE; - setSetCenteredPlayer_EM(FALSE); + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; } /* do not switch focus to non-existing (or non-active) player */ - if (centered_player_nr_next >= 0 && !ply[centered_player_nr_next].alive) + if (game.centered_player_nr_next >= 0 && + !ply[game.centered_player_nr_next].alive) { - centered_player_nr_next = centered_player_nr; - setCenteredPlayerNr_EM(centered_player_nr); - - set_centered_player = FALSE; - setSetCenteredPlayer_EM(FALSE); + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; } } @@ -697,21 +698,21 @@ void RedrawPlayfield_EM(boolean force_redraw) #endif { #if 1 - if (set_centered_player) + if (game.set_centered_player) #else - if (centered_player_nr != centered_player_nr_next) + if (game.centered_player_nr != game.centered_player_nr_next) #endif { - centered_player_nr = centered_player_nr_next; + game.centered_player_nr = game.centered_player_nr_next; draw_new_player_location = TRUE; force_redraw = TRUE; - setSetCenteredPlayer_EM(FALSE); + game.set_centered_player = FALSE; } } - if (centered_player_nr == -1) + if (game.centered_player_nr == -1) { if (draw_new_player_location) { @@ -725,8 +726,8 @@ void RedrawPlayfield_EM(boolean force_redraw) } else { - sx = PLAYER_SCREEN_X(centered_player_nr); - sy = PLAYER_SCREEN_Y(centered_player_nr); + sx = PLAYER_SCREEN_X(game.centered_player_nr); + sy = PLAYER_SCREEN_Y(game.centered_player_nr); } if (draw_new_player_location && quick_relocation) @@ -881,7 +882,7 @@ void RedrawPlayfield_EM(boolean force_redraw) } /* prevent scrolling away from the other players when focus on all players */ - if (centered_player_nr == -1) + if (game.centered_player_nr == -1) { #if 1 /* check if all players are still visible with new scrolling position */ diff --git a/src/game_em/synchro_1.c b/src/game_em/synchro_1.c index 1fe8faf0..c6f00674 100644 --- a/src/game_em/synchro_1.c +++ b/src/game_em/synchro_1.c @@ -11,7 +11,10 @@ #include "display.h" +#if 0 extern int centered_player_nr; +#endif + extern boolean checkIfAllPlayersFitToScreen(); static void check_player(struct PLAYER *); @@ -551,7 +554,8 @@ static void check_player(struct PLAYER *ply) ply->x = x; ply->y = y; - can_move = (centered_player_nr != -1 || checkIfAllPlayersFitToScreen()); + can_move = (game.centered_player_nr != -1 || + checkIfAllPlayersFitToScreen()); ply->x = oldx; ply->y = oldy; diff --git a/src/libgame/system.h b/src/libgame/system.h index 84f12877..128726a6 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -112,6 +112,9 @@ #define BUTTON_1 4 #define BUTTON_2 5 +/* values for special "focus player" bitmasks */ +#define BIT_SET_FOCUS 6 + /* values for move directions and special "button" key bitmasks */ #define MV_NONE 0 #define MV_LEFT (1 << MV_BIT_LEFT) @@ -136,6 +139,8 @@ #define KEY_BUTTON (KEY_BUTTON_1 | KEY_BUTTON_2) #define KEY_ACTION (KEY_MOTION | KEY_BUTTON) +#define SET_FOCUS (1 << BIT_SET_FOCUS) + #define MV_DIR_FROM_BIT(x) ((x) < NUM_DIRECTIONS ? 1 << (x) : \ (x) == MV_BIT_UPLEFT ? MV_UPLEFT : \ (x) == MV_BIT_UPRIGHT ? MV_UPRIGHT : \ @@ -218,6 +223,11 @@ #define CURSOR_DEFAULT 0 #define CURSOR_PLAYFIELD 1 +/* fundamental game speed values */ +#define ONE_SECOND_DELAY 1000 /* delay value for one second */ +#define GAME_FRAME_DELAY 20 /* frame delay in milliseconds */ +#define FFWD_FRAME_DELAY 10 /* 200% speed for fast forward */ +#define FRAMES_PER_SECOND (ONE_SECOND_DELAY / GAME_FRAME_DELAY) /* maximum playfield size supported by libgame functions */ #define MAX_PLAYFIELD_WIDTH 128 diff --git a/src/main.c b/src/main.c index 2daf291a..ec2ec514 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ #include "main.h" #include "init.h" #include "game.h" +#include "tape.h" #include "events.h" #include "config.h" diff --git a/src/main.h b/src/main.h index bb7d8766..b2a69ad3 100644 --- a/src/main.h +++ b/src/main.h @@ -765,10 +765,6 @@ #define EL_NAME(e) ((e) >= 0 ? element_info[e].token_name : "(?)") /* fundamental game speed values */ -#define ONE_SECOND_DELAY 1000 /* delay value for one second */ -#define GAME_FRAME_DELAY 20 /* frame delay in milliseconds */ -#define FFWD_FRAME_DELAY 10 /* 200% speed for fast forward */ -#define FRAMES_PER_SECOND (ONE_SECOND_DELAY / GAME_FRAME_DELAY) #define MICROLEVEL_SCROLL_DELAY 50 /* delay for scrolling micro level */ #define MICROLEVEL_LABEL_DELAY 250 /* delay for micro level label */ @@ -776,13 +772,14 @@ #define MAX_LEVEL_NAME_LEN 32 #define MAX_LEVEL_AUTHOR_LEN 32 #define MAX_ELEMENT_NAME_LEN 32 -#define MAX_TAPE_LEN (1000 * FRAMES_PER_SECOND) /* max.time x fps */ #define MAX_TAPES_PER_SET 1024 #define MAX_SCORE_ENTRIES 100 #define MAX_NUM_AMOEBA 100 +#if 0 /* game.h */ #define MAX_INVENTORY_SIZE 1000 #define STD_NUM_KEYS 4 #define MAX_NUM_KEYS 8 +#endif #define NUM_BELTS 4 #define NUM_BELT_PARTS 3 #define MIN_ENVELOPE_XSIZE 1 @@ -1785,107 +1782,6 @@ struct Content int e[3][3]; }; -struct PlayerInfo -{ - boolean present; /* player present in level playfield */ - boolean connected; /* player connected (locally or via network) */ - boolean active; /* player present and connected */ - - int index_nr; /* player number (0 to 3) */ - int index_bit; /* player number bit (1 << 0 to 1 << 3) */ - int element_nr; /* element (EL_PLAYER_1 to EL_PLAYER_4) */ - int client_nr; /* network client identifier */ - - byte action; /* action from local input device */ - byte effective_action; /* action acknowledged from network server - or summarized over all configured input - devices when in single player mode */ - byte programmed_action; /* action forced by game itself (like moving - through doors); overrides other actions */ - - int jx, jy, last_jx, last_jy; - int MovDir, MovPos, GfxDir, GfxPos; - int Frame, StepFrame; - - int GfxAction; - - boolean use_murphy; - int artwork_element; - - boolean block_last_field; - int block_delay_adjustment; /* needed for different engine versions */ - - boolean can_fall_into_acid; - - boolean LevelSolved, GameOver; - - int last_move_dir; - - boolean is_waiting; - boolean is_moving; - boolean is_auto_moving; - boolean is_digging; - boolean is_snapping; - boolean is_collecting; - boolean is_pushing; - boolean is_switching; - boolean is_dropping; - boolean is_dropping_pressed; - - boolean is_bored; - boolean is_sleeping; - - boolean cannot_move; - - int frame_counter_bored; - int frame_counter_sleeping; - - int anim_delay_counter; - int post_delay_counter; - - int dir_waiting; - int action_waiting, last_action_waiting; - int special_action_bored; - int special_action_sleeping; - - int num_special_action_bored; - int num_special_action_sleeping; - - int switch_x, switch_y; - int drop_x, drop_y; - - int show_envelope; - - int move_delay; - int move_delay_value; - int move_delay_value_next; - int move_delay_reset_counter; - - int push_delay; - int push_delay_value; - - unsigned long actual_frame_counter; - - int drop_delay; - int drop_pressed_delay; - - int step_counter; - - int score; - int gems_still_needed; - int sokobanfields_still_needed; - int lights_still_needed; - int friends_still_needed; - int key[MAX_NUM_KEYS]; - int dynabomb_count, dynabomb_size, dynabombs_left, dynabomb_xl; - int shield_normal_time_left; - int shield_deadly_time_left; - - int inventory_element[MAX_INVENTORY_SIZE]; - int inventory_infinite_element; - int inventory_size; -}; - struct LevelSetInfo { int music[MAX_LEVELS]; @@ -2014,99 +1910,6 @@ struct LevelInfo boolean changed; /* set when level was changed in the editor */ }; -struct TapeInfo -{ - int file_version; /* file format version the tape is stored with */ - int game_version; /* game release version the tape was created with */ - int engine_version; /* game engine version the tape was recorded with */ - - char *level_identifier; - int level_nr; - unsigned long random_seed; - unsigned long date; - unsigned long counter; - unsigned long length; - unsigned long length_seconds; - unsigned int delay_played; - boolean pause_before_death; - boolean recording, playing, pausing; - boolean fast_forward; - boolean warp_forward; - boolean deactivate_display; - boolean auto_play; - boolean auto_play_level_solved; - boolean quick_resume; - boolean single_step; - boolean changed; - boolean player_participates[MAX_PLAYERS]; - int num_participating_players; - - struct - { - byte action[MAX_PLAYERS]; - byte delay; - } pos[MAX_TAPE_LEN]; - - boolean no_valid_file; /* set when tape file missing or invalid */ -}; - -struct GameInfo -{ - /* values for engine initialization */ - int default_push_delay_fixed; - int default_push_delay_random; - - /* constant within running game */ - int engine_version; - int emulation; - int initial_move_delay; - int initial_move_delay_value; - int initial_push_delay_value; - - /* flags to handle bugs in and changes between different engine versions */ - /* (for the latest engine version, these flags should always be "FALSE") */ - boolean use_change_when_pushing_bug; - boolean use_block_last_field_bug; - boolean max_num_changes_per_frame; - boolean use_reverse_scan_direction; - - /* variable within running game */ - int yamyam_content_nr; - boolean magic_wall_active; - int magic_wall_time_left; - int light_time_left; - int timegate_time_left; - int belt_dir[4]; - int belt_dir_nr[4]; - int switchgate_pos; - int wind_direction; - boolean gravity; - boolean explosions_delayed; - boolean envelope_active; - -#if 1 - /* values for the new EMC elements */ - int lenses_time_left; - int magnify_time_left; - boolean ball_state; - int ball_content_nr; -#endif - - /* values for player idle animation (no effect on engine) */ - int player_boring_delay_fixed; - int player_boring_delay_random; - int player_sleeping_delay_fixed; - int player_sleeping_delay_random; - - /* values for special game initialization control */ - boolean restart_level; - - /* values for special game control */ - int centered_player_nr; - int centered_player_nr_next; - boolean set_centered_player; -}; - struct GlobalInfo { char *autoplay_leveldir; @@ -2505,10 +2308,8 @@ extern int graphics_action_mapping[]; extern struct LevelSetInfo levelset; extern struct LevelInfo level, level_template; -extern struct PlayerInfo stored_player[], *local_player; extern struct HiScore highscore[]; extern struct TapeInfo tape; -extern struct GameInfo game; extern struct GlobalInfo global; extern struct MenuInfo menu; extern struct DoorInfo door_1, door_2; diff --git a/src/screens.c b/src/screens.c index 76e24447..fd78deb5 100644 --- a/src/screens.c +++ b/src/screens.c @@ -3193,6 +3193,14 @@ void HandleGameActions() recorded_player_action = (tape.playing ? TapePlayAction() : NULL); +#if 1 + if (tape.set_centered_player) + { + game.centered_player_nr_next = tape.centered_player_nr_next; + game.set_centered_player = TRUE; + } +#endif + #if 1 /* !!! CHECK THIS (tape.pausing is always FALSE here!) !!! */ if (recorded_player_action == NULL && tape.pausing) diff --git a/src/tape.c b/src/tape.c index e8fb1b7e..becd0ad9 100644 --- a/src/tape.c +++ b/src/tape.c @@ -485,6 +485,9 @@ void TapeErase() for (i = 0; i < MAX_PLAYERS; i++) tape.player_participates[i] = FALSE; + + tape.centered_player_nr_next = -1; + tape.set_centered_player = FALSE; } static void TapeRewind() @@ -502,6 +505,9 @@ static void TapeRewind() tape.quick_resume = FALSE; tape.single_step = FALSE; + tape.centered_player_nr_next = -1; + tape.set_centered_player = FALSE; + InitRND(tape.random_seed); } @@ -585,8 +591,9 @@ void TapeStopRecording() MapTapeEjectButton(); } -void TapeRecordAction(byte action[MAX_PLAYERS]) +void TapeRecordAction(byte action_raw[MAX_PLAYERS]) { + byte action[MAX_PLAYERS]; int i; if (!tape.recording) /* (record action even when tape is paused) */ @@ -598,6 +605,19 @@ void TapeRecordAction(byte action[MAX_PLAYERS]) return; } + for (i = 0; i < MAX_PLAYERS; i++) + action[i] = action_raw[i]; + + if (tape.set_centered_player) + { + for (i = 0; i < MAX_PLAYERS; i++) + if (tape.centered_player_nr_next == i || + tape.centered_player_nr_next == -1) + action[i] |= SET_FOCUS; + + tape.set_centered_player = FALSE; + } + if (tape.pos[tape.counter].delay > 0) /* already stored action */ { boolean changed_events = FALSE; @@ -778,6 +798,21 @@ byte *TapePlayAction() for (i = 0; i < MAX_PLAYERS; i++) action[i] = tape.pos[tape.counter].action[i]; + tape.set_centered_player = FALSE; + tape.centered_player_nr_next = -999; + + for (i = 0; i < MAX_PLAYERS; i++) + { + if (action[i] & SET_FOCUS) + { + tape.set_centered_player = TRUE; + tape.centered_player_nr_next = + (tape.centered_player_nr_next == -999 ? i : -1); + } + + action[i] &= ~SET_FOCUS; + } + tape.delay_played++; if (tape.delay_played >= tape.pos[tape.counter].delay) { diff --git a/src/tape.h b/src/tape.h index 3cb2038a..18107add 100644 --- a/src/tape.h +++ b/src/tape.h @@ -14,13 +14,14 @@ #ifndef TAPE_H #define TAPE_H -#include "main.h" - /* values for TapeTogglePause() */ #define TAPE_TOGGLE_MANUAL TRUE #define TAPE_TOGGLE_AUTOMATIC FALSE +/* values for tape properties */ +#define MAX_TAPE_LEN (1000 * FRAMES_PER_SECOND) /* max.time x fps */ + /* some positions in the video tape control window */ #define VIDEO_DISPLAY1_XPOS 5 #define VIDEO_DISPLAY1_YPOS 5 @@ -92,6 +93,45 @@ #define VIDEO_DISPLAY_SYMBOL_ONLY -2 +struct TapeInfo +{ + int file_version; /* file format version the tape is stored with */ + int game_version; /* game release version the tape was created with */ + int engine_version; /* game engine version the tape was recorded with */ + + char *level_identifier; + int level_nr; + unsigned long random_seed; + unsigned long date; + unsigned long counter; + unsigned long length; + unsigned long length_seconds; + unsigned int delay_played; + boolean pause_before_death; + boolean recording, playing, pausing; + boolean fast_forward; + boolean warp_forward; + boolean deactivate_display; + boolean auto_play; + boolean auto_play_level_solved; + boolean quick_resume; + boolean single_step; + boolean changed; + boolean player_participates[MAX_PLAYERS]; + int num_participating_players; + int centered_player_nr_next; + boolean set_centered_player; + + struct + { + byte action[MAX_PLAYERS]; + byte delay; + } pos[MAX_TAPE_LEN]; + + boolean no_valid_file; /* set when tape file missing or invalid */ +}; + + void DrawVideoDisplay(unsigned long, unsigned long); void DrawCompleteVideoDisplay(void); diff --git a/src/tools.c b/src/tools.c index f9b4f639..74e4c8d8 100644 --- a/src/tools.c +++ b/src/tools.c @@ -5125,6 +5125,7 @@ int font2baseimg(int font_nr) return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT]; } +#if 0 void setCenteredPlayerNr_EM(int centered_player_nr) { game.centered_player_nr = game.centered_player_nr_next = centered_player_nr; @@ -5153,6 +5154,7 @@ boolean getSetCenteredPlayer_EM() { return game.set_centered_player; } +#endif int getNumActivePlayers_EM() { diff --git a/src/tools.h b/src/tools.h index 0168369e..b1d0dd86 100644 --- a/src/tools.h +++ b/src/tools.h @@ -15,6 +15,7 @@ #define TOOLS_H #include "main.h" +#include "game.h" /* for SetDrawtoField */ #define DRAW_DIRECT 0 -- 2.34.1