X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=2ccc79cd1ca3c16341cfdf204b3a052249ba2e1c;hp=5968b1ded7e0abc96e391632bb64cae47c948050;hb=3915df993ef01086469a8a7f575b2525e9887f65;hpb=de5140b18022b8d5db653e1175e7ffd202b2645d diff --git a/src/game.c b/src/game.c index 5968b1de..2ccc79cd 100644 --- a/src/game.c +++ b/src/game.c @@ -1119,6 +1119,8 @@ void ExitPlayer(struct PlayerInfo *); static int getInvisibleActiveFromInvisibleElement(int); static int getInvisibleFromInvisibleActiveElement(int); +static void TestFieldAfterSnapping(int, int, int, int, int); + static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; // for detection of endless loops, caused by custom element programming @@ -3717,6 +3719,8 @@ void InitGame(void) player->shield_normal_time_left = 0; player->shield_deadly_time_left = 0; + player->last_removed_element = EL_UNDEFINED; + player->inventory_infinite_element = EL_UNDEFINED; player->inventory_size = 0; @@ -4714,7 +4718,7 @@ void GameWon(void) { static int time_count_steps; static int time, time_final; - static int score, score_final; + static float score, score_final; // needed for time score < 10 for 10 seconds static int health, health_final; static int game_over_delay_1 = 0; static int game_over_delay_2 = 0; @@ -4722,6 +4726,8 @@ void GameWon(void) int game_over_delay_value_1 = 50; int game_over_delay_value_2 = 25; int game_over_delay_value_3 = 50; + int time_score_base = MIN(MAX(1, level.time_score_base), 10); + float time_score = (float)level.score[SC_TIME_BONUS] / time_score_base; if (!game.LevelSolved_GameWon) { @@ -4755,19 +4761,23 @@ void GameWon(void) score = score_final = game.score_final; health = health_final = game.health_final; - if (level.score[SC_TIME_BONUS] > 0) + if (time_score > 0) { + int time_frames = 0; + if (TimeLeft > 0) { time_final = 0; - score_final += TimeLeft * level.score[SC_TIME_BONUS]; + time_frames = TimeLeft * FRAMES_PER_SECOND - TimeFrames; } else if (game.no_time_limit && TimePlayed < 999) { time_final = 999; - score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS]; + time_frames = (999 - TimePlayed) * FRAMES_PER_SECOND - TimeFrames; } + score_final += time_score * time_frames / FRAMES_PER_SECOND + 0.5; + time_count_steps = MAX(1, ABS(time_final - time) / 100); game_over_delay_1 = game_over_delay_value_1; @@ -4775,7 +4785,7 @@ void GameWon(void) if (level.game_engine_type == GAME_ENGINE_TYPE_MM) { health_final = 0; - score_final += health * level.score[SC_TIME_BONUS]; + score_final += health * time_score; game_over_delay_2 = game_over_delay_value_2; } @@ -4864,7 +4874,11 @@ void GameWon(void) time_count_steps = 1; time += time_count_steps * time_count_dir; - score += time_count_steps * level.score[SC_TIME_BONUS]; + score += time_count_steps * time_score; + + // set final score to correct rounding differences after counting score + if (time == time_final) + score = score_final; game.LevelSolved_CountingTime = time; game.LevelSolved_CountingScore = score; @@ -4896,7 +4910,7 @@ void GameWon(void) int health_count_dir = (health < health_final ? +1 : -1); health += health_count_dir; - score += level.score[SC_TIME_BONUS]; + score += time_score; game.LevelSolved_CountingHealth = health; game.LevelSolved_CountingScore = score; @@ -12040,10 +12054,17 @@ void GameActions_RND(void) MovDelay[x][y]--; if (MovDelay[x][y] <= 0) { + int element = Store[x][y]; + int move_direction = MovDir[x][y]; + int player_index_bit = Store2[x][y]; + + Store[x][y] = 0; + Store2[x][y] = 0; + RemoveField(x, y); TEST_DrawLevelField(x, y); - TestIfElementTouchesCustomElement(x, y); // for empty space + TestFieldAfterSnapping(x, y, element, move_direction, player_index_bit); } } @@ -13044,6 +13065,21 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if (!player->is_pushing) TestIfElementTouchesCustomElement(jx, jy); // for empty space + if (level.finish_dig_collect && + (player->is_digging || player->is_collecting)) + { + int last_element = player->last_removed_element; + int move_direction = player->MovDir; + int enter_side = MV_DIR_OPPOSITE(move_direction); + int change_event = (player->is_digging ? CE_PLAYER_DIGS_X : + CE_PLAYER_COLLECTS_X); + + CheckTriggeredElementChangeByPlayer(jx, jy, last_element, change_event, + player->index_bit, enter_side); + + player->last_removed_element = EL_UNDEFINED; + } + if (!player->active) RemovePlayer(player); } @@ -13778,7 +13814,8 @@ void ExitPlayer(struct PlayerInfo *player) game.players_still_needed--; } -static void setFieldForSnapping(int x, int y, int element, int direction) +static void SetFieldForSnapping(int x, int y, int element, int direction, + int player_index_bit) { struct ElementInfo *ei = &element_info[element]; int direction_bit = MV_DIR_TO_BIT(direction); @@ -13788,6 +13825,9 @@ static void setFieldForSnapping(int x, int y, int element, int direction) Tile[x][y] = EL_ELEMENT_SNAPPING; MovDelay[x][y] = MOVE_DELAY_NORMAL_SPEED + 1 - 1; + MovDir[x][y] = direction; + Store[x][y] = element; + Store2[x][y] = player_index_bit; ResetGfxAnimation(x, y); @@ -13797,6 +13837,20 @@ static void setFieldForSnapping(int x, int y, int element, int direction) GfxFrame[x][y] = -1; } +static void TestFieldAfterSnapping(int x, int y, int element, int direction, + int player_index_bit) +{ + TestIfElementTouchesCustomElement(x, y); // for empty space + + if (level.finish_dig_collect) + { + int dig_side = MV_DIR_OPPOSITE(direction); + + CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X, + player_index_bit, dig_side); + } +} + /* ============================================================================= checkDiagonalPushing() @@ -14076,22 +14130,28 @@ static int DigField(struct PlayerInfo *player, PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING); - CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X, - player->index_bit, dig_side); + // use old behaviour for old levels (digging) + if (!level.finish_dig_collect) + { + CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X, + player->index_bit, dig_side); - // if digging triggered player relocation, finish digging tile - if (mode == DF_DIG && (player->jx != jx || player->jy != jy)) - setFieldForSnapping(x, y, element, move_direction); + // if digging triggered player relocation, finish digging tile + if (mode == DF_DIG && (player->jx != jx || player->jy != jy)) + SetFieldForSnapping(x, y, element, move_direction, player->index_bit); + } if (mode == DF_SNAP) { if (level.block_snap_field) - setFieldForSnapping(x, y, element, move_direction); + SetFieldForSnapping(x, y, element, move_direction, player->index_bit); else - TestIfElementTouchesCustomElement(x, y); // for empty space + TestFieldAfterSnapping(x, y, element, move_direction, player->index_bit); - CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X, - player->index_bit, dig_side); + // use old behaviour for old levels (snapping) + if (!level.finish_dig_collect) + CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X, + player->index_bit, dig_side); } } else if (player_can_move_or_snap && IS_COLLECTIBLE(element)) @@ -14203,25 +14263,28 @@ static int DigField(struct PlayerInfo *player, RaiseScoreElement(element); PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING); - if (is_player) + // use old behaviour for old levels (collecting) + if (!level.finish_dig_collect && is_player) { CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_COLLECTS_X, player->index_bit, dig_side); // if collecting triggered player relocation, finish collecting tile if (mode == DF_DIG && (player->jx != jx || player->jy != jy)) - setFieldForSnapping(x, y, element, move_direction); + SetFieldForSnapping(x, y, element, move_direction, player->index_bit); } if (mode == DF_SNAP) { if (level.block_snap_field) - setFieldForSnapping(x, y, element, move_direction); + SetFieldForSnapping(x, y, element, move_direction, player->index_bit); else - TestIfElementTouchesCustomElement(x, y); // for empty space + TestFieldAfterSnapping(x, y, element, move_direction, player->index_bit); - CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X, - player->index_bit, dig_side); + // use old behaviour for old levels (snapping) + if (!level.finish_dig_collect) + CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X, + player->index_bit, dig_side); } } else if (player_can_move_or_snap && IS_PUSHABLE(element)) @@ -14559,6 +14622,8 @@ static int DigField(struct PlayerInfo *player, { player->is_collecting = !player->is_digging; player->is_active = TRUE; + + player->last_removed_element = element; } }