X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=06de1e48621fab80bf5e0595823c6814083eefd2;hb=d3ffb1e08b58d32e36682e8376c26dd5585bb421;hp=08fee26493a335478bbff0302e66a297c0d5d788;hpb=174df2f6abf5f72b5539176a2591a3c1ee83f045;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 08fee264..06de1e48 100644 --- a/src/game.c +++ b/src/game.c @@ -25,10 +25,13 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_STUFF (TRUE * 1) +#define USE_NEW_STUFF ( * 1) -#define USE_NEW_SP_SLIPPERY (TRUE * USE_NEW_STUFF * 1) -#define USE_NEW_COLLECT_COUNT (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_SP_SLIPPERY (USE_NEW_STUFF * 1) +#define USE_NEW_COLLECT_COUNT (USE_NEW_STUFF * 1) +#define USE_NEW_PLAYER_ANIM (USE_NEW_STUFF * 1) +#define USE_NEW_ALL_SLIPPERY (USE_NEW_STUFF * 1) +#define USE_NEW_PLAYER_SPEED (USE_NEW_STUFF * 1) /* for DigField() */ @@ -89,16 +92,25 @@ #define INITIAL_MOVE_DELAY_ON 0 /* values for player movement speed (which is in fact a delay value) */ +#define MOVE_DELAY_MIN_SPEED 32 #define MOVE_DELAY_NORMAL_SPEED 8 #define MOVE_DELAY_HIGH_SPEED 4 +#define MOVE_DELAY_MAX_SPEED 1 +#if 0 #define DOUBLE_MOVE_DELAY(x) (x = (x <= MOVE_DELAY_HIGH_SPEED ? x * 2 : x)) #define HALVE_MOVE_DELAY(x) (x = (x >= MOVE_DELAY_HIGH_SPEED ? x / 2 : x)) +#else +#define DOUBLE_MOVE_DELAY(x) (x = (x < MOVE_DELAY_MIN_SPEED ? x * 2 : x)) +#define HALVE_MOVE_DELAY(x) (x = (x > MOVE_DELAY_MAX_SPEED ? x / 2 : x)) +#endif #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value)) #define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value)) /* values for other actions */ #define MOVE_STEPSIZE_NORMAL (TILEX / MOVE_DELAY_NORMAL_SPEED) +#define MOVE_STEPSIZE_MIN (1) +#define MOVE_STEPSIZE_MAX (TILEX) #define GET_DX_FROM_DIR(d) ((d) == MV_LEFT ? -1 : (d) == MV_RIGHT ? 1 : 0) #define GET_DY_FROM_DIR(d) ((d) == MV_UP ? -1 : (d) == MV_DOWN ? 1 : 0) @@ -233,8 +245,8 @@ 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); +static void KillPlayerUnlessEnemyProtected(int, int); +static void KillPlayerUnlessExplosionProtected(int, int); static void TestIfPlayerTouchesCustomElement(int, int); static void TestIfElementTouchesCustomElement(int, int); @@ -1572,6 +1584,8 @@ void InitGame() player->move_delay = game.initial_move_delay; player->move_delay_value = game.initial_move_delay_value; + player->move_delay_value_next = -1; + player->move_delay_reset_counter = 0; player->push_delay = -1; /* initialized when pushing starts */ @@ -1699,6 +1713,26 @@ void InitGame() emulate_sb ? EMU_SOKOBAN : emulate_sp ? EMU_SUPAPLEX : EMU_NONE); +#if USE_NEW_ALL_SLIPPERY + /* initialize type of slippery elements */ + for (i = 0; i < MAX_NUM_ELEMENTS; i++) + { + if (!IS_CUSTOM_ELEMENT(i)) + { + /* default: elements slip down either to the left or right randomly */ + element_info[i].slippery_type = SLIPPERY_ANY_RANDOM; + + /* SP style elements prefer to slip down on the left side */ + if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i)) + element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT; + + /* BD style elements prefer to slip down on the left side */ + if (game.emulation == EMU_BOULDERDASH) + element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT; + } + } +#endif + /* initialize explosion and ignition delay */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) { @@ -2299,7 +2333,7 @@ void GameWon() PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING); } - /* Hero disappears */ + /* player disappears */ if (ExitX >= 0 && ExitY >= 0) DrawLevelField(ExitX, ExitY); @@ -2867,7 +2901,7 @@ void RelocatePlayer(int jx, int jy, int el_player_raw) if (player == local_player) /* only visually relocate local player */ DrawRelocatePlayer(player); - TestIfHeroTouchesBadThing(jx, jy); + TestIfPlayerTouchesBadThing(jx, jy); TestIfPlayerTouchesCustomElement(jx, jy); if (IS_CUSTOM_ELEMENT(element)) @@ -3118,7 +3152,7 @@ void Explode(int ex, int ey, int phase, int mode) if (IS_PLAYER(x, y) && PLAYERINFO(x, y)->present && !PLAYER_EXPLOSION_PROTECTED(x, y)) { - KillHeroUnlessExplosionProtected(x, y); + KillPlayerUnlessExplosionProtected(x, y); border_explosion = TRUE; } else if (CAN_EXPLODE_BY_EXPLOSION(border_element)) @@ -3712,7 +3746,7 @@ void Impact(int x, int y) if (impact && element == EL_AMOEBA_DROP) { if (object_hit && IS_PLAYER(x, y + 1)) - KillHeroUnlessEnemyProtected(x, y + 1); + KillPlayerUnlessEnemyProtected(x, y + 1); else if (object_hit && smashed == EL_PENGUIN) Bang(x, y + 1); else @@ -3754,7 +3788,7 @@ void Impact(int x, int y) { if (CAN_SMASH_PLAYER(element)) { - KillHeroUnlessEnemyProtected(x, y + 1); + KillPlayerUnlessEnemyProtected(x, y + 1); return; } } @@ -4757,11 +4791,26 @@ void StartMoving(int x, int y) Feld[x + 1][y + 1] == EL_ACID)); boolean can_fall_any = (can_fall_left || can_fall_right); boolean can_fall_both = (can_fall_left && can_fall_right); + int slippery_type = element_info[Feld[x][y + 1]].slippery_type; - if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1])) +#if USE_NEW_ALL_SLIPPERY + if (can_fall_any && slippery_type != SLIPPERY_ANY_RANDOM) { - int slippery_type = element_info[Feld[x][y + 1]].slippery_type; + if (slippery_type == SLIPPERY_ANY_LEFT_RIGHT && can_fall_both) + can_fall_right = FALSE; + else if (slippery_type == SLIPPERY_ANY_RIGHT_LEFT && can_fall_both) + can_fall_left = FALSE; + else if (slippery_type == SLIPPERY_ONLY_LEFT) + can_fall_right = FALSE; + else if (slippery_type == SLIPPERY_ONLY_RIGHT) + can_fall_left = FALSE; + can_fall_any = (can_fall_left || can_fall_right); + can_fall_both = FALSE; + } +#else + if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1])) + { if (slippery_type == SLIPPERY_ONLY_LEFT) can_fall_right = FALSE; else if (slippery_type == SLIPPERY_ONLY_RIGHT) @@ -4774,7 +4823,10 @@ void StartMoving(int x, int y) can_fall_any = (can_fall_left || can_fall_right); can_fall_both = (can_fall_left && can_fall_right); } +#endif +#if USE_NEW_ALL_SLIPPERY +#else #if USE_NEW_SP_SLIPPERY /* !!! better use the same properties as for custom elements here !!! */ else if (game.engine_version >= VERSION_IDENT(3,1,1,0) && @@ -4784,7 +4836,19 @@ void StartMoving(int x, int y) can_fall_both = FALSE; } #endif +#endif + +#if USE_NEW_ALL_SLIPPERY + if (can_fall_both) + { + if (element == EL_BD_ROCK || element == EL_BD_DIAMOND) + can_fall_right = FALSE; /* slip down on left side */ + else + can_fall_left = !(can_fall_right = RND(2)); + can_fall_both = FALSE; + } +#else if (can_fall_both) { if (game.emulation == EMU_BOULDERDASH || @@ -4795,6 +4859,7 @@ void StartMoving(int x, int y) can_fall_both = FALSE; } +#endif if (can_fall_any) { @@ -4997,7 +5062,7 @@ void StartMoving(int x, int y) IN_LEV_FIELD(newx, newy) && IS_PLAYER(newx, newy) && !PLAYER_ENEMY_PROTECTED(newx, newy)) { - TestIfBadThingRunsIntoHero(x, y, MovDir[x][y]); + TestIfBadThingRunsIntoPlayer(x, y, MovDir[x][y]); return; } @@ -5298,7 +5363,7 @@ void StartMoving(int x, int y) DrawLevelElementAnimation(x, y, element); if (DONT_TOUCH(element)) - TestIfBadThingTouchesHero(x, y); + TestIfBadThingTouchesPlayer(x, y); return; } @@ -5312,11 +5377,6 @@ void StartMoving(int x, int y) ContinueMoving(x, y); } -/* (emacs is confused here for some reason; this makes it happy again ;-) ) */ -void dummy() -{ -} - void ContinueMoving(int x, int y) { int element = Feld[x][y]; @@ -5525,7 +5585,7 @@ void ContinueMoving(int x, int y) if (DONT_TOUCH(element)) /* object may be nasty to player or others */ { - TestIfBadThingTouchesHero(newx, newy); + TestIfBadThingTouchesPlayer(newx, newy); TestIfBadThingTouchesFriend(newx, newy); if (!IS_CUSTOM_ELEMENT(element)) @@ -6441,14 +6501,15 @@ static int getSpecialActionElement(int element, int number, int base_element) EL_EMPTY); } -static int getModifiedActionNumber(int value_old, int value_min, int value_max, - int operator, int operand) +static int getModifiedActionNumber(int value_old, int operator, int operand, + int value_min, int value_max) { - int value_new = (operator == CA_MODE_ADD ? value_old + operand : + int value_new = (operator == CA_MODE_SET ? operand : + operator == CA_MODE_ADD ? value_old + operand : operator == CA_MODE_SUBTRACT ? value_old - operand : operator == CA_MODE_MULTIPLY ? value_old * operand : operator == CA_MODE_DIVIDE ? value_old / MAX(1, operand) : - operator == CA_MODE_SET ? operand : + operator == CA_MODE_MODULO ? value_old % MAX(1, operand) : value_old); return (value_new < value_min ? value_min : @@ -6476,10 +6537,38 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_arg == CA_ARG_ELEMENT_TARGET ? change->target_element : EL_EMPTY); + int action_arg_number_min = + (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MIN : + CA_ARG_MIN); + + int action_arg_number_max = + (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MAX : + action_type == CA_SET_GEMS ? 999 : + action_type == CA_SET_TIME ? 9999 : + action_type == CA_SET_SCORE ? 99999 : + action_type == CA_SET_CE_SCORE ? 9999 : + action_type == CA_SET_CE_COUNT ? 9999 : + CA_ARG_MAX); + + int action_arg_number_reset = + (action_type == CA_SET_PLAYER_SPEED ? TILEX/game.initial_move_delay_value : + action_type == CA_SET_GEMS ? level.gems_needed : + action_type == CA_SET_TIME ? level.time : + action_type == CA_SET_SCORE ? 0 : + action_type == CA_SET_CE_SCORE ? 0 : + action_type == CA_SET_CE_COUNT ? ei->collect_count_initial : + 0); + + int action_arg_number_normal = + (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_NORMAL : + action_arg_number_reset); + int action_arg_number = (action_arg <= CA_ARG_MAX ? action_arg : - action_arg == CA_ARG_NUMBER_MIN ? CA_ARG_MIN : - action_arg == CA_ARG_NUMBER_MAX ? CA_ARG_MAX : + action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min : + action_arg == CA_ARG_NUMBER_MAX ? action_arg_number_max : + action_arg == CA_ARG_NUMBER_RESET ? action_arg_number_reset : + action_arg == CA_ARG_NUMBER_NORMAL ? action_arg_number_normal : action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score : #if USE_NEW_COLLECT_COUNT action_arg == CA_ARG_NUMBER_CE_COUNT ? Count[x][y] : @@ -6489,6 +6578,19 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CHANGE_DELAY(change) : -1); + int action_arg_number_old = + (action_type == CA_SET_GEMS ? local_player->gems_still_needed : + action_type == CA_SET_TIME ? TimeLeft : + action_type == CA_SET_SCORE ? local_player->score : + action_type == CA_SET_CE_SCORE ? ei->collect_score : + action_type == CA_SET_CE_COUNT ? Count[x][y] : + 0); + + int action_arg_number_new = + getModifiedActionNumber(action_arg_number_old, + action_mode, action_arg_number, + action_arg_number_min, action_arg_number_max); + /* (for explicit player choice, set invalid value to "no player") */ int action_arg_player_bits = (action_arg == CA_ARG_PLAYER_ANY ? action_arg - CA_ARG_PLAYER : @@ -6530,7 +6632,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { for (i = 0; i < MAX_PLAYERS; i++) if (action_arg_player_bits & (1 << i)) - KillHero(&stored_player[i]); + KillPlayer(&stored_player[i]); break; } @@ -6605,38 +6707,33 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { if (trigger_player_bits & (1 << i)) { - if (action_arg == CA_ARG_NUMBER_RESET) - stored_player[i].move_delay_value = game.initial_move_delay_value; - else if (action_arg == CA_ARG_NUMBER_NORMAL) - stored_player[i].move_delay_value = MOVE_DELAY_NORMAL_SPEED; - else if (action_arg == CA_ARG_NUMBER_MIN) - stored_player[i].move_delay_value = 16; - else if (action_arg == CA_ARG_NUMBER_MAX) - stored_player[i].move_delay_value = MOVE_DELAY_HIGH_SPEED; - else + int move_stepsize = TILEX / stored_player[i].move_delay_value; + + if (action_mode == CA_MODE_ADD || action_mode == CA_MODE_SUBTRACT) { -#if 0 - if (action_mode == CA_MODE_ADD) - { - action_mode = CA_MODE_DIVIDE; - action_arg_number = (1 << action_arg_number); - } - else if (action_mode == CA_MODE_SUBTRACT) - { - action_mode = CA_MODE_MULTIPLY; - action_arg_number = (1 << action_arg_number); - } + /* translate "+" and "-" to "*" and "/" with powers of two */ + action_arg_number = 1 << action_arg_number; + action_mode = (action_mode == CA_MODE_ADD ? CA_MODE_MULTIPLY : + CA_MODE_DIVIDE); + } + + move_stepsize = + getModifiedActionNumber(move_stepsize, + action_mode, + action_arg_number, + action_arg_number_min, + action_arg_number_max); - int mode = (action_mode == CA_MODE_MULTIPLY ? CA_MODE_DIVIDE : - action_mode == CA_MODE_DIVIDE ? CA_MODE_MULTIPLY : - action_mode); + /* make sure that value is power of 2 */ + move_stepsize = (1 << log_2(move_stepsize)); - stored_player[i].move_delay_value = - getModifiedActionNumber(stored_player[i].move_delay_value, - 1, 16, - action_mode, action_arg_number); + /* do no immediately change -- the player might just be moving */ + stored_player[i].move_delay_value_next = TILEX / move_stepsize; + +#if 0 + printf("::: move_delay_value == %d [%d]\n", + stored_player[i].move_delay_value_next, action_arg_number); #endif - } } } @@ -6645,9 +6742,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) case CA_SET_GEMS: { - local_player->gems_still_needed = - getModifiedActionNumber(local_player->gems_still_needed, 0, 999, - action_mode, action_arg_number); + local_player->gems_still_needed = action_arg_number_new; DrawGameValue_Emeralds(local_player->gems_still_needed); @@ -6658,10 +6753,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { if (level.time > 0) /* only modify limited time value */ { - TimeLeft = getModifiedActionNumber(TimeLeft, 0, 9999, - action_mode, action_arg_number); + TimeLeft = action_arg_number_new; DrawGameValue_Time(TimeLeft); + + if (!TimeLeft && setup.time_limit) + for (i = 0; i < MAX_PLAYERS; i++) + KillPlayer(&stored_player[i]); } break; @@ -6669,9 +6767,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) case CA_SET_SCORE: { - local_player->score = - getModifiedActionNumber(local_player->score, 0, 9999, - action_mode, action_arg_number); + local_player->score = action_arg_number_new; DrawGameValue_Score(local_player->score); @@ -6680,9 +6776,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) case CA_SET_CE_SCORE: { - ei->collect_score = - getModifiedActionNumber(ei->collect_score, 0, 9999, - action_mode, action_arg_number); + ei->collect_score = action_arg_number_new; + break; } @@ -6691,8 +6786,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) #if USE_NEW_COLLECT_COUNT int count_last = Count[x][y]; - Count[x][y] = getModifiedActionNumber(Count[x][y], 0, 9999, - action_mode, action_arg_number); + Count[x][y] = action_arg_number_new; #if 0 printf("::: Count == %d\n", Count[x][y]); @@ -6808,7 +6902,7 @@ static void ChangeElementNowExt(struct ElementChangeInfo *change, Changed[x][y] |= ChangeEvent[x][y]; /* ignore same changes in this frame */ #endif - TestIfBadThingTouchesHero(x, y); + TestIfBadThingTouchesPlayer(x, y); TestIfPlayerTouchesCustomElement(x, y); TestIfElementTouchesCustomElement(x, y); } @@ -6980,7 +7074,8 @@ static void ChangeElement(int x, int y, int page) struct ElementChangeInfo *change = &ei->change_page[page]; #ifdef DEBUG - if (!CAN_CHANGE(element) && !CAN_CHANGE(Back[x][y])) + if (!CAN_CHANGE_OR_HAS_ACTION(element) && + !CAN_CHANGE_OR_HAS_ACTION(Back[x][y])) { printf("\n\n"); printf("ChangeElement(): %d,%d: element = %d ('%s')\n", @@ -6991,7 +7086,7 @@ static void ChangeElement(int x, int y, int page) #endif /* this can happen with classic bombs on walkable, changing elements */ - if (!CAN_CHANGE(element)) + if (!CAN_CHANGE_OR_HAS_ACTION(element)) { #if 0 if (!CAN_CHANGE(Back[x][y])) /* prevent permanent repetition */ @@ -7005,24 +7100,30 @@ static void ChangeElement(int x, int y, int page) { ChangeDelay[x][y] = GET_CHANGE_DELAY(change) + 1; - ResetGfxAnimation(x, y); - ResetRandomAnimationValue(x, y); + if (change->can_change) + { + ResetGfxAnimation(x, y); + ResetRandomAnimationValue(x, y); - if (change->pre_change_function) - change->pre_change_function(x, y); + if (change->pre_change_function) + change->pre_change_function(x, y); + } } ChangeDelay[x][y]--; if (ChangeDelay[x][y] != 0) /* continue element change */ { - int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); + if (change->can_change) + { + int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); - if (IS_ANIMATED(graphic)) - DrawLevelGraphicAnimationIfNeeded(x, y, graphic); + if (IS_ANIMATED(graphic)) + DrawLevelGraphicAnimationIfNeeded(x, y, graphic); - if (change->change_function) - change->change_function(x, y); + if (change->change_function) + change->change_function(x, y); + } } else /* finish element change */ { @@ -7042,11 +7143,17 @@ static void ChangeElement(int x, int y, int page) return; } - if (ChangeElementNow(x, y, element, page)) + if (change->can_change) { - if (change->post_change_function) - change->post_change_function(x, y); + if (ChangeElementNow(x, y, element, page)) + { + if (change->post_change_function) + change->post_change_function(x, y); + } } + + if (change->has_action) + ExecuteCustomElementAction(x, y, element, page); } } @@ -7101,9 +7208,13 @@ static boolean CheckTriggeredElementChangeExt(int trigger_element, ChangeEvent[x][y] = trigger_event; ChangeElement(x, y, p); } - +#if 1 + else if (change->has_action) + ExecuteCustomElementAction(x, y, element, p); +#else if (change->has_action) ExecuteCustomElementAction(x, y, element, p); +#endif } } @@ -7170,9 +7281,13 @@ static boolean CheckElementChangeExt(int x, int y, change_done = TRUE; } - +#if 1 + else if (change->has_action) + ExecuteCustomElementAction(x, y, element, p); +#else if (change->has_action) ExecuteCustomElementAction(x, y, element, p); +#endif } } @@ -7413,12 +7528,25 @@ void AdvanceFrameAndPlayerCounters(int player_nr) for (i = 0; i < MAX_PLAYERS; i++) { boolean advance_player_counters = (player_nr == -1 || player_nr == i); - int move_frames = - MOVE_DELAY_NORMAL_SPEED / stored_player[i].move_delay_value; + int move_delay_value = stored_player[i].move_delay_value; + int move_frames = MOVE_DELAY_NORMAL_SPEED / move_delay_value; if (!advance_player_counters) /* not all players may be affected */ continue; +#if USE_NEW_PLAYER_ANIM + if (move_frames == 0) /* less than one move per game frame */ + { + int stepsize = TILEX / move_delay_value; + int delay = move_delay_value / MOVE_DELAY_NORMAL_SPEED; + int count = (stored_player[i].is_moving ? + ABS(stored_player[i].MovPos) / stepsize : FrameCounter); + + if (count % delay == 0) + move_frames = 1; + } +#endif + stored_player[i].Frame += move_frames; if (stored_player[i].MovPos != 0) @@ -7672,11 +7800,25 @@ void GameActions() if (IS_CHANGING(x, y) && (game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y])) { + int page = element_info[element].event_page_nr[CE_DELAY]; #if 0 - ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : - element_info[element].event_page_nr[CE_DELAY]); + ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : page); +#else + +#if 0 + printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]); +#endif + +#if 1 + ChangeElement(x, y, page); #else - ChangeElement(x, y, element_info[element].event_page_nr[CE_DELAY]); + if (CAN_CHANGE(element)) + ChangeElement(x, y, page); + + if (HAS_ACTION(element)) + ExecuteCustomElementAction(x, y, element, page); +#endif + #endif element = Feld[x][y]; @@ -7920,7 +8062,7 @@ void GameActions() if (!TimeLeft && setup.time_limit) for (i = 0; i < MAX_PLAYERS; i++) - KillHero(&stored_player[i]); + KillPlayer(&stored_player[i]); } else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */ DrawGameValue_Time(TimePlayed); @@ -8156,10 +8298,10 @@ boolean MovePlayerOneStep(struct PlayerInfo *player, InitMovingField(jx, jy, MV_DOWN); Store[jx][jy] = EL_ACID; ContinueMoving(jx, jy); - BuryHero(player); + BuryPlayer(player); } else - TestIfHeroRunsIntoBadThing(jx, jy, player->MovDir); + TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir); return MF_MOVING; } @@ -8179,6 +8321,12 @@ boolean MovePlayerOneStep(struct PlayerInfo *player, player->jy = new_jy; StorePlayer[new_jx][new_jy] = player->element_nr; + if (player->move_delay_value_next != -1) + { + player->move_delay_value = player->move_delay_value_next; + player->move_delay_value_next = -1; + } + player->MovPos = (dx > 0 || dy > 0 ? -1 : 1) * (TILEX - TILEX / player->move_delay_value); @@ -8374,12 +8522,12 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) if (game.engine_version < VERSION_IDENT(3,0,7,0)) { - TestIfHeroTouchesBadThing(jx, jy); + TestIfPlayerTouchesBadThing(jx, jy); TestIfPlayerTouchesCustomElement(jx, jy); } if (!player->active) - RemoveHero(player); + RemovePlayer(player); return moved; } @@ -8390,8 +8538,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) int last_jx = player->last_jx, last_jy = player->last_jy; int move_stepsize = TILEX / player->move_delay_value; - if (!player->active || !player->MovPos) +#if USE_NEW_PLAYER_SPEED + if (!player->active) + return; + + if (player->MovPos == 0 && mode == SCROLL_GO_ON) /* player not moving */ + return; +#else + if (!player->active || player->MovPos == 0) return; +#endif if (mode == SCROLL_INIT) { @@ -8421,20 +8577,47 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) MovDelay[last_jx][last_jy] = last_field_block_delay + 1; } +#if USE_NEW_PLAYER_SPEED + if (player->MovPos != 0) /* player has not yet reached destination */ + return; +#else return; +#endif } else if (!FrameReached(&player->actual_frame_counter, 1)) return; +#if 0 + printf("::: player->MovPos: %d -> %d\n", + player->MovPos, + player->MovPos + (player->MovPos > 0 ? -1 : 1) * move_stepsize); +#endif + +#if USE_NEW_PLAYER_SPEED + if (player->MovPos != 0) + { + player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; + player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); + + /* before DrawPlayer() to draw correct player graphic for this case */ + if (player->MovPos == 0) + CheckGravityMovement(player); + } +#else player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); /* before DrawPlayer() to draw correct player graphic for this case */ if (player->MovPos == 0) CheckGravityMovement(player); +#endif if (player->MovPos == 0) /* player reached destination field */ { +#if 0 + printf("::: player reached destination field\n"); +#endif + if (player->move_delay_reset_counter > 0) { player->move_delay_reset_counter--; @@ -8457,7 +8640,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) Feld[jx][jy] == EL_SP_EXIT_OPENING) /* <-- special case */ { DrawPlayer(player); /* needed here only to cleanup last field */ - RemoveHero(player); + RemovePlayer(player); if (local_player->friends_still_needed == 0 || IS_SP_ELEMENT(Feld[jx][jy])) @@ -8492,7 +8675,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if (game.engine_version >= VERSION_IDENT(3,0,7,0)) { - TestIfHeroTouchesBadThing(jx, jy); + TestIfPlayerTouchesBadThing(jx, jy); TestIfPlayerTouchesCustomElement(jx, jy); /* needed because pushed element has not yet reached its destination, @@ -8501,7 +8684,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) TestIfElementTouchesCustomElement(jx, jy); /* for empty space */ if (!player->active) - RemoveHero(player); + RemovePlayer(player); } if (level.use_step_counter) @@ -8521,7 +8704,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if (!TimeLeft && setup.time_limit) for (i = 0; i < MAX_PLAYERS; i++) - KillHero(&stored_player[i]); + KillPlayer(&stored_player[i]); } else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */ DrawGameValue_Time(TimePlayed); @@ -8860,7 +9043,7 @@ void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir) !IS_INDESTRUCTIBLE(bad_element)) Bang(kill_x, kill_y); else if (!PLAYER_ENEMY_PROTECTED(good_x, good_y)) - KillHero(player); + KillPlayer(player); } else Bang(good_x, good_y); @@ -8953,29 +9136,29 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) !IS_INDESTRUCTIBLE(bad_element)) Bang(bad_x, bad_y); else if (!PLAYER_ENEMY_PROTECTED(kill_x, kill_y)) - KillHero(player); + KillPlayer(player); } else Bang(kill_x, kill_y); } } -void TestIfHeroTouchesBadThing(int x, int y) +void TestIfPlayerTouchesBadThing(int x, int y) { TestIfGoodThingHitsBadThing(x, y, MV_NO_MOVING); } -void TestIfHeroRunsIntoBadThing(int x, int y, int move_dir) +void TestIfPlayerRunsIntoBadThing(int x, int y, int move_dir) { TestIfGoodThingHitsBadThing(x, y, move_dir); } -void TestIfBadThingTouchesHero(int x, int y) +void TestIfBadThingTouchesPlayer(int x, int y) { TestIfBadThingHitsGoodThing(x, y, MV_NO_MOVING); } -void TestIfBadThingRunsIntoHero(int x, int y, int move_dir) +void TestIfBadThingRunsIntoPlayer(int x, int y, int move_dir) { TestIfBadThingHitsGoodThing(x, y, move_dir); } @@ -9024,7 +9207,7 @@ void TestIfBadThingTouchesOtherBadThing(int bad_x, int bad_y) Bang(bad_x, bad_y); } -void KillHero(struct PlayerInfo *player) +void KillPlayer(struct PlayerInfo *player) { int jx = player->jx, jy = player->jy; @@ -9039,22 +9222,22 @@ void KillHero(struct PlayerInfo *player) player->shield_deadly_time_left = 0; Bang(jx, jy); - BuryHero(player); + BuryPlayer(player); } -static void KillHeroUnlessEnemyProtected(int x, int y) +static void KillPlayerUnlessEnemyProtected(int x, int y) { if (!PLAYER_ENEMY_PROTECTED(x, y)) - KillHero(PLAYERINFO(x, y)); + KillPlayer(PLAYERINFO(x, y)); } -static void KillHeroUnlessExplosionProtected(int x, int y) +static void KillPlayerUnlessExplosionProtected(int x, int y) { if (!PLAYER_EXPLOSION_PROTECTED(x, y)) - KillHero(PLAYERINFO(x, y)); + KillPlayer(PLAYERINFO(x, y)); } -void BuryHero(struct PlayerInfo *player) +void BuryPlayer(struct PlayerInfo *player) { int jx = player->jx, jy = player->jy; @@ -9065,10 +9248,10 @@ void BuryHero(struct PlayerInfo *player) PlayLevelSound(jx, jy, SND_GAME_LOSING); player->GameOver = TRUE; - RemoveHero(player); + RemovePlayer(player); } -void RemoveHero(struct PlayerInfo *player) +void RemovePlayer(struct PlayerInfo *player) { int jx = player->jx, jy = player->jy; int i, found = FALSE; @@ -9079,6 +9262,9 @@ void RemoveHero(struct PlayerInfo *player) if (!ExplodeField[jx][jy]) StorePlayer[jx][jy] = 0; + if (player->is_moving) + DrawLevelField(player->last_jx, player->last_jy); + for (i = 0; i < MAX_PLAYERS; i++) if (stored_player[i].active) found = TRUE;