From f7eeeedb1a0bb21cbd8366cf241faffc76aafc16 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Mon, 1 Mar 2004 09:37:58 +0100 Subject: [PATCH] rnd-20040301-1-src * use unlimited number of droppable elements when "count" set to zero * added option to use step limit instead of time limit for level * added player and change page as trigger for custom element change --- ChangeLog | 7 ++ src/conftime.h | 2 +- src/editor.c | 134 +++++++++++++++++++------------- src/files.c | 17 +++-- src/game.c | 203 +++++++++++++++++++++++++++++++++++++++---------- src/init.c | 6 +- src/main.c | 2 +- src/main.h | 7 +- 8 files changed, 274 insertions(+), 104 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71f243a9..2061b83c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-02-28 + * use unlimited number of droppable elements when "count" set to zero + * added option to use step limit instead of time limit for level + +2004-02-27 + * added player and change page as trigger for custom element change + 2004-02-24 * fixed bug with exploding amoeba (explosion 3x3 instead of 1x1) diff --git a/src/conftime.h b/src/conftime.h index 1fc08875..8c2c13bb 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2004-02-28 01:51]" +#define COMPILE_DATE_STRING "[2004-03-01 02:26]" diff --git a/src/editor.c b/src/editor.c index 8f921bc6..5a567832 100644 --- a/src/editor.c +++ b/src/editor.c @@ -439,31 +439,32 @@ /* selectbox identifiers */ #define GADGET_ID_SELECTBOX_FIRST (GADGET_ID_TEXT_AREA_FIRST + 1) -#define GADGET_ID_CUSTOM_WALK_TO_ACTION (GADGET_ID_SELECTBOX_FIRST + 0) -#define GADGET_ID_CUSTOM_CONSISTENCY (GADGET_ID_SELECTBOX_FIRST + 1) -#define GADGET_ID_CUSTOM_DEADLINESS (GADGET_ID_SELECTBOX_FIRST + 2) -#define GADGET_ID_CUSTOM_MOVE_PATTERN (GADGET_ID_SELECTBOX_FIRST + 3) -#define GADGET_ID_CUSTOM_MOVE_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 4) -#define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 5) -#define GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE (GADGET_ID_SELECTBOX_FIRST + 6) -#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 7) -#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 8) -#define GADGET_ID_CUSTOM_ACCESS_TYPE (GADGET_ID_SELECTBOX_FIRST + 9) -#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 10) -#define GADGET_ID_CUSTOM_ACCESS_PROTECTED (GADGET_ID_SELECTBOX_FIRST + 11) -#define GADGET_ID_CUSTOM_ACCESS_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 12) -#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 13) -#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 14) -#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 15) -#define GADGET_ID_CHANGE_SIDE (GADGET_ID_SELECTBOX_FIRST + 16) -#define GADGET_ID_CHANGE_PLAYER (GADGET_ID_SELECTBOX_FIRST + 17) -#define GADGET_ID_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 18) -#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 19) -#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 20) -#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 21) +#define GADGET_ID_TIME_OR_STEPS (GADGET_ID_SELECTBOX_FIRST + 0) +#define GADGET_ID_CUSTOM_WALK_TO_ACTION (GADGET_ID_SELECTBOX_FIRST + 1) +#define GADGET_ID_CUSTOM_CONSISTENCY (GADGET_ID_SELECTBOX_FIRST + 2) +#define GADGET_ID_CUSTOM_DEADLINESS (GADGET_ID_SELECTBOX_FIRST + 3) +#define GADGET_ID_CUSTOM_MOVE_PATTERN (GADGET_ID_SELECTBOX_FIRST + 4) +#define GADGET_ID_CUSTOM_MOVE_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 5) +#define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 6) +#define GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE (GADGET_ID_SELECTBOX_FIRST + 7) +#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 8) +#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 9) +#define GADGET_ID_CUSTOM_ACCESS_TYPE (GADGET_ID_SELECTBOX_FIRST + 10) +#define GADGET_ID_CUSTOM_ACCESS_LAYER (GADGET_ID_SELECTBOX_FIRST + 11) +#define GADGET_ID_CUSTOM_ACCESS_PROTECTED (GADGET_ID_SELECTBOX_FIRST + 12) +#define GADGET_ID_CUSTOM_ACCESS_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 13) +#define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 14) +#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 15) +#define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 16) +#define GADGET_ID_CHANGE_SIDE (GADGET_ID_SELECTBOX_FIRST + 17) +#define GADGET_ID_CHANGE_PLAYER (GADGET_ID_SELECTBOX_FIRST + 18) +#define GADGET_ID_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 19) +#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 20) +#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 21) +#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 22) /* textbutton identifiers */ -#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 22) +#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 23) #define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0) #define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1) @@ -627,30 +628,34 @@ #define ED_TEXTAREA_ID_LEVEL_LAST ED_TEXTAREA_ID_ENVELOPE /* values for selectbox gadgets */ -#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE 0 -#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER 1 -#define ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED 2 -#define ED_SELECTBOX_ID_CUSTOM_ACCESS_DIRECTION 3 -#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION 4 -#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 5 -#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 6 -#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 7 -#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 8 -#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 9 -#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 10 -#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 11 -#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 12 -#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 13 -#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 14 -#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 15 -#define ED_SELECTBOX_ID_CHANGE_SIDE 16 -#define ED_SELECTBOX_ID_CHANGE_PLAYER 17 -#define ED_SELECTBOX_ID_CHANGE_PAGE 18 -#define ED_SELECTBOX_ID_CHANGE_POWER 19 -#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 20 -#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 21 - -#define ED_NUM_SELECTBOX 22 +#define ED_SELECTBOX_ID_TIME_OR_STEPS 0 +#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE 1 +#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER 2 +#define ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED 3 +#define ED_SELECTBOX_ID_CUSTOM_ACCESS_DIRECTION 4 +#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION 5 +#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN 6 +#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION 7 +#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE 8 +#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 9 +#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS 10 +#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE 11 +#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS 12 +#define ED_SELECTBOX_ID_CUSTOM_CONSISTENCY 13 +#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 14 +#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 15 +#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 16 +#define ED_SELECTBOX_ID_CHANGE_SIDE 17 +#define ED_SELECTBOX_ID_CHANGE_PLAYER 18 +#define ED_SELECTBOX_ID_CHANGE_PAGE 19 +#define ED_SELECTBOX_ID_CHANGE_POWER 20 +#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 21 +#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 22 + +#define ED_NUM_SELECTBOX 23 + +#define ED_SELECTBOX_ID_LEVEL_FIRST ED_SELECTBOX_ID_TIME_OR_STEPS +#define ED_SELECTBOX_ID_LEVEL_LAST ED_SELECTBOX_ID_TIME_OR_STEPS #define ED_SELECTBOX_ID_CUSTOM1_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE #define ED_SELECTBOX_ID_CUSTOM1_LAST ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE @@ -913,7 +918,7 @@ static struct GADGET_ID_LEVEL_GEMSLIMIT_DOWN, GADGET_ID_LEVEL_GEMSLIMIT_UP, GADGET_ID_LEVEL_GEMSLIMIT_TEXT, GADGET_ID_NONE, &level.gems_needed, - "number of emeralds to collect:", NULL, NULL + "number of gems to collect:", NULL, NULL }, { ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(4), @@ -921,7 +926,7 @@ static struct GADGET_ID_LEVEL_TIMELIMIT_DOWN, GADGET_ID_LEVEL_TIMELIMIT_UP, GADGET_ID_LEVEL_TIMELIMIT_TEXT, GADGET_ID_NONE, &level.time, - "time available to solve level:", NULL, "(0 => no time limit)" + "time or step limit to solve level:", NULL, NULL }, { ED_SETTINGS_XPOS(0), ED_COUNTER_YPOS(5), @@ -929,7 +934,7 @@ static struct GADGET_ID_LEVEL_TIMESCORE_DOWN, GADGET_ID_LEVEL_TIMESCORE_UP, GADGET_ID_LEVEL_TIMESCORE_TEXT, GADGET_ID_NONE, &level.score[SC_TIME_BONUS], - "score for each 10 seconds left:", NULL, NULL + "score for each 10 sec/steps left:", NULL, NULL }, { ED_SETTINGS_XPOS(0), ED_COUNTER2_YPOS(8), @@ -1134,6 +1139,14 @@ static struct } }; +static struct ValueTextInfo options_time_or_steps[] = +{ + { 0, "seconds" }, + { 1, "steps" }, + + { -1, NULL } +}; + static struct ValueTextInfo options_access_type[] = { { EP_WALKABLE, "walkable" }, @@ -1440,6 +1453,17 @@ static struct char *text_left, *text_right, *infotext; } selectbox_info[ED_NUM_SELECTBOX] = { + /* ---------- level and editor settings ---------------------------------- */ + + { + -1, ED_COUNTER_YPOS(4), + GADGET_ID_TIME_OR_STEPS, GADGET_ID_LEVEL_TIMELIMIT_UP, + -1, + options_time_or_steps, + &level.use_step_counter, + NULL, "(0 => no limit)", "time or step limit" + }, + /* ---------- element settings: configure 1 (custom elements) ----------- */ { @@ -5769,7 +5793,7 @@ static void CopyClassicElementPropertiesToEditor(int element) if (bit_nr > -1) custom_element_properties[EP_CAN_MOVE_INTO_ACID] = - ((level.can_move_into_acid & (1 << bit_nr)) != 0); + ((level.can_move_into_acid_bits & (1 << bit_nr)) != 0); } #endif } @@ -5945,10 +5969,10 @@ static void CopyClassicElementPropertiesToGame(int element) if (bit_nr > -1) { - level.can_move_into_acid &= ~(1 << bit_nr); + level.can_move_into_acid_bits &= ~(1 << bit_nr); if (custom_element_properties[EP_CAN_MOVE_INTO_ACID]) - level.can_move_into_acid |= (1 << bit_nr); + level.can_move_into_acid_bits |= (1 << bit_nr); } } #endif @@ -6258,6 +6282,10 @@ static void DrawLevelInfoWindow() for (i = ED_COUNTER_ID_LEVEL_FIRST; i <= ED_COUNTER_ID_LEVEL_LAST; i++) MapCounterButtons(i); + /* draw selectbox gadgets */ + for (i = ED_SELECTBOX_ID_LEVEL_FIRST; i <= ED_SELECTBOX_ID_LEVEL_LAST; i++) + MapSelectboxGadget(i); + /* draw checkbutton gadgets */ for (i=ED_CHECKBUTTON_ID_LEVEL_FIRST; i <= ED_CHECKBUTTON_ID_LEVEL_LAST; i++) MapCheckbuttonGadget(i); diff --git a/src/files.c b/src/files.c index 5fd205cb..8e6ec1bb 100644 --- a/src/files.c +++ b/src/files.c @@ -29,7 +29,7 @@ #define CHUNK_SIZE_NONE -1 /* do not write chunk size */ #define FILE_VERS_CHUNK_SIZE 8 /* size of file version chunk */ #define LEVEL_HEADER_SIZE 80 /* size of level file header */ -#define LEVEL_HEADER_UNUSED 8 /* unused level header bytes */ +#define LEVEL_HEADER_UNUSED 7 /* unused level header bytes */ #define LEVEL_CHUNK_CNT2_SIZE 160 /* size of level CNT2 chunk */ #define LEVEL_CHUNK_CNT2_UNUSED 11 /* unused CNT2 chunk bytes */ #define LEVEL_CHUNK_CNT3_HEADER 16 /* size of level CNT3 header */ @@ -162,7 +162,9 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->use_spring_bug = FALSE; - level->can_move_into_acid = ~0; /* everything can move into acid */ + level->can_move_into_acid_bits = ~0; /* everything can move into acid */ + + level->use_step_counter = FALSE; level->use_custom_template = FALSE; @@ -655,7 +657,9 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level) level->use_spring_bug = (getFile8Bit(file) == 1 ? TRUE : FALSE); - level->can_move_into_acid = getFile16BitBE(file); + level->can_move_into_acid_bits = getFile16BitBE(file); + + level->use_step_counter = (getFile8Bit(file) == 1 ? TRUE : FALSE); ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED); @@ -2057,7 +2061,7 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) { int i, j; - level->can_move_into_acid = 0; /* nothing can move into acid */ + level->can_move_into_acid_bits = 0; /* nothing can move into acid */ setMoveIntoAcidProperty(level, EL_ROBOT, TRUE); setMoveIntoAcidProperty(level, EL_SATELLITE, TRUE); @@ -2367,7 +2371,9 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) putFile8Bit(file, (level->use_spring_bug ? 1 : 0)); - putFile16BitBE(file, level->can_move_into_acid); + putFile16BitBE(file, level->can_move_into_acid_bits); + + putFile8Bit(file, (level->use_step_counter ? 1 : 0)); WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED); } @@ -2908,6 +2914,7 @@ void DumpLevel(struct LevelInfo *level) printf("Player blocks last field: %s\n", (level->block_last_field ? "yes" : "no")); printf("SP player blocks last field: %s\n", (level->sp_block_last_field ? "yes" : "no")); printf("use spring bug: %s\n", (level->use_spring_bug ? "yes" : "no")); + printf("use step counter: %s\n", (level->use_step_counter ? "yes" : "no")); printf_line("-", 79); } diff --git a/src/game.c b/src/game.c index 7ff1a5e4..bffde89c 100644 --- a/src/game.c +++ b/src/game.c @@ -241,6 +241,7 @@ int DigField(struct PlayerInfo *, int, int, int, int, int, int, int); static void InitBeltMovement(void); static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); +static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *); static void KillHeroUnlessEnemyProtected(int, int); static void KillHeroUnlessExplosionProtected(int, int); @@ -1471,6 +1472,7 @@ void InitGame() player->shield_normal_time_left = 0; player->shield_deadly_time_left = 0; + player->inventory_infinite_element = EL_UNDEFINED; player->inventory_size = 0; DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH); @@ -1494,6 +1496,7 @@ void InitGame() TimeFrames = 0; TimePlayed = 0; TimeLeft = level.time; + TapeTime = 0; ScreenMovDir = MV_NO_MOVING; ScreenMovPos = 0; @@ -7177,6 +7180,10 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) printf("::: player %d acts [%d]\n", player->index_nr, FrameCounter); #endif +#if 0 + /* !!! TEST !!! */ + CheckGravityMovement(player); +#endif if (button1) snapped = SnapField(player, dx, dy); else @@ -7214,7 +7221,7 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH); SnapField(player, 0, 0); - CheckGravityMovement(player); + CheckGravityMovementWhenNotMoving(player); if (player->MovPos == 0) SetPlayerWaiting(player, TRUE); @@ -7295,7 +7302,7 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action) DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH); SnapField(player, 0, 0); - CheckGravityMovement(player); + CheckGravityMovementWhenNotMoving(player); if (player->MovPos == 0) InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir); @@ -7395,11 +7402,29 @@ void GameActions() { int actual_player_action = stored_player[i].effective_action; +#if 1 + /* OLD: overwrite programmed action with tape action (BAD!!!) */ if (stored_player[i].programmed_action) actual_player_action = stored_player[i].programmed_action; +#endif if (recorded_player_action) + { +#if 0 + if (stored_player[i].programmed_action && + stored_player[i].programmed_action != recorded_player_action[i]) + printf("::: %d <-> %d\n", + stored_player[i].programmed_action, recorded_player_action[i]); +#endif + actual_player_action = recorded_player_action[i]; + } + +#if 0 + /* NEW: overwrite tape action with programmed action */ + if (stored_player[i].programmed_action) + actual_player_action = stored_player[i].programmed_action; +#endif tape_action[i] = PlayerActions(&stored_player[i], actual_player_action); @@ -7833,39 +7858,44 @@ void GameActions() if (TimeFrames >= FRAMES_PER_SECOND) { TimeFrames = 0; - TimePlayed++; + TapeTime++; - for (i = 0; i < MAX_PLAYERS; i++) + if (!level.use_step_counter) { - struct PlayerInfo *player = &stored_player[i]; + TimePlayed++; - if (SHIELD_ON(player)) + for (i = 0; i < MAX_PLAYERS; i++) { - player->shield_normal_time_left--; + struct PlayerInfo *player = &stored_player[i]; - if (player->shield_deadly_time_left > 0) - player->shield_deadly_time_left--; - } - } + if (SHIELD_ON(player)) + { + player->shield_normal_time_left--; - if (tape.recording || tape.playing) - DrawVideoDisplay(VIDEO_STATE_TIME_ON, TimePlayed); + if (player->shield_deadly_time_left > 0) + player->shield_deadly_time_left--; + } + } - if (TimeLeft > 0) - { - TimeLeft--; + if (TimeLeft > 0) + { + TimeLeft--; - if (TimeLeft <= 10 && setup.time_limit) - PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); + if (TimeLeft <= 10 && setup.time_limit) + PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); - DrawGameValue_Time(TimeLeft); + DrawGameValue_Time(TimeLeft); - if (!TimeLeft && setup.time_limit) - for (i = 0; i < MAX_PLAYERS; i++) - KillHero(&stored_player[i]); + if (!TimeLeft && setup.time_limit) + for (i = 0; i < MAX_PLAYERS; i++) + KillHero(&stored_player[i]); + } + else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */ + DrawGameValue_Time(TimePlayed); } - else if (level.time == 0 && !AllPlayersGone) /* level without time limit */ - DrawGameValue_Time(TimePlayed); + + if (tape.recording || tape.playing) + DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime); } DrawAllPlayers(); @@ -8067,6 +8097,27 @@ static void CheckGravityMovement(struct PlayerInfo *player) } } +static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *player) +{ +#if 1 + return CheckGravityMovement(player); +#endif + + if (game.gravity && !player->programmed_action) + { + int jx = player->jx, jy = player->jy; + boolean field_under_player_is_free = + (IN_LEV_FIELD(jx, jy + 1) && IS_FREE(jx, jy + 1)); + boolean player_is_standing_on_valid_field = + (IS_WALKABLE_INSIDE(Feld[jx][jy]) || + (IS_WALKABLE(Feld[jx][jy]) && + !(element_info[Feld[jx][jy]].access_direction & MV_DOWN))); + + if (field_under_player_is_free && !player_is_standing_on_valid_field) + player->programmed_action = MV_DOWN; + } +} + /* MovePlayerOneStep() ----------------------------------------------------------------------------- @@ -8214,9 +8265,16 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) !tape.playing) return FALSE; #else + +#if 1 + if (!FrameReached(&player->move_delay, player->move_delay_value)) + return FALSE; +#else if (!FrameReached(&player->move_delay, player->move_delay_value) && !(tape.playing && tape.file_version < FILE_VERSION_2_0)) return FALSE; +#endif + #endif /* remove the last programmed player action */ @@ -8407,7 +8465,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) } else { - CheckGravityMovement(player); + CheckGravityMovementWhenNotMoving(player); /* player->last_move_dir = MV_NO_MOVING; @@ -8526,6 +8584,42 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) RemoveHero(player); } + if (level.use_step_counter) + { + int i; + + TimePlayed++; + + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + if (SHIELD_ON(player)) + { + player->shield_normal_time_left--; + + if (player->shield_deadly_time_left > 0) + player->shield_deadly_time_left--; + } + } + + if (TimeLeft > 0) + { + TimeLeft--; + + if (TimeLeft <= 10 && setup.time_limit) + PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); + + DrawGameValue_Time(TimeLeft); + + if (!TimeLeft && setup.time_limit) + for (i = 0; i < MAX_PLAYERS; i++) + KillHero(&stored_player[i]); + } + else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */ + DrawGameValue_Time(TimePlayed); + } + if (tape.single_step && tape.recording && !tape.pausing && !player->programmed_action) TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); @@ -9562,9 +9656,12 @@ int DigField(struct PlayerInfo *player, { int i; - for (i = 0; i < element_info[element].collect_count; i++) - if (player->inventory_size < MAX_INVENTORY_SIZE) - player->inventory_element[player->inventory_size++] = element; + if (element_info[element].collect_count == 0) + player->inventory_infinite_element = element; + else + for (i = 0; i < element_info[element].collect_count; i++) + if (player->inventory_size < MAX_INVENTORY_SIZE) + player->inventory_element[player->inventory_size++] = element; DrawGameValue_Dynamite(local_player->inventory_size); } @@ -9945,25 +10042,43 @@ boolean DropElement(struct PlayerInfo *player) { int jx = player->jx, jy = player->jy; int old_element = Feld[jx][jy]; - int new_element; + int new_element = (player->inventory_size > 0 ? + player->inventory_element[player->inventory_size - 1] : + player->inventory_infinite_element != EL_UNDEFINED ? + player->inventory_infinite_element : + player->dynabombs_left > 0 ? + EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr : + EL_UNDEFINED); /* check if player is active, not moving and ready to drop */ if (!player->active || player->MovPos || player->drop_delay > 0) return FALSE; /* check if player has anything that can be dropped */ - if (player->inventory_size == 0 && player->dynabombs_left == 0) +#if 1 + if (new_element == EL_UNDEFINED) + return FALSE; +#else + if (player->inventory_size == 0 && + player->inventory_infinite_element == EL_UNDEFINED && + player->dynabombs_left == 0) return FALSE; +#endif /* check if anything can be dropped at the current position */ if (IS_ACTIVE_BOMB(old_element) || old_element == EL_EXPLOSION) return FALSE; /* collected custom elements can only be dropped on empty fields */ +#if 1 + if (IS_CUSTOM_ELEMENT(new_element) && old_element != EL_EMPTY) + return FALSE; +#else if (player->inventory_size > 0 && IS_CUSTOM_ELEMENT(player->inventory_element[player->inventory_size - 1]) && old_element != EL_EMPTY) return FALSE; +#endif if (old_element != EL_EMPTY) Back[jx][jy] = old_element; /* store old element on this field */ @@ -9971,19 +10086,26 @@ boolean DropElement(struct PlayerInfo *player) ResetGfxAnimation(jx, jy); ResetRandomAnimationValue(jx, jy); - if (player->inventory_size > 0) + if (player->inventory_size > 0 || + player->inventory_infinite_element != EL_UNDEFINED) { - player->inventory_size--; - new_element = player->inventory_element[player->inventory_size]; + if (player->inventory_size > 0) + { + player->inventory_size--; - if (new_element == EL_DYNAMITE) - new_element = EL_DYNAMITE_ACTIVE; - else if (new_element == EL_SP_DISK_RED) - new_element = EL_SP_DISK_RED_ACTIVE; +#if 0 + new_element = player->inventory_element[player->inventory_size]; +#endif - Feld[jx][jy] = new_element; + DrawGameValue_Dynamite(local_player->inventory_size); - DrawGameValue_Dynamite(local_player->inventory_size); + if (new_element == EL_DYNAMITE) + new_element = EL_DYNAMITE_ACTIVE; + else if (new_element == EL_SP_DISK_RED) + new_element = EL_SP_DISK_RED_ACTIVE; + } + + Feld[jx][jy] = new_element; if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy))) DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0); @@ -10006,7 +10128,10 @@ boolean DropElement(struct PlayerInfo *player) else /* player is dropping a dyna bomb */ { player->dynabombs_left--; + +#if 0 new_element = EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr; +#endif Feld[jx][jy] = new_element; diff --git a/src/init.c b/src/init.c index ed480b14..a78ee611 100644 --- a/src/init.c +++ b/src/init.c @@ -1640,10 +1640,10 @@ void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set) if (bit_nr > -1) { - level->can_move_into_acid &= ~(1 << bit_nr); + level->can_move_into_acid_bits &= ~(1 << bit_nr); if (set) - level->can_move_into_acid |= (1 << bit_nr); + level->can_move_into_acid_bits |= (1 << bit_nr); } } @@ -1652,7 +1652,7 @@ boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element) int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID); if (bit_nr > -1) - return ((level->can_move_into_acid & (1 << bit_nr)) != 0); + return ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0); return FALSE; } diff --git a/src/main.c b/src/main.c index 5729b931..8dfd8930 100644 --- a/src/main.c +++ b/src/main.c @@ -90,7 +90,7 @@ int ZX, ZY; int ExitX, ExitY; int AllPlayersGone; -int TimeFrames, TimePlayed, TimeLeft; +int TimeFrames, TimePlayed, TimeLeft, TapeTime; boolean network_player_action_received = FALSE; diff --git a/src/main.h b/src/main.h index 370d2891..e40f4d88 100644 --- a/src/main.h +++ b/src/main.h @@ -1372,6 +1372,7 @@ struct PlayerInfo int shield_deadly_time_left; int inventory_element[MAX_INVENTORY_SIZE]; + int inventory_infinite_element; int inventory_size; }; @@ -1422,7 +1423,7 @@ struct LevelInfo int time_light; int time_timegate; - int can_move_into_acid; /* bits indicate property for element groups */ + int can_move_into_acid_bits; /* bits indicate property for element groups */ boolean double_speed; boolean initial_gravity; @@ -1431,6 +1432,8 @@ struct LevelInfo boolean sp_block_last_field; /* player blocks previous field while moving */ boolean use_spring_bug; /* for compatibility with old levels */ + int use_step_counter; /* count steps instead of seconds for level */ + short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; boolean use_custom_template; /* use custom properties from template file */ @@ -1843,7 +1846,7 @@ extern int ZX, ZY; extern int ExitX, ExitY; extern int AllPlayersGone; -extern int TimeFrames, TimePlayed, TimeLeft; +extern int TimeFrames, TimePlayed, TimeLeft, TapeTime; extern boolean SiebAktiv; extern int SiebCount; -- 2.34.1