X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=5301f167ef7d2f59d5cf7c431b715f0b3c7288fc;hb=47572a41886623747cb380fc127a814d00028c6f;hp=d4a70eae1d5daabc145386e0cec4b801566d5084;hpb=bc1e7fc2edb32a410dfa7cf098933010d5014761;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index d4a70eae..5301f167 100644 --- a/src/game.c +++ b/src/game.c @@ -98,6 +98,8 @@ RND(element_info[e].push_delay_random)) #define GET_NEW_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \ RND(element_info[e].move_delay_random)) +#define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \ + (element_info[e].move_delay_random)) #define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition) \ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \ @@ -677,7 +679,7 @@ static void InitField(int x, int y, boolean init_game) case EL_PIG: case EL_DRAGON: - MovDir[x][y] = 1 << RND(4); + GfxDir[x][y] = MovDir[x][y] = 1 << RND(4); break; #if 0 @@ -800,13 +802,19 @@ static void InitGameEngine() /* dynamically adjust player properties according to game engine version */ game.initial_move_delay = - (game.engine_version <= VERSION_IDENT(2,0,1) ? INITIAL_MOVE_DELAY_ON : + (game.engine_version <= VERSION_IDENT(2,0,1,0) ? INITIAL_MOVE_DELAY_ON : INITIAL_MOVE_DELAY_OFF); /* dynamically adjust player properties according to level information */ game.initial_move_delay_value = (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED); + /* ---------- initialize player's initial push delay --------------------- */ + + /* dynamically adjust player properties according to game engine version */ + game.initial_push_delay_value = + (game.engine_version < VERSION_IDENT(3,0,7,1) ? 5 : -1); + /* ---------- initialize changing elements ------------------------------- */ /* initialize changing elements information */ @@ -927,8 +935,8 @@ static void InitGameEngine() { if (!IS_CUSTOM_ELEMENT(i)) { - element_info[i].push_delay_fixed = 2; - element_info[i].push_delay_random = 8; + element_info[i].push_delay_fixed = game.default_push_delay_fixed; + element_info[i].push_delay_random = game.default_push_delay_random; } } @@ -1030,28 +1038,28 @@ void InitGame() player->MovDir = MV_NO_MOVING; player->MovPos = 0; - player->Pushing = FALSE; - player->Switching = FALSE; player->GfxPos = 0; player->GfxDir = MV_NO_MOVING; player->GfxAction = ACTION_DEFAULT; player->Frame = 0; player->StepFrame = 0; - player->switch_x = -1; - player->switch_y = -1; - player->use_murphy_graphic = FALSE; - player->use_disk_red_graphic = FALSE; player->actual_frame_counter = 0; player->last_move_dir = MV_NO_MOVING; - player->is_moving = FALSE; player->is_waiting = FALSE; + player->is_moving = FALSE; player->is_digging = FALSE; + player->is_snapping = FALSE; player->is_collecting = FALSE; + player->is_pushing = FALSE; + player->is_switching = FALSE; + + player->switch_x = -1; + player->switch_y = -1; player->show_envelope = 0; @@ -1059,9 +1067,7 @@ void InitGame() player->move_delay_value = game.initial_move_delay_value; player->push_delay = 0; - player->push_delay_value = 5; - - player->snapped = FALSE; + player->push_delay_value = game.initial_push_delay_value; player->last_jx = player->last_jy = 0; player->jx = player->jy = 0; @@ -1132,7 +1138,8 @@ void InitGame() ChangePage[x][y] = -1; Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0; AmoebaNr[x][y] = 0; - JustStopped[x][y] = 0; + WasJustMoving[x][y] = 0; + WasJustFalling[x][y] = 0; Stop[x][y] = FALSE; Pushed[x][y] = FALSE; @@ -1143,9 +1150,10 @@ void InitGame() ExplodeField[x][y] = EX_NO_EXPLOSION; GfxFrame[x][y] = 0; - GfxAction[x][y] = ACTION_DEFAULT; GfxRandom[x][y] = INIT_GFX_RANDOM(); GfxElement[x][y] = EL_UNDEFINED; + GfxAction[x][y] = ACTION_DEFAULT; + GfxDir[x][y] = MV_NO_MOVING; } } @@ -1597,6 +1605,8 @@ void InitMovDir(int x, int y) } break; } + + GfxDir[x][y] = MovDir[x][y]; } void InitAmoebaNr(int x, int y) @@ -1841,6 +1851,7 @@ static void ResetGfxAnimation(int x, int y) { GfxFrame[x][y] = 0; GfxAction[x][y] = ACTION_DEFAULT; + GfxDir[x][y] = MovDir[x][y]; } void InitMovingField(int x, int y, int direction) @@ -1851,10 +1862,11 @@ void InitMovingField(int x, int y, int direction) int newx = x + dx; int newy = y + dy; - if (!JustStopped[x][y] || direction != MovDir[x][y]) + if (!WasJustMoving[x][y] || direction != MovDir[x][y]) ResetGfxAnimation(x, y); MovDir[newx][newy] = MovDir[x][y] = direction; + GfxDir[x][y] = direction; if (Feld[newx][newy] == EL_EMPTY) Feld[newx][newy] = EL_BLOCKED; @@ -1865,8 +1877,9 @@ void InitMovingField(int x, int y, int direction) GfxAction[x][y] = ACTION_MOVING; GfxFrame[newx][newy] = GfxFrame[x][y]; - GfxAction[newx][newy] = GfxAction[x][y]; GfxRandom[newx][newy] = GfxRandom[x][y]; + GfxAction[newx][newy] = GfxAction[x][y]; + GfxDir[newx][newy] = GfxDir[x][y]; } void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y) @@ -1950,6 +1963,7 @@ static void RemoveField(int x, int y) GfxElement[x][y] = EL_UNDEFINED; GfxAction[x][y] = ACTION_DEFAULT; + GfxDir[x][y] = MV_NO_MOVING; } void RemoveMovingField(int x, int y) @@ -2150,7 +2164,7 @@ void Explode(int ex, int ey, int phase, int mode) #if 0 /* --- This is only really needed (and now handled) in "Impact()". --- */ /* do not explode moving elements that left the explode field in time */ - if (game.engine_version >= RELEASE_IDENT(2,2,0,7) && + if (game.engine_version >= VERSION_IDENT(2,2,0,7) && center_element == EL_EMPTY && (mode == EX_NORMAL || mode == EX_CENTER)) return; #endif @@ -2205,7 +2219,7 @@ void Explode(int ex, int ey, int phase, int mode) #else if ((IS_INDESTRUCTIBLE(element) && - (game.engine_version < VERSION_IDENT(2,2,0) || + (game.engine_version < VERSION_IDENT(2,2,0,0) || (!IS_WALKABLE_OVER(element) && !IS_WALKABLE_UNDER(element)))) || element == EL_FLAMES) continue; @@ -2327,6 +2341,7 @@ void Explode(int ex, int ey, int phase, int mode) RemoveField(x, y); #else MovDir[x][y] = MovPos[x][y] = 0; + GfxDir[x][y] = MovDir[x][y]; AmoebaNr[x][y] = 0; #endif #endif @@ -2415,6 +2430,7 @@ void Explode(int ex, int ey, int phase, int mode) Back[x][y] = 0; MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0; + GfxDir[x][y] = MV_NO_MOVING; ChangeDelay[x][y] = 0; ChangePage[x][y] = -1; @@ -2966,7 +2982,7 @@ void Impact(int x, int y) MovPos[x][y + 1] <= TILEY / 2)); /* do not smash moving elements that left the smashed field in time */ - if (game.engine_version >= RELEASE_IDENT(2,2,0,7) && IS_MOVING(x, y + 1) && + if (game.engine_version >= VERSION_IDENT(2,2,0,7) && IS_MOVING(x, y + 1) && ABS(MovPos[x][y + 1] + getElementMoveStepsize(x, y + 1)) >= TILEX) object_hit = FALSE; @@ -3173,7 +3189,7 @@ void Impact(int x, int y) PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT); } -void TurnRound(int x, int y) +inline static void TurnRoundExt(int x, int y) { static struct { @@ -3713,6 +3729,32 @@ void TurnRound(int x, int y) } } +static void TurnRound(int x, int y) +{ + int direction = MovDir[x][y]; + +#if 1 + GfxDir[x][y] = MovDir[x][y]; +#endif + + TurnRoundExt(x, y); + +#if 0 + GfxDir[x][y] = MovDir[x][y]; +#endif + + if (direction != MovDir[x][y]) + GfxFrame[x][y] = 0; + +#if 0 + if (MovDelay[x][y]) + GfxAction[x][y] = ACTION_XXX_LEFT + MV_DIR_BIT(direction); +#else + if (MovDelay[x][y]) + GfxAction[x][y] = ACTION_WAITING; +#endif +} + static boolean JustBeingPushed(int x, int y) { int i; @@ -3721,7 +3763,7 @@ static boolean JustBeingPushed(int x, int y) { struct PlayerInfo *player = &stored_player[i]; - if (player->active && player->Pushing && player->MovPos) + if (player->active && player->is_pushing && player->MovPos) { int next_jx = player->jx + (player->jx - player->last_jx); int next_jy = player->jy + (player->jy - player->last_jy); @@ -3736,16 +3778,22 @@ static boolean JustBeingPushed(int x, int y) void StartMoving(int x, int y) { - boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0)); + boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0,0)); boolean started_moving = FALSE; /* some elements can fall _and_ move */ int element = Feld[x][y]; if (Stop[x][y]) return; +#if 1 + /* !!! this should be handled more generic (not only for mole) !!! */ + if (MovDelay[x][y] == 0) + GfxAction[x][y] = ACTION_DEFAULT; +#else /* !!! this should be handled more generic (not only for mole) !!! */ if (element != EL_MOLE && GfxAction[x][y] != ACTION_DIGGING) GfxAction[x][y] = ACTION_DEFAULT; +#endif if (CAN_FALL(element) && y < lev_fieldy - 1) { @@ -3892,36 +3940,37 @@ void StartMoving(int x, int y) #endif } #if 1 - -#if 0 - /* TEST: bug where player gets not killed by falling rock ... */ - else if (CAN_SMASH(element) && - (Feld[x][y + 1] == EL_BLOCKED || - IS_PLAYER(x, y + 1)) && - JustStopped[x][y] && !Pushed[x][y + 1]) + else if ((game.engine_version < VERSION_IDENT(2,2,0,7) && + CAN_SMASH(element) && WasJustMoving[x][y] && !Pushed[x][y + 1] && + (Feld[x][y + 1] == EL_BLOCKED)) || + (game.engine_version >= VERSION_IDENT(3,0,7,0) && + CAN_SMASH(element) && WasJustFalling[x][y] && + (Feld[x][y + 1] == EL_BLOCKED || IS_PLAYER(x, y + 1)))) #else #if 1 - else if (game.engine_version < RELEASE_IDENT(2,2,0,7) && + else if (game.engine_version < VERSION_IDENT(2,2,0,7) && CAN_SMASH(element) && Feld[x][y + 1] == EL_BLOCKED && - JustStopped[x][y] && !Pushed[x][y + 1]) + WasJustMoving[x][y] && !Pushed[x][y + 1]) #else else if (CAN_SMASH(element) && Feld[x][y + 1] == EL_BLOCKED && - JustStopped[x][y]) + WasJustMoving[x][y]) #endif #endif { - /* calling "Impact()" here is not only completely unneccessary - (because it already gets called from "ContinueMoving()" in - all relevant situations), but also completely bullshit, because - "JustStopped" also indicates a finished *horizontal* movement; - we must keep this trash for backwards compatibility with older - tapes */ + /* this is needed for a special case not covered by calling "Impact()" + from "ContinueMoving()": if an element moves to a tile directly below + another element which was just falling on that tile (which was empty + in the previous frame), the falling element above would just stop + instead of smashing the element below (in previous version, the above + element was just checked for "moving" instead of "falling", resulting + in incorrect smashes caused by horizontal movement of the above + element; also, the case of the player being the element to smash was + simply not covered here... :-/ ) */ Impact(x, y); } -#endif else if (IS_FREE(x, y + 1) && element == EL_SPRING && use_spring_bug) { if (MovDir[x][y] == MV_NO_MOVING) @@ -3932,7 +3981,7 @@ void StartMoving(int x, int y) } else if (IS_FREE(x, y + 1) || Feld[x][y + 1] == EL_DIAMOND_BREAKING) { - if (JustStopped[x][y]) /* prevent animation from being restarted */ + if (WasJustFalling[x][y]) /* prevent animation from being restarted */ MovDir[x][y] = MV_DOWN; InitMovingField(x, y, MV_DOWN); @@ -3951,13 +4000,13 @@ void StartMoving(int x, int y) else if (IS_SLIPPERY(Feld[x][y + 1]) && !Store[x][y + 1]) #else else if (IS_SLIPPERY(Feld[x][y + 1]) && !Store[x][y + 1] && - !IS_FALLING(x, y + 1) && !JustStopped[x][y + 1] && + !IS_FALLING(x, y + 1) && !WasJustMoving[x][y + 1] && element != EL_DX_SUPABOMB) #endif #else else if (((IS_SLIPPERY(Feld[x][y + 1]) && !IS_PLAYER(x, y + 1)) || (IS_EM_SLIPPERY_WALL(Feld[x][y + 1]) && IS_GEM(element))) && - !IS_FALLING(x, y + 1) && !JustStopped[x][y + 1] && + !IS_FALLING(x, y + 1) && !WasJustMoving[x][y + 1] && element != EL_DX_SUPABOMB && element != EL_SP_DISK_ORANGE) #endif { @@ -4088,7 +4137,13 @@ void StartMoving(int x, int y) /* !!! PLACE THIS SOMEWHERE AFTER "TurnRound()" !!! */ ResetGfxAnimation(x, y); #endif + +#if 0 + if (GfxAction[x][y] != ACTION_WAITING) + printf("::: %d: %d != ACTION_WAITING\n", element, GfxAction[x][y]); + GfxAction[x][y] = ACTION_WAITING; +#endif } if (element == EL_ROBOT || @@ -4117,12 +4172,27 @@ void StartMoving(int x, int y) dir == MV_RIGHT ? IMG_FLAMES_1_RIGHT : dir == MV_UP ? IMG_FLAMES_1_UP : dir == MV_DOWN ? IMG_FLAMES_1_DOWN : IMG_EMPTY); - int frame = getGraphicAnimationFrame(graphic, -1); + int frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]); + +#if 0 + printf("::: %d, %d\n", GfxAction[x][y], GfxFrame[x][y]); +#endif + + GfxAction[x][y] = ACTION_ATTACKING; - for (i=1; i<=3; i++) + if (IS_PLAYER(x, y)) + DrawPlayerField(x, y); + else + DrawLevelField(x, y); + + PlaySoundLevelActionIfLoop(x, y, ACTION_ATTACKING); + + for (i=1; i <= 3; i++) { - int xx = x + i*dx, yy = y + i*dy; - int sx = SCREENX(xx), sy = SCREENY(yy); + int xx = x + i * dx; + int yy = y + i * dy; + int sx = SCREENX(xx); + int sy = SCREENY(yy); int flame_graphic = graphic + (i - 1); if (!IN_LEV_FIELD(xx, yy) || IS_DRAGONFIRE_PROOF(Feld[xx][yy])) @@ -4139,7 +4209,10 @@ void StartMoving(int x, int y) Feld[xx][yy] = EL_FLAMES; if (IN_SCR_FIELD(sx, sy)) + { + DrawLevelFieldCrumbledSand(xx, yy); DrawGraphic(sx, sy, flame_graphic, frame); + } } else { @@ -4157,10 +4230,12 @@ void StartMoving(int x, int y) return; } +#if 0 /* special case of "moving" animation of waiting elements (FIX THIS !!!); for all other elements GfxAction will be set by InitMovingField() */ if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY) GfxAction[x][y] = ACTION_MOVING; +#endif } /* now make next step */ @@ -4216,7 +4291,7 @@ void StartMoving(int x, int y) if (DigField(local_player, newx, newy, 0, 0, DF_DIG) == MF_MOVING) DrawLevelField(newx, newy); else - MovDir[x][y] = MV_NO_MOVING; + GfxDir[x][y] = MovDir[x][y] = MV_NO_MOVING; } else if (!IS_FREE(newx, newy)) { @@ -4260,14 +4335,15 @@ void StartMoving(int x, int y) DrawPlayerField(x, y); else DrawLevelField(x, y); + return; } else { boolean wanna_flame = !RND(10); int dx = newx - x, dy = newy - y; - int newx1 = newx+1*dx, newy1 = newy+1*dy; - int newx2 = newx+2*dx, newy2 = newy+2*dy; + int newx1 = newx + 1 * dx, newy1 = newy + 1 * dy; + int newx2 = newx + 2 * dx, newy2 = newy + 2 * dy; int element1 = (IN_LEV_FIELD(newx1, newy1) ? MovingOrBlocked2Element(newx1, newy1) : EL_STEELWALL); int element2 = (IN_LEV_FIELD(newx2, newy2) ? @@ -4292,6 +4368,7 @@ void StartMoving(int x, int y) PlaySoundLevel(x, y, SND_DRAGON_ATTACKING); MovDelay[x][y] = 50; + Feld[newx][newy] = EL_FLAMES; if (IN_LEV_FIELD(newx1, newy1) && Feld[newx1][newy1] == EL_EMPTY) Feld[newx1][newy1] = EL_FLAMES; @@ -4526,8 +4603,9 @@ void ContinueMoving(int x, int y) /* copy animation control values to new field */ GfxFrame[newx][newy] = GfxFrame[x][y]; - GfxAction[newx][newy] = GfxAction[x][y]; /* keep action one frame */ GfxRandom[newx][newy] = GfxRandom[x][y]; /* keep same random value */ + GfxAction[newx][newy] = GfxAction[x][y]; /* keep action one frame */ + GfxDir[newx][newy] = GfxDir[x][y]; /* keep element direction */ Pushed[x][y] = Pushed[newx][newy] = FALSE; @@ -4551,8 +4629,9 @@ void ContinueMoving(int x, int y) */ if (!CAN_MOVE(element) || - (CAN_FALL(element) && MovDir[newx][newy] == MV_DOWN)) - MovDir[newx][newy] = 0; + (CAN_FALL(element) && direction == MV_DOWN)) + GfxDir[x][y] = MovDir[newx][newy] = 0; + #endif #endif @@ -4564,11 +4643,16 @@ void ContinueMoving(int x, int y) /* prevent pushed element from moving on in pushed direction */ if (pushed && CAN_MOVE(element) && element_info[element].move_pattern & MV_ANY_DIRECTION && - !(element_info[element].move_pattern & MovDir[newx][newy])) + !(element_info[element].move_pattern & direction)) TurnRound(newx, newy); if (!pushed) /* special case: moving object pushed by player */ - JustStopped[newx][newy] = 3; + { + WasJustMoving[newx][newy] = 3; + + if (CAN_FALL(element) && direction == MV_DOWN) + WasJustFalling[newx][newy] = 3; + } if (DONT_TOUCH(element)) /* object may be nasty to player or others */ { @@ -5239,7 +5323,7 @@ void MauerWaechst(int x, int y) if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) { - int graphic = el_dir2img(Feld[x][y], MovDir[x][y]); + int graphic = el_dir2img(Feld[x][y], GfxDir[x][y]); int frame = getGraphicAnimationFrame(graphic, 17 - MovDelay[x][y]); DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame); @@ -5270,7 +5354,7 @@ void MauerWaechst(int x, int y) Feld[x][y] = Store[x][y]; Store[x][y] = 0; - MovDir[x][y] = MV_NO_MOVING; + GfxDir[x][y] = MovDir[x][y] = MV_NO_MOVING; DrawLevelField(x, y); } } @@ -5315,7 +5399,7 @@ void MauerAbleger(int ax, int ay) { Feld[ax][ay-1] = EL_EXPANDABLE_WALL_GROWING; Store[ax][ay-1] = element; - MovDir[ax][ay-1] = MV_UP; + GfxDir[ax][ay-1] = MovDir[ax][ay-1] = MV_UP; if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay-1))) DrawGraphic(SCREENX(ax), SCREENY(ay - 1), IMG_EXPANDABLE_WALL_GROWING_UP, 0); @@ -5325,7 +5409,7 @@ void MauerAbleger(int ax, int ay) { Feld[ax][ay+1] = EL_EXPANDABLE_WALL_GROWING; Store[ax][ay+1] = element; - MovDir[ax][ay+1] = MV_DOWN; + GfxDir[ax][ay+1] = MovDir[ax][ay+1] = MV_DOWN; if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay+1))) DrawGraphic(SCREENX(ax), SCREENY(ay + 1), IMG_EXPANDABLE_WALL_GROWING_DOWN, 0); @@ -5341,7 +5425,7 @@ void MauerAbleger(int ax, int ay) { Feld[ax-1][ay] = EL_EXPANDABLE_WALL_GROWING; Store[ax-1][ay] = element; - MovDir[ax-1][ay] = MV_LEFT; + GfxDir[ax-1][ay] = MovDir[ax-1][ay] = MV_LEFT; if (IN_SCR_FIELD(SCREENX(ax-1), SCREENY(ay))) DrawGraphic(SCREENX(ax - 1), SCREENY(ay), IMG_EXPANDABLE_WALL_GROWING_LEFT, 0); @@ -5352,7 +5436,7 @@ void MauerAbleger(int ax, int ay) { Feld[ax+1][ay] = EL_EXPANDABLE_WALL_GROWING; Store[ax+1][ay] = element; - MovDir[ax+1][ay] = MV_RIGHT; + GfxDir[ax+1][ay] = MovDir[ax+1][ay] = MV_RIGHT; if (IN_SCR_FIELD(SCREENX(ax+1), SCREENY(ay))) DrawGraphic(SCREENX(ax + 1), SCREENY(ay), IMG_EXPANDABLE_WALL_GROWING_RIGHT, 0); @@ -5686,7 +5770,7 @@ static void ChangeElement(int x, int y, int page) if (ChangeDelay[x][y] != 0) /* continue element change */ { - int graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]); + int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); if (IS_ANIMATED(graphic)) DrawLevelGraphicAnimationIfNeeded(x, y, graphic); @@ -5743,9 +5827,18 @@ static boolean CheckTriggeredElementSideChange(int lx, int ly, struct ElementChangeInfo *change = &element_info[element].change_page[j]; if (change->can_change && +#if 1 + change->events & CH_EVENT_BIT(trigger_event) && +#endif change->sides & trigger_side && change->trigger_element == trigger_element) { +#if 0 + if (!(change->events & CH_EVENT_BIT(trigger_event))) + printf("::: !!! %d triggers %d: using wrong page %d [event %d]\n", + trigger_element-EL_CUSTOM_START+1, i+1, j, trigger_event); +#endif + change_element = TRUE; page = j; @@ -5974,7 +6067,7 @@ void GameActions() #endif #if 1 - if (game.engine_version < RELEASE_IDENT(2,2,0,7)) + if (game.engine_version < VERSION_IDENT(2,2,0,7)) { for (i=0; ijx; int y = player->jy; - if (player->active && player->Pushing && player->is_moving && + if (player->active && player->is_pushing && player->is_moving && IS_MOVING(x, y)) { ContinueMoving(x, y); @@ -6013,8 +6106,10 @@ void GameActions() #endif Stop[x][y] = FALSE; - if (JustStopped[x][y] > 0) - JustStopped[x][y]--; + if (WasJustMoving[x][y] > 0) + WasJustMoving[x][y]--; + if (WasJustFalling[x][y] > 0) + WasJustFalling[x][y]--; GfxFrame[x][y]++; @@ -6049,7 +6144,7 @@ void GameActions() { element = Feld[x][y]; #if 1 - graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]); + graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); #else graphic = el2img(element); #endif @@ -6086,7 +6181,12 @@ void GameActions() #if 1 /* this may take place after moving, so 'element' may have changed */ +#if 0 if (IS_CHANGING(x, y)) +#else + if (IS_CHANGING(x, y) && + (game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y])) +#endif { #if 0 ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : @@ -6096,7 +6196,7 @@ void GameActions() #endif element = Feld[x][y]; - graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]); + graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); } #endif @@ -6105,7 +6205,7 @@ void GameActions() StartMoving(x, y); #if 1 - graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]); + graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); #if 0 if (element == EL_MOLE) printf("::: %d, %d, %d [%d]\n", @@ -6784,7 +6884,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) #if 1 InitPlayerGfxAnimation(player, ACTION_DEFAULT); #else - if (!(moved & MF_MOVING) && !player->Pushing) + if (!(moved & MF_MOVING) && !player->is_pushing) player->Frame = 0; #endif #endif @@ -6803,11 +6903,11 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) player->last_move_dir = player->MovDir; player->is_moving = TRUE; #if 1 - player->snapped = FALSE; + player->is_snapping = FALSE; #endif #if 1 - player->Switching = FALSE; + player->is_switching = FALSE; #endif @@ -6858,7 +6958,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) player->is_moving = FALSE; } - if (game.engine_version < VERSION_IDENT(3,0,7)) + if (game.engine_version < VERSION_IDENT(3,0,7,0)) { TestIfHeroTouchesBadThing(jx, jy); TestIfPlayerTouchesCustomElement(jx, jy); @@ -6935,10 +7035,13 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) player->LevelSolved = player->GameOver = TRUE; } - if (game.engine_version >= VERSION_IDENT(3,0,7)) + if (game.engine_version >= VERSION_IDENT(3,0,7,0)) { TestIfHeroTouchesBadThing(jx, jy); TestIfPlayerTouchesCustomElement(jx, jy); +#if 1 + TestIfElementTouchesCustomElement(jx, jy); /* for empty space */ +#endif if (!player->active) RemoveHero(player); @@ -7018,7 +7121,7 @@ void TestIfPlayerTouchesCustomElement(int x, int y) if (IS_PLAYER(x, y)) { - if (game.engine_version < VERSION_IDENT(3,0,7)) + if (game.engine_version < VERSION_IDENT(3,0,7,0)) border_element = Feld[xx][yy]; /* may be moving! */ else if (!IS_MOVING(xx, yy) && !IS_BLOCKED(xx, yy)) border_element = Feld[xx][yy]; @@ -7034,7 +7137,7 @@ void TestIfPlayerTouchesCustomElement(int x, int y) } else if (IS_PLAYER(xx, yy)) { - if (game.engine_version >= VERSION_IDENT(3,0,7)) + if (game.engine_version >= VERSION_IDENT(3,0,7,0)) { struct PlayerInfo *player = PLAYERINFO(xx, yy); @@ -7092,7 +7195,7 @@ void TestIfElementTouchesCustomElement(int x, int y) if (!IN_LEV_FIELD(xx, yy)) continue; - if (game.engine_version < VERSION_IDENT(3,0,7)) + if (game.engine_version < VERSION_IDENT(3,0,7,0)) border_element = Feld[xx][yy]; /* may be moving! */ else if (!IS_MOVING(xx, yy) && !IS_BLOCKED(xx, yy)) border_element = Feld[xx][yy]; @@ -7272,7 +7375,7 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) if (bad_element == EL_ROBOT && player->is_moving) continue; /* robot does not kill player if he is moving */ - if (game.engine_version >= VERSION_IDENT(3,0,7)) + if (game.engine_version >= VERSION_IDENT(3,0,7,0)) { if (player->MovPos != 0 && !(player->MovDir & touch_dir[i])) continue; /* center and border element do not touch */ @@ -7482,7 +7585,7 @@ int DigField(struct PlayerInfo *player, CH_SIDE_BOTTOM, /* moving up */ CH_SIDE_TOP, /* moving down */ }; - boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0)); + boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0,0)); int jx = player->jx, jy = player->jy; int dx = x - jx, dy = y - jy; int nextx = x + dx, nexty = y + dy; @@ -7500,11 +7603,11 @@ int DigField(struct PlayerInfo *player, } if (player->MovPos == 0) /* last pushing move finished */ - player->Pushing = FALSE; + player->is_pushing = FALSE; if (mode == DF_NO_PUSH) /* player just stopped pushing */ { - player->Switching = FALSE; + player->is_switching = FALSE; player->push_delay = 0; return MF_NO_ACTION; @@ -7517,7 +7620,7 @@ int DigField(struct PlayerInfo *player, if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy])) #else if (IS_TUBE(Feld[jx][jy]) || - (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0))) + (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0,0))) #endif { int i = 0; @@ -7552,146 +7655,11 @@ int DigField(struct PlayerInfo *player, element = Feld[x][y]; if (mode == DF_SNAP && !IS_SNAPPABLE(element) && - game.engine_version >= VERSION_IDENT(2,2,0)) + game.engine_version >= VERSION_IDENT(2,2,0,0)) return MF_NO_ACTION; switch (element) { -#if 0 - case EL_ROBOT_WHEEL: - Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE; - ZX = x; - ZY = y; - DrawLevelField(x, y); - PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING); - return MF_ACTION; - break; -#endif - -#if 0 - case EL_SP_TERMINAL: - { - int xx, yy; - - PlaySoundLevel(x, y, SND_SP_TERMINAL_ACTIVATING); - - for (yy=0; yySwitching) -#endif - { - player->Switching = TRUE; - player->switch_x = x; - player->switch_y = y; - - ToggleBeltSwitch(x, y); - PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING); - } - return MF_ACTION; - break; -#endif - -#if 0 - case EL_SWITCHGATE_SWITCH_UP: - case EL_SWITCHGATE_SWITCH_DOWN: -#if 1 - if (!PLAYER_SWITCHING(player, x, y)) -#else - if (!player->Switching) -#endif - { - player->Switching = TRUE; - player->switch_x = x; - player->switch_y = y; - - ToggleSwitchgateSwitch(x, y); - PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING); - } - return MF_ACTION; - break; -#endif - -#if 0 - case EL_LIGHT_SWITCH: - case EL_LIGHT_SWITCH_ACTIVE: -#if 1 - if (!PLAYER_SWITCHING(player, x, y)) -#else - if (!player->Switching) -#endif - { - player->Switching = TRUE; - player->switch_x = x; - player->switch_y = y; - - ToggleLightSwitch(x, y); - PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ? - SND_LIGHT_SWITCH_ACTIVATING : - SND_LIGHT_SWITCH_DEACTIVATING); - } - return MF_ACTION; - break; -#endif - -#if 0 - case EL_TIMEGATE_SWITCH: - ActivateTimegateSwitch(x, y); - PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVATING); - - return MF_ACTION; - break; -#endif - -#if 0 - case EL_BALLOON_SWITCH_LEFT: - case EL_BALLOON_SWITCH_RIGHT: - case EL_BALLOON_SWITCH_UP: - case EL_BALLOON_SWITCH_DOWN: - case EL_BALLOON_SWITCH_ANY: - if (element == EL_BALLOON_SWITCH_ANY) - game.balloon_dir = move_direction; - else - game.balloon_dir = (element == EL_BALLOON_SWITCH_LEFT ? MV_LEFT : - element == EL_BALLOON_SWITCH_RIGHT ? MV_RIGHT : - element == EL_BALLOON_SWITCH_UP ? MV_UP : - element == EL_BALLOON_SWITCH_DOWN ? MV_DOWN : - MV_NO_MOVING); - PlaySoundLevel(x, y, SND_CLASS_BALLOON_SWITCH_ACTIVATING); - - return MF_ACTION; - break; -#endif - case EL_SP_PORT_LEFT: case EL_SP_PORT_RIGHT: case EL_SP_PORT_UP: @@ -7783,27 +7751,6 @@ int DigField(struct PlayerInfo *player, } break; -#if 0 - case EL_LAMP: - Feld[x][y] = EL_LAMP_ACTIVE; - local_player->lights_still_needed--; - DrawLevelField(x, y); - PlaySoundLevel(x, y, SND_LAMP_ACTIVATING); - return MF_ACTION; - break; -#endif - -#if 0 - case EL_TIME_ORB_FULL: - Feld[x][y] = EL_TIME_ORB_EMPTY; - TimeLeft += 10; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2); - DrawLevelField(x, y); - PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE); - return MF_ACTION; - break; -#endif - default: if (IS_WALKABLE(element)) @@ -7887,7 +7834,10 @@ int DigField(struct PlayerInfo *player, CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_DIGGED); - TestIfElementTouchesCustomElement(x, y); /* for empty space */ +#if 1 + if (mode == DF_SNAP) + TestIfElementTouchesCustomElement(x, y); /* for empty space */ +#endif break; } @@ -7919,8 +7869,6 @@ int DigField(struct PlayerInfo *player, if (player->inventory_size < MAX_INVENTORY_SIZE) player->inventory_element[player->inventory_size++] = element; - player->use_disk_red_graphic = (element == EL_SP_DISK_RED); - DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->inventory_size, 3), FONT_TEXT_2); } @@ -7984,7 +7932,10 @@ int DigField(struct PlayerInfo *player, CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_COLLECTED); - TestIfElementTouchesCustomElement(x, y); /* for empty space */ +#if 1 + if (mode == DF_SNAP) + TestIfElementTouchesCustomElement(x, y); /* for empty space */ +#endif break; } @@ -8000,6 +7951,21 @@ int DigField(struct PlayerInfo *player, !(element == EL_SPRING && use_spring_bug)) return MF_NO_ACTION; +#if 1 + if (CAN_MOVE(element) && GET_MAX_MOVE_DELAY(element) == 0 && + ((move_direction & MV_VERTICAL && + ((element_info[element].move_pattern & MV_LEFT && + IN_LEV_FIELD(x - 1, y) && IS_FREE(x - 1, y)) || + (element_info[element].move_pattern & MV_RIGHT && + IN_LEV_FIELD(x + 1, y) && IS_FREE(x + 1, y)))) || + (move_direction & MV_HORIZONTAL && + ((element_info[element].move_pattern & MV_UP && + IN_LEV_FIELD(x, y - 1) && IS_FREE(x, y - 1)) || + (element_info[element].move_pattern & MV_DOWN && + IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1)))))) + return MF_NO_ACTION; +#endif + #if 1 /* do not push elements already moving away faster than player */ if (CAN_MOVE(element) && MovDir[x][y] == move_direction && @@ -8009,11 +7975,38 @@ int DigField(struct PlayerInfo *player, if (element == EL_SPRING && MovDir[x][y] != MV_NO_MOVING) return MF_NO_ACTION; #endif - if (!player->Pushing && - game.engine_version >= RELEASE_IDENT(2,2,0,7)) + +#if 1 + if (game.engine_version >= VERSION_IDENT(3,0,7,1)) + { + if (player->push_delay_value == -1) + player->push_delay_value = GET_NEW_PUSH_DELAY(element); + } + else if (game.engine_version >= VERSION_IDENT(2,2,0,7)) + { + if (!player->is_pushing) + player->push_delay_value = GET_NEW_PUSH_DELAY(element); + } + + /* + if (game.engine_version >= VERSION_IDENT(2,2,0,7) && + (game.engine_version < VERSION_IDENT(3,0,7,1) || + !player_is_pushing)) + player->push_delay_value = GET_NEW_PUSH_DELAY(element); + */ +#else + if (!player->is_pushing && + game.engine_version >= VERSION_IDENT(2,2,0,7)) player->push_delay_value = GET_NEW_PUSH_DELAY(element); +#endif - player->Pushing = TRUE; +#if 0 + printf("::: push delay: %ld [%d, %d] [%d]\n", + player->push_delay_value, FrameCounter, game.engine_version, + player->is_pushing); +#endif + + player->is_pushing = TRUE; if (!(IN_LEV_FIELD(nextx, nexty) && (IS_FREE(nextx, nexty) || @@ -8030,7 +8023,17 @@ int DigField(struct PlayerInfo *player, if (!FrameReached(&player->push_delay, player->push_delay_value) && !(tape.playing && tape.file_version < FILE_VERSION_2_0) && element != EL_SPRING && element != EL_BALLOON) + { + /* make sure that there is no move delay before next try to push */ + if (game.engine_version >= VERSION_IDENT(3,0,7,1)) + player->move_delay = INITIAL_MOVE_DELAY_OFF; + return MF_NO_ACTION; + } + +#if 0 + printf("::: NOW PUSHING... [%d]\n", FrameCounter); +#endif if (IS_SB_ELEMENT(element)) { @@ -8078,18 +8081,15 @@ int DigField(struct PlayerInfo *player, Pushed[x][y] = TRUE; Pushed[nextx][nexty] = TRUE; - if (game.engine_version < RELEASE_IDENT(2,2,0,7)) + if (game.engine_version < VERSION_IDENT(2,2,0,7)) player->push_delay_value = GET_NEW_PUSH_DELAY(element); + else + player->push_delay_value = -1; /* get new value later */ -#if 1 CheckTriggeredElementSideChange(x, y, element, dig_side, CE_OTHER_GETS_PUSHED); CheckElementSideChange(x, y, element, dig_side, CE_PUSHED_BY_PLAYER, -1); -#else - CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_PUSHED); - CheckElementChange(x, y, element, CE_PUSHED_BY_PLAYER); -#endif break; } @@ -8098,9 +8098,11 @@ int DigField(struct PlayerInfo *player, if (PLAYER_SWITCHING(player, x, y)) return MF_ACTION; -#if 1 + player->is_switching = TRUE; + player->switch_x = x; + player->switch_y = y; + PlaySoundLevelElementAction(x, y, element, ACTION_ACTIVATING); -#endif if (element == EL_ROBOT_WHEEL) { @@ -8109,92 +8111,42 @@ int DigField(struct PlayerInfo *player, ZY = y; DrawLevelField(x, y); - -#if 0 - PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING); -#endif } else if (element == EL_SP_TERMINAL) { int xx, yy; -#if 0 - PlaySoundLevel(x, y, SND_SP_TERMINAL_ACTIVATING); -#endif - - for (yy=0; yySwitching = TRUE; - player->switch_x = x; - player->switch_y = y; - - ToggleBeltSwitch(x, y); - -#if 0 - PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING); -#endif - } + ToggleBeltSwitch(x, y); } else if (element == EL_SWITCHGATE_SWITCH_UP || element == EL_SWITCHGATE_SWITCH_DOWN) { -#if 0 - if (!PLAYER_SWITCHING(player, x, y)) -#endif - { - player->Switching = TRUE; - player->switch_x = x; - player->switch_y = y; - - ToggleSwitchgateSwitch(x, y); - -#if 0 - PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING); -#endif - } + ToggleSwitchgateSwitch(x, y); } else if (element == EL_LIGHT_SWITCH || element == EL_LIGHT_SWITCH_ACTIVE) { -#if 0 - if (!PLAYER_SWITCHING(player, x, y)) -#endif - { - player->Switching = TRUE; - player->switch_x = x; - player->switch_y = y; - - ToggleLightSwitch(x, y); + ToggleLightSwitch(x, y); #if 0 - PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ? - SND_LIGHT_SWITCH_ACTIVATING : - SND_LIGHT_SWITCH_DEACTIVATING); + PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ? + SND_LIGHT_SWITCH_ACTIVATING : + SND_LIGHT_SWITCH_DEACTIVATING); #endif - } } else if (element == EL_TIMEGATE_SWITCH) { ActivateTimegateSwitch(x, y); - -#if 0 - PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVATING); -#endif } else if (element == EL_BALLOON_SWITCH_LEFT || element == EL_BALLOON_SWITCH_RIGHT || @@ -8210,10 +8162,6 @@ int DigField(struct PlayerInfo *player, element == EL_BALLOON_SWITCH_UP ? MV_UP : element == EL_BALLOON_SWITCH_DOWN ? MV_DOWN : MV_NO_MOVING); - -#if 0 - PlaySoundLevel(x, y, SND_CLASS_BALLOON_SWITCH_ACTIVATING); -#endif } else if (element == EL_LAMP) { @@ -8221,10 +8169,6 @@ int DigField(struct PlayerInfo *player, local_player->lights_still_needed--; DrawLevelField(x, y); - -#if 0 - PlaySoundLevel(x, y, SND_LAMP_ACTIVATING); -#endif } else if (element == EL_TIME_ORB_FULL) { @@ -8243,13 +8187,9 @@ int DigField(struct PlayerInfo *player, } else { -#if 1 if (!PLAYER_SWITCHING(player, x, y)) -#else - if (!player->Switching) -#endif { - player->Switching = TRUE; + player->is_switching = TRUE; player->switch_x = x; player->switch_y = y; @@ -8284,7 +8224,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) dy == -1 ? MV_UP : dy == +1 ? MV_DOWN : MV_NO_MOVING); - if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0)) + if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0,0)) return FALSE; if (!player->active || !IN_LEV_FIELD(x, y)) @@ -8296,50 +8236,37 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) if (!dx && !dy) { if (player->MovPos == 0) - player->Pushing = FALSE; + player->is_pushing = FALSE; - player->snapped = FALSE; + player->is_snapping = FALSE; if (player->MovPos == 0) { + player->is_moving = FALSE; player->is_digging = FALSE; player->is_collecting = FALSE; -#if 1 - player->is_moving = FALSE; -#endif } -#if 0 - printf("::: trying to snap...\n"); -#endif - return FALSE; } - if (player->snapped) + if (player->is_snapping) return FALSE; player->MovDir = snap_direction; -#if 1 + player->is_moving = FALSE; player->is_digging = FALSE; player->is_collecting = FALSE; -#if 1 - player->is_moving = FALSE; -#endif -#endif if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION) return FALSE; - player->snapped = TRUE; -#if 1 + player->is_snapping = TRUE; + + player->is_moving = FALSE; player->is_digging = FALSE; player->is_collecting = FALSE; -#if 1 - player->is_moving = FALSE; -#endif -#endif DrawLevelField(x, y); BackToFront(); @@ -8383,14 +8310,9 @@ boolean DropElement(struct PlayerInfo *player) { int new_element = player->inventory_element[--player->inventory_size]; -#if 1 Feld[jx][jy] = (new_element == EL_DYNAMITE ? EL_DYNAMITE_ACTIVE : new_element == EL_SP_DISK_RED ? EL_SP_DISK_RED_ACTIVE : new_element); -#else - Feld[jx][jy] = (player->use_disk_red_graphic ? EL_SP_DISK_RED_ACTIVE : - EL_DYNAMITE_ACTIVE); -#endif DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->inventory_size, 3), FONT_TEXT_2);