X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=1736366565c50950c217301519f37d01f8a42ec1;hb=c956237d7c5507aea649ce7b20c00d7bd9d37a7a;hp=fb479b0e964d2086a206fd79e217ab23fc2ae3fb;hpb=d93da39940cf3a69a4ceae6f212170784c0032c8;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index fb479b0e..17363665 100644 --- a/src/game.c +++ b/src/game.c @@ -723,7 +723,7 @@ void InitGame() { Feld[x][y] = Ur[x][y]; MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; - Store[x][y] = Store2[x][y] = StorePlayer[x][y] = 0; + Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0; AmoebaNr[x][y] = 0; JustStopped[x][y] = 0; Stop[x][y] = FALSE; @@ -941,7 +941,8 @@ void InitGame() if (setup.sound_music) PlayMusic(level_nr); - KeyboardAutoRepeatOff(); + if (!tape.playing) + KeyboardAutoRepeatOff(); if (options.debug) { @@ -1378,7 +1379,7 @@ static int MovingOrBlocked2ElementIfNotLeaving(int x, int y) static void RemoveField(int x, int y) { Feld[x][y] = EL_EMPTY; - GfxElement[x][y] = EL_EMPTY; + GfxElement[x][y] = EL_UNDEFINED; MovPos[x][y] = 0; MovDir[x][y] = 0; MovDelay[x][y] = 0; @@ -1433,13 +1434,18 @@ void DrawDynamite(int x, int y) if (!IN_SCR_FIELD(sx, sy) || IS_PLAYER(x, y)) return; - if (Store[x][y]) + if (IS_WALKABLE_INSIDE(Back[x][y])) + return; + + if (Back[x][y]) + DrawGraphic(sx, sy, el2img(Back[x][y]), 0); + else if (Store[x][y]) DrawGraphic(sx, sy, el2img(Store[x][y]), 0); frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]); #if 1 - if (Store[x][y]) + if (Back[x][y] || Store[x][y]) DrawGraphicThruMask(sx, sy, graphic, frame); else DrawGraphic(sx, sy, graphic, frame); @@ -1500,6 +1506,10 @@ void Explode(int ex, int ey, int phase, int mode) { int center_element = Feld[ex][ey]; + /* remove things displayed in background while burning dynamite */ + if (!IS_INDESTRUCTIBLE(Back[ex][ey])) + Back[ex][ey] = 0; + if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey)) { /* put moving element to center field (and let it explode there) */ @@ -1525,7 +1535,10 @@ void Explode(int ex, int ey, int phase, int mode) RemoveMovingField(x, y); } - if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES) + if ((IS_INDESTRUCTIBLE(element) && + (game.engine_version < VERSION_IDENT(2,2,0) || + (!IS_WALKABLE_OVER(element) && !IS_WALKABLE_UNDER(element)))) || + element == EL_FLAMES) continue; if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y))) @@ -1540,6 +1553,11 @@ void Explode(int ex, int ey, int phase, int mode) continue; } + /* save walkable background elements while explosion on same tile */ + if (IS_INDESTRUCTIBLE(element)) + Back[x][y] = element; + + /* ignite explodable elements reached by other explosion */ if (element == EL_EXPLOSION) element = Store2[x][y]; @@ -1595,7 +1613,7 @@ void Explode(int ex, int ey, int phase, int mode) Store[x][y] = EL_PEARL; else if (element == EL_WALL_CRYSTAL) Store[x][y] = EL_CRYSTAL; - else if (!IS_PFORTE(Store[x][y])) + else Store[x][y] = EL_EMPTY; if (x != ex || y != ey || @@ -1612,7 +1630,7 @@ void Explode(int ex, int ey, int phase, int mode) } Feld[x][y] = EL_EXPLOSION; - GfxElement[x][y] = EL_EMPTY; + GfxElement[x][y] = EL_UNDEFINED; MovDir[x][y] = MovPos[x][y] = 0; AmoebaNr[x][y] = 0; ExplodePhase[x][y] = 1; @@ -1666,6 +1684,11 @@ void Explode(int ex, int ey, int phase, int mode) element = Feld[x][y] = Store[x][y]; Store[x][y] = Store2[x][y] = 0; + + if (Back[x][y] && IS_INDESTRUCTIBLE(Back[x][y])) + element = Feld[x][y] = Back[x][y]; + Back[x][y] = 0; + MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0; InitField(x, y, FALSE); if (CAN_MOVE(element) || COULD_MOVE(element)) @@ -1686,12 +1709,17 @@ void Explode(int ex, int ey, int phase, int mode) if (phase == delay) DrawLevelFieldCrumbledSand(x, y); - if (IS_PFORTE(Store[x][y])) + if (IS_WALKABLE_OVER(Back[x][y])) { - DrawLevelElement(x, y, Store[x][y]); + DrawLevelElement(x, y, Back[x][y]); DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame); } - else + else if (IS_WALKABLE_UNDER(Back[x][y])) + { + DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame); + DrawLevelElementThruMask(x, y, Back[x][y]); + } + else if (!IS_WALKABLE_INSIDE(Back[x][y])) DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame); } } @@ -3072,7 +3100,7 @@ void StartMoving(int x, int y) int flame_graphic = graphic + (i - 1); if (!IN_LEV_FIELD(xx, yy) || - IS_SOLID(Feld[xx][yy]) || Feld[xx][yy] == EL_EXPLOSION) + IS_HISTORIC_SOLID(Feld[xx][yy]) || Feld[xx][yy] == EL_EXPLOSION) break; if (MovDelay[x][y]) @@ -4137,22 +4165,22 @@ void MauerWaechst(int x, int y) { if (MovDir[x][y] == MV_LEFT) { - if (IN_LEV_FIELD(x - 1, y) && IS_MAUER(Feld[x - 1][y])) + if (IN_LEV_FIELD(x - 1, y) && IS_WALL(Feld[x - 1][y])) DrawLevelField(x - 1, y); } else if (MovDir[x][y] == MV_RIGHT) { - if (IN_LEV_FIELD(x + 1, y) && IS_MAUER(Feld[x + 1][y])) + if (IN_LEV_FIELD(x + 1, y) && IS_WALL(Feld[x + 1][y])) DrawLevelField(x + 1, y); } else if (MovDir[x][y] == MV_UP) { - if (IN_LEV_FIELD(x, y - 1) && IS_MAUER(Feld[x][y - 1])) + if (IN_LEV_FIELD(x, y - 1) && IS_WALL(Feld[x][y - 1])) DrawLevelField(x, y - 1); } else { - if (IN_LEV_FIELD(x, y + 1) && IS_MAUER(Feld[x][y + 1])) + if (IN_LEV_FIELD(x, y + 1) && IS_WALL(Feld[x][y + 1])) DrawLevelField(x, y + 1); } @@ -4251,13 +4279,13 @@ void MauerAbleger(int ax, int ay) if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei)) DrawLevelField(ax, ay); - if (!IN_LEV_FIELD(ax, ay-1) || IS_MAUER(Feld[ax][ay-1])) + if (!IN_LEV_FIELD(ax, ay-1) || IS_WALL(Feld[ax][ay-1])) oben_massiv = TRUE; - if (!IN_LEV_FIELD(ax, ay+1) || IS_MAUER(Feld[ax][ay+1])) + if (!IN_LEV_FIELD(ax, ay+1) || IS_WALL(Feld[ax][ay+1])) unten_massiv = TRUE; - if (!IN_LEV_FIELD(ax-1, ay) || IS_MAUER(Feld[ax-1][ay])) + if (!IN_LEV_FIELD(ax-1, ay) || IS_WALL(Feld[ax-1][ay])) links_massiv = TRUE; - if (!IN_LEV_FIELD(ax+1, ay) || IS_MAUER(Feld[ax+1][ay])) + if (!IN_LEV_FIELD(ax+1, ay) || IS_WALL(Feld[ax+1][ay])) rechts_massiv = TRUE; if (((oben_massiv && unten_massiv) || @@ -5030,7 +5058,7 @@ static void CheckGravityMovement(struct PlayerInfo *player) if (field_under_player_is_free && !player_is_moving_to_valid_field && - !IS_WALKABLE_THROUGH(Feld[jx][jy])) + !IS_WALKABLE_INSIDE(Feld[jx][jy])) player->programmed_action = MV_DOWN; } } @@ -5604,8 +5632,8 @@ void KillHero(struct PlayerInfo *player) if (!player->active) return; - if (IS_PFORTE(Feld[jx][jy])) - Feld[jx][jy] = EL_EMPTY; + /* remove accessible field at the player's position */ + Feld[jx][jy] = EL_EMPTY; /* deactivate shield (else Bang()/Explode() would not work right) */ player->shield_normal_time_left = 0; @@ -5657,18 +5685,52 @@ void RemoveHero(struct PlayerInfo *player) ExitY = ZY = jy; } -#if 0 /* checkDiagonalPushing() ----------------------------------------------------------------------------- check if diagonal input device direction results in pushing of object + (by checking if the alternative direction is walkable, diggable, ...) */ -static boolean checkDiagonalPushing(int x, int y, int real_dx, int real_dy) +static boolean checkDiagonalPushing(struct PlayerInfo *player, + int x, int y, int real_dx, int real_dy) { -} + int jx = player->jx, jy = player->jy; + int dx = x - jx, dy = y - jy; + + if (real_dx && real_dy) /* diagonal direction input => do check */ + { + /* diagonal direction: check alternative direction */ + int xx = jx + (dx == 0 ? real_dx : 0); + int yy = jy + (dy == 0 ? real_dy : 0); + + if (IN_LEV_FIELD(xx, yy)) + { + int element = Feld[xx][yy]; + +#if 0 + if (IS_HISTORIC_SOLID(element) != + (!(IS_WALKABLE(element) || + IS_DIGGABLE(element) || + IS_COLLECTIBLE(element)))) + printf("::: %d ['%s'] [%d, %d]\n", + element, + element_info[element].token_name, + game.engine_version, tape.engine_version); #endif + if (game.engine_version < VERSION_IDENT(2,2,0)) + return IS_HISTORIC_SOLID(element); + else + return !(IS_WALKABLE(element) || + IS_DIGGABLE(element) || + IS_COLLECTIBLE(element)); + } + } + + return TRUE; /* no diagonal direction input => push object */ +} + /* DigField() ----------------------------------------------------------------------------- @@ -5706,9 +5768,15 @@ int DigField(struct PlayerInfo *player, if (IS_MOVING(x, y) || IS_PLAYER(x, y)) return MF_NO_ACTION; - if (IS_TUBE(Feld[jx][jy])) +#if 0 + 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))) +#endif { int i = 0; + int tube_element = (IS_TUBE(Feld[jx][jy]) ? Feld[jx][jy] : Back[jx][jy]); int tube_leave_directions[][2] = { { EL_TUBE_ANY, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN }, @@ -5725,7 +5793,7 @@ int DigField(struct PlayerInfo *player, { -1, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN } }; - while (tube_leave_directions[i][0] != Feld[jx][jy]) + while (tube_leave_directions[i][0] != tube_element) { i++; if (tube_leave_directions[i][0] == -1) /* should not happen */ @@ -6016,11 +6084,17 @@ int DigField(struct PlayerInfo *player, if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy)) return MF_NO_ACTION; +#if 1 + if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) + return MF_NO_ACTION; +#else if (real_dy) { - if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy])) + if (IN_LEV_FIELD(jx, jy+real_dy) && + !IS_HISTORIC_SOLID(Feld[jx][jy+real_dy])) return MF_NO_ACTION; } +#endif if (player->push_delay == 0) player->push_delay = FrameCounter; @@ -6262,16 +6336,23 @@ int DigField(struct PlayerInfo *player, || !IS_SB_ELEMENT(element)))) return MF_NO_ACTION; +#if 1 + if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) + return MF_NO_ACTION; +#else if (dx && real_dy) { - if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy])) + if (IN_LEV_FIELD(jx, jy+real_dy) && + !IS_HISTORIC_SOLID(Feld[jx][jy+real_dy])) return MF_NO_ACTION; } else if (dy && real_dx) { - if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy])) + if (IN_LEV_FIELD(jx+real_dx, jy) && + !IS_HISTORIC_SOLID(Feld[jx+real_dx][jy])) return MF_NO_ACTION; } +#endif if (player->push_delay == 0) player->push_delay = FrameCounter; @@ -6371,16 +6452,23 @@ int DigField(struct PlayerInfo *player, if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy)) return MF_NO_ACTION; +#if 1 + if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) + return MF_NO_ACTION; +#else if (dx && real_dy) { - if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy])) + if (IN_LEV_FIELD(jx, jy+real_dy) && + !IS_HISTORIC_SOLID(Feld[jx][jy+real_dy])) return MF_NO_ACTION; } else if (dy && real_dx) { - if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy])) + if (IN_LEV_FIELD(jx+real_dx, jy) && + !IS_HISTORIC_SOLID(Feld[jx+real_dx][jy])) return MF_NO_ACTION; } +#endif if (player->push_delay == 0) player->push_delay = FrameCounter; @@ -6473,8 +6561,19 @@ boolean PlaceBomb(struct PlayerInfo *player) IS_ACTIVE_BOMB(element) || element == EL_EXPLOSION) return FALSE; +#if 0 if (element != EL_EMPTY) + return FALSE; +#endif + + if (element != EL_EMPTY) + { +#if 0 Store[jx][jy] = element; +#else + Back[jx][jy] = element; +#endif + } MovDelay[jx][jy] = 96;