X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=7f6186c4f58130a519c16626ca5306ae9dc338b8;hb=f52403a0aa33b4a127df6e16193c9c9163e48197;hp=9bea6aae0330e532290662908f43b0378f578e48;hpb=949d7f40ef925eef7e473b12d5fc08a81d9c2eff;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 9bea6aae..7f6186c4 100644 --- a/src/game.c +++ b/src/game.c @@ -25,12 +25,14 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_STUFF (TRUE * 1) - -#define USE_NEW_SP_SLIPPERY (TRUE * USE_NEW_STUFF * 1) -#define USE_NEW_COLLECT_COUNT (TRUE * USE_NEW_STUFF * 1) -#define USE_NEW_PLAYER_ANIM (TRUE * USE_NEW_STUFF * 1) +#define 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) +#define USE_NEW_DELAYED_ACTION (USE_NEW_STUFF * 1) /* for DigField() */ #define DF_NO_PUSH 0 @@ -243,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); @@ -1261,6 +1263,9 @@ static void InitGameEngine() ei->change->change_function = ch_delay->change_function; ei->change->post_change_function = ch_delay->post_change_function; + ei->change->can_change = TRUE; + ei->change->can_change_or_has_action = TRUE; + ei->has_change_event[CE_DELAY] = TRUE; SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE); @@ -1582,6 +1587,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 */ @@ -1709,6 +1716,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++) { @@ -1906,7 +1933,7 @@ void InitGame() for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++) { - content = element_info[element].content[xx][yy]; + content = element_info[element].content.e[xx][yy]; is_player = ELEM_IS_PLAYER(content); if (is_player && (found_rating < 2 || element < found_element)) @@ -1923,7 +1950,9 @@ void InitGame() for (i = 0; i < element_info[element].num_change_pages; i++) { - content= element_info[element].change_page[i].target_content[xx][yy]; + content = + element_info[element].change_page[i].target_content.e[xx][yy]; + is_player = ELEM_IS_PLAYER(content); if (is_player && (found_rating < 1 || element < found_element)) @@ -2309,7 +2338,7 @@ void GameWon() PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING); } - /* Hero disappears */ + /* player disappears */ if (ExitX >= 0 && ExitY >= 0) DrawLevelField(ExitX, ExitY); @@ -2877,7 +2906,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)) @@ -3039,10 +3068,10 @@ void Explode(int ex, int ey, int phase, int mode) else if (center_element == EL_AMOEBA_TO_DIAMOND) Store[x][y] = level.amoeba_content; else if (center_element == EL_YAMYAM) - Store[x][y] = level.yamyam_content[game.yamyam_content_nr][xx][yy]; + Store[x][y] = level.yamyam_content[game.yamyam_content_nr].e[xx][yy]; else if (IS_CUSTOM_ELEMENT(center_element) && - element_info[center_element].content[xx][yy] != EL_EMPTY) - Store[x][y] = element_info[center_element].content[xx][yy]; + element_info[center_element].content.e[xx][yy] != EL_EMPTY) + Store[x][y] = element_info[center_element].content.e[xx][yy]; else if (element == EL_WALL_EMERALD) Store[x][y] = EL_EMERALD; else if (element == EL_WALL_DIAMOND) @@ -3060,7 +3089,7 @@ void Explode(int ex, int ey, int phase, int mode) else if (element == EL_WALL_CRYSTAL) Store[x][y] = EL_CRYSTAL; else if (IS_CUSTOM_ELEMENT(element) && !CAN_EXPLODE(element)) - Store[x][y] = element_info[element].content[1][1]; + Store[x][y] = element_info[element].content.e[1][1]; else Store[x][y] = EL_EMPTY; @@ -3128,7 +3157,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)) @@ -3722,7 +3751,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 @@ -3764,7 +3793,7 @@ void Impact(int x, int y) { if (CAN_SMASH_PLAYER(element)) { - KillHeroUnlessEnemyProtected(x, y + 1); + KillPlayerUnlessEnemyProtected(x, y + 1); return; } } @@ -4767,11 +4796,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) @@ -4784,7 +4828,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) && @@ -4794,7 +4841,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 || @@ -4805,6 +4864,7 @@ void StartMoving(int x, int y) can_fall_both = FALSE; } +#endif if (can_fall_any) { @@ -5007,7 +5067,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; } @@ -5308,7 +5368,7 @@ void StartMoving(int x, int y) DrawLevelElementAnimation(x, y, element); if (DONT_TOUCH(element)) - TestIfBadThingTouchesHero(x, y); + TestIfBadThingTouchesPlayer(x, y); return; } @@ -5530,7 +5590,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)) @@ -5970,10 +6030,14 @@ void AmoebeAbleger(int ax, int ay) void Life(int ax, int ay) { int x1, y1, x2, y2; +#if 0 static int life[4] = { 2, 3, 3, 3 }; /* parameters for "game of life" */ +#endif int life_time = 40; int element = Feld[ax][ay]; int graphic = el2img(element); + int *life_parameter = (element == EL_GAME_OF_LIFE ? level.game_of_life : + level.biomaze); boolean changed = FALSE; if (IS_ANIMATED(graphic)) @@ -6016,7 +6080,8 @@ void Life(int ax, int ay) if (xx == ax && yy == ay) /* field in the middle */ { - if (nachbarn < life[0] || nachbarn > life[1]) + if (nachbarn < life_parameter[0] || + nachbarn > life_parameter[1]) { Feld[xx][yy] = EL_EMPTY; if (!Stop[xx][yy]) @@ -6027,7 +6092,8 @@ void Life(int ax, int ay) } else if (IS_FREE(xx, yy) || CAN_GROW_INTO(Feld[xx][yy])) { /* free border field */ - if (nachbarn >= life[2] && nachbarn <= life[3]) + if (nachbarn >= life_parameter[2] && + nachbarn <= life_parameter[3]) { Feld[xx][yy] = element; MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1); @@ -6449,11 +6515,12 @@ static int getSpecialActionElement(int element, int number, int base_element) 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 : @@ -6535,19 +6602,17 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) 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 : + (action_arg == CA_ARG_PLAYER_ANY ? PLAYER_BITS_ANY : action_arg >= CA_ARG_PLAYER_1 && action_arg <= CA_ARG_PLAYER_4 ? action_arg - CA_ARG_PLAYER : action_arg >= CA_ARG_1 && - action_arg <= CA_ARG_PLAYER_4 ? (1 << (action_arg - 1)) : + action_arg <= CA_ARG_PLAYER_4 ? (1 << (action_arg - CA_ARG_1)) : action_arg_element >= EL_PLAYER_1 && action_arg_element <= EL_PLAYER_4 ? (1 << (action_arg_element - EL_PLAYER_1)) : - 0); + PLAYER_BITS_ANY); - /* (for implicit player choice, set invalid value to "all players") */ int trigger_player_bits = (change->actual_trigger_player >= EL_PLAYER_1 && change->actual_trigger_player <= EL_PLAYER_4 ? @@ -6576,7 +6641,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; } @@ -6653,6 +6718,14 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { int move_stepsize = TILEX / stored_player[i].move_delay_value; + if (action_mode == CA_MODE_ADD || action_mode == CA_MODE_SUBTRACT) + { + /* 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, @@ -6663,11 +6736,12 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) /* make sure that value is power of 2 */ move_stepsize = (1 << log_2(move_stepsize)); - stored_player[i].move_delay_value = TILEX / move_stepsize; + /* 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\n", - stored_player[i].move_delay_value); + printf("::: move_delay_value == %d [%d]\n", + stored_player[i].move_delay_value_next, action_arg_number); #endif } } @@ -6694,7 +6768,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) if (!TimeLeft && setup.time_limit) for (i = 0; i < MAX_PLAYERS; i++) - KillHero(&stored_player[i]); + KillPlayer(&stored_player[i]); } break; @@ -6837,7 +6911,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); } @@ -6898,7 +6972,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page) boolean is_destructible; int ex = x + xx - 1; int ey = y + yy - 1; - int content_element = change->target_content[xx][yy]; + int content_element = change->target_content.e[xx][yy]; int e; can_replace[xx][yy] = TRUE; @@ -6970,7 +7044,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page) ChangeEvent[ex][ey] = ChangeEvent[x][y]; - content_element = change->target_content[xx][yy]; + content_element = change->target_content.e[xx][yy]; target_element = GET_TARGET_ELEMENT(content_element, change); ChangeElementNowExt(change, ex, ey, target_element); @@ -6984,7 +7058,10 @@ static boolean ChangeElementNow(int x, int y, int element, int page) } if (something_has_changed) + { PlayLevelSoundElementAction(x, y, element, ACTION_CHANGING); + PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + page); + } } } else @@ -6994,6 +7071,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page) ChangeElementNowExt(change, x, y, target_element); PlayLevelSoundElementAction(x, y, element, ACTION_CHANGING); + PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + page); } /* this uses direct change before indirect change */ @@ -7002,6 +7080,100 @@ static boolean ChangeElementNow(int x, int y, int element, int page) return TRUE; } +#if USE_NEW_DELAYED_ACTION + +static void ChangeElement(int x, int y, int page) +{ + int element = MovingOrBlocked2Element(x, y); + struct ElementInfo *ei = &element_info[element]; + struct ElementChangeInfo *change = &ei->change_page[page]; + +#ifdef DEBUG + 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", + x, y, element, element_info[element].token_name); + printf("ChangeElement(): This should never happen!\n"); + printf("\n\n"); + } +#endif + + /* this can happen with classic bombs on walkable, changing elements */ + if (!CAN_CHANGE_OR_HAS_ACTION(element)) + { +#if 0 + if (!CAN_CHANGE(Back[x][y])) /* prevent permanent repetition */ + ChangeDelay[x][y] = 0; +#endif + + return; + } + + if (ChangeDelay[x][y] == 0) /* initialize element change */ + { + ChangeDelay[x][y] = GET_CHANGE_DELAY(change) + 1; + + if (change->can_change) + { + ResetGfxAnimation(x, y); + ResetRandomAnimationValue(x, y); + + if (change->pre_change_function) + change->pre_change_function(x, y); + } + } + + ChangeDelay[x][y]--; + + if (ChangeDelay[x][y] != 0) /* continue element change */ + { + 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 (change->change_function) + change->change_function(x, y); + } + } + else /* finish element change */ + { + if (ChangePage[x][y] != -1) /* remember page from delayed change */ + { + page = ChangePage[x][y]; + ChangePage[x][y] = -1; + + change = &ei->change_page[page]; + } + + if (IS_MOVING(x, y)) /* never change a running system ;-) */ + { + ChangeDelay[x][y] = 1; /* try change after next move step */ + ChangePage[x][y] = page; /* remember page to use for change */ + + return; + } + + if (change->can_change) + { + 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); + } +} + +#else + static void ChangeElement(int x, int y, int page) { int element = MovingOrBlocked2Element(x, y); @@ -7079,6 +7251,8 @@ static void ChangeElement(int x, int y, int page) } } +#endif + static boolean CheckTriggeredElementChangeExt(int trigger_element, int trigger_event, int trigger_player, @@ -7130,9 +7304,19 @@ static boolean CheckTriggeredElementChangeExt(int trigger_element, ChangeEvent[x][y] = trigger_event; ChangeElement(x, y, p); } - +#if USE_NEW_DELAYED_ACTION + else if (change->has_action) + { + ExecuteCustomElementAction(x, y, element, p); + PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p); + } +#else if (change->has_action) + { ExecuteCustomElementAction(x, y, element, p); + PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p); + } +#endif } } @@ -7199,9 +7383,19 @@ static boolean CheckElementChangeExt(int x, int y, change_done = TRUE; } - +#if USE_NEW_DELAYED_ACTION + else if (change->has_action) + { + ExecuteCustomElementAction(x, y, element, p); + PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p); + } +#else if (change->has_action) + { ExecuteCustomElementAction(x, y, element, p); + PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + p); + } +#endif } } @@ -7723,11 +7917,16 @@ void GameActions() printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]); #endif +#if 1 + ChangeElement(x, y, page); +#else if (CAN_CHANGE(element)) ChangeElement(x, y, page); - if (HAS_ACTION(element) && ChangeDelay[x][y] == 0) + if (HAS_ACTION(element)) ExecuteCustomElementAction(x, y, element, page); +#endif + #endif element = Feld[x][y]; @@ -7971,7 +8170,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); @@ -8207,10 +8406,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; } @@ -8230,6 +8429,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); @@ -8425,12 +8630,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; } @@ -8441,9 +8646,17 @@ 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) { player->actual_frame_counter = FrameCounter; @@ -8472,20 +8685,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--; @@ -8508,7 +8748,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])) @@ -8543,7 +8783,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, @@ -8552,7 +8792,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) @@ -8572,7 +8812,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); @@ -8911,7 +9151,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); @@ -9004,29 +9244,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); } @@ -9075,7 +9315,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; @@ -9090,22 +9330,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; @@ -9116,10 +9356,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; @@ -9130,6 +9370,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;