X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=0efc0328827c6ce3f65b309b3a1c92356c8ddea4;hb=1c636a51bb573815d24a27dcc20b3283d89d1b8b;hp=7b225c5eac9621eb61e6ee2dc195b16d6a4b4c76;hpb=0ae305660baec1a7568ac7df7f296b695904d59a;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 7b225c5e..0efc0328 100644 --- a/src/game.c +++ b/src/game.c @@ -107,7 +107,7 @@ (condition) || \ (DONT_COLLIDE_WITH(e) && \ IS_PLAYER(x, y) && \ - !PLAYER_PROTECTED(x, y)))) + !PLAYER_ENEMY_PROTECTED(x, y)))) #else #define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition) \ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \ @@ -216,7 +216,8 @@ static void ScrollScreen(struct PlayerInfo *, int); static void InitBeltMovement(void); static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); -static void KillHeroUnlessProtected(int, int); +static void KillHeroUnlessEnemyProtected(int, int); +static void KillHeroUnlessExplosionProtected(int, int); static void TestIfPlayerTouchesCustomElement(int, int); static void TestIfElementTouchesCustomElement(int, int); @@ -606,6 +607,10 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) player->present = TRUE; + player->block_last_field = (element == EL_SP_MURPHY ? + level.sp_block_last_field : + level.block_last_field); + if (!options.network || player->connected) { player->active = TRUE; @@ -866,7 +871,7 @@ static void resolve_group_element(int group_element, int recursion_depth) group_element - EL_GROUP_START + 1); /* replace element which caused too deep recursion by question mark */ - group->element_resolved[group->num_elements_resolved++] = EL_CHAR_QUESTION; + group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN; return; } @@ -1105,6 +1110,19 @@ static void InitGameEngine() element_info[e].push_delay_random = push_delay_list[i].push_delay_random; } + /* set push delay value for Supaplex elements for newer engine versions */ + if (game.engine_version >= VERSION_IDENT(3,0,9,0)) + { + for (i = 0; i < MAX_NUM_ELEMENTS; i++) + { + if (IS_SP_ELEMENT(i)) + { + element_info[i].push_delay_fixed = 6; + element_info[i].push_delay_random = 0; + } + } + } + /* ---------- initialize move stepsize ----------------------------------- */ /* initialize move stepsize values to default */ @@ -1210,6 +1228,8 @@ void InitGame() player->use_murphy_graphic = FALSE; + player->block_last_field = FALSE; + player->actual_frame_counter = 0; player->step_counter = 0; @@ -1774,15 +1794,15 @@ void InitMovDir(int x, int y) int move_direction_initial = ei->move_direction_initial; int move_pattern = ei->move_pattern; - if (move_direction_initial == MV_PREVIOUS) + if (move_direction_initial == MV_START_PREVIOUS) { if (MovDir[x][y] != MV_NO_MOVING) return; - move_direction_initial = MV_AUTOMATIC; + move_direction_initial = MV_START_AUTOMATIC; } - if (move_direction_initial == MV_RANDOM) + if (move_direction_initial == MV_START_RANDOM) MovDir[x][y] = 1 << RND(4); else if (move_direction_initial & MV_ANY_DIRECTION) MovDir[x][y] = move_direction_initial; @@ -2319,6 +2339,10 @@ void CheckDynamite(int x, int y) void RelocatePlayer(int x, int y, int element) { struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1]; + boolean ffwd_delay = (tape.playing && tape.fast_forward); + boolean no_delay = (tape.index_search); + int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay); + int wait_delay_value = (no_delay ? 0 : frame_delay_value); if (player->GameOver) /* do not reanimate dead player */ return; @@ -2339,7 +2363,7 @@ void RelocatePlayer(int x, int y, int element) DrawPlayer(player); BackToFront(); - Delay(GAME_FRAME_DELAY); + Delay(wait_delay_value); } DrawPlayer(player); /* needed here only to cleanup last field */ @@ -2383,11 +2407,11 @@ void RelocatePlayer(int x, int y, int element) /* scroll in two steps of half tile size to make things smoother */ BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY); FlushDisplay(); - Delay(GAME_FRAME_DELAY); + Delay(wait_delay_value); /* scroll second step to align at full tile size */ BackToFront(); - Delay(GAME_FRAME_DELAY); + Delay(wait_delay_value); } } } @@ -2513,7 +2537,7 @@ void Explode(int ex, int ey, int phase, int mode) RemoveField(x, y); #endif - if (IS_PLAYER(ex, ey) && !PLAYER_PROTECTED(ex, ey)) + if (IS_PLAYER(ex, ey) && !PLAYER_EXPLOSION_PROTECTED(ex, ey)) { switch(StorePlayer[ex][ey]) { @@ -2656,7 +2680,7 @@ void Explode(int ex, int ey, int phase, int mode) int element = Store2[x][y]; if (IS_PLAYER(x, y)) - KillHeroUnlessProtected(x, y); + KillHeroUnlessExplosionProtected(x, y); else if (CAN_EXPLODE_BY_FIRE(element)) { Feld[x][y] = Store2[x][y]; @@ -2813,7 +2837,7 @@ void Bang(int x, int y) #endif #if 1 - if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y)) + if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y)) #else if (IS_PLAYER(x, y)) #endif @@ -3304,7 +3328,7 @@ void Impact(int x, int y) if (impact && element == EL_AMOEBA_DROP) { if (object_hit && IS_PLAYER(x, y + 1)) - KillHeroUnlessProtected(x, y + 1); + KillHeroUnlessEnemyProtected(x, y + 1); else if (object_hit && smashed == EL_PENGUIN) Bang(x, y + 1); else @@ -3346,7 +3370,7 @@ void Impact(int x, int y) { if (CAN_SMASH_PLAYER(element)) { - KillHeroUnlessProtected(x, y + 1); + KillHeroUnlessEnemyProtected(x, y + 1); return; } } @@ -4687,7 +4711,7 @@ void StartMoving(int x, int y) if (DONT_COLLIDE_WITH(element) && IN_LEV_FIELD(newx, newy) && IS_PLAYER(newx, newy) && - !PLAYER_PROTECTED(newx, newy)) + !PLAYER_ENEMY_PROTECTED(newx, newy)) { #if 1 TestIfBadThingRunsIntoHero(x, y, MovDir[x][y]); @@ -5238,15 +5262,7 @@ void ContinueMoving(int x, int y) #if 0 if (IN_LEV_FIELD(nextx, nexty)) { - static int opposite_directions[] = - { - MV_RIGHT, - MV_LEFT, - MV_DOWN, - MV_UP - }; - int move_dir_bit = MV_DIR_BIT(direction); - int opposite_direction = opposite_directions[move_dir_bit]; + int opposite_direction = MV_DIR_OPPOSITE(direction); int hitting_side = direction; int touched_side = opposite_direction; int touched_element = MovingOrBlocked2Element(nextx, nexty); @@ -6209,7 +6225,7 @@ static void ChangeElementNowExt(int x, int y, int target_element) /* check if element under player changes from accessible to unaccessible (needed for special case of dropping element which then changes) */ - if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) && + if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) && IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element)) { Bang(x, y); @@ -6224,7 +6240,7 @@ static void ChangeElementNowExt(int x, int y, int target_element) ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); - if (element_info[Feld[x][y]].move_direction_initial == MV_PREVIOUS) + if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS) MovDir[x][y] = previous_move_direction; InitField(x, y, FALSE); @@ -7991,6 +8007,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) #if 0 DrawPlayer(player); #endif + return; } else if (!FrameReached(&player->actual_frame_counter, 1)) @@ -7999,7 +8016,8 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); - if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) + if (!player->block_last_field && + Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) Feld[last_jx][last_jy] = EL_EMPTY; /* before DrawPlayer() to draw correct player graphic for this case */ @@ -8037,6 +8055,10 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) } #endif + if (player->block_last_field && + Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) + Feld[last_jx][last_jy] = EL_EMPTY; + player->last_jx = jx; player->last_jy = jy; @@ -8308,15 +8330,7 @@ void TestIfElementHitsCustomElement(int x, int y, int direction) if (IN_LEV_FIELD(hitx, hity)) { - static int opposite_directions[] = - { - MV_RIGHT, - MV_LEFT, - MV_DOWN, - MV_UP - }; - int move_dir_bit = MV_DIR_BIT(direction); - int opposite_direction = opposite_directions[move_dir_bit]; + int opposite_direction = MV_DIR_OPPOSITE(direction); int hitting_side = direction; int touched_side = opposite_direction; int touched_element = MovingOrBlocked2Element(hitx, hity); @@ -8445,7 +8459,7 @@ void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir) if (player->shield_deadly_time_left > 0) Bang(kill_x, kill_y); - else if (!PLAYER_PROTECTED(good_x, good_y)) + else if (!PLAYER_ENEMY_PROTECTED(good_x, good_y)) KillHero(player); } else @@ -8537,7 +8551,7 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) if (player->shield_deadly_time_left > 0) Bang(bad_x, bad_y); - else if (!PLAYER_PROTECTED(kill_x, kill_y)) + else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y)) KillHero(player); } else @@ -8627,9 +8641,15 @@ void KillHero(struct PlayerInfo *player) BuryHero(player); } -static void KillHeroUnlessProtected(int x, int y) +static void KillHeroUnlessEnemyProtected(int x, int y) +{ + if (!PLAYER_ENEMY_PROTECTED(x, y)) + KillHero(PLAYERINFO(x, y)); +} + +static void KillHeroUnlessExplosionProtected(int x, int y) { - if (!PLAYER_PROTECTED(x, y)) + if (!PLAYER_EXPLOSION_PROTECTED(x, y)) KillHero(PLAYERINFO(x, y)); } @@ -9498,6 +9518,11 @@ boolean DropElement(struct PlayerInfo *player) PlayLevelSoundAction(jx, jy, ACTION_DROPPING); +#if 1 + /* needed if previous element just changed to "empty" in the last frame */ + Changed[jx][jy] = 0; /* allow another change */ +#endif + CheckTriggeredElementChange(jx, jy, new_element, CE_OTHER_GETS_DROPPED); CheckElementChange(jx, jy, new_element, CE_DROPPED_BY_PLAYER); @@ -9535,7 +9560,7 @@ boolean DropElement(struct PlayerInfo *player) int move_stepsize = element_info[new_element].move_stepsize; int direction, dx, dy, nextx, nexty; - if (element_info[new_element].move_direction_initial == MV_AUTOMATIC) + if (element_info[new_element].move_direction_initial == MV_START_AUTOMATIC) MovDir[jx][jy] = player->MovDir; direction = MovDir[jx][jy]; @@ -9555,7 +9580,7 @@ boolean DropElement(struct PlayerInfo *player) } else { - Changed[jx][jy] = 0; /* allow another change */ + Changed[jx][jy] = 0; /* allow another change */ #if 1 TestIfElementHitsCustomElement(jx, jy, direction);