X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=f86dffae3620dba97bb42b44651eb822562bb30c;hb=84a3ee86461e2311032274e0b7d7a857e02a76ab;hp=46a99c8f56a446056158b673ba5fdd1825448696;hpb=ef8c5a2593702e86fb1566cfc25dda5f35df2ea0;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 46a99c8f..f86dffae 100644 --- a/src/game.c +++ b/src/game.c @@ -89,6 +89,8 @@ #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value)) #define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value)) +#define INIT_GFX_RANDOM() (SimpleRND(1000000)) + /* game button identifiers */ #define GAME_CTRL_ID_STOP 0 #define GAME_CTRL_ID_PAUSE 1 @@ -100,6 +102,10 @@ #define NUM_GAME_BUTTONS 6 /* forward declaration for internal use */ +#if 0 +static void ResetGfxAnimation(int, int); +#endif + static void InitBeltMovement(void); static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); @@ -115,48 +121,12 @@ static void HandleGameButtons(struct GadgetInfo *); static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; -#define IS_ANIMATED(g) (graphic_info[g].anim_frames > 1) - /* ------------------------------------------------------------------------- */ -/* sound definitions */ +/* definition of elements that automatically change to other elements after */ +/* a specified time, eventually calling a function when changing */ /* ------------------------------------------------------------------------- */ -static struct -{ - char *text; - int value; - boolean is_loop; -} sound_action_properties[] = -{ - /* insert _all_ loop sound actions here */ - { ".waiting", ACTION_WAITING, TRUE }, - { ".moving", ACTION_MOVING, TRUE }, /* continuos moving */ - { ".active", ACTION_ACTIVE, TRUE }, - { ".growing", ACTION_GROWING, TRUE }, - { ".attacking", ACTION_ATTACKING, TRUE }, - - /* other (non-loop) sound actions are optional */ - { ".stepping", ACTION_MOVING, FALSE }, /* discrete moving */ - { ".digging", ACTION_DIGGING, FALSE }, - { ".collecting", ACTION_COLLECTING, FALSE }, - { ".passing", ACTION_PASSING, FALSE }, - { ".impact", ACTION_IMPACT, FALSE }, - { ".pushing", ACTION_PUSHING, FALSE }, - { ".activating", ACTION_ACTIVATING, FALSE }, - { NULL, 0, 0 }, -}; -static int element_action_sound[MAX_NUM_ELEMENTS][NUM_ACTIONS]; -static boolean is_loop_sound[NUM_SOUND_FILES]; - -#define IS_LOOP_SOUND(x) (is_loop_sound[x]) - - -/* ------------------------------------------------------------------------- - definition of elements that automatically change to other elements after - a specified time, eventually calling a function when changing - ------------------------------------------------------------------------- */ - /* forward declaration for changer functions */ static void InitBuggyBase(int x, int y); static void WarnBuggyBase(int x, int y); @@ -194,6 +164,9 @@ static struct ChangingElementInfo changing_element_list[] = { EL_TIMEGATE_OPENING, EL_TIMEGATE_OPEN, 29, NULL, NULL, NULL }, { EL_TIMEGATE_CLOSING, EL_TIMEGATE_CLOSED, 29, NULL, NULL, NULL }, + { EL_ACID_SPLASH_LEFT, EL_EMPTY, 8, NULL, NULL, NULL }, + { EL_ACID_SPLASH_RIGHT, EL_EMPTY, 8, NULL, NULL, NULL }, + { EL_SP_BUGGY_BASE, EL_SP_BUGGY_BASE_ACTIVATING, 0, InitBuggyBase, NULL, NULL }, { EL_SP_BUGGY_BASE_ACTIVATING,EL_SP_BUGGY_BASE_ACTIVE, 0, @@ -220,60 +193,6 @@ static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS]; #define IS_AUTO_CHANGING(e) (changing_element[e].base_element != EL_UNDEFINED) - -#ifdef DEBUG -#if 0 -static unsigned int getStateCheckSum(int counter) -{ - int x, y; - unsigned int mult = 1; - unsigned int checksum = 0; - /* - static short lastFeld[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; - */ - static boolean first_game = TRUE; - - for (y=0; y ANIM_DELAY(graphic)) +#endif + ResetRandomAnimationValue(x, y); +#endif + + GfxFrame[x][y] = 0; + GfxAction[x][y] = ACTION_DEFAULT; + +#if 0 + if (Feld[x][y] == EL_ROCK) + printf("ResetGfxAnimation: EL_ROCK [%d, %d]\n", + JustStopped[x][y], MovDir[x][y]); +#endif +} + void InitMovingField(int x, int y, int direction) { int element = Feld[x][y]; @@ -1432,10 +1290,9 @@ void InitMovingField(int x, int y, int direction) int newy = y + (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); if (!JustStopped[x][y] || direction != MovDir[x][y]) - GfxFrame[x][y] = 0; + ResetGfxAnimation(x, y); - MovDir[x][y] = direction; - MovDir[newx][newy] = direction; + MovDir[newx][newy] = MovDir[x][y] = direction; if (Feld[newx][newy] == EL_EMPTY) Feld[newx][newy] = EL_BLOCKED; @@ -1444,6 +1301,10 @@ void InitMovingField(int x, int y, int direction) GfxAction[x][y] = ACTION_FALLING; else GfxAction[x][y] = ACTION_MOVING; + + GfxFrame[newx][newy] = GfxFrame[x][y]; + GfxAction[newx][newy] = GfxAction[x][y]; + GfxRandom[newx][newy] = GfxRandom[x][y]; } void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y) @@ -1584,17 +1445,15 @@ void DrawDynamite(int x, int y) void CheckDynamite(int x, int y) { - int element = Feld[x][y]; - if (MovDelay[x][y] != 0) /* dynamite is still waiting to explode */ { MovDelay[x][y]--; if (MovDelay[x][y] != 0) { - if (checkDrawLevelGraphicAnimation(x, y, el2img(element))) - DrawDynamite(x, y); + DrawDynamite(x, y); + /* !!! correct: "PlaySoundLevelActionIfLoop" etc. !!! */ PlaySoundLevelAction(x, y, ACTION_ACTIVE); return; @@ -1926,27 +1785,27 @@ void Bang(int x, int y) } } -void Blurb(int x, int y) +void SplashAcid(int x, int y) { int element = Feld[x][y]; if (element != EL_ACID_SPLASH_LEFT && - element != EL_ACID_SPLASH_RIGHT) /* start */ + element != EL_ACID_SPLASH_RIGHT) { PlaySoundLevel(x, y, SND_ACID_SPLASHING); + if (IN_LEV_FIELD(x-1, y) && IS_FREE(x-1, y) && (!IN_LEV_FIELD(x-1, y-1) || !CAN_FALL(MovingOrBlocked2Element(x-1, y-1)))) - { Feld[x-1][y] = EL_ACID_SPLASH_LEFT; - } + if (IN_LEV_FIELD(x+1, y) && IS_FREE(x+1, y) && (!IN_LEV_FIELD(x+1, y-1) || !CAN_FALL(MovingOrBlocked2Element(x+1, y-1)))) - { Feld[x+1][y] = EL_ACID_SPLASH_RIGHT; - } } + +#if 0 else /* go on */ { int graphic = (element == EL_ACID_SPLASH_LEFT ? @@ -1973,6 +1832,7 @@ void Blurb(int x, int y) } } } +#endif } static void InitBeltMovement() @@ -2287,22 +2147,33 @@ void Impact(int x, int y) return; object_hit = (!IS_FREE(x, y+1) && (!IS_MOVING(x, y+1) || - MovDir[x][y+1]!=MV_DOWN || - MovPos[x][y+1]<=TILEY/2)); + MovDir[x][y+1] != MV_DOWN || + MovPos[x][y+1] <= TILEY / 2)); if (object_hit) smashed = MovingOrBlocked2Element(x, y+1); } if (!lastline && smashed == EL_ACID) /* element falls into acid */ { - Blurb(x, y); + SplashAcid(x, y); return; } +#if 1 + if (lastline || object_hit) + { +#if 0 + MovDir[x][y] = 0; +#endif + ResetGfxAnimation(x, y); + DrawLevelField(x, y); + } +#endif + if ((element == EL_BOMB || element == EL_SP_DISK_ORANGE || element == EL_DX_SUPABOMB) && - (lastline || object_hit)) /* element is bomb */ + (lastline || object_hit)) /* element is bomb */ { Bang(x, y); return; @@ -2324,6 +2195,8 @@ void Impact(int x, int y) { Feld[x][y] = EL_AMOEBA_CREATING; Store[x][y] = EL_AMOEBA_WET; + + ResetRandomAnimationValue(x, y); } return; } @@ -2331,7 +2204,8 @@ void Impact(int x, int y) if (!lastline && object_hit) /* check which object was hit */ { if (CAN_CHANGE(element) && - (smashed == EL_MAGIC_WALL || smashed == EL_BD_MAGIC_WALL)) + (smashed == EL_MAGIC_WALL || + smashed == EL_BD_MAGIC_WALL)) { int xx, yy; int activated_magic_wall = @@ -2352,29 +2226,31 @@ void Impact(int x, int y) SND_BD_MAGIC_WALL_ACTIVATING)); } - if (IS_PLAYER(x, y+1)) + if (IS_PLAYER(x, y + 1)) { KillHeroUnlessProtected(x, y+1); return; } else if (smashed == EL_PENGUIN) { - Bang(x, y+1); + Bang(x, y + 1); return; } else if (element == EL_BD_DIAMOND) { if (IS_ENEMY(smashed) && IS_BD_ELEMENT(smashed)) { - Bang(x, y+1); + Bang(x, y + 1); return; } } - else if ((element == EL_SP_INFOTRON || element == EL_SP_ZONK) && - (smashed == EL_SP_SNIKSNAK || smashed == EL_SP_ELECTRON || + else if ((element == EL_SP_INFOTRON || + element == EL_SP_ZONK) && + (smashed == EL_SP_SNIKSNAK || + smashed == EL_SP_ELECTRON || smashed == EL_SP_DISK_ORANGE)) { - Bang(x, y+1); + Bang(x, y + 1); return; } else if (element == EL_ROCK || @@ -2382,19 +2258,23 @@ void Impact(int x, int y) element == EL_BD_ROCK) { if (IS_ENEMY(smashed) || - smashed == EL_BOMB || smashed == EL_SP_DISK_ORANGE || + smashed == EL_BOMB || + smashed == EL_SP_DISK_ORANGE || smashed == EL_DX_SUPABOMB || - smashed == EL_SATELLITE || smashed == EL_PIG || - smashed == EL_DRAGON || smashed == EL_MOLE) + smashed == EL_SATELLITE || + smashed == EL_PIG || + smashed == EL_DRAGON || + smashed == EL_MOLE) { - Bang(x, y+1); + Bang(x, y + 1); return; } - else if (!IS_MOVING(x, y+1)) + else if (!IS_MOVING(x, y + 1)) { - if (smashed == EL_LAMP || smashed == EL_LAMP_ACTIVE) + if (smashed == EL_LAMP || + smashed == EL_LAMP_ACTIVE) { - Bang(x, y+1); + Bang(x, y + 1); return; } else if (smashed == EL_NUT) @@ -2447,6 +2327,13 @@ void Impact(int x, int y) return; } +#if 0 + printf("::: -> %d,%d [%d]\n", element, ACTION_IMPACT, + element_info[element].sound[ACTION_IMPACT]); + + PlaySound(177); +#endif + /* play sound of object that hits the ground */ if (lastline || object_hit) PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT); @@ -3020,9 +2907,13 @@ void StartMoving(int x, int y) EL_BD_MAGIC_WALL_FILLING); Store[x][y] = element; } +#if 0 else if (CAN_SMASH(element) && Feld[x][y+1] == EL_ACID) +#else + else if (CAN_FALL(element) && Feld[x][y+1] == EL_ACID) +#endif { - Blurb(x, y); + SplashAcid(x, y); InitMovingField(x, y, MV_DOWN); started_moving = TRUE; @@ -3044,6 +2935,9 @@ void StartMoving(int x, int y) } else if (IS_FREE(x, y+1)) { + if (JustStopped[x][y]) /* prevent animation from being restarted */ + MovDir[x][y] = MV_DOWN; + InitMovingField(x, y, MV_DOWN); started_moving = TRUE; } @@ -3161,8 +3055,12 @@ void StartMoving(int x, int y) MovDelay[x][y]--; if (element == EL_ROBOT || - element == EL_YAMYAM || element == EL_DARK_YAMYAM) + element == EL_YAMYAM || + element == EL_DARK_YAMYAM) { +#if 1 + DrawLevelElementAnimationIfNeeded(x, y, element); +#else if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) { int graphic = el2img(element); @@ -3170,7 +3068,11 @@ void StartMoving(int x, int y) DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame); } +#endif +#if 1 + PlaySoundLevelAction(x, y, ACTION_WAITING); +#else if (MovDelay[x][y] % 4 == 3) { if (element == EL_YAMYAM) @@ -3178,19 +3080,20 @@ void StartMoving(int x, int y) else if (element == EL_DARK_YAMYAM) PlaySoundLevel(x, y, SND_DARK_YAMYAM_WAITING); } +#endif } else if (element == EL_SP_ELECTRON) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); else if (element == EL_DRAGON) { int i; int dir = MovDir[x][y]; int dx = (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0); int dy = (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0); - int graphic = (dir == MV_LEFT ? IMG_FLAMES_LEFT1 : - dir == MV_RIGHT ? IMG_FLAMES_RIGHT1 : - dir == MV_UP ? IMG_FLAMES_UP1 : - dir == MV_DOWN ? IMG_FLAMES_DOWN1 : IMG_EMPTY); + int graphic = (dir == MV_LEFT ? IMG_FLAMES1_LEFT : + dir == MV_RIGHT ? IMG_FLAMES1_RIGHT : + dir == MV_UP ? IMG_FLAMES1_UP : + dir == MV_DOWN ? IMG_FLAMES1_DOWN : IMG_EMPTY); int frame = getGraphicAnimationFrame(graphic, -1); for (i=1; i<=3; i++) @@ -3257,7 +3160,7 @@ void StartMoving(int x, int y) IN_LEV_FIELD(newx, newy) && MovDir[x][y] == MV_DOWN && Feld[newx][newy] == EL_ACID) { - Blurb(x, y); + SplashAcid(x, y); Store[x][y] = EL_ACID; } else if (element == EL_PENGUIN && IN_LEV_FIELD(newx, newy)) @@ -3438,11 +3341,11 @@ void StartMoving(int x, int y) element == EL_SP_SNIKSNAK || element == EL_MOLE) DrawLevelField(x, y); else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); else if (element == EL_SATELLITE) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); else if (element == EL_SP_ELECTRON) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); if (DONT_TOUCH(element)) TestIfBadThingTouchesHero(x, y); @@ -3577,9 +3480,20 @@ void ContinueMoving(int x, int y) MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; MovDelay[newx][newy] = 0; +#if 0 + /* all done in "InitMovingField()" */ GfxAction[newx][newy] = GfxAction[x][y]; /* keep action one frame */ - GfxAction[x][y] = ACTION_DEFAULT; + GfxRandom[newx][newy] = GfxRandom[x][y]; /* keep same random value */ +#endif + + /* copy animation control values to new field */ + GfxFrame[newx][newy] = GfxFrame[x][y]; + GfxAction[newx][newy] = GfxAction[x][y]; + GfxRandom[newx][newy] = GfxRandom[x][y]; + + ResetGfxAnimation(x, y); /* reset animation values for old field */ +#if 1 #if 0 if (!CAN_MOVE(element)) MovDir[newx][newy] = 0; @@ -3592,6 +3506,7 @@ void ContinueMoving(int x, int y) if (!CAN_MOVE(element) || (element == EL_SPRING && MovDir[newx][newy] == MV_DOWN)) MovDir[newx][newy] = 0; +#endif #endif DrawLevelField(x, y); @@ -4116,38 +4031,6 @@ static void StopRobotWheel(int x, int y) ZX = ZY = -1; } -#if 1 -void RobotWheel(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_ROBOT_WHEEL_ACTIVE, -1); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_ROBOT_WHEEL_ACTIVE, frame); - } - - PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVE); - - return; - } - } - - Feld[x][y] = EL_ROBOT_WHEEL; - DrawLevelField(x, y); - - if (ZX == x && ZY == y) - ZX = ZY = -1; -} -#endif - static void InitTimegateWheel(int x, int y) { MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND; @@ -4158,106 +4041,6 @@ static void RunTimegateWheel(int x, int y) PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVE); } -#if 1 -void TimegateWheel(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_TIMEGATE_SWITCH_ACTIVE, -1); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_SWITCH_ACTIVE, frame); - } - - PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVE); - - return; - } - } - - Feld[x][y] = EL_TIMEGATE_SWITCH; - DrawLevelField(x, y); - - /* THIS HAS NO EFFECT AT ALL! */ -#if 1 - /* !!! THIS LOOKS WRONG !!! */ - if (ZX == x && ZY == y) - ZX = ZY = -1; -#endif - -} -#endif - -#if 1 -void NussKnacken(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 7; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_NUT_CRACKING, - 6 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_NUT_CRACKING, frame); - } - - return; - } - } - - Feld[x][y] = EL_EMERALD; - DrawLevelField(x, y); -} -#endif - -#if 1 -void BreakingPearl(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 9; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_PEARL_BREAKING, - 8 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_PEARL_BREAKING, frame); - } - - return; - } - } - - Feld[x][y] = EL_EMPTY; - DrawLevelField(x, y); -} -#endif - -void SiebAktivieren(int x, int y, int type) -{ - int graphic = (type == 1 ? IMG_MAGIC_WALL_FULL : IMG_BD_MAGIC_WALL_FULL); - - DrawLevelGraphicAnimation(x, y, graphic); -} - void CheckExit(int x, int y) { if (local_player->gems_still_needed > 0 || @@ -4280,174 +4063,11 @@ void CheckExitSP(int x, int y) PlaySoundLevelNearest(x, y, SND_SP_EXIT_OPENING); } -#if 1 -void AusgangstuerOeffnen(int x, int y) +static void CloseAllOpenTimegates() { - int delay = 6; - - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 5 * delay; + int x, y; - if (MovDelay[x][y]) /* wait some time before next frame */ - { - int tuer; - - MovDelay[x][y]--; - tuer = MovDelay[x][y] / delay; - - if (!(MovDelay[x][y] % delay)) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_EXIT_OPENING, - 29 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_EXIT_OPENING, frame); - } - } - - if (MovDelay[x][y]) - return; - } - - Feld[x][y] = EL_EXIT_OPEN; - DrawLevelField(x, y); -} -#endif - -#if 1 -void OpenSwitchgate(int x, int y) -{ - int delay = 6; - - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 5 * delay; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - - if (!(MovDelay[x][y] % delay)) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_SWITCHGATE_OPENING, - 29 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_SWITCHGATE_OPENING, frame); - } - } - - if (MovDelay[x][y]) - return; - } - - Feld[x][y] = EL_SWITCHGATE_OPEN; - DrawLevelField(x, y); -} -#endif - -#if 1 -void CloseSwitchgate(int x, int y) -{ - int delay = 6; - - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 5 * delay; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - - if (!(MovDelay[x][y] % delay)) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_SWITCHGATE_CLOSING, - 29 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_SWITCHGATE_CLOSING, frame); - } - } - - if (MovDelay[x][y]) - return; - } - - Feld[x][y] = EL_SWITCHGATE_CLOSED; - DrawLevelField(x, y); -} -#endif - -#if 1 -void OpenTimegate(int x, int y) -{ - int delay = 6; - - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 5 * delay; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - - if (!(MovDelay[x][y] % delay)) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_TIMEGATE_OPENING, - 29 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_OPENING, frame); - } - } - - if (MovDelay[x][y]) - return; - } - - Feld[x][y] = EL_TIMEGATE_OPEN; - DrawLevelField(x, y); -} -#endif - -#if 1 -void CloseTimegate(int x, int y) -{ - int delay = 6; - - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 5 * delay; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - - if (!(MovDelay[x][y] % delay)) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_TIMEGATE_CLOSING, - 29 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_CLOSING, frame); - } - } - - if (MovDelay[x][y]) - return; - } - - Feld[x][y] = EL_TIMEGATE_CLOSED; - DrawLevelField(x, y); -} -#endif - -static void CloseAllOpenTimegates() -{ - int x, y; - - for (y=0; yjx, jy = local_player->jy; - if (element == EL_MAGIC_WALL_FULL || - element == EL_MAGIC_WALL_ACTIVE || - element == EL_MAGIC_WALL_EMPTYING) - { - SiebAktivieren(x, y, 1); - sieb = TRUE; - } - else if (element == EL_BD_MAGIC_WALL_FULL || - element == EL_BD_MAGIC_WALL_ACTIVE || - element == EL_BD_MAGIC_WALL_EMPTYING) - { - SiebAktivieren(x, y, 2); - sieb = TRUE; - } - /* play the element sound at the position nearest to the player */ - if (sieb && ABS(x-jx)+ABS(y-jy) < ABS(sieb_x-jx)+ABS(sieb_y-jy)) + if ((element == EL_MAGIC_WALL_FULL || + element == EL_MAGIC_WALL_ACTIVE || + element == EL_MAGIC_WALL_EMPTYING || + element == EL_BD_MAGIC_WALL_FULL || + element == EL_BD_MAGIC_WALL_ACTIVE || + element == EL_BD_MAGIC_WALL_EMPTYING) && + ABS(x-jx) + ABS(y-jy) < ABS(magic_wall_x-jx) + ABS(magic_wall_y-jy)) { - sieb_x = x; - sieb_y = y; + magic_wall_x = x; + magic_wall_y = y; } } } @@ -5447,14 +4929,14 @@ void GameActions() { if (!(game.magic_wall_time_left % 4)) { - int element = Feld[sieb_x][sieb_y]; + int element = Feld[magic_wall_x][magic_wall_y]; if (element == EL_BD_MAGIC_WALL_FULL || element == EL_BD_MAGIC_WALL_ACTIVE || element == EL_BD_MAGIC_WALL_EMPTYING) - PlaySoundLevel(sieb_x, sieb_y, SND_BD_MAGIC_WALL_ACTIVE); + PlaySoundLevel(magic_wall_x, magic_wall_y, SND_BD_MAGIC_WALL_ACTIVE); else - PlaySoundLevel(sieb_x, sieb_y, SND_MAGIC_WALL_ACTIVE); + PlaySoundLevel(magic_wall_x, magic_wall_y, SND_MAGIC_WALL_ACTIVE); } if (game.magic_wall_time_left > 0) @@ -5703,7 +5185,7 @@ boolean MoveFigureOneStep(struct PlayerInfo *player, { if (element == EL_ACID && dx == 0 && dy == 1) { - Blurb(jx, jy); + SplashAcid(jx, jy); Feld[jx][jy] = EL_PLAYER1; InitMovingField(jx, jy, MV_DOWN); Store[jx][jy] = EL_ACID; @@ -6593,7 +6075,9 @@ int DigField(struct PlayerInfo *player, case EL_SPRING: if (mode == DF_SNAP) return MF_NO_ACTION; + /* no "break" -- fall through to next case */ + /* the following elements can be pushed by "snapping" */ case EL_BD_ROCK: if (dy) @@ -6614,7 +6098,8 @@ int DigField(struct PlayerInfo *player, player->push_delay = FrameCounter; #if 0 if (!FrameReached(&player->push_delay, player->push_delay_value) && - !tape.playing && element != EL_SPRING) + !tape.playing && + element != EL_SPRING) return MF_NO_ACTION; #else if (!FrameReached(&player->push_delay, player->push_delay_value) && @@ -6925,6 +6410,48 @@ int DigField(struct PlayerInfo *player, break; default: + if (IS_PUSHABLE(element)) + { + if (mode == DF_SNAP) + return MF_NO_ACTION; + + if (CAN_FALL(element) && dy) + return MF_NO_ACTION; + + player->Pushing = TRUE; + + if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy)) + return MF_NO_ACTION; + + if (dx && real_dy) + { + if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_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])) + return MF_NO_ACTION; + } + + if (player->push_delay == 0) + player->push_delay = FrameCounter; + + if (!FrameReached(&player->push_delay, player->push_delay_value) && + !(tape.playing && tape.file_version < FILE_VERSION_2_0)) + return MF_NO_ACTION; + + RemoveField(x, y); + Feld[x + dx][y + dy] = element; + + player->push_delay_value = 2 + RND(8); + + DrawLevelField(x + dx, y + dy); + PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING); + + break; + } + return MF_NO_ACTION; } @@ -6989,7 +6516,9 @@ boolean PlaceBomb(struct PlayerInfo *player) Store[jx][jy] = element; MovDelay[jx][jy] = 96; - GfxFrame[jx][jy] = 0; + + ResetGfxAnimation(jx, jy); + ResetRandomAnimationValue(jx, jy); if (player->dynamite) { @@ -7023,10 +6552,29 @@ boolean PlaceBomb(struct PlayerInfo *player) return TRUE; } +/* ------------------------------------------------------------------------- */ +/* game sound playing functions */ +/* ------------------------------------------------------------------------- */ + +static int *loop_sound_frame = NULL; +static int *loop_sound_volume = NULL; + +void InitPlaySoundLevel() +{ + int num_sounds = getSoundListSize(); + + if (loop_sound_frame != NULL) + free(loop_sound_frame); + + if (loop_sound_volume != NULL) + free(loop_sound_volume); + + loop_sound_frame = checked_calloc(num_sounds * sizeof(int)); + loop_sound_volume = checked_calloc(num_sounds * sizeof(int)); +} + static void PlaySoundLevel(int x, int y, int nr) { - static int loop_sound_frame[NUM_SOUND_FILES]; - static int loop_sound_volume[NUM_SOUND_FILES]; int sx = SCREENX(x), sy = SCREENY(y); int volume, stereo_position; int max_distance = 8; @@ -7087,9 +6635,9 @@ static void PlaySoundLevelAction(int x, int y, int sound_action) static void PlaySoundLevelElementAction(int x, int y, int element, int sound_action) { - int sound_effect = element_action_sound[element][sound_action]; + int sound_effect = element_info[element].sound[sound_action]; - if (sound_effect != -1) + if (sound_effect != SND_UNDEFINED) PlaySoundLevel(x, y, sound_effect); }