X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=3ea77684d612d9913c01cf3afeff7201c1809c37;hb=efcb2b55f390a09641eab90dd3582bb3ef716664;hp=837d41036992abab6a31ddacf701f4de7c409f49;hpb=f2d0f3fed679ea3573f51aa298adce2d9a78d8be;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 837d4103..3ea77684 100644 --- a/src/game.c +++ b/src/game.c @@ -44,9 +44,14 @@ #define USE_GFX_RESET_GFX_ANIMATION (USE_NEW_STUFF * 1) #define USE_BOTH_SWITCHGATE_SWITCHES (USE_NEW_STUFF * 1) #define USE_PLAYER_GRAVITY (USE_NEW_STUFF * 1) +#define USE_FIXED_BORDER_RUNNING_GFX (USE_NEW_STUFF * 1) +#define USE_QUICKSAND_BD_ROCK_BUGFIX (USE_NEW_STUFF * 0) #define USE_QUICKSAND_IMPACT_BUGFIX (USE_NEW_STUFF * 0) +#define USE_CODE_THAT_BREAKS_SNAKE_BITE (USE_NEW_STUFF * 1) + + /* for DigField() */ #define DF_NO_PUSH 0 #define DF_DIG 1 @@ -1767,8 +1772,22 @@ static void InitGameEngine() { if (!IS_CUSTOM_ELEMENT(i)) { +#if 1 + /* set default push delay values (corrected since version 3.0.7-1) */ + if (game.engine_version < VERSION_IDENT(3,0,7,1)) + { + element_info[i].push_delay_fixed = 2; + element_info[i].push_delay_random = 8; + } + else + { + element_info[i].push_delay_fixed = 8; + element_info[i].push_delay_random = 8; + } +#else element_info[i].push_delay_fixed = game.default_push_delay_fixed; element_info[i].push_delay_random = game.default_push_delay_random; +#endif } } @@ -1979,6 +1998,8 @@ void InitGame() player->last_move_dir = MV_NONE; + player->is_active = FALSE; + player->is_waiting = FALSE; player->is_moving = FALSE; player->is_auto_moving = FALSE; @@ -5844,7 +5865,12 @@ void StartMoving(int x, int y) started_moving = TRUE; Feld[x][y] = EL_QUICKSAND_EMPTYING; +#if USE_QUICKSAND_BD_ROCK_BUGFIX + if (Store[x][y] != EL_ROCK && Store[x][y] != EL_BD_ROCK) + Store[x][y] = EL_ROCK; +#else Store[x][y] = EL_ROCK; +#endif PlayLevelSoundAction(x, y, ACTION_EMPTYING); } @@ -7787,7 +7813,8 @@ void MauerAbleger(int ax, int ay) if (element == EL_EXPANDABLE_WALL_HORIZONTAL || element == EL_EXPANDABLE_WALL_ANY || - element == EL_EXPANDABLE_WALL) + element == EL_EXPANDABLE_WALL || + element == EL_BD_EXPANDABLE_WALL) { if (links_frei) { @@ -8396,6 +8423,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) if (ei->collect_score == 0) { + int xx, yy; + #if 0 printf("::: CE_SCORE_GETS_ZERO\n"); #endif @@ -8406,6 +8435,26 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) #if 0 printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]); #endif + +#if 1 + /* + This is a very special case that seems to be a mixture between + CheckElementChange() and CheckTriggeredElementChange(): while + the first one only affects single elements that are triggered + directly, the second one affects multiple elements in the playfield + that are triggered indirectly by another element. This is a third + case: Changing the CE score always affects multiple identical CEs, + so every affected CE must be checked, not only the single CE for + which the CE score was changed in the first place (as every instance + of that CE shares the same CE score, and therefore also can change)! + */ + SCAN_PLAYFIELD(xx, yy) + { + if (Feld[xx][yy] == element) + CheckElementChange(xx, yy, element, EL_UNDEFINED, + CE_SCORE_GETS_ZERO); + } +#endif } } @@ -8436,8 +8485,15 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) #if USE_NEW_CUSTOM_VALUE int last_ce_value = CustomValue[x][y]; #endif - boolean add_player = (ELEM_IS_PLAYER(new_element) && - IS_WALKABLE(old_element)); + boolean new_element_is_player = ELEM_IS_PLAYER(new_element); + boolean add_player_onto_element = (new_element_is_player && +#if USE_CODE_THAT_BREAKS_SNAKE_BITE + /* this breaks SnakeBite when a snake is + halfway through a door that closes */ + /* NOW FIXED AT LEVEL INIT IN files.c */ + new_element != EL_SOKOBAN_FIELD_PLAYER && +#endif + IS_WALKABLE(old_element)); #if 0 /* check if element under the player changes from accessible to unaccessible @@ -8451,7 +8507,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) } #endif - if (!add_player) + if (!add_player_onto_element) { if (IS_MOVING(x, y) || IS_BLOCKED(x, y)) RemoveMovingField(x, y); @@ -8502,7 +8558,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) #endif /* "ChangeCount" not set yet to allow "entered by player" change one time */ - if (ELEM_IS_PLAYER(new_element)) + if (new_element_is_player) RelocatePlayer(x, y, new_element); if (is_change) @@ -9625,6 +9681,10 @@ void GameActions_EM_Main() for (i = 0; i < MAX_PLAYERS; i++) effective_action[i] = stored_player[i].effective_action; +#if 0 + printf("::: %04d: %08x\n", FrameCounter, effective_action[0]); +#endif + GameActions_EM(effective_action, warp_mode); CheckLevelTime(); @@ -9995,7 +10055,8 @@ void GameActions_RND() else if (element == EL_EXPANDABLE_WALL || element == EL_EXPANDABLE_WALL_HORIZONTAL || element == EL_EXPANDABLE_WALL_VERTICAL || - element == EL_EXPANDABLE_WALL_ANY) + element == EL_EXPANDABLE_WALL_ANY || + element == EL_BD_EXPANDABLE_WALL) MauerAbleger(x, y); else if (element == EL_FLAMES) CheckForDragon(x, y); @@ -10348,7 +10409,7 @@ static void CheckGravityMovement(struct PlayerInfo *player) { int move_dir_horizontal = player->effective_action & MV_HORIZONTAL; int move_dir_vertical = player->effective_action & MV_VERTICAL; - boolean player_is_snapping = player->effective_action & JOY_BUTTON_1; + boolean player_is_snapping = (player->effective_action & JOY_BUTTON_1); int jx = player->jx, jy = player->jy; boolean player_is_moving_to_valid_field = (!player_is_snapping && @@ -10571,6 +10632,8 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) player->move_delay_value = original_move_delay_value; } + player->is_active = FALSE; + if (player->last_move_dir & MV_HORIZONTAL) { if (!(moved |= MovePlayerOneStep(player, 0, dy, dx, dy))) @@ -10582,6 +10645,17 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) moved |= MovePlayerOneStep(player, 0, dy, dx, dy); } +#if USE_FIXED_BORDER_RUNNING_GFX + if (!moved && !player->is_active) + { + player->is_moving = FALSE; + player->is_digging = FALSE; + player->is_collecting = FALSE; + player->is_snapping = FALSE; + player->is_pushing = FALSE; + } +#endif + jx = player->jx; jy = player->jy; @@ -11681,6 +11755,8 @@ int DigField(struct PlayerInfo *player, game.engine_version >= VERSION_IDENT(2,2,0,0)) old_element = Back[jx][jy]; + /* checking here causes player to move into acid even if the current field + cannot be left to that direction */ #if 0 #if USE_FIXED_DONT_RUN_INTO if (player_can_move && DONT_RUN_INTO(element)) @@ -11702,6 +11778,43 @@ int DigField(struct PlayerInfo *player, #endif #endif +#if 1 /* ------------------------------ NEW ------------------------------ */ + + if (IS_WALKABLE(old_element) && !ACCESS_FROM(old_element, move_direction)) + return MP_NO_ACTION; /* field has no opening in this direction */ + + if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction)) + return MP_NO_ACTION; /* field has no opening in this direction */ + +#if USE_FIXED_DONT_RUN_INTO + if (player_can_move && element == EL_ACID && move_direction == MV_DOWN) + { + SplashAcid(x, y); +#if 1 + Feld[jx][jy] = player->artwork_element; +#else + Feld[jx][jy] = EL_PLAYER_1; +#endif + InitMovingField(jx, jy, MV_DOWN); + Store[jx][jy] = EL_ACID; + ContinueMoving(jx, jy); + BuryPlayer(player); + + return MP_DONT_RUN_INTO; + } +#endif + +#if USE_FIXED_DONT_RUN_INTO + if (player_can_move && DONT_RUN_INTO(element)) + { + TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir); + + return MP_DONT_RUN_INTO; + } +#endif + +#else /* ------------------------------ OLD ------------------------------ */ + #if 1 #if USE_FIXED_DONT_RUN_INTO if (player_can_move && DONT_RUN_INTO(element)) @@ -11719,6 +11832,7 @@ int DigField(struct PlayerInfo *player, if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction)) return MP_NO_ACTION; /* field has no opening in this direction */ + /* checking here causes player to explode when moving into acid */ #if 1 #if USE_FIXED_DONT_RUN_INTO if (player_can_move && element == EL_ACID && move_direction == MV_DOWN) @@ -11735,6 +11849,8 @@ int DigField(struct PlayerInfo *player, #endif #endif +#endif /* ------------------------------ END ------------------------------ */ + #if 0 #if USE_FIXED_DONT_RUN_INTO if (player_can_move && DONT_RUN_INTO(element)) @@ -11861,6 +11977,21 @@ int DigField(struct PlayerInfo *player, if (!player->key[EM_GATE_GRAY_ACTIVE_NR(element)]) return MP_NO_ACTION; } + else if (IS_EMC_GATE(element)) + { + if (!player->key[EMC_GATE_NR(element)]) + return MP_NO_ACTION; + } + else if (IS_EMC_GATE_GRAY(element)) + { + if (!player->key[EMC_GATE_GRAY_NR(element)]) + return MP_NO_ACTION; + } + else if (IS_EMC_GATE_GRAY_ACTIVE(element)) + { + if (!player->key[EMC_GATE_GRAY_ACTIVE_NR(element)]) + return MP_NO_ACTION; + } else if (IS_SP_PORT(element)) { if (element == EL_SP_GRAVITY_PORT_LEFT || @@ -12109,6 +12240,7 @@ int DigField(struct PlayerInfo *player, } player->is_pushing = TRUE; + player->is_active = TRUE; if (!(IN_LEV_FIELD(nextx, nexty) && (IS_FREE(nextx, nexty) || @@ -12361,7 +12493,10 @@ int DigField(struct PlayerInfo *player, if (is_player) /* function can also be called by EL_PENGUIN */ { if (Feld[x][y] != element) /* really digged/collected something */ + { player->is_collecting = !player->is_digging; + player->is_active = TRUE; + } } return MP_MOVING; @@ -12430,6 +12565,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) return FALSE; player->is_snapping = TRUE; + player->is_active = TRUE; if (player->MovPos == 0) {